Add more error checks, Add failing test case

This commit is contained in:
MrLetsplay 2024-06-12 22:28:07 +02:00
parent 905a0a5fa6
commit 30d454a9d2
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
3 changed files with 72 additions and 3 deletions

View File

@ -56,7 +56,7 @@ public class SharedDocument implements MessageListener {
Identifier[] newPos = Util.generatePositionBetween(charBefore.position(), charAfter.position(), site); Identifier[] newPos = Util.generatePositionBetween(charBefore.position(), charAfter.position(), site);
lamport++; lamport++;
Char ch = new Char(newPos, lamport, bytes[i]); Char ch = new Char(newPos, lamport, bytes[i]);
charBag.add(ch); if(charBag.add(ch) == -1) throw new IllegalStateException("Couldn't insert newly created char");
changes[i] = new Change(path, ChangeType.ADD, ch); changes[i] = new Change(path, ChangeType.ADD, ch);
charBefore = ch; charBefore = ch;
} }
@ -110,7 +110,7 @@ public class SharedDocument implements MessageListener {
// TODO: more efficient implementation (e.g. range delete in CharBag) // TODO: more efficient implementation (e.g. range delete in CharBag)
Char toRemove = charBag.get(index + 1); Char toRemove = charBag.get(index + 1);
changes[n] = new Change(path, ChangeType.REMOVE, toRemove); changes[n] = new Change(path, ChangeType.REMOVE, toRemove);
charBag.remove(toRemove); if(charBag.remove(toRemove) == -1) throw new IllegalStateException("Couldn't remove existing char");
} }
@ -195,7 +195,6 @@ public class SharedDocument implements MessageListener {
Change c = change.change(); Change c = change.change();
if(!c.documentPath().equals(path)) return; if(!c.documentPath().equals(path)) return;
System.out.println("Change: " + c + " | " + Arrays.toString(c.character().position()));
switch(c.type()) { switch(c.type()) {
case ADD -> remoteInsert(c.character()); case ADD -> remoteInsert(c.character());
case REMOVE -> remoteDelete(c.character()); case REMOVE -> remoteDelete(c.character());

View File

@ -1,6 +1,7 @@
package me.mrletsplay.shareclientcore.document; package me.mrletsplay.shareclientcore.document;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
public class Util { public class Util {
@ -44,6 +45,10 @@ public class Util {
return newPosition.toArray(Identifier[]::new); return newPosition.toArray(Identifier[]::new);
} }
System.err.println("Got invalid state");
System.err.println(c1 + "/" + c2);
System.err.println(Arrays.toString(before));
System.err.println(Arrays.toString(after));
throw new RuntimeException("Invalid site order"); throw new RuntimeException("Invalid site order");
} }

View File

@ -2,6 +2,8 @@ package me.mrletsplay.shareclientcore;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Random;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import me.mrletsplay.shareclientcore.connection.DummyConnection; import me.mrletsplay.shareclientcore.connection.DummyConnection;
@ -32,6 +34,69 @@ public class SharingTest {
assertEquals("This is a test!Hello World!", sharedA.getContentsAsString()); assertEquals("This is a test!Hello World!", sharedA.getContentsAsString());
assertEquals("This is a test!Hello World!", sharedB.getContentsAsString()); assertEquals("This is a test!Hello World!", sharedB.getContentsAsString());
sharedA.localDelete(10, 11);
assertEquals("This is a World!", sharedA.getContentsAsString());
assertEquals("This is a World!", sharedB.getContentsAsString());
sharedB.localDelete(7, 8);
assertEquals("This is!", sharedA.getContentsAsString());
assertEquals("This is!", sharedB.getContentsAsString());
}
@Test
public void testSharedDocument2() {
DummyConnection a = new DummyConnection(0);
DummyConnection b = new DummyConnection(1);
a.setSendMessageHandler(m -> b.receive(m));
b.setSendMessageHandler(m -> a.receive(m));
SharedDocument sharedA = new SharedDocument(a, "doc");
SharedDocument sharedB = new SharedDocument(b, "doc");
a.addListener(sharedA);
b.addListener(sharedB);
String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890";
Random r = new Random(0);
for(int i = 0; i < 1000; i++) {
switch(r.nextInt(sharedA.getContents().length == 0 ? 2 : 4)) {
case 0: {
// Insert A
char[] insert = new char[r.nextInt(16)];
for(int j = 0; j < insert.length; j++) insert[j] = chars.charAt(r.nextInt(chars.length()));
sharedA.localInsert(r.nextInt(sharedA.getContents().length + 1), String.valueOf(insert));
}
case 1: {
// Insert B
char[] insert = new char[r.nextInt(16)];
for(int j = 0; j < insert.length; j++) insert[j] = chars.charAt(r.nextInt(chars.length()));
sharedB.localInsert(r.nextInt(sharedB.getContents().length + 1), String.valueOf(insert));
}
case 2: {
// Delete A
int len = sharedA.getContents().length;
int idx = r.nextInt(len);
int n = r.nextInt(len - idx);
sharedA.localDelete(idx, n);
}
case 3: {
// Delete B
int len = sharedB.getContents().length;
int idx = r.nextInt(len);
int n = r.nextInt(len - idx + 1);
sharedB.localDelete(idx, n);
}
}
System.out.println("A: " + sharedA.getContentsAsString());
System.out.println("B: " + sharedB.getContentsAsString());
assertEquals(sharedA.getContentsAsString(), sharedB.getContentsAsString());
}
} }
} }