Skip to content

Commit

Permalink
Add serializer tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
kuujo committed May 28, 2015
1 parent 25cf376 commit 5117804
Show file tree
Hide file tree
Showing 19 changed files with 472 additions and 66 deletions.
40 changes: 28 additions & 12 deletions io/src/main/java/net/kuujo/copycat/io/AbstractBuffer.java
Expand Up @@ -631,16 +631,22 @@ public boolean readBoolean(long offset) {

@Override
public String readUTF8() {
byte[] bytes = new byte[readUnsignedShort(checkRead(Short.BYTES))];
read(checkRead(bytes.length), bytes, 0, bytes.length);
return new String(bytes, StandardCharsets.UTF_8);
if (readByte() != 0) {
byte[] bytes = new byte[readUnsignedShort()];
read(bytes, 0, bytes.length);
return new String(bytes, StandardCharsets.UTF_8);
}
return null;
}

@Override
public String readUTF8(long offset) {
byte[] bytes = new byte[readUnsignedShort(checkRead(offset, Short.BYTES))];
read(checkRead(offset + Short.BYTES, bytes.length), bytes, 0, bytes.length);
return new String(bytes, StandardCharsets.UTF_8);
if (readByte(offset) != 0) {
byte[] bytes = new byte[readUnsignedShort(offset + Byte.BYTES)];
read(offset + Byte.BYTES + Short.BYTES, bytes, 0, bytes.length);
return new String(bytes, StandardCharsets.UTF_8);
}
return null;
}

@Override
Expand Down Expand Up @@ -853,16 +859,26 @@ public Buffer writeBoolean(long offset, boolean b) {

@Override
public Buffer writeUTF8(String s) {
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
return writeUnsignedShort(checkWrite(Short.BYTES), bytes.length)
.write(checkWrite(bytes.length), bytes, 0, bytes.length);
if (s == null) {
return writeByte(0);
} else {
writeByte(1);
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
return writeUnsignedShort(bytes.length)
.write(bytes, 0, bytes.length);
}
}

@Override
public Buffer writeUTF8(long offset, String s) {
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
return writeUnsignedShort(checkWrite(offset, Short.BYTES), bytes.length)
.write(checkWrite(offset + Short.BYTES, bytes.length), bytes, 0, bytes.length);
if (s == null) {
return writeByte(offset, 0);
} else {
writeByte(offset, 1);
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
return writeUnsignedShort(offset + Byte.BYTES, bytes.length)
.write(offset + Byte.BYTES + Short.BYTES, bytes, 0, bytes.length);
}
}

@Override
Expand Down
4 changes: 2 additions & 2 deletions io/src/main/java/net/kuujo/copycat/io/Buffer.java
Expand Up @@ -958,13 +958,13 @@ default boolean isFile() {
String readUTF8();

/**
* Reads a 1 byte boolean from the buffer at the given offset.
* Reads a UTF-8 string from the buffer at the given offset.
* <p>
* The string will be read from the given offset. If the given index is out of the bounds of the buffer then a
* {@link IndexOutOfBoundsException} will be thrown.
*
* @param offset The offset at which to read the boolean.
* @return The read boolean.
* @return The read string.
* @throws IndexOutOfBoundsException If the given offset is out of the bounds of the buffer. Note that
* bounds are determined by the buffer's {@link Buffer#limit()} rather than capacity.
* @see Buffer#readUTF8()
Expand Down
9 changes: 6 additions & 3 deletions io/src/main/java/net/kuujo/copycat/io/BufferReader.java
Expand Up @@ -302,9 +302,12 @@ public boolean readBoolean() {

@Override
public String readUTF8() {
byte[] bytes = new byte[readUnsignedShort()];
read(bytes, 0, bytes.length);
return new String(bytes, StandardCharsets.UTF_8);
if (readByte() != 0) {
byte[] bytes = new byte[readUnsignedShort()];
read(bytes, 0, bytes.length);
return new String(bytes, StandardCharsets.UTF_8);
}
return null;
}

@Override
Expand Down
11 changes: 8 additions & 3 deletions io/src/main/java/net/kuujo/copycat/io/BufferWriter.java
Expand Up @@ -315,9 +315,14 @@ public BufferWriter writeBoolean(boolean b) {

@Override
public BufferWriter writeUTF8(String s) {
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
return writeUnsignedShort(bytes.length)
.write(bytes, 0, bytes.length);
if (s == null) {
return writeByte(0);
} else {
writeByte(1);
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
return writeUnsignedShort(bytes.length)
.write(bytes, 0, bytes.length);
}
}

@Override
Expand Down
20 changes: 14 additions & 6 deletions io/src/main/java/net/kuujo/copycat/io/FileBytes.java
Expand Up @@ -386,9 +386,12 @@ public boolean readBoolean(long offset) {

@Override
public String readUTF8(long offset) {
byte[] bytes = new byte[readUnsignedShort(offset)];
read(offset + Short.BYTES, bytes, 0, bytes.length);
return new String(bytes, StandardCharsets.UTF_8);
if (readByte(offset) != 0) {
byte[] bytes = new byte[readUnsignedShort(offset + Byte.BYTES)];
read(offset + Byte.BYTES + Short.BYTES, bytes, 0, bytes.length);
return new String(bytes, StandardCharsets.UTF_8);
}
return null;
}

@Override
Expand Down Expand Up @@ -570,9 +573,14 @@ public Bytes writeBoolean(long offset, boolean b) {

@Override
public Bytes writeUTF8(long offset, String s) {
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
return writeUnsignedShort(offset, bytes.length)
.write(offset + Short.BYTES, bytes, 0, bytes.length);
if (s == null) {
return writeByte(offset, 0);
} else {
writeByte(offset, 1);
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
return writeUnsignedShort(offset + Byte.BYTES, bytes.length)
.write(offset + Byte.BYTES + Short.BYTES, bytes, 0, bytes.length);
}
}

@Override
Expand Down
9 changes: 6 additions & 3 deletions io/src/main/java/net/kuujo/copycat/io/NativeBytes.java
Expand Up @@ -206,9 +206,12 @@ public boolean readBoolean(long offset) {

@Override
public String readUTF8(long offset) {
byte[] bytes = new byte[readUnsignedShort(offset)];
read(offset + Short.BYTES, bytes, 0, bytes.length);
return new String(bytes, StandardCharsets.UTF_8);
if (readByte(offset) != 0) {
byte[] bytes = new byte[readUnsignedShort(offset + Byte.BYTES)];
read(offset + Byte.BYTES + Short.BYTES, bytes, 0, bytes.length);
return new String(bytes, StandardCharsets.UTF_8);
}
return null;
}

@Override
Expand Down
5 changes: 5 additions & 0 deletions io/src/main/java/net/kuujo/copycat/io/ReadOnlyBuffer.java
Expand Up @@ -235,6 +235,11 @@ public Buffer writeBoolean(boolean b) {
throw new ReadOnlyBufferException();
}

@Override
public Buffer writeUTF8(String s) {
throw new ReadOnlyBufferException();
}

@Override
public Buffer flush() {
throw new ReadOnlyBufferException();
Expand Down
Expand Up @@ -16,26 +16,29 @@
package net.kuujo.copycat.io.serializer;

import net.kuujo.copycat.io.Buffer;
import org.testng.annotations.Test;

import static org.testng.Assert.*;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;

/**
* Serializer test.
* Big decimal serializer.
*
* @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/
@Test
public class ObjectWriterTest {
@Serialize(@Serialize.Type(id=8, type=BigDecimal.class))
public class BigDecimalWriter implements ObjectWriter<BigDecimal> {

/**
* Tests serializing a string.
*/
public void testSerializeString() {
Serializer serializer = new Serializer();
Buffer buffer = serializer.writeObject("Hello world!").flip();
String result = serializer.readObject(buffer);
assertEquals(result, "Hello world!");
@Override
public void write(BigDecimal object, Buffer buffer, Serializer serializer) {
byte[] bytes = object.toPlainString().getBytes(StandardCharsets.UTF_8);
buffer.writeInt(bytes.length).write(bytes);
}

@Override
public BigDecimal read(Class<BigDecimal> type, Buffer buffer, Serializer serializer) {
byte[] bytes = new byte[buffer.readInt()];
buffer.read(bytes);
return new BigDecimal(new String(bytes, StandardCharsets.UTF_8));
}

}
Expand Up @@ -22,7 +22,7 @@
*
* @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/
@Serialize(@Serialize.Type(id=2, type=Double.class))
@Serialize(@Serialize.Type(id=3, type=Double.class))
public class DoubleWriter implements ObjectWriter<Double> {

@Override
Expand Down
Expand Up @@ -22,7 +22,7 @@
*
* @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/
@Serialize(@Serialize.Type(id=1, type=Float.class))
@Serialize(@Serialize.Type(id=2, type=Float.class))
public class FloatWriter implements ObjectWriter<Float> {

@Override
Expand Down
Expand Up @@ -22,7 +22,7 @@
*
* @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/
@Serialize(@Serialize.Type(id=4, type=Integer.class))
@Serialize(@Serialize.Type(id=5, type=Integer.class))
public class IntegerWriter implements ObjectWriter<Integer> {

@Override
Expand Down
Expand Up @@ -25,12 +25,12 @@
*
* @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/
@Serialize(@Serialize.Type(id=5, type=List.class))
@Serialize(@Serialize.Type(id=9, type=List.class))
public class ListWriter implements ObjectWriter<List> {

@Override
public void write(List object, Buffer buffer, Serializer serializer) {
buffer.writeInt(object.size());
buffer.writeUnsignedShort(object.size());
for (Object value : object) {
serializer.writeObject(value, buffer);
}
Expand All @@ -39,7 +39,7 @@ public void write(List object, Buffer buffer, Serializer serializer) {
@Override
@SuppressWarnings("unchecked")
public List read(Class<List> type, Buffer buffer, Serializer serializer) {
int size = buffer.readInt();
int size = buffer.readUnsignedShort();
List object = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
object.add(serializer.readObject(buffer));
Expand Down
53 changes: 53 additions & 0 deletions io/src/main/java/net/kuujo/copycat/io/serializer/MapWriter.java
@@ -0,0 +1,53 @@
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.kuujo.copycat.io.serializer;

import net.kuujo.copycat.io.Buffer;

import java.util.HashMap;
import java.util.Map;

/**
* Map serializer.
*
* @author <a href="http://github.com/kuujo">Jordan Halterman</a>
*/
@Serialize(@Serialize.Type(id=11, type=Map.class))
public class MapWriter implements ObjectWriter<Map> {

@Override
public void write(Map object, Buffer buffer, Serializer serializer) {
buffer.writeUnsignedShort(object.size());
for (Map.Entry entry : ((Map<?, ?>) object).entrySet()) {
serializer.writeObject(entry.getKey(), buffer);
serializer.writeObject(entry.getValue(), buffer);
}
}

@Override
@SuppressWarnings("unchecked")
public Map read(Class<Map> type, Buffer buffer, Serializer serializer) {
int size = buffer.readUnsignedShort();
Map object = new HashMap<>(size);
for (int i = 0; i < size; i++) {
Object key = serializer.readObject(buffer);
Object value = serializer.readObject(buffer);
object.put(key, value);
}
return object;
}

}
23 changes: 11 additions & 12 deletions io/src/main/java/net/kuujo/copycat/io/serializer/Serializer.java
Expand Up @@ -52,14 +52,14 @@ public class Serializer {
private final ReferencePool<Buffer> bufferPool = new HeapBufferPool();

@SuppressWarnings("unchecked")
public Serializer(String... packages) {
public Serializer(Object... resources) {
this.registry = new SerializerRegistry();

String[] allPackages = new String[packages.length + 1];
System.arraycopy(packages, 0, allPackages, 0, packages.length);
allPackages[packages.length] = COPYCAT_PACKAGE;
Object[] allResources = new String[resources.length + 1];
System.arraycopy(resources, 0, allResources, 0, resources.length);
allResources[resources.length] = COPYCAT_PACKAGE;

registerSerializers(allPackages);
registerSerializers(allResources);
}

private Serializer(SerializerRegistry registry) {
Expand All @@ -70,8 +70,8 @@ private Serializer(SerializerRegistry registry) {
* Registers serializers from the given packages.
*/
@SuppressWarnings("unchecked")
private void registerSerializers(String... packages) {
Reflections reflections = new Reflections(packages);
private void registerSerializers(Object... resources) {
Reflections reflections = new Reflections(resources);

for (Class<? extends ObjectWriter> writer : reflections.getSubTypesOf(ObjectWriter.class)) {
Serialize serialize = writer.getAnnotation(Serialize.class);
Expand All @@ -86,7 +86,7 @@ private void registerSerializers(String... packages) {
} else {
Class type = TypeResolver.resolveRawArgument(ObjectWriter.class, writer);
if (type != null) {
registry.register((Class) type, writer);
registry.register(type, writer);
}
}
}
Expand Down Expand Up @@ -286,7 +286,7 @@ private <T> Buffer writeWritableId(int id, T writable, Buffer buffer, ObjectWrit
*/
@SuppressWarnings("unchecked")
private <T> Buffer writeWritableClass(Class<?> type, T writable, Buffer buffer, ObjectWriter writer) {
writer.write(writable, buffer.writeByte(TYPE_WRITABLE_CLASS).writeInt(type.getName().getBytes().length).write(type.getName().getBytes()), this);
writer.write(writable, buffer.writeByte(TYPE_WRITABLE_CLASS).writeUTF8(type.getName()), this);
return buffer;
}

Expand Down Expand Up @@ -380,9 +380,7 @@ private <T> T readWritableId(Buffer buffer) {
*/
@SuppressWarnings("unchecked")
private <T> T readWritableClass(Buffer buffer) {
byte[] bytes = new byte[buffer.readInt()];
buffer.read(bytes);
String name = new String(bytes);
String name = buffer.readUTF8();
try {
Class<?> type = Class.forName(name);
if (type == null)
Expand All @@ -405,6 +403,7 @@ private <T> T readWritableClass(Buffer buffer) {
@SuppressWarnings("unchecked")
private <T> T readSerializable(Buffer buffer) {
byte[] bytes = new byte[buffer.readInt()];
buffer.read(bytes);
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
try {
return (T) in.readObject();
Expand Down

0 comments on commit 5117804

Please sign in to comment.