Don't register listener for SharedDocument, Add tests
This commit is contained in:
parent
4b0ec70f54
commit
f82812577e
@ -1,8 +0,0 @@
|
|||||||
package me.mrletsplay.shareclientcore;
|
|
||||||
|
|
||||||
public class ShareClient {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -3,6 +3,8 @@ package me.mrletsplay.shareclientcore.connection.message;
|
|||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public record ChecksumMessage(int siteID, String documentPath, byte[] checksum) implements AddressableMessage {
|
public record ChecksumMessage(int siteID, String documentPath, byte[] checksum) implements AddressableMessage {
|
||||||
|
|
||||||
@ -19,6 +21,28 @@ public record ChecksumMessage(int siteID, String documentPath, byte[] checksum)
|
|||||||
out.write(checksum);
|
out.write(checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + Arrays.hashCode(checksum);
|
||||||
|
result = prime * result + Objects.hash(documentPath, siteID);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
ChecksumMessage other = (ChecksumMessage) obj;
|
||||||
|
return Arrays.equals(checksum, other.checksum) && Objects.equals(documentPath, other.documentPath)
|
||||||
|
&& siteID == other.siteID;
|
||||||
|
}
|
||||||
|
|
||||||
public static ChecksumMessage deserialize(DataInputStream in) throws IOException {
|
public static ChecksumMessage deserialize(DataInputStream in) throws IOException {
|
||||||
try {
|
try {
|
||||||
return new ChecksumMessage(in.readInt(), in.readUTF(), in.readNBytes(in.readInt()));
|
return new ChecksumMessage(in.readInt(), in.readUTF(), in.readNBytes(in.readInt()));
|
||||||
|
@ -3,8 +3,12 @@ package me.mrletsplay.shareclientcore.connection.message;
|
|||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public record FullSyncMessage(int siteID, String documentPath, byte[] content) implements AddressableMessage {
|
import me.mrletsplay.shareclientcore.document.Char;
|
||||||
|
|
||||||
|
public record FullSyncMessage(int siteID, String documentPath, List<Char> content) implements AddressableMessage {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MessageType getType() {
|
public MessageType getType() {
|
||||||
@ -15,13 +19,26 @@ public record FullSyncMessage(int siteID, String documentPath, byte[] content) i
|
|||||||
public void serialize(DataOutputStream out) throws IOException {
|
public void serialize(DataOutputStream out) throws IOException {
|
||||||
out.writeInt(siteID);
|
out.writeInt(siteID);
|
||||||
out.writeUTF(documentPath);
|
out.writeUTF(documentPath);
|
||||||
out.writeInt(content.length);
|
|
||||||
out.write(content);
|
out.writeInt(content.size());
|
||||||
|
for(Char c : content) {
|
||||||
|
c.serialize(out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FullSyncMessage deserialize(DataInputStream in) throws IOException {
|
public static FullSyncMessage deserialize(DataInputStream in) throws IOException {
|
||||||
try {
|
try {
|
||||||
return new FullSyncMessage(in.readInt(), in.readUTF(), in.readNBytes(in.readInt()));
|
int siteID = in.readInt();
|
||||||
|
String documentPath = in.readUTF();
|
||||||
|
|
||||||
|
int contentSize = in.readInt();
|
||||||
|
List<Char> content = new ArrayList<>(contentSize);
|
||||||
|
for(int i = 0; i < contentSize; i++) {
|
||||||
|
content.add(Char.deserialize(in));
|
||||||
|
System.out.println(content.get(content.size() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FullSyncMessage(siteID, documentPath, content);
|
||||||
}catch(IllegalArgumentException e) {
|
}catch(IllegalArgumentException e) {
|
||||||
throw new IOException("Invalid content length", e);
|
throw new IOException("Invalid content length", e);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ public interface Message extends SerializableObject {
|
|||||||
case REQUEST_CHECKSUM -> m = RequestChecksumMessage.deserialize(dIn);
|
case REQUEST_CHECKSUM -> m = RequestChecksumMessage.deserialize(dIn);
|
||||||
case FULL_SYNC -> m = FullSyncMessage.deserialize(dIn);
|
case FULL_SYNC -> m = FullSyncMessage.deserialize(dIn);
|
||||||
case CHECKSUM -> m = ChecksumMessage.deserialize(dIn);
|
case CHECKSUM -> m = ChecksumMessage.deserialize(dIn);
|
||||||
default -> m = new BasicMessage(type);
|
default -> m = new BasicMessage(type);// TODO: implement missing message types and delete BasicMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
@ -5,7 +5,15 @@ import java.util.List;
|
|||||||
|
|
||||||
public class ArrayCharBag implements CharBag {
|
public class ArrayCharBag implements CharBag {
|
||||||
|
|
||||||
private List<Char> chars = new ArrayList<>();
|
private List<Char> chars;
|
||||||
|
|
||||||
|
public ArrayCharBag() {
|
||||||
|
this.chars = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayCharBag(List<Char> chars) {
|
||||||
|
this.chars = new ArrayList<>(chars);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int add(Char character) {
|
public int add(Char character) {
|
||||||
@ -37,6 +45,11 @@ public class ArrayCharBag implements CharBag {
|
|||||||
return chars.size();
|
return chars.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Char> toList() {
|
||||||
|
return new ArrayList<>(chars);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return chars.stream()
|
return chars.stream()
|
||||||
|
@ -21,6 +21,7 @@ public record Char(Identifier[] position, int lamport, char value) implements Se
|
|||||||
result = prime * result + Objects.hash(lamport, value);
|
result = prime * result + Objects.hash(lamport, value);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj)
|
if (this == obj)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package me.mrletsplay.shareclientcore.document;
|
package me.mrletsplay.shareclientcore.document;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface CharBag {
|
public interface CharBag {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,6 +31,12 @@ public interface CharBag {
|
|||||||
*/
|
*/
|
||||||
public int size();
|
public int size();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects the chars in this bag ordered by their position into a list
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<Char> toList();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collects the chars in this bag ordered by their position into a string
|
* Collects the chars in this bag ordered by their position into a string
|
||||||
* @return A string containing the chars
|
* @return A string containing the chars
|
||||||
|
@ -2,6 +2,7 @@ package me.mrletsplay.shareclientcore.document;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import me.mrletsplay.shareclientcore.connection.Change;
|
import me.mrletsplay.shareclientcore.connection.Change;
|
||||||
@ -28,8 +29,6 @@ public class SharedDocument implements MessageListener {
|
|||||||
this.site = connection.getSiteID();
|
this.site = connection.getSiteID();
|
||||||
this.listeners = new HashSet<>();
|
this.listeners = new HashSet<>();
|
||||||
|
|
||||||
connection.addListener(this);
|
|
||||||
|
|
||||||
charBag.add(Char.START_OF_DOCUMENT);
|
charBag.add(Char.START_OF_DOCUMENT);
|
||||||
charBag.add(Char.END_OF_DOCUMENT);
|
charBag.add(Char.END_OF_DOCUMENT);
|
||||||
if(initialContents != null && !initialContents.isEmpty()) {
|
if(initialContents != null && !initialContents.isEmpty()) {
|
||||||
@ -135,6 +134,16 @@ public class SharedDocument implements MessageListener {
|
|||||||
return charBag;
|
return charBag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects the chars in this document ordered by their position into a list.<br>
|
||||||
|
* This differs from {@link CharBag#toList()} in that this method does not include the {@link Char#START_OF_DOCUMENT} and {@link Char#END_OF_DOCUMENT} chars.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<Char> toList() {
|
||||||
|
List<Char> chars = charBag.toList();
|
||||||
|
return chars.subList(1, chars.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
public String getContents() {
|
public String getContents() {
|
||||||
String contents = charBag.toString();
|
String contents = charBag.toString();
|
||||||
return contents.substring(1, contents.length() - 1);
|
return contents.substring(1, contents.length() - 1);
|
||||||
|
102
src/test/java/me/mrletsplay/shareclientcore/MessageTest.java
Normal file
102
src/test/java/me/mrletsplay/shareclientcore/MessageTest.java
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package me.mrletsplay.shareclientcore;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import me.mrletsplay.shareclientcore.connection.Change;
|
||||||
|
import me.mrletsplay.shareclientcore.connection.ChangeType;
|
||||||
|
import me.mrletsplay.shareclientcore.connection.message.ChangeMessage;
|
||||||
|
import me.mrletsplay.shareclientcore.connection.message.ChecksumMessage;
|
||||||
|
import me.mrletsplay.shareclientcore.connection.message.ClientHelloMessage;
|
||||||
|
import me.mrletsplay.shareclientcore.connection.message.FullSyncMessage;
|
||||||
|
import me.mrletsplay.shareclientcore.connection.message.Message;
|
||||||
|
import me.mrletsplay.shareclientcore.connection.message.PeerJoinMessage;
|
||||||
|
import me.mrletsplay.shareclientcore.connection.message.PeerLeaveMessage;
|
||||||
|
import me.mrletsplay.shareclientcore.connection.message.RequestChecksumMessage;
|
||||||
|
import me.mrletsplay.shareclientcore.connection.message.RequestFullSyncMessage;
|
||||||
|
import me.mrletsplay.shareclientcore.connection.message.ServerHelloMessage;
|
||||||
|
import me.mrletsplay.shareclientcore.document.Char;
|
||||||
|
import me.mrletsplay.shareclientcore.document.Identifier;
|
||||||
|
|
||||||
|
public class MessageTest {
|
||||||
|
|
||||||
|
private static byte[] serialize(Message m) throws IOException {
|
||||||
|
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||||
|
DataOutputStream dOut = new DataOutputStream(bOut);
|
||||||
|
dOut.writeUTF(m.getType().name());
|
||||||
|
m.serialize(dOut);
|
||||||
|
return bOut.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Message deserialize(byte[] bytes) throws IOException {
|
||||||
|
return Message.deserialize(ByteBuffer.wrap(bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangeMessage() throws IOException {
|
||||||
|
Change change = new Change("Project:src/test.txt", ChangeType.ADD, new Char(new Identifier[] {new Identifier(0, 1), new Identifier(1, 3)}, 42, 'e'));
|
||||||
|
ChangeMessage m = new ChangeMessage(change);
|
||||||
|
assertEquals(deserialize(serialize(m)), m, "Deserialized message must equal message");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClientHelloMessage() throws IOException {
|
||||||
|
ClientHelloMessage m = new ClientHelloMessage("User123", "abcdefg");
|
||||||
|
assertEquals(deserialize(serialize(m)), m, "Deserialized message must equal message");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPeerJoinMessage() throws IOException {
|
||||||
|
PeerJoinMessage m = new PeerJoinMessage("User234", 2);
|
||||||
|
assertEquals(deserialize(serialize(m)), m, "Deserialized message must equal message");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPeerLeaveMessage() throws IOException {
|
||||||
|
PeerLeaveMessage m = new PeerLeaveMessage(2);
|
||||||
|
assertEquals(deserialize(serialize(m)), m, "Deserialized message must equal message");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testServerHelloMessage() throws IOException {
|
||||||
|
ServerHelloMessage m = new ServerHelloMessage(42, 3);
|
||||||
|
assertEquals(deserialize(serialize(m)), m, "Deserialized message must equal message");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChecksumMessage() throws IOException {
|
||||||
|
ChecksumMessage m = new ChecksumMessage(2, "Project:src/test.txt", new byte[] {1, 2, 3, 4, 5, 6});
|
||||||
|
assertEquals(deserialize(serialize(m)), m, "Deserialized message must equal message");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFullSyncMessage() throws IOException {
|
||||||
|
List<Char> chars = Arrays.asList(
|
||||||
|
new Char(new Identifier[] {new Identifier(0, 1), new Identifier(1, 3)}, 42, 'e'),
|
||||||
|
new Char(new Identifier[] {new Identifier(0, 1), new Identifier(1, 3), new Identifier(1, 4)}, 333, 'f')
|
||||||
|
);
|
||||||
|
FullSyncMessage m = new FullSyncMessage(2, "Project:src/test.txt", chars);
|
||||||
|
assertEquals(deserialize(serialize(m)), m, "Deserialized message must equal message");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequestChecksumMessage() throws IOException {
|
||||||
|
RequestChecksumMessage m = new RequestChecksumMessage(2, "Project:src/test.txt");
|
||||||
|
assertEquals(deserialize(serialize(m)), m, "Deserialized message must equal message");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRequestFullSyncMessage() throws IOException {
|
||||||
|
RequestFullSyncMessage m = new RequestFullSyncMessage(2, "Project:src/test.txt");
|
||||||
|
assertEquals(deserialize(serialize(m)), m, "Deserialized message must equal message");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user