diff --git a/build.gradle.kts b/build.gradle.kts index f1e3a05b..8a0e4870 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,11 +16,8 @@ import Build_gradle.Extras.bcVersion import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask -import org.gradle.internal.impldep.org.junit.experimental.categories.Categories.CategoryFilter.include -import org.jetbrains.kotlin.js.translate.context.Namer.kotlin import java.time.Instant -import java.util.Properties -import kotlin.collections.ArrayList +import java.util.* import kotlin.collections.component1 import kotlin.collections.component2 import kotlin.collections.set @@ -49,9 +46,9 @@ plugins { id("com.dorkbox.VersionUpdate") version "1.4.1" // setup checking for the latest version of a plugin or dependency - id("com.github.ben-manes.versions") version "0.20.0" + id("com.github.ben-manes.versions") version "0.21.0" - kotlin("jvm") version "1.3.11" + kotlin("jvm") version "1.3.21" } object Extras { @@ -247,91 +244,6 @@ repositories { jcenter() } -/////////////////////////////// -////// UTILITIES COMPILE -/////////////////////////////// - -// as long as the 'Utilities' project is ALSO imported into IntelliJ, class resolution will work (add the sources in the intellij project) -val utils : Configuration by configurations.creating - -fun javaFile(vararg fileNames: String): Iterable { - val fileList = ArrayList(fileNames.size) - - fileNames.forEach { name -> - fileList.add(name.replace('.', '/') + ".java") - } - - return fileList -} - - -task("compileUtils") { - // we don't want the default include of **/*.java - includes.clear() - - source = fileTree("../Utilities/src") - include(javaFile( - "dorkbox.util.OS", - "dorkbox.util.OSType", - "dorkbox.util.Property", - "dorkbox.util.NamedThreadFactory", - "dorkbox.util.DelayTimer", - "dorkbox.util.IO", - "dorkbox.util.FileUtil", - "dorkbox.util.Base64Fast", - "dorkbox.util.RandomUtil", - "dorkbox.util.Sys", - "dorkbox.util.HashUtil", - "dorkbox.util.NativeLoader", - - "dorkbox.util.FastThreadLocal", - "dorkbox.util.LocationResolver", - "dorkbox.util.MathUtil", - "dorkbox.util.MersenneTwisterFast", - "dorkbox.util.NativeLoader", - - "dorkbox.util.generics.TypeResolver", - "dorkbox.util.generics.DefaultMethodHelper", - "dorkbox.util.generics.ClassHelper", - - "dorkbox.util.bytes.BigEndian", - "dorkbox.util.bytes.UByte", - "dorkbox.util.bytes.UInteger", - "dorkbox.util.bytes.ULong", - "dorkbox.util.bytes.Unsigned", - "dorkbox.util.bytes.UNumber", - "dorkbox.util.bytes.UShort", - "dorkbox.util.bytes.ByteArrayWrapper", - "dorkbox.util.bytes.OptimizeUtilsByteArray", - "dorkbox.util.bytes.OptimizeUtilsByteBuf", - - "dorkbox.util.exceptions.SecurityException", - "dorkbox.util.exceptions.InitializationException", - - - "dorkbox.util.collections.ObjectIntMap", - "dorkbox.util.collections.IntMap", - "dorkbox.util.collections.IntArray", - "dorkbox.util.collections.ConcurrentIterator", - "dorkbox.util.collections.ConcurrentEntry", - "dorkbox.util.collections.LockFreeHashMap", - "dorkbox.util.collections.LockFreeIntMap", - "dorkbox.util.collections.LockFreeIntBiMap", - "dorkbox.util.collections.LockFreeObjectIntBiMap", - - "dorkbox.util.crypto.CryptoECC", - "dorkbox.util.crypto.CryptoAES" - )) - - // entire packages/directories - include("dorkbox/util/serialization/**/*.java") - include("dorkbox/util/entropy/**/*.java") - include("dorkbox/util/storage/**/*.java") - - classpath = files(utils) - destinationDir = file("$rootDir/build/classes_utilities") -} - /////////////////////////////// ////// Task defaults /////////////////////////////// @@ -347,9 +259,6 @@ tasks.withType { } tasks.jar.get().apply { - // include applicable class files from subset of Utilities project - from((tasks["compileUtils"] as JavaCompile).outputs) - manifest { // https://docs.oracle.com/javase/tutorial/deployment/jar/packageman.html attributes["Name"] = Extras.name @@ -372,26 +281,25 @@ tasks.compileJava.get().apply { dependencies { - val netty = api("io.netty:netty-all:4.1.32.Final") - val kryo = api("com.esotericsoftware:kryo:4.0.2") - api("net.jpountz.lz4:lz4:1.3.0") + implementation("io.netty:netty-all:4.1.34.Final") + implementation("com.esotericsoftware:kryo:5.0.0-RC2") + implementation("net.jpountz.lz4:lz4:1.3.0") - val bc = api("org.bouncycastle:bcprov-jdk15on:$bcVersion") - api("org.bouncycastle:bcpg-jdk15on:$bcVersion") - api("org.bouncycastle:bcmail-jdk15on:$bcVersion") - api("org.bouncycastle:bctls-jdk15on:$bcVersion") + implementation("org.bouncycastle:bcprov-jdk15on:$bcVersion") + implementation("org.bouncycastle:bcpg-jdk15on:$bcVersion") + implementation("org.bouncycastle:bcmail-jdk15on:$bcVersion") + implementation("org.bouncycastle:bctls-jdk15on:$bcVersion") + implementation("net.jodah:typetools:0.6.1") + implementation("de.javakaffee:kryo-serializers:0.45") - api("com.dorkbox:ObjectPool:2.11") + implementation("com.dorkbox:ObjectPool:2.11") + implementation("com.dorkbox:Utilities:1.1") - val slf4j = implementation ("org.slf4j:slf4j-api:1.7.25") + implementation("org.slf4j:slf4j-api:1.7.25") testCompile("junit:junit:4.12") testCompile("ch.qos.logback:logback-classic:1.2.3") - - // add compile utils to dependencies - implementation(files((tasks["compileUtils"] as JavaCompile).outputs)) - utils.dependencies += listOf(netty, kryo, slf4j, bc) } /////////////////////////////// @@ -529,7 +437,7 @@ tasks.named("dependencyUpdates") { ////// Gradle Wrapper Configuration. ///// Run this task, then refresh the gradle project /////////////////////////////// -val wrapperUpdate by tasks.creating(Wrapper::class) { +task("wrapperUpdate") { gradleVersion = "5.3" distributionUrl = distributionUrl.replace("bin", "all") } diff --git a/src/dorkbox/network/connection/ConnectionManager.java b/src/dorkbox/network/connection/ConnectionManager.java index 0053ced1..fe546fc0 100644 --- a/src/dorkbox/network/connection/ConnectionManager.java +++ b/src/dorkbox/network/connection/ConnectionManager.java @@ -35,10 +35,10 @@ import dorkbox.network.connection.ping.PingMessage; import dorkbox.util.Property; import dorkbox.util.collections.ConcurrentEntry; import dorkbox.util.generics.ClassHelper; -import dorkbox.util.generics.TypeResolver; import io.netty.bootstrap.DatagramCloseMessage; import io.netty.util.concurrent.ImmediateEventExecutor; import io.netty.util.concurrent.Promise; +import net.jodah.typetools.TypeResolver; // .equals() compares the identity on purpose,this because we cannot create two separate objects that are somehow equal to each other. @SuppressWarnings("unchecked") diff --git a/src/dorkbox/network/connection/KryoExtra.java b/src/dorkbox/network/connection/KryoExtra.java index f7b7427d..eddc245f 100644 --- a/src/dorkbox/network/connection/KryoExtra.java +++ b/src/dorkbox/network/connection/KryoExtra.java @@ -22,9 +22,6 @@ import org.bouncycastle.crypto.modes.GCMBlockCipher; import org.bouncycastle.crypto.params.ParametersWithIV; import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.util.DefaultClassResolver; -import com.esotericsoftware.kryo.util.DefaultStreamFactory; -import com.esotericsoftware.kryo.util.MapReferenceResolver; import dorkbox.network.pipeline.ByteBufInput; import dorkbox.network.pipeline.ByteBufOutput; @@ -93,7 +90,7 @@ class KryoExtra extends Kryo { public KryoExtra(final NetworkSerializationManager serializationManager) { - super(new DefaultClassResolver(), new MapReferenceResolver(), new DefaultStreamFactory()); + super(); this.serializationManager = serializationManager; } diff --git a/src/dorkbox/network/pipeline/ByteBufInput.java b/src/dorkbox/network/pipeline/ByteBufInput.java index a081f884..da0c3fc7 100644 --- a/src/dorkbox/network/pipeline/ByteBufInput.java +++ b/src/dorkbox/network/pipeline/ByteBufInput.java @@ -35,13 +35,15 @@ package dorkbox.network.pipeline; import java.io.DataInput; +import java.io.IOException; import java.io.InputStream; import com.esotericsoftware.kryo.KryoException; import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; +import com.esotericsoftware.kryo.util.Util; import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; /** * An {@link InputStream} which reads data from a {@link ByteBuf}. @@ -56,461 +58,674 @@ import io.netty.buffer.ByteBuf; *

* Utility methods are provided for efficiently reading primitive types and strings. *

- * Modified from KRYO to use ByteBuf. + *

+ *

+ *

+ * Modified from KRYO ByteBufferInput to use ByteBuf instead of ByteBuffer. */ public class ByteBufInput extends Input { - private char[] inputChars = new char[32]; private ByteBuf byteBuf; - private int startIndex; + private int initialReaderIndex = 0; + private int initialWriterIndex = 0; - /** - * Creates an uninitialized Input. {@link #setBuffer(ByteBuf)} must be called before the Input is used. - */ - public - ByteBufInput() { + private byte[] tempBuffer; + + /** Creates an uninitialized Input, {@link #setBuffer(ByteBuf)} must be called before the Input is used. */ + public ByteBufInput () { } - public - ByteBufInput(ByteBuf buffer) { + /** Creates a new Input for reading from a direct {@link ByteBuf}. + * @param bufferSize The size of the buffer. An exception is thrown if more bytes than this are read and + * {@link #fill(ByteBuf, int, int)} does not supply more bytes. */ + public ByteBufInput (int bufferSize) { + this.capacity = bufferSize; + byteBuf = Unpooled.buffer(bufferSize); + } + + /** Creates a new Input for reading from a {@link ByteBuf} which is filled with the specified bytes. */ + public ByteBufInput (byte[] bytes) { + this(bytes, 0, bytes.length); + } + + /** Creates a new Input for reading from a {@link ByteBuf} which is filled with the specified bytes. + * @see #setBuffer(byte[], int, int) */ + public ByteBufInput (byte[] bytes, int offset, int count) { + if (bytes == null) throw new IllegalArgumentException("bytes cannot be null."); + + setBuffer(Unpooled.wrappedBuffer(bytes, offset, count)); + } + + /** Creates a new Input for reading from a ByteBuffer. */ + public ByteBufInput (ByteBuf buffer) { setBuffer(buffer); } - public final - void setBuffer(ByteBuf byteBuf) { - this.byteBuf = byteBuf; - - if (byteBuf != null) { - startIndex = byteBuf.readerIndex(); // where the object starts... - } - else { - startIndex = 0; - } + /** @see Input#Input(InputStream) */ + public ByteBufInput (InputStream inputStream) { + this(4096); + if (inputStream == null) throw new IllegalArgumentException("inputStream cannot be null."); + this.inputStream = inputStream; } - public - ByteBuf getByteBuf() { + /** @see Input#Input(InputStream, int) */ + public ByteBufInput (InputStream inputStream, int bufferSize) { + this(bufferSize); + if (inputStream == null) throw new IllegalArgumentException("inputStream cannot be null."); + this.inputStream = inputStream; + } + + /** Throws {@link UnsupportedOperationException} because this input uses a ByteBuffer, not a byte[]. + * @deprecated + * @see #getByteBuf() */ + public byte[] getBuffer () { + throw new UnsupportedOperationException("This input does not used a byte[], see #getByteBuf()."); + } + + /** Throws {@link UnsupportedOperationException} because this input uses a ByteBuffer, not a byte[]. + * @deprecated + * @see #setBuffer(ByteBuf) */ + public void setBuffer (byte[] bytes) { + throw new UnsupportedOperationException("This input does not used a byte[], see #setByteBuf(ByteBuf)."); + } + + /** Throws {@link UnsupportedOperationException} because this input uses a ByteBuffer, not a byte[]. + * @deprecated + * @see #setBuffer(ByteBuf) */ + public void setBuffer (byte[] bytes, int offset, int count) { + throw new UnsupportedOperationException("This input does not used a byte[], see #setByteBuf()."); + } + + /** Sets a new buffer to read from. The bytes are not copied, the old buffer is discarded and the new buffer used in its place. + * The position, limit, and capacity are set to match the specified buffer. The total is reset. The + * {@link #setInputStream(InputStream) InputStream} is set to null. */ + public void setBuffer(ByteBuf buffer) { + if (buffer == null) throw new IllegalArgumentException("buffer cannot be null."); + byteBuf = buffer; + + initialReaderIndex = byteBuf.readerIndex(); // where the object starts... + initialWriterIndex = byteBuf.writerIndex(); // where the object ends... + + position = initialReaderIndex; + limit = initialWriterIndex; + capacity = buffer.capacity(); + total = 0; + inputStream = null; + } + + public ByteBuf getByteBuf () { return byteBuf; } - /** - * Sets a new buffer. The position and total are reset, discarding any buffered bytes. - */ - @Override - @Deprecated - public - void setBuffer(byte[] bytes) { - throw new RuntimeException("Cannot access this method!"); + public void setInputStream (InputStream inputStream) { + this.inputStream = inputStream; + limit = 0; + reset(); } - /** - * Sets a new buffer. The position and total are reset, discarding any buffered bytes. - */ - @Override - @Deprecated - public - void setBuffer(byte[] bytes, int offset, int count) { - throw new RuntimeException("Cannot access this method!"); + public void reset () { + super.reset(); + + byteBuf.setIndex(initialReaderIndex, initialWriterIndex); } - @Override - @Deprecated - public - byte[] getBuffer() { - throw new RuntimeException("Cannot access this method!"); + /** Fills the buffer with more bytes. The default implementation reads from the {@link #getInputStream() InputStream}, if set. + * Can be overridden to fill the bytes from another source. */ + protected int fill (ByteBuf buffer, int offset, int count) throws KryoException { + if (inputStream == null) return -1; + try { + if (tempBuffer == null) tempBuffer = new byte[2048]; + buffer.readerIndex(offset); + int total = 0; + while (count > 0) { + int read = inputStream.read(tempBuffer, 0, Math.min(tempBuffer.length, count)); + if (read == -1) { + if (total == 0) return -1; + break; + } + buffer.writeBytes(tempBuffer, 0, read); + count -= read; + total += read; + } + buffer.readerIndex(offset); + return total; + } catch (IOException ex) { + throw new KryoException(ex); + } } - @Override - @Deprecated - public - InputStream getInputStream() { - throw new RuntimeException("Cannot access this method!"); + protected int require (int required) throws KryoException { + int remaining = limit - position; + if (remaining >= required) return remaining; + if (required > capacity) throw new KryoException("Buffer too small: capacity: " + capacity + ", required: " + required); + + int count; + // Try to fill the buffer. + if (remaining > 0) { + count = fill(byteBuf, limit, capacity - limit); + if (count == -1) throw new KryoException("Buffer underflow."); + remaining += count; + if (remaining >= required) { + limit += count; + return remaining; + } + } + + // Compact. Position after compaction can be non-zero. + // CANNOT COMPACT A BYTEBUF + // byteBuffer.position(position); + // byteBuffer.compact(); + // total += position; + // position = 0; + // + // while (true) { + // count = fill(byteBuffer, remaining, capacity - remaining); + // if (count == -1) { + // if (remaining >= required) break; + // throw new KryoException("Buffer underflow."); + // } + // remaining += count; + // if (remaining >= required) break; // Enough has been read. + // } + // limit = remaining; + // byteBuffer.position(0); + return remaining; } - /** - * Sets a new InputStream. The position and total are reset, discarding any buffered bytes. - * - * @param inputStream May be null. - */ - @Override - @Deprecated - public - void setInputStream(InputStream inputStream) { - throw new RuntimeException("Cannot access this method!"); + /** Fills the buffer with at least the number of bytes specified, if possible. + * @param optional Must be > 0. + * @return the number of bytes remaining, but not more than optional, or -1 if {@link #fill(ByteBuf, int, int)} is unable to + * provide more bytes. */ + protected int optional (int optional) throws KryoException { + int remaining = limit - position; + if (remaining >= optional) return optional; + optional = Math.min(optional, capacity); + + // Try to fill the buffer. + int count = fill(byteBuf, limit, capacity - limit); + if (count == -1) return remaining == 0 ? -1 : Math.min(remaining, optional); + remaining += count; + if (remaining >= optional) { + limit += count; + return optional; + } + + // Compact. + // CANNOT COMPACT A BYTEBUF + // byteBuffer.compact(); + // total += position; + // position = 0; + // + // while (true) { + // count = fill(byteBuffer, remaining, capacity - remaining); + // if (count == -1) break; + // remaining += count; + // if (remaining >= optional) break; // Enough has been read. + // } + // limit = remaining; + // byteBuffer.position(position); + return remaining == 0 ? -1 : Math.min(remaining, optional); } - /** - * Returns the number of bytes read. - */ - @Override - public - long total() { - return byteBuf.readerIndex() - startIndex; - } + // InputStream: - /** - * Returns the current position in the buffer. - */ - @Override - public - int position() { - return byteBuf.readerIndex(); - } - - /** - * Sets the current position in the buffer. - */ - @Override - @Deprecated - public - void setPosition(int position) { - throw new RuntimeException("Cannot access this method!"); - } - - /** - * Returns the limit for the buffer. - */ - @Override - public - int limit() { - return byteBuf.writerIndex(); - } - - /** - * Sets the limit in the buffer. - */ - @Override - @Deprecated - public - void setLimit(int limit) { - throw new RuntimeException("Cannot access this method!"); - } - - /** - * Sets the position and total to zero. - */ - @Override - public - void rewind() { - byteBuf.readerIndex(startIndex); - } - - /** - * Discards the specified number of bytes. - */ - @Override - public - void skip(int count) throws KryoException { - byteBuf.skipBytes(count); - } - - /** - * Fills the buffer with more bytes. Can be overridden to fill the bytes from a source other than the InputStream. - */ - @Override - @Deprecated - protected - int fill(byte[] buffer, int offset, int count) throws KryoException { - throw new RuntimeException("Cannot access this method!"); - } - - - // InputStream - - /** - * Reads a single byte as an int from 0 to 255, or -1 if there are no more bytes are available. - */ - @Override - public - int read() throws KryoException { + public int read () throws KryoException { + if (optional(1) <= 0) return -1; + position++; return byteBuf.readByte() & 0xFF; } - /** - * Reads bytes.length bytes or less and writes them to the specified byte[], starting at 0, and returns the number of bytes - * read. - */ - @Override - public - int read(byte[] bytes) throws KryoException { - int start = byteBuf.readerIndex(); - byteBuf.readBytes(bytes); - int end = byteBuf.readerIndex(); - return end - start; // return how many bytes were actually read. + public int read (byte[] bytes) throws KryoException { + return read(bytes, 0, bytes.length); } - /** - * Reads count bytes or less and writes them to the specified byte[], starting at offset, and returns the number of bytes read - * or -1 if no more bytes are available. - */ - @Override - public - int read(byte[] bytes, int offset, int count) throws KryoException { - if (bytes == null) { - throw new IllegalArgumentException("bytes cannot be null."); + public int read (byte[] bytes, int offset, int count) throws KryoException { + if (bytes == null) throw new IllegalArgumentException("bytes cannot be null."); + int startingCount = count; + int copyCount = Math.min(limit - position, count); + while (true) { + byteBuf.getBytes(offset, bytes, 0, copyCount); + position += copyCount; + count -= copyCount; + if (count == 0) break; + offset += copyCount; + copyCount = optional(count); + if (copyCount == -1) { + // End of data. + if (startingCount == count) return -1; + break; + } + if (position == limit) break; } - - int start = byteBuf.readerIndex(); - byteBuf.readBytes(bytes, offset, count); - int end = byteBuf.readerIndex(); - return end - start; // return how many bytes were actually read. + return startingCount - count; } - /** - * Discards the specified number of bytes. - */ - @Override - public - long skip(long count) throws KryoException { + public void setPosition (int position) { + this.position = position; + byteBuf.readerIndex(position); + } + + public void setLimit (int limit) { + this.limit = limit; + byteBuf.writerIndex(limit); + } + + public void skip (int count) throws KryoException { + super.skip(count); + byteBuf.readerIndex(position); + } + + public long skip (long count) throws KryoException { long remaining = count; while (remaining > 0) { - int skip = Math.max(Integer.MAX_VALUE, (int) remaining); + int skip = (int)Math.min(Util.maxArraySize, remaining); skip(skip); remaining -= skip; } return count; } - /** - * Closes the underlying InputStream, if any. - */ - @Override - @Deprecated - public - void close() throws KryoException { - // does nothing. + public void close () throws KryoException { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException ignored) { + } + } } - // byte + // byte: - /** - * Reads a single byte. - */ - @Override - public - byte readByte() throws KryoException { + public byte readByte () throws KryoException { + if (position == limit) require(1); + position++; return byteBuf.readByte(); } - /** - * Reads a byte as an int from 0 to 255. - */ - @Override - public - int readByteUnsigned() throws KryoException { - return byteBuf.readUnsignedByte(); + public int readByteUnsigned () throws KryoException { + if (position == limit) require(1); + position++; + return byteBuf.readByte() & 0xFF; } - /** - * Reads the specified number of bytes into a new byte[]. - */ - @Override - public - byte[] readBytes(int length) throws KryoException { + public byte[] readBytes (int length) throws KryoException { byte[] bytes = new byte[length]; readBytes(bytes, 0, length); return bytes; } - /** - * Reads bytes.length bytes and writes them to the specified byte[], starting at index 0. - */ - @Override - public - void readBytes(byte[] bytes) throws KryoException { - readBytes(bytes, 0, bytes.length); - } - - /** - * Reads count bytes and writes them to the specified byte[], starting at offset. - */ - @Override - public - void readBytes(byte[] bytes, int offset, int count) throws KryoException { - if (bytes == null) { - throw new IllegalArgumentException("bytes cannot be null."); + public void readBytes (byte[] bytes, int offset, int count) throws KryoException { + if (bytes == null) throw new IllegalArgumentException("bytes cannot be null."); + int copyCount = Math.min(limit - position, count); + while (true) { + byteBuf.readBytes(bytes, offset, copyCount); + position += copyCount; + count -= copyCount; + if (count == 0) break; + offset += copyCount; + copyCount = Math.min(count, capacity); + require(copyCount); } - - byteBuf.readBytes(bytes, offset, count); } - // int + // int: - /** - * Reads a 4 byte int. - */ - @Override - public - int readInt() throws KryoException { - return byteBuf.readInt(); + public int readInt () throws KryoException { + require(4); + position += 4; + ByteBuf byteBuf = this.byteBuf; + return byteBuf.readByte() & 0xFF // + | (byteBuf.readByte() & 0xFF) << 8 // + | (byteBuf.readByte() & 0xFF) << 16 // + | (byteBuf.readByte() & 0xFF) << 24; } - - /** - * Reads a 1-5 byte int. This stream may consider such a variable length encoding request as a hint. It is not guaranteed that - * a variable length encoding will be really used. The stream may decide to use native-sized integer representation for - * efficiency reasons. - **/ - @Override - public - int readInt(boolean optimizePositive) throws KryoException { - return readVarInt(optimizePositive); - } - - /** - * Reads a 1-5 byte int. It is guaranteed that a variable length encoding will be used. - */ - @Override - public - int readVarInt(boolean optimizePositive) throws KryoException { - ByteBuf buffer = byteBuf; - - int b = buffer.readByte(); + public int readVarInt (boolean optimizePositive) throws KryoException { + if (require(1) < 5) return readVarInt_slow(optimizePositive); + int b = byteBuf.readByte(); int result = b & 0x7F; if ((b & 0x80) != 0) { - b = buffer.readByte(); + ByteBuf byteBuf = this.byteBuf; + b = byteBuf.readByte(); result |= (b & 0x7F) << 7; if ((b & 0x80) != 0) { - b = buffer.readByte(); + b = byteBuf.readByte(); result |= (b & 0x7F) << 14; if ((b & 0x80) != 0) { - b = buffer.readByte(); + b = byteBuf.readByte(); result |= (b & 0x7F) << 21; if ((b & 0x80) != 0) { - b = buffer.readByte(); + b = byteBuf.readByte(); result |= (b & 0x7F) << 28; } } } } - return optimizePositive ? result : result >>> 1 ^ -(result & 1); + position = byteBuf.readerIndex(); + return optimizePositive ? result : ((result >>> 1) ^ -(result & 1)); } + private int readVarInt_slow (boolean optimizePositive) { + // The buffer is guaranteed to have at least 1 byte. + position++; + int b = byteBuf.readByte(); + int result = b & 0x7F; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + ByteBuf byteBuf = this.byteBuf; + position++; + b = byteBuf.readByte(); + result |= (b & 0x7F) << 7; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + position++; + b = byteBuf.readByte(); + result |= (b & 0x7F) << 14; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + position++; + b = byteBuf.readByte(); + result |= (b & 0x7F) << 21; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + position++; + b = byteBuf.readByte(); + result |= (b & 0x7F) << 28; + } + } + } + } + return optimizePositive ? result : ((result >>> 1) ^ -(result & 1)); + } - /** - * Returns true if enough bytes are available to read an int with {@link #readInt(boolean)}. - */ - @Override - public - boolean canReadInt() throws KryoException { - ByteBuf buffer = byteBuf; - int limit = buffer.writerIndex(); - - if (limit - buffer.readerIndex() >= 5) { - return true; - } - - if ((buffer.readByte() & 0x80) == 0) { - return true; - } - if (buffer.readerIndex() == limit) { - return false; - } - if ((buffer.readByte() & 0x80) == 0) { - return true; - } - if (buffer.readerIndex() == limit) { - return false; - } - if ((buffer.readByte() & 0x80) == 0) { - return true; - } - if (buffer.readerIndex() == limit) { - return false; - } - if ((buffer.readByte() & 0x80) == 0) { - return true; - } - if (buffer.readerIndex() == limit) { - return false; - } + public boolean canReadVarInt () throws KryoException { + if (limit - position >= 5) return true; + if (optional(5) <= 0) return false; + int p = position, limit = this.limit; + ByteBuf byteBuf = this.byteBuf; + if ((byteBuf.getByte(p++) & 0x80) == 0) return true; + if (p == limit) return false; + if ((byteBuf.getByte(p++) & 0x80) == 0) return true; + if (p == limit) return false; + if ((byteBuf.getByte(p++) & 0x80) == 0) return true; + if (p == limit) return false; + if ((byteBuf.getByte(p++) & 0x80) == 0) return true; + if (p == limit) return false; return true; } - /** - * Returns true if enough bytes are available to read a long with {@link #readLong(boolean)}. - */ - @Override - public - boolean canReadLong() throws KryoException { - ByteBuf buffer = byteBuf; - int limit = buffer.writerIndex(); + /** Reads the boolean part of a varint flag. The position is not advanced, {@link #readVarIntFlag(boolean)} should be used to + * advance the position. */ + public boolean readVarIntFlag () { + if (position == limit) require(1); + return (byteBuf.getByte(position) & 0x80) != 0; + } - if (limit - buffer.readerIndex() >= 9) { - return true; + /** Reads the 1-5 byte int part of a varint flag. The position is advanced so if the boolean part is needed it should be read + * first with {@link #readVarIntFlag()}. */ + public int readVarIntFlag (boolean optimizePositive) { + if (require(1) < 5) return readVarIntFlag_slow(optimizePositive); + int b = byteBuf.readByte(); + int result = b & 0x3F; // Mask first 6 bits. + if ((b & 0x40) != 0) { // Bit 7 means another byte, bit 8 means UTF8. + ByteBuf byteBuf = this.byteBuf; + b = byteBuf.readByte(); + result |= (b & 0x7F) << 6; + if ((b & 0x80) != 0) { + b = byteBuf.readByte(); + result |= (b & 0x7F) << 13; + if ((b & 0x80) != 0) { + b = byteBuf.readByte(); + result |= (b & 0x7F) << 20; + if ((b & 0x80) != 0) { + b = byteBuf.readByte(); + result |= (b & 0x7F) << 27; + } + } + } } + position = byteBuf.readerIndex(); + return optimizePositive ? result : ((result >>> 1) ^ -(result & 1)); + } - if ((buffer.readByte() & 0x80) == 0) { - return true; + private int readVarIntFlag_slow (boolean optimizePositive) { + // The buffer is guaranteed to have at least 1 byte. + position++; + int b = byteBuf.readByte(); + int result = b & 0x3F; + if ((b & 0x40) != 0) { + if (position == limit) require(1); + position++; + ByteBuf byteBuf = this.byteBuf; + b = byteBuf.readByte(); + result |= (b & 0x7F) << 6; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + position++; + b = byteBuf.readByte(); + result |= (b & 0x7F) << 13; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + position++; + b = byteBuf.readByte(); + result |= (b & 0x7F) << 20; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + position++; + b = byteBuf.readByte(); + result |= (b & 0x7F) << 27; + } + } + } } - if (buffer.readerIndex() == limit) { - return false; + return optimizePositive ? result : ((result >>> 1) ^ -(result & 1)); + } + + // long: + + public long readLong () throws KryoException { + require(8); + position += 8; + ByteBuf byteBuf = this.byteBuf; + return byteBuf.readByte() & 0xFF // + | (byteBuf.readByte() & 0xFF) << 8 // + | (byteBuf.readByte() & 0xFF) << 16 // + | (long)(byteBuf.readByte() & 0xFF) << 24 // + | (long)(byteBuf.readByte() & 0xFF) << 32 // + | (long)(byteBuf.readByte() & 0xFF) << 40 // + | (long)(byteBuf.readByte() & 0xFF) << 48 // + | (long)byteBuf.readByte() << 56; + } + + public long readVarLong (boolean optimizePositive) throws KryoException { + if (require(1) < 9) return readVarLong_slow(optimizePositive); + int b = byteBuf.readByte(); + long result = b & 0x7F; + if ((b & 0x80) != 0) { + ByteBuf byteBuf = this.byteBuf; + b = byteBuf.readByte(); + result |= (b & 0x7F) << 7; + if ((b & 0x80) != 0) { + b = byteBuf.readByte(); + result |= (b & 0x7F) << 14; + if ((b & 0x80) != 0) { + b = byteBuf.readByte(); + result |= (b & 0x7F) << 21; + if ((b & 0x80) != 0) { + b = byteBuf.readByte(); + result |= (long)(b & 0x7F) << 28; + if ((b & 0x80) != 0) { + b = byteBuf.readByte(); + result |= (long)(b & 0x7F) << 35; + if ((b & 0x80) != 0) { + b = byteBuf.readByte(); + result |= (long)(b & 0x7F) << 42; + if ((b & 0x80) != 0) { + b = byteBuf.readByte(); + result |= (long)(b & 0x7F) << 49; + if ((b & 0x80) != 0) { + b = byteBuf.readByte(); + result |= (long)b << 56; + } + } + } + } + } + } + } } - if ((buffer.readByte() & 0x80) == 0) { - return true; - } - if (buffer.readerIndex() == limit) { - return false; - } - if ((buffer.readByte() & 0x80) == 0) { - return true; - } - if (buffer.readerIndex() == limit) { - return false; - } - if ((buffer.readByte() & 0x80) == 0) { - return true; - } - if (buffer.readerIndex() == limit) { - return false; - } - if ((buffer.readByte() & 0x80) == 0) { - return true; - } - if (buffer.readerIndex() == limit) { - return false; - } - if ((buffer.readByte() & 0x80) == 0) { - return true; - } - if (buffer.readerIndex() == limit) { - return false; - } - if ((buffer.readByte() & 0x80) == 0) { - return true; - } - if (buffer.readerIndex() == limit) { - return false; - } - if ((buffer.readByte() & 0x80) == 0) { - return true; - } - if (buffer.readerIndex() == limit) { - return false; + position = byteBuf.readerIndex(); + return optimizePositive ? result : ((result >>> 1) ^ -(result & 1)); + } + + private long readVarLong_slow (boolean optimizePositive) { + // The buffer is guaranteed to have at least 1 byte. + position++; + int b = byteBuf.readByte(); + long result = b & 0x7F; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + ByteBuf byteBuf = this.byteBuf; + position++; + b = byteBuf.readByte(); + result |= (b & 0x7F) << 7; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + position++; + b = byteBuf.readByte(); + result |= (b & 0x7F) << 14; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + position++; + b = byteBuf.readByte(); + result |= (b & 0x7F) << 21; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + position++; + b = byteBuf.readByte(); + result |= (long)(b & 0x7F) << 28; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + position++; + b = byteBuf.readByte(); + result |= (long)(b & 0x7F) << 35; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + position++; + b = byteBuf.readByte(); + result |= (long)(b & 0x7F) << 42; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + position++; + b = byteBuf.readByte(); + result |= (long)(b & 0x7F) << 49; + if ((b & 0x80) != 0) { + if (position == limit) require(1); + position++; + b = byteBuf.readByte(); + result |= (long)b << 56; + } + } + } + } + } + } + } } + return optimizePositive ? result : ((result >>> 1) ^ -(result & 1)); + } + + public boolean canReadVarLong () throws KryoException { + if (limit - position >= 9) return true; + if (optional(5) <= 0) return false; + int p = position, limit = this.limit; + ByteBuf byteBuf = this.byteBuf; + if ((byteBuf.getByte(p++) & 0x80) == 0) return true; + if (p == limit) return false; + if ((byteBuf.getByte(p++) & 0x80) == 0) return true; + if (p == limit) return false; + if ((byteBuf.getByte(p++) & 0x80) == 0) return true; + if (p == limit) return false; + if ((byteBuf.getByte(p++) & 0x80) == 0) return true; + if (p == limit) return false; + if ((byteBuf.getByte(p++) & 0x80) == 0) return true; + if (p == limit) return false; + if ((byteBuf.getByte(p++) & 0x80) == 0) return true; + if (p == limit) return false; + if ((byteBuf.getByte(p++) & 0x80) == 0) return true; + if (p == limit) return false; + if ((byteBuf.getByte(p++) & 0x80) == 0) return true; + if (p == limit) return false; return true; } - // string + // float: - /** - * Reads the length and string of UTF8 characters, or null. This can read strings written by {@link Output#writeString(String)} - * , {@link Output#writeString(CharSequence)}, and {@link Output#writeAscii(String)}. - * - * @return May be null. - */ - @Override - public - String readString() { - ByteBuf buffer = byteBuf; + public float readFloat () throws KryoException { + require(4); + ByteBuf byteBuf = this.byteBuf; + int p = this.position; + this.position = p + 4; + return Float.intBitsToFloat(byteBuf.readByte() & 0xFF // + | (byteBuf.readByte() & 0xFF) << 8 // + | (byteBuf.readByte() & 0xFF) << 16 // + | (byteBuf.readByte() & 0xFF) << 24); + } - int b = buffer.readByte(); - if ((b & 0x80) == 0) { - return readAscii(); // ASCII. - } + // double: + + public double readDouble () throws KryoException { + require(8); + ByteBuf byteBuf = this.byteBuf; + int p = position; + position = p + 8; + return Double.longBitsToDouble(byteBuf.readByte() & 0xFF // + | (byteBuf.readByte() & 0xFF) << 8 // + | (byteBuf.readByte() & 0xFF) << 16 // + | (long)(byteBuf.readByte() & 0xFF) << 24 // + | (long)(byteBuf.readByte() & 0xFF) << 32 // + | (long)(byteBuf.readByte() & 0xFF) << 40 // + | (long)(byteBuf.readByte() & 0xFF) << 48 // + | (long)byteBuf.readByte() << 56); + } + + // boolean: + + public boolean readBoolean () throws KryoException { + if (position == limit) require(1); + position++; + return byteBuf.readByte() == 1 ? true : false; + } + + // short: + + public short readShort () throws KryoException { + require(2); + position += 2; + return (short)((byteBuf.readByte() & 0xFF) | ((byteBuf.readByte() & 0xFF) << 8)); + } + + public int readShortUnsigned () throws KryoException { + require(2); + position += 2; + return (byteBuf.readByte() & 0xFF) | ((byteBuf.readByte() & 0xFF) << 8); + } + + // char: + + public char readChar () throws KryoException { + require(2); + position += 2; + return (char)((byteBuf.readByte() & 0xFF) | ((byteBuf.readByte() & 0xFF) << 8)); + } + + // String: + + public String readString () { + if (!readVarIntFlag()) return readAsciiString(); // ASCII. // Null, empty, or UTF8. - int charCount = readUtf8Length(b); + int charCount = readVarIntFlag(true); switch (charCount) { case 0: return null; @@ -518,64 +733,54 @@ class ByteBufInput extends Input { return ""; } charCount--; - if (inputChars.length < charCount) { - inputChars = new char[charCount]; - } - readUtf8(charCount); - return new String(inputChars, 0, charCount); + readUtf8Chars(charCount); + return new String(chars, 0, charCount); } - private - int readUtf8Length(int b) { - int result = b & 0x3F; // Mask all but first 6 bits. - if ((b & 0x40) != 0) { // Bit 7 means another byte, bit 8 means UTF8. - ByteBuf buffer = byteBuf; - b = buffer.readByte(); - result |= (b & 0x7F) << 6; - if ((b & 0x80) != 0) { - b = buffer.readByte(); - result |= (b & 0x7F) << 13; - if ((b & 0x80) != 0) { - b = buffer.readByte(); - result |= (b & 0x7F) << 20; - if ((b & 0x80) != 0) { - b = buffer.readByte(); - result |= (b & 0x7F) << 27; - } - } - } + public StringBuilder readStringBuilder () { + if (!readVarIntFlag()) return new StringBuilder(readAsciiString()); // ASCII. + // Null, empty, or UTF8. + int charCount = readVarIntFlag(true); + switch (charCount) { + case 0: + return null; + case 1: + return new StringBuilder(""); } - return result; + charCount--; + readUtf8Chars(charCount); + StringBuilder builder = new StringBuilder(charCount); + builder.append(chars, 0, charCount); + return builder; } - private - void readUtf8(int charCount) { - ByteBuf buffer = byteBuf; - char[] chars = this.inputChars; // will be the correct size. + private void readUtf8Chars (int charCount) { + if (chars.length < charCount) chars = new char[charCount]; + char[] chars = this.chars; // Try to read 7 bit ASCII chars. + ByteBuf byteBuf = this.byteBuf; int charIndex = 0; - int count = charCount; - int b; + int count = Math.min(require(1), charCount); while (charIndex < count) { - b = buffer.readByte(); - if (b < 0) { - buffer.readerIndex(buffer.readerIndex() - 1); - break; - } - chars[charIndex++] = (char) b; + int b = byteBuf.readByte(); + if (b < 0) break; + chars[charIndex++] = (char)b; } + position += charIndex; // If buffer didn't hold all chars or any were not ASCII, use slow path for remainder. if (charIndex < charCount) { - readUtf8_slow(charCount, charIndex); + byteBuf.readerIndex(position); + readUtf8Chars_slow(charCount, charIndex); } } - private - void readUtf8_slow(int charCount, int charIndex) { - ByteBuf buffer = byteBuf; - char[] chars = this.inputChars; + private void readUtf8Chars_slow (int charCount, int charIndex) { + ByteBuf byteBuf = this.byteBuf; + char[] chars = this.chars; while (charIndex < charCount) { - int b = buffer.readByte() & 0xFF; + if (position == limit) require(1); + position++; + int b = byteBuf.readByte() & 0xFF; switch (b >> 4) { case 0: case 1: @@ -585,217 +790,185 @@ class ByteBufInput extends Input { case 5: case 6: case 7: - chars[charIndex] = (char) b; + chars[charIndex] = (char)b; break; case 12: case 13: - chars[charIndex] = (char) ((b & 0x1F) << 6 | buffer.readByte() & 0x3F); + if (position == limit) require(1); + position++; + chars[charIndex] = (char)((b & 0x1F) << 6 | byteBuf.readByte() & 0x3F); break; case 14: - chars[charIndex] = (char) ((b & 0x0F) << 12 | (buffer.readByte() & 0x3F) << 6 | buffer.readByte() & 0x3F); + require(2); + position += 2; + int b2 = byteBuf.readByte(); + int b3 = byteBuf.readByte(); + chars[charIndex] = (char)((b & 0x0F) << 12 | (b2 & 0x3F) << 6 | b3 & 0x3F); break; } charIndex++; } } - private - String readAscii() { - ByteBuf buffer = byteBuf; - - int start = buffer.readerIndex() - 1; - int b; - do { - b = buffer.readByte(); - } while ((b & 0x80) == 0); - int i = buffer.readerIndex() - 1; - buffer.setByte(i, buffer.getByte(i) & 0x7F); // Mask end of ascii bit. - - int capp = buffer.readerIndex() - start; - - byte[] ba = new byte[capp]; - buffer.getBytes(start, ba); - - @SuppressWarnings("deprecation") - String value = new String(ba, 0, 0, capp); - - buffer.setByte(i, buffer.getByte(i) | 0x80); - return value; - } - - - /** - * Reads the length and string of UTF8 characters, or null. This can read strings written by {@link Output#writeString(String)} - * , {@link Output#writeString(CharSequence)}, and {@link Output#writeAscii(String)}. - * - * @return May be null. - */ - @Override - public - StringBuilder readStringBuilder() { - ByteBuf buffer = byteBuf; - - int b = buffer.readByte(); - if ((b & 0x80) == 0) { - return new StringBuilder(readAscii()); // ASCII. - } - // Null, empty, or UTF8. - int charCount = readUtf8Length(b); - switch (charCount) { - case 0: - return null; - case 1: - return new StringBuilder(""); - } - charCount--; - if (inputChars.length < charCount) { - inputChars = new char[charCount]; - } - readUtf8(charCount); - - StringBuilder builder = new StringBuilder(charCount); - builder.append(inputChars, 0, charCount); - return builder; - } - - // float - - /** - * Reads a 4 byte float. - */ - @Override - public - float readFloat() throws KryoException { - return Float.intBitsToFloat(readInt()); - } - - /** - * Reads a 1-5 byte float with reduced precision. - */ - @Override - public - float readFloat(float precision, boolean optimizePositive) throws KryoException { - return readInt(optimizePositive) / precision; - } - - // short - - /** - * Reads a 2 byte short. - */ - @Override - public - short readShort() throws KryoException { - return byteBuf.readShort(); - } - - /** - * Reads a 2 byte short as an int from 0 to 65535. - */ - @Override - public - int readShortUnsigned() throws KryoException { - return byteBuf.readUnsignedShort(); - } - - // long - - /** - * Reads an 8 byte long. - */ - @Override - public - long readLong() throws KryoException { - return byteBuf.readLong(); - } - - /** - * Reads a 1-9 byte long. - */ - @Override - public - long readLong(boolean optimizePositive) throws KryoException { - ByteBuf buffer = byteBuf; - int b = buffer.readByte(); - long result = b & 0x7F; - if ((b & 0x80) != 0) { - b = buffer.readByte(); - result |= (b & 0x7F) << 7; - if ((b & 0x80) != 0) { - b = buffer.readByte(); - result |= (b & 0x7F) << 14; - if ((b & 0x80) != 0) { - b = buffer.readByte(); - result |= (b & 0x7F) << 21; - if ((b & 0x80) != 0) { - b = buffer.readByte(); - result |= (long) (b & 0x7F) << 28; - if ((b & 0x80) != 0) { - b = buffer.readByte(); - result |= (long) (b & 0x7F) << 35; - if ((b & 0x80) != 0) { - b = buffer.readByte(); - result |= (long) (b & 0x7F) << 42; - if ((b & 0x80) != 0) { - b = buffer.readByte(); - result |= (long) (b & 0x7F) << 49; - if ((b & 0x80) != 0) { - b = buffer.readByte(); - result |= (long) b << 56; - } - } - } - } - } - } + private String readAsciiString () { + char[] chars = this.chars; + ByteBuf byteBuf = this.byteBuf; + int charCount = 0; + for (int n = Math.min(chars.length, limit - position); charCount < n; charCount++) { + int b = byteBuf.readByte(); + if ((b & 0x80) == 0x80) { + position = byteBuf.readerIndex(); + chars[charCount] = (char)(b & 0x7F); + return new String(chars, 0, charCount + 1); } + chars[charCount] = (char)b; } - if (!optimizePositive) { - result = result >>> 1 ^ -(result & 1); + position = byteBuf.readerIndex(); + return readAscii_slow(charCount); + } + + private String readAscii_slow (int charCount) { + char[] chars = this.chars; + ByteBuf byteBuf = this.byteBuf; + while (true) { + if (position == limit) require(1); + position++; + int b = byteBuf.readByte(); + if (charCount == chars.length) { + char[] newChars = new char[charCount * 2]; + System.arraycopy(chars, 0, newChars, 0, charCount); + chars = newChars; + this.chars = newChars; + } + if ((b & 0x80) == 0x80) { + chars[charCount] = (char)(b & 0x7F); + return new String(chars, 0, charCount + 1); + } + chars[charCount++] = (char)b; } - return result; } + // Primitive arrays: - // boolean - - /** - * Reads a 1 byte boolean. - */ - @Override - public - boolean readBoolean() throws KryoException { - return byteBuf.readBoolean(); + public int[] readInts (int length) throws KryoException { + int[] array = new int[length]; + if (optional(length << 2) == length << 2) { + ByteBuf byteBuf = this.byteBuf; + for (int i = 0; i < length; i++) { + array[i] = byteBuf.readByte() & 0xFF // + | (byteBuf.readByte() & 0xFF) << 8 // + | (byteBuf.readByte() & 0xFF) << 16 // + | (byteBuf.readByte() & 0xFF) << 24; + } + position = byteBuf.readerIndex(); + } else { + for (int i = 0; i < length; i++) + array[i] = readInt(); + } + return array; } - // char - - /** - * Reads a 2 byte char. - */ - @Override - public - char readChar() throws KryoException { - return byteBuf.readChar(); + public long[] readLongs (int length) throws KryoException { + long[] array = new long[length]; + if (optional(length << 3) == length << 3) { + ByteBuf byteBuf = this.byteBuf; + for (int i = 0; i < length; i++) { + array[i] = byteBuf.readByte() & 0xFF// + | (byteBuf.readByte() & 0xFF) << 8 // + | (byteBuf.readByte() & 0xFF) << 16 // + | (long)(byteBuf.readByte() & 0xFF) << 24 // + | (long)(byteBuf.readByte() & 0xFF) << 32 // + | (long)(byteBuf.readByte() & 0xFF) << 40 // + | (long)(byteBuf.readByte() & 0xFF) << 48 // + | (long)byteBuf.readByte() << 56; + } + position = byteBuf.readerIndex(); + } else { + for (int i = 0; i < length; i++) + array[i] = readLong(); + } + return array; } - // double - - /** - * Reads an 8 bytes double. - */ - @Override - public - double readDouble() throws KryoException { - return Double.longBitsToDouble(readLong()); + public float[] readFloats (int length) throws KryoException { + float[] array = new float[length]; + if (optional(length << 2) == length << 2) { + ByteBuf byteBuf = this.byteBuf; + for (int i = 0; i < length; i++) { + array[i] = Float.intBitsToFloat(byteBuf.readByte() & 0xFF // + | (byteBuf.readByte() & 0xFF) << 8 // + | (byteBuf.readByte() & 0xFF) << 16 // + | (byteBuf.readByte() & 0xFF) << 24); + } + position = byteBuf.readerIndex(); + } else { + for (int i = 0; i < length; i++) + array[i] = readFloat(); + } + return array; } - /** - * Reads a 1-9 byte double with reduced precision. - */ - @Override - public - double readDouble(double precision, boolean optimizePositive) throws KryoException { - return readLong(optimizePositive) / precision; + public double[] readDoubles (int length) throws KryoException { + double[] array = new double[length]; + if (optional(length << 3) == length << 3) { + ByteBuf byteBuf = this.byteBuf; + for (int i = 0; i < length; i++) { + array[i] = Double.longBitsToDouble(byteBuf.readByte() & 0xFF // + | (byteBuf.readByte() & 0xFF) << 8 // + | (byteBuf.readByte() & 0xFF) << 16 // + | (long)(byteBuf.readByte() & 0xFF) << 24 // + | (long)(byteBuf.readByte() & 0xFF) << 32 // + | (long)(byteBuf.readByte() & 0xFF) << 40 // + | (long)(byteBuf.readByte() & 0xFF) << 48 // + | (long)byteBuf.readByte() << 56); + } + position = byteBuf.readerIndex(); + } else { + for (int i = 0; i < length; i++) + array[i] = readDouble(); + } + return array; + } + + public short[] readShorts (int length) throws KryoException { + short[] array = new short[length]; + if (optional(length << 1) == length << 1) { + ByteBuf byteBuf = this.byteBuf; + for (int i = 0; i < length; i++) + array[i] = (short)((byteBuf.readByte() & 0xFF) | ((byteBuf.readByte() & 0xFF) << 8)); + position = byteBuf.readerIndex(); + } else { + for (int i = 0; i < length; i++) + array[i] = readShort(); + } + return array; + } + + public char[] readChars (int length) throws KryoException { + char[] array = new char[length]; + if (optional(length << 1) == length << 1) { + ByteBuf byteBuf = this.byteBuf; + for (int i = 0; i < length; i++) + array[i] = (char)((byteBuf.readByte() & 0xFF) | ((byteBuf.readByte() & 0xFF) << 8)); + position = byteBuf.readerIndex(); + } else { + for (int i = 0; i < length; i++) + array[i] = readChar(); + } + return array; + } + + public boolean[] readBooleans (int length) throws KryoException { + boolean[] array = new boolean[length]; + if (optional(length) == length) { + ByteBuf byteBuf = this.byteBuf; + for (int i = 0; i < length; i++) + array[i] = byteBuf.readByte() != 0; + position = byteBuf.readerIndex(); + } else { + for (int i = 0; i < length; i++) + array[i] = readBoolean(); + } + return array; } } diff --git a/src/dorkbox/network/pipeline/ByteBufOutput.java b/src/dorkbox/network/pipeline/ByteBufOutput.java index 86b24b4a..a2d93ba7 100644 --- a/src/dorkbox/network/pipeline/ByteBufOutput.java +++ b/src/dorkbox/network/pipeline/ByteBufOutput.java @@ -34,12 +34,16 @@ */ package dorkbox.network.pipeline; +import java.io.DataOutput; +import java.io.IOException; +import java.io.OutputStream; + import com.esotericsoftware.kryo.KryoException; import com.esotericsoftware.kryo.io.Output; -import io.netty.buffer.ByteBuf; +import com.esotericsoftware.kryo.util.Util; -import java.io.DataOutput; -import java.io.OutputStream; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; /** * An {@link OutputStream} which writes data to a {@link ByteBuf}. @@ -58,622 +62,752 @@ import java.io.OutputStream; * Modified from KRYO to use ByteBuf. */ public class ByteBufOutput extends Output { - private ByteBuf byteBuf; - private int startIndex; + private int initialReaderIndex = 0; + private int initialWriterIndex = 0; - /** Creates an uninitialized Output. {@link #setBuffer(ByteBuf)} must be called before the Output is used. */ - public ByteBufOutput () { - } - - public ByteBufOutput(ByteBuf buffer) { - setBuffer(buffer); - } - - public final void setBuffer(ByteBuf byteBuf) { - this.byteBuf = byteBuf; - - if (byteBuf != null) { - this.byteBuf.readerIndex(0); - startIndex = byteBuf.writerIndex(); - } else { - startIndex = 0; - } + /** Creates an uninitialized Output, {@link #setBuffer(ByteBuf)} must be called before the Output is used. */ + public ByteBufOutput () { } - public ByteBuf getByteBuf() { + /** Creates a new Output for writing to a direct {@link ByteBuf}. + * @param bufferSize The size of the buffer. An exception is thrown if more bytes than this are written and {@link #flush()} + * does not empty the buffer. */ + public ByteBufOutput (int bufferSize) { + this(bufferSize, bufferSize); + } + + /** Creates a new Output for writing to a direct ByteBuffer. + * @param bufferSize The initial size of the buffer. + * @param maxBufferSize If {@link #flush()} does not empty the buffer, the buffer is doubled as needed until it exceeds + * maxBufferSize and an exception is thrown. Can be -1 for no maximum. */ + public ByteBufOutput (int bufferSize, int maxBufferSize) { + if (maxBufferSize < -1) throw new IllegalArgumentException("maxBufferSize cannot be < -1: " + maxBufferSize); + this.capacity = bufferSize; + this.maxCapacity = maxBufferSize == -1 ? Util.maxArraySize : maxBufferSize; + byteBuf = Unpooled.buffer(bufferSize); + } + + /** Creates a new Output for writing to a ByteBuffer. */ + public ByteBufOutput (ByteBuf buffer) { + setBuffer(buffer); + } + + /** Creates a new Output for writing to a ByteBuffer. + * @param maxBufferSize If {@link #flush()} does not empty the buffer, the buffer is doubled as needed until it exceeds + * maxBufferSize and an exception is thrown. Can be -1 for no maximum. */ + public ByteBufOutput (ByteBuf buffer, int maxBufferSize) { + setBuffer(buffer, maxBufferSize); + } + + /** @see Output#Output(OutputStream) */ + public ByteBufOutput (OutputStream outputStream) { + this(4096, 4096); + if (outputStream == null) throw new IllegalArgumentException("outputStream cannot be null."); + this.outputStream = outputStream; + } + + /** @see Output#Output(OutputStream, int) */ + public ByteBufOutput (OutputStream outputStream, int bufferSize) { + this(bufferSize, bufferSize); + if (outputStream == null) throw new IllegalArgumentException("outputStream cannot be null."); + this.outputStream = outputStream; + } + + public OutputStream getOutputStream () { + return outputStream; + } + + /** Throws {@link UnsupportedOperationException} because this output uses a ByteBuffer, not a byte[]. + * @deprecated + * @see #getByteBuf() */ + public byte[] getBuffer () { + throw new UnsupportedOperationException("This buffer does not used a byte[], see #getByteBuffer()."); + } + + /** Throws {@link UnsupportedOperationException} because this output uses a ByteBuffer, not a byte[]. + * @deprecated + * @see #getByteBuf() */ + public void setBuffer (byte[] buffer) { + throw new UnsupportedOperationException("This buffer does not used a byte[], see #setByteBuffer(ByteBuffer)."); + } + + /** Throws {@link UnsupportedOperationException} because this output uses a ByteBuffer, not a byte[]. + * @deprecated + * @see #getByteBuf() */ + public void setBuffer (byte[] buffer, int maxBufferSize) { + throw new UnsupportedOperationException("This buffer does not used a byte[], see #setByteBuffer(ByteBuffer)."); + } + + /** Allocates a new direct ByteBuffer with the specified bytes and sets it as the new buffer. + * @see #setBuffer(ByteBuf) */ + public void setBuffer (byte[] bytes, int offset, int count) { + setBuffer(Unpooled.wrappedBuffer(bytes, offset, count)); + } + + /** Sets a new buffer to write to. The max size is the buffer's length. + * @see #setBuffer(ByteBuf, int) */ + public void setBuffer (ByteBuf buffer) { + setBuffer(buffer, buffer.capacity()); + } + + /** Sets a new buffer to write to. The bytes are not copied, the old buffer is discarded and the new buffer used in its place. + * The position and capacity are set to match the specified buffer. The total is reset. The + * {@link #setOutputStream(OutputStream) OutputStream} is set to null. + * @param maxBufferSize If {@link #flush()} does not empty the buffer, the buffer is doubled as needed until it exceeds + * maxBufferSize and an exception is thrown. Can be -1 for no maximum. */ + public void setBuffer (ByteBuf buffer, int maxBufferSize) { + if (buffer == null) throw new IllegalArgumentException("buffer cannot be null."); + if (maxBufferSize < -1) throw new IllegalArgumentException("maxBufferSize cannot be < -1: " + maxBufferSize); + + initialReaderIndex = buffer.readerIndex(); + initialWriterIndex = buffer.writerIndex(); + + this.byteBuf = buffer; + this.maxCapacity = maxBufferSize == -1 ? Util.maxArraySize : maxBufferSize; + capacity = buffer.capacity(); + position = initialWriterIndex; + total = 0; + outputStream = null; + } + + /** Returns the buffer. The bytes between zero and {@link #position()} are the data that has been written. */ + public ByteBuf getByteBuf () { return byteBuf; } - - @Override - @Deprecated - public OutputStream getOutputStream () { - throw new RuntimeException("Cannot access this method!"); - } - - /** Sets a new OutputStream. The position and total are reset, discarding any buffered bytes. - * @param outputStream May be null. */ - @Override - @Deprecated - public void setOutputStream (OutputStream outputStream) { - throw new RuntimeException("Cannot access this method!"); - } - - /** Sets the buffer that will be written to. {@link #setBuffer(byte[], int)} is called with the specified buffer's length as the - * maxBufferSize. */ - @Override - @Deprecated - public void setBuffer (byte[] buffer) { - throw new RuntimeException("Cannot access this method!"); - } - - /** Sets the buffer that will be written to. The position and total are reset, discarding any buffered bytes. The - * {@link #setOutputStream(OutputStream) OutputStream} is set to null. - * @param maxBufferSize The buffer is doubled as needed until it exceeds maxBufferSize and an exception is thrown. */ - @Override - @Deprecated - public void setBuffer (byte[] buffer, int maxBufferSize) { - throw new RuntimeException("Cannot access this method!"); - } - - /** Returns the buffer. The bytes between zero and {@link #position()} are the data that has been written. */ - @Override - @Deprecated - public byte[] getBuffer () { - throw new RuntimeException("Cannot access this method!"); - } - - /** Returns a new byte array containing the bytes currently in the buffer between zero and {@link #position()}. */ - @Override - @Deprecated public byte[] toBytes () { - throw new RuntimeException("Cannot access this method!"); - } + byte[] newBuffer = new byte[position]; + byteBuf.readerIndex(initialReaderIndex); + byteBuf.getBytes(initialReaderIndex, newBuffer, 0, position); + return newBuffer; + } - /** Returns the current position in the buffer. This is the number of bytes that have not been flushed. */ - @Override - public int position () { - return byteBuf.writerIndex(); - } - - /** Sets the current position in the buffer. */ - @Override - @Deprecated public void setPosition (int position) { - throw new RuntimeException("Cannot access this method!"); - } + this.position = position; + this.byteBuf.writerIndex(position); + } - /** Returns the total number of bytes written. This may include bytes that have not been flushed. */ - @Override - public long total () { - return byteBuf.writerIndex() - startIndex; - } + public void reset () { + super.reset(); + byteBuf.setIndex(initialReaderIndex, initialWriterIndex); + } - /** Sets the position and total to zero. */ - @Override - public void clear () { - byteBuf.readerIndex(0); - byteBuf.writerIndex(startIndex); - } + protected boolean require (int required) throws KryoException { + int origCode = byteBuf.ensureWritable(1, true); + if (origCode == 0) { + // 0 if the buffer has enough writable bytes, and its capacity is unchanged. + return false; + } + else if (origCode == 2) { + // 2 if the buffer has enough writable bytes, and its capacity has been increased. + capacity = byteBuf.capacity(); + return true; + } + else if (origCode == 3) { + // 3 if the buffer does not have enough bytes, but its capacity has been increased to its maximum. + capacity = byteBuf.capacity(); + return true; + } + else { + // flush and try again. + flush(); + } - // OutputStream + // only got here because we were unable to resize the buffer! + origCode = byteBuf.ensureWritable(1, true); + + if (origCode == 0) { + // 0 if the buffer has enough writable bytes, and its capacity is unchanged. + return false; + } else if (origCode == 1) { + // 1 if the buffer does not have enough bytes, and its capacity is unchanged. + throw new KryoException("Buffer overflow. Max capacity: " + maxCapacity + ", required: " + required); + } + else if (origCode == 2) { + // 2 if the buffer has enough writable bytes, and its capacity has been increased. + capacity = byteBuf.capacity(); + return true; + } + else if (origCode == 3) { + // 3 if the buffer does not have enough bytes, but its capacity has been increased to its maximum. + capacity = byteBuf.capacity(); + return true; + } + else { + throw new KryoException("Unknown buffer resize code: " + origCode); + } + } + + // OutputStream: - /** Writes the buffered bytes to the underlying OutputStream, if any. */ - @Override - @Deprecated public void flush () throws KryoException { - // do nothing... - } + if (outputStream == null) return; + try { + byte[] tmp = new byte[position]; + byteBuf.getBytes(initialReaderIndex, tmp); + byteBuf.readerIndex(initialReaderIndex); + outputStream.write(tmp, 0, position); + } catch (IOException ex) { + throw new KryoException(ex); + } + total += position; + position = 0; + } - /** Flushes any buffered bytes and closes the underlying OutputStream, if any. */ - @Override - @Deprecated public void close () throws KryoException { - // do nothing... - } + flush(); + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException ignored) { + } + } + } - /** Writes a byte. */ - @Override public void write (int value) throws KryoException { - byteBuf.writeByte(value); - } + if (position == capacity) require(1); + byteBuf.writeByte((byte)value); + position++; + } - /** Writes the bytes. Note the byte[] length is not written. */ - @Override public void write (byte[] bytes) throws KryoException { - if (bytes == null) { - throw new IllegalArgumentException("bytes cannot be null."); - } - writeBytes(bytes, 0, bytes.length); - } + if (bytes == null) throw new IllegalArgumentException("bytes cannot be null."); + writeBytes(bytes, 0, bytes.length); + } - /** Writes the bytes. Note the byte[] length is not written. */ - @Override public void write (byte[] bytes, int offset, int length) throws KryoException { - writeBytes(bytes, offset, length); - } + writeBytes(bytes, offset, length); + } - // byte + // byte: - @Override public void writeByte (byte value) throws KryoException { - byteBuf.writeByte(value); - } + if (position == capacity) require(1); + byteBuf.writeByte(value); + position++; + } - @Override public void writeByte (int value) throws KryoException { - byteBuf.writeByte((byte)value); - } + if (position == capacity) require(1); + byteBuf.writeByte((byte)value); + position++; + } - /** Writes the bytes. Note the byte[] length is not written. */ - @Override public void writeBytes (byte[] bytes) throws KryoException { - if (bytes == null) { - throw new IllegalArgumentException("bytes cannot be null."); - } - writeBytes(bytes, 0, bytes.length); - } + if (bytes == null) throw new IllegalArgumentException("bytes cannot be null."); + writeBytes(bytes, 0, bytes.length); + } - /** Writes the bytes. Note the byte[] length is not written. */ - @Override public void writeBytes (byte[] bytes, int offset, int count) throws KryoException { - if (bytes == null) { - throw new IllegalArgumentException("bytes cannot be null."); + if (bytes == null) throw new IllegalArgumentException("bytes cannot be null."); + int copyCount = Math.min(capacity - position, count); + while (true) { + byteBuf.writeBytes(bytes, offset, copyCount); + position += copyCount; + count -= copyCount; + if (count == 0) return; + offset += copyCount; + copyCount = Math.min(capacity, count); + require(copyCount); } - byteBuf.writeBytes(bytes, offset, count); - } + } - // int + // int: - /** Writes a 4 byte int. */ - @Override public void writeInt (int value) throws KryoException { - byteBuf.writeInt(value); - } + require(4); + position += 4; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)value); + byteBuf.writeByte((byte)(value >> 8)); + byteBuf.writeByte((byte)(value >> 16)); + byteBuf.writeByte((byte)(value >> 24)); + } - /** Writes a 1-5 byte int. This stream may consider such a variable length encoding request as a hint. It is not guaranteed that - * a variable length encoding will be really used. The stream may decide to use native-sized integer representation for - * efficiency reasons. - * - * @param optimizePositive If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be - * inefficient (5 bytes). */ - @Override - public int writeInt (int value, boolean optimizePositive) throws KryoException { - return writeVarInt(value, optimizePositive); - } - - /** Writes a 1-5 byte int. It is guaranteed that a varible length encoding will be used. - * - * @param optimizePositive If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be - * inefficient (5 bytes). */ - @Override public int writeVarInt (int value, boolean optimizePositive) throws KryoException { - ByteBuf buffer = byteBuf; - - if (!optimizePositive) { - value = value << 1 ^ value >> 31; - } - if (value >>> 7 == 0) { - buffer.writeByte((byte)value); - return 1; - } - if (value >>> 14 == 0) { - buffer.writeByte((byte)(value & 0x7F | 0x80)); - buffer.writeByte((byte)(value >>> 7)); - return 2; - } - if (value >>> 21 == 0) { - buffer.writeByte((byte)(value & 0x7F | 0x80)); - buffer.writeByte((byte)(value >>> 7 | 0x80)); - buffer.writeByte((byte)(value >>> 14)); - return 3; - } - if (value >>> 28 == 0) { - buffer.writeByte((byte)(value & 0x7F | 0x80)); - buffer.writeByte((byte)(value >>> 7 | 0x80)); - buffer.writeByte((byte)(value >>> 14 | 0x80)); - buffer.writeByte((byte)(value >>> 21)); - return 4; - } - buffer.writeByte((byte)(value & 0x7F | 0x80)); - buffer.writeByte((byte)(value >>> 7 | 0x80)); - buffer.writeByte((byte)(value >>> 14 | 0x80)); - buffer.writeByte((byte)(value >>> 21 | 0x80)); - buffer.writeByte((byte)(value >>> 28)); - return 5; - } - - // string - - /** Writes the length and string, or null. Short strings are checked and if ASCII they are written more efficiently, else they - * are written as UTF8. If a string is known to be ASCII, {@link #writeAscii(String)} may be used. The string can be read using - * {@link ByteBufInput#readString()} or {@link ByteBufInput#readStringBuilder()}. - * @param value May be null. */ - @Override - public void writeString (String value) throws KryoException { - if (value == null) { - writeByte(0x80); // 0 means null, bit 8 means UTF8. - return; - } - int charCount = value.length(); - if (charCount == 0) { - writeByte(1 | 0x80); // 1 means empty string, bit 8 means UTF8. - return; - } - // Detect ASCII. - boolean ascii = false; - if (charCount > 1 && charCount < 64) { // only snoop 64 chars in - ascii = true; - for (int i = 0; i < charCount; i++) { - int c = value.charAt(i); - if (c > 127) { - ascii = false; - break; - } - } - } - - ByteBuf buffer = byteBuf; - if (buffer.writableBytes() < charCount) { - buffer.capacity(buffer.capacity() + charCount + 1); - } - - if (!ascii) { - writeUtf8Length(charCount + 1); - } - - int charIndex = 0; - // Try to write 8 bit chars. - for (; charIndex < charCount; charIndex++) { - int c = value.charAt(charIndex); - if (c > 127) - { - break; // whoops! detect ascii. have to continue with a slower method! - } - buffer.writeByte((byte)c); - } - if (charIndex < charCount) { - writeString_slow(value, charCount, charIndex); - } - else if (ascii) { - // specify it's ASCII - int i = buffer.writerIndex() - 1; - buffer.setByte(i, buffer.getByte(i) | 0x80); // Bit 8 means end of ASCII. - } - } - - /** Writes the length and CharSequence as UTF8, or null. The string can be read using {@link ByteBufInput#readString()} or - * {@link ByteBufInput#readStringBuilder()}. - * @param value May be null. */ - @Override - public void writeString (CharSequence value) throws KryoException { - if (value == null) { - writeByte(0x80); // 0 means null, bit 8 means UTF8. - return; - } - int charCount = value.length(); - if (charCount == 0) { - writeByte(1 | 0x80); // 1 means empty string, bit 8 means UTF8. - return; - } - writeUtf8Length(charCount + 1); - - ByteBuf buffer = byteBuf; - if (buffer.writableBytes() < charCount) { - buffer.capacity(buffer.capacity() + charCount + 1); - } - int charIndex = 0; - // Try to write 8 bit chars. - for (; charIndex < charCount; charIndex++) { - int c = value.charAt(charIndex); - if (c > 127) - { - break; // whoops! have to continue with a slower method! - } - buffer.writeByte((byte)c); - } - if (charIndex < charCount) { - writeString_slow(value, charCount, charIndex); - } - } - - /** Writes a string that is known to contain only ASCII characters. Non-ASCII strings passed to this method will be corrupted. - * Each byte is a 7 bit character with the remaining byte denoting if another character is available. This is slightly more - * efficient than {@link #writeString(String)}. The string can be read using {@link ByteBufInput#readString()} or - * {@link ByteBufInput#readStringBuilder()}. - * @param value May be null. */ - @Override - public void writeAscii (String value) throws KryoException { - if (value == null) { - writeByte(0x80); // 0 means null, bit 8 means UTF8. - return; - } - int charCount = value.length(); - if (charCount == 0) { - writeByte(1 | 0x80); // 1 means empty string, bit 8 means UTF8. - return; - } - - ByteBuf buffer = byteBuf; - if (buffer.writableBytes() < charCount) { - buffer.capacity(buffer.capacity() + charCount + 1); - } - - - int charIndex = 0; - // Try to write 8 bit chars. - for (; charIndex < charCount; charIndex++) { - int c = value.charAt(charIndex); - buffer.writeByte((byte)c); - } - // specify it's ASCII - int i = buffer.writerIndex() - 1; - buffer.setByte(i, buffer.getByte(i) | 0x80); // Bit 8 means end of ASCII. - } - - /** Writes the length of a string, which is a variable length encoded int except the first byte uses bit 8 to denote UTF8 and - * bit 7 to denote if another byte is present. */ - private void writeUtf8Length (int value) { - if (value >>> 6 == 0) { - byteBuf.writeByte((byte)(value | 0x80)); // Set bit 8. - } else if (value >>> 13 == 0) { - ByteBuf buffer = byteBuf; - buffer.writeByte((byte)(value | 0x40 | 0x80)); // Set bit 7 and 8. - buffer.writeByte((byte)(value >>> 6)); - } else if (value >>> 20 == 0) { - ByteBuf buffer = byteBuf; - buffer.writeByte((byte)(value | 0x40 | 0x80)); // Set bit 7 and 8. - buffer.writeByte((byte)(value >>> 6 | 0x80)); // Set bit 8. - buffer.writeByte((byte)(value >>> 13)); - } else if (value >>> 27 == 0) { - ByteBuf buffer = byteBuf; - buffer.writeByte((byte)(value | 0x40 | 0x80)); // Set bit 7 and 8. - buffer.writeByte((byte)(value >>> 6 | 0x80)); // Set bit 8. - buffer.writeByte((byte)(value >>> 13 | 0x80)); // Set bit 8. - buffer.writeByte((byte)(value >>> 20)); - } else { - ByteBuf buffer = byteBuf; - buffer.writeByte((byte)(value | 0x40 | 0x80)); // Set bit 7 and 8. - buffer.writeByte((byte)(value >>> 6 | 0x80)); // Set bit 8. - buffer.writeByte((byte)(value >>> 13 | 0x80)); // Set bit 8. - buffer.writeByte((byte)(value >>> 20 | 0x80)); // Set bit 8. - buffer.writeByte((byte)(value >>> 27)); - } - } - - private void writeString_slow (CharSequence value, int charCount, int charIndex) { - ByteBuf buffer = byteBuf; - - for (; charIndex < charCount; charIndex++) { - int c = value.charAt(charIndex); - if (c <= 0x007F) { - buffer.writeByte((byte)c); - } else if (c > 0x07FF) { - buffer.writeByte((byte)(0xE0 | c >> 12 & 0x0F)); - buffer.writeByte((byte)(0x80 | c >> 6 & 0x3F)); - buffer.writeByte((byte)(0x80 | c & 0x3F)); - } else { - buffer.writeByte((byte)(0xC0 | c >> 6 & 0x1F)); - buffer.writeByte((byte)(0x80 | c & 0x3F)); - } - } - } - - // float - - /** Writes a 4 byte float. */ - @Override - public void writeFloat (float value) throws KryoException { - writeInt(Float.floatToIntBits(value)); - } - - /** Writes a 1-5 byte float with reduced precision. - * @param optimizePositive If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be - * inefficient (5 bytes). */ - @Override - public int writeFloat (float value, float precision, boolean optimizePositive) throws KryoException { - return writeInt((int)(value * precision), optimizePositive); - } - - // short - - /** Writes a 2 byte short. */ - @Override - public void writeShort (int value) throws KryoException { - byteBuf.writeShort(value); - } - - // long - - /** Writes an 8 byte long. */ - @Override - public void writeLong (long value) throws KryoException { - byteBuf.writeLong(value); - } - - /** Writes a 1-9 byte long. This stream may consider such a variable length encoding request as a hint. It is not guaranteed - * that a variable length encoding will be really used. The stream may decide to use native-sized integer representation for - * efficiency reasons. - * - * @param optimizePositive If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be - * inefficient (9 bytes). */ - @Override - public int writeLong (long value, boolean optimizePositive) throws KryoException { - return writeVarLong(value, optimizePositive); - } - - /** Writes a 1-9 byte long. It is guaranteed that a varible length encoding will be used. - * @param optimizePositive If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be - * inefficient (9 bytes). */ - @Override - public int writeVarLong (long value, boolean optimizePositive) throws KryoException { - if (!optimizePositive) { - value = value << 1 ^ value >> 63; - } + if (!optimizePositive) value = (value << 1) ^ (value >> 31); if (value >>> 7 == 0) { + if (position == capacity) require(1); + position++; byteBuf.writeByte((byte)value); return 1; } if (value >>> 14 == 0) { - ByteBuf buffer = byteBuf; - buffer.writeByte((byte)(value & 0x7F | 0x80)); - buffer.writeByte((byte)(value >>> 7)); + require(2); + position += 2; + byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); + byteBuf.writeByte((byte)(value >>> 7)); return 2; } if (value >>> 21 == 0) { - ByteBuf buffer = byteBuf; - buffer.writeByte((byte)(value & 0x7F | 0x80)); - buffer.writeByte((byte)(value >>> 7 | 0x80)); - buffer.writeByte((byte)(value >>> 14)); + require(3); + position += 3; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); + byteBuf.writeByte((byte)(value >>> 7 | 0x80)); + byteBuf.writeByte((byte)(value >>> 14)); return 3; } if (value >>> 28 == 0) { - ByteBuf buffer = byteBuf; - buffer.writeByte((byte)(value & 0x7F | 0x80)); - buffer.writeByte((byte)(value >>> 7 | 0x80)); - buffer.writeByte((byte)(value >>> 14 | 0x80)); - buffer.writeByte((byte)(value >>> 21)); + require(4); + position += 4; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); + byteBuf.writeByte((byte)(value >>> 7 | 0x80)); + byteBuf.writeByte((byte)(value >>> 14 | 0x80)); + byteBuf.writeByte((byte)(value >>> 21)); + return 4; + } + require(5); + position += 5; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); + byteBuf.writeByte((byte)(value >>> 7 | 0x80)); + byteBuf.writeByte((byte)(value >>> 14 | 0x80)); + byteBuf.writeByte((byte)(value >>> 21 | 0x80)); + byteBuf.writeByte((byte)(value >>> 28)); + return 5; + } + + public int writeVarIntFlag (boolean flag, int value, boolean optimizePositive) throws KryoException { + if (!optimizePositive) value = (value << 1) ^ (value >> 31); + int first = (value & 0x3F) | (flag ? 0x80 : 0); // Mask first 6 bits, bit 8 is the flag. + if (value >>> 6 == 0) { + if (position == capacity) require(1); + byteBuf.writeByte((byte)first); + position++; + return 1; + } + if (value >>> 13 == 0) { + require(2); + position += 2; + byteBuf.writeByte((byte)(first | 0x40)); // Set bit 7. + byteBuf.writeByte((byte)(value >>> 6)); + return 2; + } + if (value >>> 20 == 0) { + require(3); + position += 3; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)(first | 0x40)); // Set bit 7. + byteBuf.writeByte((byte)((value >>> 6) | 0x80)); // Set bit 8. + byteBuf.writeByte((byte)(value >>> 13)); + return 3; + } + if (value >>> 27 == 0) { + require(4); + position += 4; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)(first | 0x40)); // Set bit 7. + byteBuf.writeByte((byte)((value >>> 6) | 0x80)); // Set bit 8. + byteBuf.writeByte((byte)((value >>> 13) | 0x80)); // Set bit 8. + byteBuf.writeByte((byte)(value >>> 20)); + return 4; + } + require(5); + position += 5; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)(first | 0x40)); // Set bit 7. + byteBuf.writeByte((byte)((value >>> 6) | 0x80)); // Set bit 8. + byteBuf.writeByte((byte)((value >>> 13) | 0x80)); // Set bit 8. + byteBuf.writeByte((byte)((value >>> 20) | 0x80)); // Set bit 8. + byteBuf.writeByte((byte)(value >>> 27)); + return 5; + } + + // long: + + public void writeLong (long value) throws KryoException { + require(8); + position += 8; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)value); + byteBuf.writeByte((byte)(value >>> 8)); + byteBuf.writeByte((byte)(value >>> 16)); + byteBuf.writeByte((byte)(value >>> 24)); + byteBuf.writeByte((byte)(value >>> 32)); + byteBuf.writeByte((byte)(value >>> 40)); + byteBuf.writeByte((byte)(value >>> 48)); + byteBuf.writeByte((byte)(value >>> 56)); + } + + public int writeVarLong (long value, boolean optimizePositive) throws KryoException { + if (!optimizePositive) value = (value << 1) ^ (value >> 63); + if (value >>> 7 == 0) { + if (position == capacity) require(1); + position++; + byteBuf.writeByte((byte)value); + return 1; + } + if (value >>> 14 == 0) { + require(2); + position += 2; + byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); + byteBuf.writeByte((byte)(value >>> 7)); + return 2; + } + if (value >>> 21 == 0) { + require(3); + position += 3; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); + byteBuf.writeByte((byte)(value >>> 7 | 0x80)); + byteBuf.writeByte((byte)(value >>> 14)); + return 3; + } + if (value >>> 28 == 0) { + require(4); + position += 4; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); + byteBuf.writeByte((byte)(value >>> 7 | 0x80)); + byteBuf.writeByte((byte)(value >>> 14 | 0x80)); + byteBuf.writeByte((byte)(value >>> 21)); return 4; } if (value >>> 35 == 0) { - ByteBuf buffer = byteBuf; - buffer.writeByte((byte)(value & 0x7F | 0x80)); - buffer.writeByte((byte)(value >>> 7 | 0x80)); - buffer.writeByte((byte)(value >>> 14 | 0x80)); - buffer.writeByte((byte)(value >>> 21 | 0x80)); - buffer.writeByte((byte)(value >>> 28)); + require(5); + position += 5; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); + byteBuf.writeByte((byte)(value >>> 7 | 0x80)); + byteBuf.writeByte((byte)(value >>> 14 | 0x80)); + byteBuf.writeByte((byte)(value >>> 21 | 0x80)); + byteBuf.writeByte((byte)(value >>> 28)); return 5; } if (value >>> 42 == 0) { - ByteBuf buffer = byteBuf; - buffer.writeByte((byte)(value & 0x7F | 0x80)); - buffer.writeByte((byte)(value >>> 7 | 0x80)); - buffer.writeByte((byte)(value >>> 14 | 0x80)); - buffer.writeByte((byte)(value >>> 21 | 0x80)); - buffer.writeByte((byte)(value >>> 28 | 0x80)); - buffer.writeByte((byte)(value >>> 35)); + require(6); + position += 6; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); + byteBuf.writeByte((byte)(value >>> 7 | 0x80)); + byteBuf.writeByte((byte)(value >>> 14 | 0x80)); + byteBuf.writeByte((byte)(value >>> 21 | 0x80)); + byteBuf.writeByte((byte)(value >>> 28 | 0x80)); + byteBuf.writeByte((byte)(value >>> 35)); return 6; } if (value >>> 49 == 0) { - ByteBuf buffer = byteBuf; - buffer.writeByte((byte)(value & 0x7F | 0x80)); - buffer.writeByte((byte)(value >>> 7 | 0x80)); - buffer.writeByte((byte)(value >>> 14 | 0x80)); - buffer.writeByte((byte)(value >>> 21 | 0x80)); - buffer.writeByte((byte)(value >>> 28 | 0x80)); - buffer.writeByte((byte)(value >>> 35 | 0x80)); - buffer.writeByte((byte)(value >>> 42)); + require(7); + position += 7; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); + byteBuf.writeByte((byte)(value >>> 7 | 0x80)); + byteBuf.writeByte((byte)(value >>> 14 | 0x80)); + byteBuf.writeByte((byte)(value >>> 21 | 0x80)); + byteBuf.writeByte((byte)(value >>> 28 | 0x80)); + byteBuf.writeByte((byte)(value >>> 35 | 0x80)); + byteBuf.writeByte((byte)(value >>> 42)); return 7; } if (value >>> 56 == 0) { - ByteBuf buffer = byteBuf; - buffer.writeByte((byte)(value & 0x7F | 0x80)); - buffer.writeByte((byte)(value >>> 7 | 0x80)); - buffer.writeByte((byte)(value >>> 14 | 0x80)); - buffer.writeByte((byte)(value >>> 21 | 0x80)); - buffer.writeByte((byte)(value >>> 28 | 0x80)); - buffer.writeByte((byte)(value >>> 35 | 0x80)); - buffer.writeByte((byte)(value >>> 42 | 0x80)); - buffer.writeByte((byte)(value >>> 49)); + require(8); + position += 8; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); + byteBuf.writeByte((byte)(value >>> 7 | 0x80)); + byteBuf.writeByte((byte)(value >>> 14 | 0x80)); + byteBuf.writeByte((byte)(value >>> 21 | 0x80)); + byteBuf.writeByte((byte)(value >>> 28 | 0x80)); + byteBuf.writeByte((byte)(value >>> 35 | 0x80)); + byteBuf.writeByte((byte)(value >>> 42 | 0x80)); + byteBuf.writeByte((byte)(value >>> 49)); return 8; } - ByteBuf buffer = byteBuf; - buffer.writeByte((byte)(value & 0x7F | 0x80)); - buffer.writeByte((byte)(value >>> 7 | 0x80)); - buffer.writeByte((byte)(value >>> 14 | 0x80)); - buffer.writeByte((byte)(value >>> 21 | 0x80)); - buffer.writeByte((byte)(value >>> 28 | 0x80)); - buffer.writeByte((byte)(value >>> 35 | 0x80)); - buffer.writeByte((byte)(value >>> 42 | 0x80)); - buffer.writeByte((byte)(value >>> 49 | 0x80)); - buffer.writeByte((byte)(value >>> 56)); + require(9); + position += 9; + ByteBuf byteBuf = this.byteBuf; + byteBuf.writeByte((byte)((value & 0x7F) | 0x80)); + byteBuf.writeByte((byte)(value >>> 7 | 0x80)); + byteBuf.writeByte((byte)(value >>> 14 | 0x80)); + byteBuf.writeByte((byte)(value >>> 21 | 0x80)); + byteBuf.writeByte((byte)(value >>> 28 | 0x80)); + byteBuf.writeByte((byte)(value >>> 35 | 0x80)); + byteBuf.writeByte((byte)(value >>> 42 | 0x80)); + byteBuf.writeByte((byte)(value >>> 49 | 0x80)); + byteBuf.writeByte((byte)(value >>> 56)); return 9; - } + } - // boolean + // float: - /** Writes a 1 byte boolean. */ - @Override - public void writeBoolean (boolean value) throws KryoException { - byteBuf.writeBoolean(value); - } + public void writeFloat (float value) throws KryoException { + require(4); + ByteBuf byteBuf = this.byteBuf; + position += 4; + int intValue = Float.floatToIntBits(value); + byteBuf.writeByte((byte)intValue); + byteBuf.writeByte((byte)(intValue >> 8)); + byteBuf.writeByte((byte)(intValue >> 16)); + byteBuf.writeByte((byte)(intValue >> 24)); + } - // char + // double: - /** Writes a 2 byte char. */ - @Override - public void writeChar (char value) throws KryoException { - byteBuf.writeChar(value); - } - - // double - - /** Writes an 8 byte double. */ - @Override public void writeDouble (double value) throws KryoException { - writeLong(Double.doubleToLongBits(value)); - } + require(8); + position += 8; + ByteBuf byteBuf = this.byteBuf; + long longValue = Double.doubleToLongBits(value); + byteBuf.writeByte((byte)longValue); + byteBuf.writeByte((byte)(longValue >>> 8)); + byteBuf.writeByte((byte)(longValue >>> 16)); + byteBuf.writeByte((byte)(longValue >>> 24)); + byteBuf.writeByte((byte)(longValue >>> 32)); + byteBuf.writeByte((byte)(longValue >>> 40)); + byteBuf.writeByte((byte)(longValue >>> 48)); + byteBuf.writeByte((byte)(longValue >>> 56)); + } - /** Writes a 1-9 byte double with reduced precision. - * @param optimizePositive If true, small positive numbers will be more efficient (1 byte) and small negative numbers will be - * inefficient (9 bytes). */ - @Override - public int writeDouble (double value, double precision, boolean optimizePositive) throws KryoException { - return writeLong((long)(value * precision), optimizePositive); - } + // short: - /** Returns the number of bytes that would be written with {@link #writeInt(int, boolean)}. */ - static public int intLength (int value, boolean optimizePositive) { - if (!optimizePositive) { - value = value << 1 ^ value >> 31; - } - if (value >>> 7 == 0) { - return 1; - } - if (value >>> 14 == 0) { - return 2; - } - if (value >>> 21 == 0) { - return 3; - } - if (value >>> 28 == 0) { - return 4; - } - return 5; - } + public void writeShort (int value) throws KryoException { + require(2); + position += 2; + byteBuf.writeByte((byte)value); + byteBuf.writeByte((byte)(value >>> 8)); + } - /** Returns the number of bytes that would be written with {@link #writeLong(long, boolean)}. */ - static public int longLength (long value, boolean optimizePositive) { - if (!optimizePositive) { - value = value << 1 ^ value >> 63; + // char: + + public void writeChar (char value) throws KryoException { + require(2); + position += 2; + byteBuf.writeByte((byte)value); + byteBuf.writeByte((byte)(value >>> 8)); + } + + // boolean: + + public void writeBoolean (boolean value) throws KryoException { + if (position == capacity) require(1); + byteBuf.writeByte((byte)(value ? 1 : 0)); + position++; + } + + // String: + + public void writeString (String value) throws KryoException { + if (value == null) { + writeByte(0x80); // 0 means null, bit 8 means UTF8. + return; } - if (value >>> 7 == 0) { - return 1; + int charCount = value.length(); + if (charCount == 0) { + writeByte(1 | 0x80); // 1 means empty string, bit 8 means UTF8. + return; } - if (value >>> 14 == 0) { - return 2; + // Detect ASCII. + outer: + if (charCount > 1 && charCount <= 32) { + for (int i = 0; i < charCount; i++) + if (value.charAt(i) > 127) break outer; + if (capacity - position < charCount) + writeAscii_slow(value, charCount); + else { + for (int i = 0, n = value.length(); i < n; ++i) + byteBuf.writeByte((byte)value.charAt(i)); + position += charCount; + } + byteBuf.setByte(position - 1, (byte)(byteBuf.getByte(position - 1) | 0x80)); + return; } - if (value >>> 21 == 0) { - return 3; + writeVarIntFlag(true, charCount + 1, true); + int charIndex = 0; + if (capacity - position >= charCount) { + // Try to write 7 bit chars. + ByteBuf byteBuf = this.byteBuf; + while (true) { + int c = value.charAt(charIndex); + if (c > 127) break; + byteBuf.writeByte((byte)c); + charIndex++; + if (charIndex == charCount) { + position = byteBuf.writerIndex(); + return; + } + } + position = byteBuf.writerIndex(); } - if (value >>> 28 == 0) { - return 4; + if (charIndex < charCount) writeUtf8_slow(value, charCount, charIndex); + } + + public void writeAscii (String value) throws KryoException { + if (value == null) { + writeByte(0x80); // 0 means null, bit 8 means UTF8. + return; } - if (value >>> 35 == 0) { - return 5; + int charCount = value.length(); + if (charCount == 0) { + writeByte(1 | 0x80); // 1 means empty string, bit 8 means UTF8. + return; } - if (value >>> 42 == 0) { - return 6; + if (capacity - position < charCount) + writeAscii_slow(value, charCount); + else { + ByteBuf byteBuf = this.byteBuf; + for (int i = 0, n = value.length(); i < n; ++i) + byteBuf.writeByte((byte)value.charAt(i)); + position += charCount; } - if (value >>> 49 == 0) { - return 7; + byteBuf.setByte(position - 1, (byte)(byteBuf.getByte(position - 1) | 0x80)); // Bit 8 means end of ASCII. + } + + private void writeUtf8_slow (String value, int charCount, int charIndex) { + for (; charIndex < charCount; charIndex++) { + if (position == capacity) require(Math.min(capacity, charCount - charIndex)); + position++; + int c = value.charAt(charIndex); + if (c <= 0x007F) + byteBuf.writeByte((byte)c); + else if (c > 0x07FF) { + byteBuf.writeByte((byte)(0xE0 | c >> 12 & 0x0F)); + require(2); + position += 2; + byteBuf.writeByte((byte)(0x80 | c >> 6 & 0x3F)); + byteBuf.writeByte((byte)(0x80 | c & 0x3F)); + } else { + byteBuf.writeByte((byte)(0xC0 | c >> 6 & 0x1F)); + if (position == capacity) require(1); + position++; + byteBuf.writeByte((byte)(0x80 | c & 0x3F)); + } } - if (value >>> 56 == 0) { - return 8; + } + + private void writeAscii_slow (String value, int charCount) throws KryoException { + ByteBuf buffer = this.byteBuf; + int charIndex = 0; + int charsToWrite = Math.min(charCount, capacity - position); + while (charIndex < charCount) { + byte[] tmp = new byte[charCount]; + value.getBytes(charIndex, charIndex + charsToWrite, tmp, 0); + buffer.writeBytes(tmp, 0, charsToWrite); + charIndex += charsToWrite; + position += charsToWrite; + charsToWrite = Math.min(charCount - charIndex, capacity); + if (require(charsToWrite)) buffer = this.byteBuf; } - return 9; - } + } + + // Primitive arrays: + + public void writeInts (int[] array, int offset, int count) throws KryoException { + if (capacity >= count << 2 && require(count << 2)) { + ByteBuf byteBuf = this.byteBuf; + for (int n = offset + count; offset < n; offset++) { + int value = array[offset]; + byteBuf.writeByte((byte)value); + byteBuf.writeByte((byte)(value >> 8)); + byteBuf.writeByte((byte)(value >> 16)); + byteBuf.writeByte((byte)(value >> 24)); + } + position = byteBuf.writerIndex(); + } else { + for (int n = offset + count; offset < n; offset++) + writeInt(array[offset]); + } + } + + public void writeLongs (long[] array, int offset, int count) throws KryoException { + if (capacity >= count << 3 && require(count << 3)) { + ByteBuf byteBuf = this.byteBuf; + for (int n = offset + count; offset < n; offset++) { + long value = array[offset]; + byteBuf.writeByte((byte)value); + byteBuf.writeByte((byte)(value >>> 8)); + byteBuf.writeByte((byte)(value >>> 16)); + byteBuf.writeByte((byte)(value >>> 24)); + byteBuf.writeByte((byte)(value >>> 32)); + byteBuf.writeByte((byte)(value >>> 40)); + byteBuf.writeByte((byte)(value >>> 48)); + byteBuf.writeByte((byte)(value >>> 56)); + } + position = byteBuf.writerIndex(); + } else { + for (int n = offset + count; offset < n; offset++) + writeLong(array[offset]); + } + } + + public void writeFloats (float[] array, int offset, int count) throws KryoException { + if (capacity >= count << 2 && require(count << 2)) { + ByteBuf byteBuf = this.byteBuf; + for (int n = offset + count; offset < n; offset++) { + int value = Float.floatToIntBits(array[offset]); + byteBuf.writeByte((byte)value); + byteBuf.writeByte((byte)(value >> 8)); + byteBuf.writeByte((byte)(value >> 16)); + byteBuf.writeByte((byte)(value >> 24)); + } + position = byteBuf.writerIndex(); + } else { + for (int n = offset + count; offset < n; offset++) + writeFloat(array[offset]); + } + } + + public void writeDoubles (double[] array, int offset, int count) throws KryoException { + if (capacity >= count << 3 && require(count << 3)) { + ByteBuf byteBuf = this.byteBuf; + for (int n = offset + count; offset < n; offset++) { + long value = Double.doubleToLongBits(array[offset]); + byteBuf.writeByte((byte)value); + byteBuf.writeByte((byte)(value >>> 8)); + byteBuf.writeByte((byte)(value >>> 16)); + byteBuf.writeByte((byte)(value >>> 24)); + byteBuf.writeByte((byte)(value >>> 32)); + byteBuf.writeByte((byte)(value >>> 40)); + byteBuf.writeByte((byte)(value >>> 48)); + byteBuf.writeByte((byte)(value >>> 56)); + } + position = byteBuf.writerIndex(); + } else { + for (int n = offset + count; offset < n; offset++) + writeDouble(array[offset]); + } + } + + public void writeShorts (short[] array, int offset, int count) throws KryoException { + if (capacity >= count << 1 && require(count << 1)) { + for (int n = offset + count; offset < n; offset++) { + int value = array[offset]; + byteBuf.writeByte((byte)value); + byteBuf.writeByte((byte)(value >>> 8)); + } + position = byteBuf.writerIndex(); + } else { + for (int n = offset + count; offset < n; offset++) + writeShort(array[offset]); + } + } + + public void writeChars (char[] array, int offset, int count) throws KryoException { + if (capacity >= count << 1 && require(count << 1)) { + for (int n = offset + count; offset < n; offset++) { + int value = array[offset]; + byteBuf.writeByte((byte)value); + byteBuf.writeByte((byte)(value >>> 8)); + } + position = byteBuf.writerIndex(); + } else { + for (int n = offset + count; offset < n; offset++) + writeChar(array[offset]); + } + } + + public void writeBooleans (boolean[] array, int offset, int count) throws KryoException { + if (capacity >= count && require(count)) { + for (int n = offset + count; offset < n; offset++) + byteBuf.writeByte(array[offset] ? (byte)1 : 0); + position = byteBuf.writerIndex(); + } else { + for (int n = offset + count; offset < n; offset++) + writeBoolean(array[offset]); + } + } } diff --git a/src/dorkbox/network/rmi/InvocationHandlerSerializer.java b/src/dorkbox/network/rmi/InvocationHandlerSerializer.java index 758fc493..f6088e5d 100644 --- a/src/dorkbox/network/rmi/InvocationHandlerSerializer.java +++ b/src/dorkbox/network/rmi/InvocationHandlerSerializer.java @@ -43,9 +43,8 @@ class InvocationHandlerSerializer extends Serializer { } @Override - @SuppressWarnings({"unchecked", "AutoBoxing"}) public - Object read(Kryo kryo, Input input, Class type) { + Object read(final Kryo kryo, final Input input, final Class type) { int objectID = input.readInt(true); KryoExtra kryoExtra = (KryoExtra) kryo; diff --git a/src/dorkbox/network/rmi/InvocationResultSerializer.java b/src/dorkbox/network/rmi/InvocationResultSerializer.java index dc421914..e0f0a002 100644 --- a/src/dorkbox/network/rmi/InvocationResultSerializer.java +++ b/src/dorkbox/network/rmi/InvocationResultSerializer.java @@ -19,6 +19,7 @@ import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import com.esotericsoftware.kryo.serializers.FieldSerializer; + import dorkbox.network.connection.KryoExtra; public @@ -37,7 +38,7 @@ class InvocationResultSerializer extends FieldSerializer { @Override public - InvokeMethodResult read(Kryo kryo, Input input, Class type) { + InvokeMethodResult read(final Kryo kryo, final Input input, final Class type) { InvokeMethodResult result = super.read(kryo, input, type); result.rmiObjectId = input.readInt(true); return result; diff --git a/src/dorkbox/network/rmi/InvokeMethodSerializer.java b/src/dorkbox/network/rmi/InvokeMethodSerializer.java index 4ee44b2a..351af804 100644 --- a/src/dorkbox/network/rmi/InvokeMethodSerializer.java +++ b/src/dorkbox/network/rmi/InvokeMethodSerializer.java @@ -91,7 +91,7 @@ class InvokeMethodSerializer extends Serializer { @Override public - InvokeMethod read(final Kryo kryo, final Input input, final Class type) { + InvokeMethod read(final Kryo kryo, final Input input, final Class type) { int objectID = input.readInt(true); int methodClassID = input.readInt(true); byte methodIndex = input.readByte(); diff --git a/src/dorkbox/network/serialization/Serialization.java b/src/dorkbox/network/serialization/Serialization.java index 561c4e0d..6681ecbc 100644 --- a/src/dorkbox/network/serialization/Serialization.java +++ b/src/dorkbox/network/serialization/Serialization.java @@ -25,21 +25,24 @@ import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.params.IESParameters; import org.bouncycastle.crypto.params.IESWithCipherParameters; +import org.objenesis.strategy.StdInstantiatorStrategy; import org.slf4j.Logger; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.KryoException; +import com.esotericsoftware.kryo.Registration; import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.factories.ReflectionSerializerFactory; -import com.esotericsoftware.kryo.factories.SerializerFactory; +import com.esotericsoftware.kryo.SerializerFactory; +import com.esotericsoftware.kryo.SerializerFactory.ReflectionSerializerFactory; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import com.esotericsoftware.kryo.serializers.CollectionSerializer; import com.esotericsoftware.kryo.serializers.FieldSerializer; +import com.esotericsoftware.kryo.util.DefaultInstantiatorStrategy; import com.esotericsoftware.kryo.util.IdentityMap; import com.esotericsoftware.kryo.util.MapReferenceResolver; -import com.esotericsoftware.kryo.util.Util; +import de.javakaffee.kryoserializers.UnmodifiableCollectionsSerializer; import dorkbox.network.connection.Connection_; import dorkbox.network.connection.KryoExtra; import dorkbox.network.connection.ping.PingMessage; @@ -55,14 +58,12 @@ import dorkbox.network.rmi.RmiRegistrationSerializer; import dorkbox.network.rmi.RmiUtils; import dorkbox.objectPool.ObjectPool; import dorkbox.objectPool.PoolableObject; -import dorkbox.util.Property; +import dorkbox.util.OS; import dorkbox.util.collections.IntMap; -import dorkbox.util.serialization.ArraysAsListSerializer; import dorkbox.util.serialization.EccPrivateKeySerializer; import dorkbox.util.serialization.EccPublicKeySerializer; import dorkbox.util.serialization.IesParametersSerializer; import dorkbox.util.serialization.IesWithCipherParametersSerializer; -import dorkbox.util.serialization.UnmodifiableCollectionsSerializer; import io.netty.bootstrap.DatagramCloseMessage; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; @@ -81,13 +82,6 @@ class Serialization implements NetworkSerializationManager { private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Serialization.class.getSimpleName()); - /** - * Specify if we want KRYO to use unsafe memory for serialization, or to use the ASM backend. Unsafe memory use is WAY faster, but is - * limited to the "same endianess" on all endpoints, and unsafe DOES NOT work on android. - */ - @Property - public static boolean useUnsafeMemory = false; - public static Serialization DEFAULT() { return DEFAULT(true, true, null); @@ -115,7 +109,7 @@ class Serialization implements NetworkSerializationManager { * Kryo#newDefaultSerializer(Class) */ public static - Serialization DEFAULT(final boolean references, final boolean registrationRequired, final SerializerFactory factory) { + Serialization DEFAULT(final boolean references, final boolean registrationRequired, final SerializerFactory factory) { final Serialization serialization = new Serialization(references, registrationRequired, @@ -137,11 +131,19 @@ class Serialization implements NetworkSerializationManager { serialization.register(StackTraceElement.class); serialization.register(StackTraceElement[].class); - // extra serializers - //noinspection ArraysAsListWithZeroOrOneArgument - serialization.register(Arrays.asList("").getClass(), new ArraysAsListSerializer()); + serialization.register(Arrays.asList().getClass()); - UnmodifiableCollectionsSerializer.registerSerializers(serialization); + // hacky way to register unmodifiable serializers + Kryo kryo = new Kryo() { + @Override + public + Registration register(final Class type, final Serializer serializer) { + serialization.register(type, serializer); + return null; + } + }; + + UnmodifiableCollectionsSerializer.registerSerializers(kryo); return serialization; } @@ -173,7 +175,7 @@ class Serialization implements NetworkSerializationManager { // reflectASM doesn't work on android - private final boolean useAsm = !useUnsafeMemory && !Util.IS_ANDROID; + private final boolean useAsm = !OS.isAndroid(); private Logger wireReadLogger; private Logger wireWriteLogger; @@ -215,7 +217,11 @@ class Serialization implements NetworkSerializationManager { // we HAVE to pre-allocate the KRYOs KryoExtra kryo = new KryoExtra(Serialization.this); - kryo.getFieldSerializerConfig().setUseAsm(useAsm); + + // BY DEFAULT, DefaultInstantiatorStrategy() will use ReflectASM + // StdInstantiatorStrategy will create classes bypasses the constructor (which can be useful in some cases) THIS IS A FALLBACK! + kryo.setInstantiatorStrategy(new DefaultInstantiatorStrategy(new StdInstantiatorStrategy())); + kryo.setRegistrationRequired(registrationRequired); kryo.setReferences(references); diff --git a/test/dorkbox/network/kryo/ArraySerializerTest.java b/test/dorkbox/network/kryo/ArraySerializerTest.java deleted file mode 100644 index f9a2285d..00000000 --- a/test/dorkbox/network/kryo/ArraySerializerTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import com.esotericsoftware.kryo.serializers.DefaultArraySerializers.ObjectArraySerializer; - -/** @author Nathan Sweet */ -public class ArraySerializerTest extends KryoTestCase { - { - supportsCopy = true; - } - - public void testArraysASM () { - kryo.getFieldSerializerConfig().setUseAsm(true); - - kryo.register(int[].class); - kryo.register(int[][].class); - kryo.register(int[][][].class); - kryo.register(String[].class); - kryo.register(Object[].class); - roundTrip(4, 4, new Object[] {null, null}); - roundTrip(6, 6, new Object[] {null, "2"}); - roundTrip(6, 18, new int[] {1, 2, 3, 4}); - roundTrip(7, 18, new int[] {1, 2, -100, 4}); - roundTrip(9, 18, new int[] {1, 2, -100, 40000}); - roundTrip(9, 20, new int[][] { {1, 2}, {100, 4}}); - roundTrip(11, 22, new int[][] { {1}, {2}, {100}, {4}}); - roundTrip(13, 24, new int[][][] { { {1}, {2}}, { {100}, {4}}}); - roundTrip(12, 12, new String[] {"11", "2222", "3", "4"}); - roundTrip(11, 11, new String[] {"11", "2222", null, "4"}); - roundTrip(28, 51, - new Object[] {new String[] {"11", "2222", null, "4"}, new int[] {1, 2, 3, 4}, new int[][] { {1, 2}, {100, 4}}}); - - ObjectArraySerializer serializer = new ObjectArraySerializer(kryo, String[].class); - kryo.register(String[].class, serializer); - serializer.setElementsAreSameType(true); - roundTrip(11, 11, new String[] {"11", "2222", null, "4"}); - serializer.setElementsAreSameType(false); - roundTrip(11, 11, new String[] {"11", "2222", null, "4"}); - roundTrip(5, 5, new String[] {null, null, null}); - roundTrip(2, 2, new String[] {}); - serializer.setElementsAreSameType(true); - roundTrip(12, 12, new String[] {"11", "2222", "3", "4"}); - serializer.setElementsCanBeNull(false); - roundTrip(12, 12, new String[] {"11", "2222", "3", "4"}); - - serializer = new ObjectArraySerializer(kryo, Float[].class); - kryo.register(Float[][].class, serializer); - kryo.register(Float[].class, serializer); - Float[][] array = new Float[4][]; - array[0] = new Float[] {0.0f, 1.0f}; - array[1] = null; - array[2] = new Float[] {2.0f, 3.0f}; - array[3] = new Float[] {3.0f}; - roundTrip(31, 31, array); - } - - public void testArraysUnsafe () { - kryo.getFieldSerializerConfig().setUseAsm(false); - - kryo.register(int[].class); - kryo.register(int[][].class); - kryo.register(int[][][].class); - kryo.register(String[].class); - kryo.register(Object[].class); - roundTrip(6, 18, new int[] {1, 2, 3, 4}); - roundTrip(7, 18, new int[] {1, 2, -100, 4}); - roundTrip(9, 18, new int[] {1, 2, -100, 40000}); - roundTrip(9, 20, new int[][] { {1, 2}, {100, 4}}); - roundTrip(11, 22, new int[][] { {1}, {2}, {100}, {4}}); - roundTrip(13, 24, new int[][][] { { {1}, {2}}, { {100}, {4}}}); - roundTrip(12, 12, new String[] {"11", "2222", "3", "4"}); - roundTrip(11, 11, new String[] {"11", "2222", null, "4"}); - roundTrip(28, 51, - new Object[] {new String[] {"11", "2222", null, "4"}, new int[] {1, 2, 3, 4}, new int[][] { {1, 2}, {100, 4}}}); - - ObjectArraySerializer serializer = new ObjectArraySerializer(kryo, String[].class); - kryo.register(String[].class, serializer); - serializer.setElementsAreSameType(true); - roundTrip(11, 11, new String[] {"11", "2222", null, "4"}); - serializer.setElementsAreSameType(false); - roundTrip(11, 11, new String[] {"11", "2222", null, "4"}); - roundTrip(5, 5, new String[] {null, null, null}); - roundTrip(2, 2, new String[] {}); - serializer.setElementsAreSameType(true); - roundTrip(12, 12, new String[] {"11", "2222", "3", "4"}); - serializer.setElementsCanBeNull(false); - roundTrip(12, 12, new String[] {"11", "2222", "3", "4"}); - - serializer = new ObjectArraySerializer(kryo, Float[].class); - kryo.register(Float[][].class, serializer); - kryo.register(Float[].class, serializer); - Float[][] array = new Float[4][]; - array[0] = new Float[] {0.0f, 1.0f}; - array[1] = null; - array[2] = new Float[] {2.0f, 3.0f}; - array[3] = new Float[] {3.0f}; - roundTrip(31, 31, array); - } -} diff --git a/test/dorkbox/network/kryo/BeanSerializerTest.java b/test/dorkbox/network/kryo/BeanSerializerTest.java deleted file mode 100644 index 4f8a071a..00000000 --- a/test/dorkbox/network/kryo/BeanSerializerTest.java +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import com.esotericsoftware.kryo.serializers.BeanSerializer; - -/** @author Nathan Sweet */ -public class BeanSerializerTest extends KryoTestCase { - { - supportsCopy = true; - } - - - @SuppressWarnings({"rawtypes"}) - public void testBeanSerializer () { - kryo.register(TestClass.class, new BeanSerializer(kryo, TestClass.class)); - - TestClass test = new TestClass(); - test.setOptional(12); - test.setNullField("value"); - test.setText("123"); - test.setChild(new TestClass()); - roundTrip(37, 43, test); - test.setNullField(null); - roundTrip(33, 39, test); - } - - static public class TestClass { - private String text = "something"; - private String nullField; - private TestClass child; - private TestClass child2; - private float abc = 1.2f; - private int optional; - - public String getText () { - return text; - } - - public void setText (String text) { - this.text = text; - } - - public String getNullField () { - return nullField; - } - - public void setNullField (String nullField) { - this.nullField = nullField; - } - - public TestClass getChild () { - return child; - } - - public void setChild (TestClass child) { - this.child = child; - } - - public TestClass getChild2 () { - return child2; - } - - public void setChild2 (TestClass child2) { - this.child2 = child2; - } - - public float getAbc () { - return abc; - } - - public void setAbc (float abc) { - this.abc = abc; - } - - public int getOptional () { - return optional; - } - - public void setOptional (int optional) { - this.optional = optional; - } - - @Override - public boolean equals (Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - TestClass other = (TestClass)obj; - if (Float.floatToIntBits(abc) != Float.floatToIntBits(other.abc)) { - return false; - } - if (child == null) { - if (other.child != null) { - return false; - } - } else if (child != this && !child.equals(other.child)) { - return false; - } - if (child2 == null) { - if (other.child2 != null) { - return false; - } - } else if (child2 != this && !child2.equals(other.child2)) { - return false; - } - if (nullField == null) { - if (other.nullField != null) { - return false; - } - } else if (!nullField.equals(other.nullField)) { - return false; - } - if (text == null) { - if (other.text != null) { - return false; - } - } else if (!text.equals(other.text)) { - return false; - } - return true; - } - - @Override - public int hashCode() { - return super.hashCode(); - } - } -} diff --git a/test/dorkbox/network/kryo/BlowfishSerializerTest.java b/test/dorkbox/network/kryo/BlowfishSerializerTest.java deleted file mode 100644 index a7117e2b..00000000 --- a/test/dorkbox/network/kryo/BlowfishSerializerTest.java +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -/** @author Nathan Sweet */ -public class BlowfishSerializerTest extends KryoTestCase { - public void testBlowfishCrypto () throws Exception { - System.err.println("BlowfishSerializerTest test is ignored because javax.crypto is not available in java 6"); - // byte[] key = javax.crypto.KeyGenerator.getInstance("Blowfish").generateKey().getEncoded(); - // kryo.register(String.class, new BlowfishSerializer(new StringSerializer(), key)); - // roundTrip(49, 49, "abcdefabcdefabcdefabcdefabcdefabcdefabcdef"); - } -} diff --git a/test/dorkbox/network/kryo/ChunkedTest.java b/test/dorkbox/network/kryo/ChunkedTest.java deleted file mode 100644 index 13fb30b3..00000000 --- a/test/dorkbox/network/kryo/ChunkedTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.InputChunked; -import com.esotericsoftware.kryo.io.Output; -import com.esotericsoftware.kryo.io.OutputChunked; - -/** @author Nathan Sweet */ -public class ChunkedTest extends KryoTestCase { - public void testChunks () { - Output output = new Output(512); - output.writeInt(1234); - OutputChunked outputChunked = new OutputChunked(output); - outputChunked.writeInt(1); - outputChunked.endChunks(); - outputChunked.writeInt(2); - outputChunked.endChunks(); - outputChunked.writeInt(3); - outputChunked.endChunks(); - outputChunked.writeInt(4); - outputChunked.endChunks(); - outputChunked.writeInt(5); - outputChunked.endChunks(); - output.writeInt(5678); - output.close(); - outputChunked.close(); - - Input input = new Input(output.getBuffer()); - assertEquals(1234, input.readInt()); - InputChunked inputChunked = new InputChunked(input); - assertEquals(1, inputChunked.readInt()); - inputChunked.nextChunks(); - inputChunked.nextChunks(); // skip 3 - assertEquals(3, inputChunked.readInt()); - inputChunked.nextChunks(); - inputChunked.nextChunks(); // skip 4 - assertEquals(5, inputChunked.readInt()); - assertEquals(5678, input.readInt()); - input.close(); - inputChunked.close(); - } -} diff --git a/test/dorkbox/network/kryo/CollectionSerializerTest.java b/test/dorkbox/network/kryo/CollectionSerializerTest.java deleted file mode 100644 index de14e486..00000000 --- a/test/dorkbox/network/kryo/CollectionSerializerTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import com.esotericsoftware.kryo.serializers.CollectionSerializer; -import com.esotericsoftware.kryo.serializers.DefaultSerializers.StringSerializer; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.concurrent.CopyOnWriteArrayList; - -/** @author Nathan Sweet */ -public class CollectionSerializerTest extends KryoTestCase { - { - supportsCopy = true; - } - - @SuppressWarnings({"unchecked","rawtypes"}) - public void testCollections () { - kryo.register(ArrayList.class); - kryo.register(LinkedList.class); - kryo.register(CopyOnWriteArrayList.class); - roundTrip(11, 11, list("1", "2", "3")); - roundTrip(13, 19, list("1", "2", null, 1, 2)); - roundTrip(15, 24, list("1", "2", null, 1, 2, 5)); - roundTrip(11, 11, list("1", "2", "3")); - roundTrip(11, 11, list("1", "2", "3")); - roundTrip(13, 13, list("1", "2", list("3"))); - roundTrip(13, 13, new LinkedList(list("1", "2", list("3")))); - roundTrip(13, 13, new CopyOnWriteArrayList(list("1", "2", list("3")))); - - CollectionSerializer serializer = new CollectionSerializer(); - kryo.register(ArrayList.class, serializer); - kryo.register(LinkedList.class, serializer); - kryo.register(CopyOnWriteArrayList.class, serializer); - serializer.setElementClass(String.class, kryo.getSerializer(String.class)); - roundTrip(8, 8, list("1", "2", "3")); - serializer.setElementClass(String.class, new StringSerializer()); - roundTrip(8, 8, list("1", "2", "3")); - serializer.setElementsCanBeNull(false); - roundTrip(8, 8, list("1", "2", "3")); - } -} diff --git a/test/dorkbox/network/kryo/CompatibleFieldSerializerTest.java b/test/dorkbox/network/kryo/CompatibleFieldSerializerTest.java deleted file mode 100644 index bffcda4c..00000000 --- a/test/dorkbox/network/kryo/CompatibleFieldSerializerTest.java +++ /dev/null @@ -1,511 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -package dorkbox.network.kryo; - -import java.io.FileNotFoundException; - -import com.esotericsoftware.kryo.serializers.CompatibleFieldSerializer; -import com.esotericsoftware.kryo.serializers.FieldSerializer; - -/** - * @author Nathan Sweet - */ -public -class CompatibleFieldSerializerTest extends KryoTestCase { - { - supportsCopy = true; - } - - public - void testCompatibleFieldSerializer() throws FileNotFoundException { - TestClass object1 = new TestClass(); - object1.child = new TestClass(); - object1.other = new AnotherClass(); - object1.other.value = "meow"; - kryo.setDefaultSerializer(CompatibleFieldSerializer.class); - kryo.register(TestClass.class); - kryo.register(AnotherClass.class); - roundTrip(107, 107, object1); - } - - public - void testAddedField() throws FileNotFoundException { - TestClass object1 = new TestClass(); - object1.child = new TestClass(); - object1.other = new AnotherClass(); - object1.other.value = "meow"; - - CompatibleFieldSerializer serializer = new CompatibleFieldSerializer(kryo, TestClass.class); - serializer.removeField("text"); - kryo.register(TestClass.class, serializer); - kryo.register(AnotherClass.class, new CompatibleFieldSerializer(kryo, AnotherClass.class)); - roundTrip(80, 80, object1); - - kryo.register(TestClass.class, new CompatibleFieldSerializer(kryo, TestClass.class)); - Object object2 = kryo.readClassAndObject(input); - assertEquals(object1, object2); - } - - public - void testAddedFieldToClassWithManyFields() throws FileNotFoundException { - // class must have more than CompatibleFieldSerializer#THRESHOLD_BINARY_SEARCH number of fields - ClassWithManyFields object1 = new ClassWithManyFields(); - object1.aa = "aa"; - object1.a0 = "a0"; - object1.bb = "bb"; - object1.b0 = "b0"; - object1.cc = "cc"; - object1.c0 = "c0"; - object1.dd = "dd"; - object1.d0 = "d0"; - object1.ee = "ee"; - object1.e0 = "e0"; - object1.ff = "ff"; - object1.f0 = "f0"; - object1.gg = "gg"; - object1.g0 = "g0"; - object1.hh = "hh"; - object1.h0 = "h0"; - object1.ii = "ii"; - object1.i0 = "i0"; - object1.jj = "jj"; - object1.j0 = "j0"; - object1.kk = "kk"; - object1.k0 = "k0"; - object1.ll = "ll"; - object1.mm = "mm"; - object1.nn = "nn"; - object1.oo = "oo"; - object1.pp = "pp"; - object1.qq = "qq"; - object1.rr = "rr"; - object1.ss = "ss"; - object1.tt = "tt"; - object1.uu = "uu"; - object1.vv = "vv"; - object1.ww = "ww"; - object1.xx = "xx"; - object1.yy = "yy"; - object1.zz = "zzaa"; - - CompatibleFieldSerializer serializer = new CompatibleFieldSerializer(kryo, ClassWithManyFields.class); - serializer.removeField("bAdd"); - kryo.register(ClassWithManyFields.class, serializer); - roundTrip(226, 226, object1); - - kryo.register(ClassWithManyFields.class, new CompatibleFieldSerializer(kryo, ClassWithManyFields.class)); - Object object2 = kryo.readClassAndObject(input); - assertEquals(object1, object2); - } - - public - void testRemovedField() throws FileNotFoundException { - TestClass object1 = new TestClass(); - object1.child = new TestClass(); - - kryo.register(TestClass.class, new CompatibleFieldSerializer(kryo, TestClass.class)); - roundTrip(94, 94, object1); - - CompatibleFieldSerializer serializer = new CompatibleFieldSerializer(kryo, TestClass.class); - serializer.removeField("text"); - kryo.register(TestClass.class, serializer); - Object object2 = kryo.readClassAndObject(input); - assertEquals(object1, object2); - } - - public - void testRemovedFieldFromClassWithManyFields() throws FileNotFoundException { - // class must have more than CompatibleFieldSerializer#THRESHOLD_BINARY_SEARCH number of fields - ClassWithManyFields object1 = new ClassWithManyFields(); - object1.aa = "aa"; - object1.a0 = "a0"; - object1.bAdd = "bAdd"; - object1.bb = "bb"; - object1.b0 = "b0"; - object1.cc = "cc"; - object1.c0 = "c0"; - object1.dd = "dd"; - object1.d0 = "d0"; - object1.ee = "ee"; - object1.e0 = "e0"; - object1.ff = "ff"; - object1.f0 = "f0"; - object1.gg = "gg"; - object1.g0 = "g0"; - object1.hh = "hh"; - object1.h0 = "h0"; - object1.ii = "ii"; - object1.i0 = "i0"; - object1.jj = "jj"; - object1.j0 = "j0"; - object1.kk = "kk"; - object1.k0 = "k0"; - object1.ll = "ll"; - object1.mm = "mm"; - object1.nn = "nn"; - object1.oo = "oo"; - object1.pp = "pp"; - object1.qq = "qq"; - object1.rr = "rr"; - object1.ss = "ss"; - object1.tt = "tt"; - object1.uu = "uu"; - object1.vv = "vv"; - object1.ww = "ww"; - object1.xx = "xx"; - object1.yy = "yy"; - object1.zz = "zzaa"; - - - kryo.register(ClassWithManyFields.class, new CompatibleFieldSerializer(kryo, ClassWithManyFields.class)); - roundTrip(236, 236, object1); - - CompatibleFieldSerializer serializer = new CompatibleFieldSerializer(kryo, ClassWithManyFields.class); - serializer.removeField("bAdd"); - kryo.register(ClassWithManyFields.class, serializer); - Object object2 = kryo.readClassAndObject(input); - assertTrue(object2 instanceof ClassWithManyFields); - assertNull("the bAdd field should be null", ((ClassWithManyFields) object2).bAdd); - // update the field in order to verify the remainder of the object was deserialized correctly - ((ClassWithManyFields) object2).bAdd = object1.bAdd; - assertEquals(object1, object2); - } - - public - void testExtendedClass() throws FileNotFoundException { - ExtendedTestClass extendedObject = new ExtendedTestClass(); - - // this test would fail with DEFAULT field name strategy - kryo.getFieldSerializerConfig() - .setCachedFieldNameStrategy(FieldSerializer.CachedFieldNameStrategy.EXTENDED); - - CompatibleFieldSerializer serializer = new CompatibleFieldSerializer(kryo, ExtendedTestClass.class); - kryo.register(ExtendedTestClass.class, serializer); - roundTrip(286, 286, extendedObject); - - ExtendedTestClass object2 = (ExtendedTestClass) kryo.readClassAndObject(input); - assertEquals(extendedObject, object2); - } - - static public - class TestClass { - public String text = "something"; - public int moo = 120; - public long moo2 = 1234120; - public TestClass child; - public int zzz = 123; - public AnotherClass other; - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - TestClass other = (TestClass) obj; - if (child == null) { - if (other.child != null) - return false; - } - else if (!child.equals(other.child)) - return false; - if (moo != other.moo) - return false; - if (moo2 != other.moo2) - return false; - if (text == null) { - if (other.text != null) - return false; - } - else if (!text.equals(other.text)) - return false; - if (zzz != other.zzz) - return false; - return true; - } - } - - - static public - class ExtendedTestClass extends TestClass { - // keep the same names of attributes like TestClass - public String text = "extendedSomething"; - public int moo = 127; - public long moo2 = 5555; - public TestClass child; - public int zzz = 222; - public AnotherClass other; - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ExtendedTestClass other = (ExtendedTestClass) obj; - - if (!super.equals(obj)) - return false; - if (child == null) { - if (other.child != null) - return false; - } - else if (!child.equals(other.child)) - return false; - if (moo != other.moo) - return false; - if (moo2 != other.moo2) - return false; - if (text == null) { - if (other.text != null) - return false; - } - else if (!text.equals(other.text)) - return false; - if (zzz != other.zzz) - return false; - return true; - } - } - - - static public - class AnotherClass { - String value; - } - - - static public - class ClassWithManyFields { - public String aa; - public String bb; - public String bAdd; - public String cc; - public String dd; - public String ee; - public String ff; - public String gg; - public String hh; - public String ii; - public String jj; - public String kk; - public String ll; - public String mm; - public String nn; - public String oo; - public String pp; - public String qq; - public String rr; - public String ss; - public String tt; - public String uu; - public String vv; - public String ww; - public String xx; - public String yy; - public String zz; - public String a0; - public String b0; - public String c0; - public String d0; - public String e0; - public String f0; - public String g0; - public String h0; - public String i0; - public String j0; - public String k0; - - - @Override - public - boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - final ClassWithManyFields that = (ClassWithManyFields) o; - - if (aa != null ? !aa.equals(that.aa) : that.aa != null) { - return false; - } - if (bb != null ? !bb.equals(that.bb) : that.bb != null) { - return false; - } - if (bAdd != null ? !bAdd.equals(that.bAdd) : that.bAdd != null) { - return false; - } - if (cc != null ? !cc.equals(that.cc) : that.cc != null) { - return false; - } - if (dd != null ? !dd.equals(that.dd) : that.dd != null) { - return false; - } - if (ee != null ? !ee.equals(that.ee) : that.ee != null) { - return false; - } - if (ff != null ? !ff.equals(that.ff) : that.ff != null) { - return false; - } - if (gg != null ? !gg.equals(that.gg) : that.gg != null) { - return false; - } - if (hh != null ? !hh.equals(that.hh) : that.hh != null) { - return false; - } - if (ii != null ? !ii.equals(that.ii) : that.ii != null) { - return false; - } - if (jj != null ? !jj.equals(that.jj) : that.jj != null) { - return false; - } - if (kk != null ? !kk.equals(that.kk) : that.kk != null) { - return false; - } - if (ll != null ? !ll.equals(that.ll) : that.ll != null) { - return false; - } - if (mm != null ? !mm.equals(that.mm) : that.mm != null) { - return false; - } - if (nn != null ? !nn.equals(that.nn) : that.nn != null) { - return false; - } - if (oo != null ? !oo.equals(that.oo) : that.oo != null) { - return false; - } - if (pp != null ? !pp.equals(that.pp) : that.pp != null) { - return false; - } - if (qq != null ? !qq.equals(that.qq) : that.qq != null) { - return false; - } - if (rr != null ? !rr.equals(that.rr) : that.rr != null) { - return false; - } - if (ss != null ? !ss.equals(that.ss) : that.ss != null) { - return false; - } - if (tt != null ? !tt.equals(that.tt) : that.tt != null) { - return false; - } - if (uu != null ? !uu.equals(that.uu) : that.uu != null) { - return false; - } - if (vv != null ? !vv.equals(that.vv) : that.vv != null) { - return false; - } - if (ww != null ? !ww.equals(that.ww) : that.ww != null) { - return false; - } - if (xx != null ? !xx.equals(that.xx) : that.xx != null) { - return false; - } - if (yy != null ? !yy.equals(that.yy) : that.yy != null) { - return false; - } - if (zz != null ? !zz.equals(that.zz) : that.zz != null) { - return false; - } - if (a0 != null ? !a0.equals(that.a0) : that.a0 != null) { - return false; - } - if (b0 != null ? !b0.equals(that.b0) : that.b0 != null) { - return false; - } - if (c0 != null ? !c0.equals(that.c0) : that.c0 != null) { - return false; - } - if (d0 != null ? !d0.equals(that.d0) : that.d0 != null) { - return false; - } - if (e0 != null ? !e0.equals(that.e0) : that.e0 != null) { - return false; - } - if (f0 != null ? !f0.equals(that.f0) : that.f0 != null) { - return false; - } - if (g0 != null ? !g0.equals(that.g0) : that.g0 != null) { - return false; - } - if (h0 != null ? !h0.equals(that.h0) : that.h0 != null) { - return false; - } - if (i0 != null ? !i0.equals(that.i0) : that.i0 != null) { - return false; - } - if (j0 != null ? !j0.equals(that.j0) : that.j0 != null) { - return false; - } - return k0 != null ? k0.equals(that.k0) : that.k0 == null; - } - - @Override - public - int hashCode() { - int result = aa != null ? aa.hashCode() : 0; - result = 31 * result + (bb != null ? bb.hashCode() : 0); - result = 31 * result + (bAdd != null ? bAdd.hashCode() : 0); - result = 31 * result + (cc != null ? cc.hashCode() : 0); - result = 31 * result + (dd != null ? dd.hashCode() : 0); - result = 31 * result + (ee != null ? ee.hashCode() : 0); - result = 31 * result + (ff != null ? ff.hashCode() : 0); - result = 31 * result + (gg != null ? gg.hashCode() : 0); - result = 31 * result + (hh != null ? hh.hashCode() : 0); - result = 31 * result + (ii != null ? ii.hashCode() : 0); - result = 31 * result + (jj != null ? jj.hashCode() : 0); - result = 31 * result + (kk != null ? kk.hashCode() : 0); - result = 31 * result + (ll != null ? ll.hashCode() : 0); - result = 31 * result + (mm != null ? mm.hashCode() : 0); - result = 31 * result + (nn != null ? nn.hashCode() : 0); - result = 31 * result + (oo != null ? oo.hashCode() : 0); - result = 31 * result + (pp != null ? pp.hashCode() : 0); - result = 31 * result + (qq != null ? qq.hashCode() : 0); - result = 31 * result + (rr != null ? rr.hashCode() : 0); - result = 31 * result + (ss != null ? ss.hashCode() : 0); - result = 31 * result + (tt != null ? tt.hashCode() : 0); - result = 31 * result + (uu != null ? uu.hashCode() : 0); - result = 31 * result + (vv != null ? vv.hashCode() : 0); - result = 31 * result + (ww != null ? ww.hashCode() : 0); - result = 31 * result + (xx != null ? xx.hashCode() : 0); - result = 31 * result + (yy != null ? yy.hashCode() : 0); - result = 31 * result + (zz != null ? zz.hashCode() : 0); - result = 31 * result + (a0 != null ? a0.hashCode() : 0); - result = 31 * result + (b0 != null ? b0.hashCode() : 0); - result = 31 * result + (c0 != null ? c0.hashCode() : 0); - result = 31 * result + (d0 != null ? d0.hashCode() : 0); - result = 31 * result + (e0 != null ? e0.hashCode() : 0); - result = 31 * result + (f0 != null ? f0.hashCode() : 0); - result = 31 * result + (g0 != null ? g0.hashCode() : 0); - result = 31 * result + (h0 != null ? h0.hashCode() : 0); - result = 31 * result + (i0 != null ? i0.hashCode() : 0); - result = 31 * result + (j0 != null ? j0.hashCode() : 0); - result = 31 * result + (k0 != null ? k0.hashCode() : 0); - return result; - } - } -} diff --git a/test/dorkbox/network/kryo/CopyTest.java b/test/dorkbox/network/kryo/CopyTest.java deleted file mode 100644 index f9629a95..00000000 --- a/test/dorkbox/network/kryo/CopyTest.java +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import java.util.ArrayList; - -@SuppressWarnings({"rawtypes", "unchecked"}) -public class CopyTest extends KryoTestCase { - @Override - protected void setUp () throws Exception { - super.setUp(); - kryo.setRegistrationRequired(false); - } - - public void testBasic () { - ArrayList test = new ArrayList(); - test.add("one"); - test.add("two"); - test.add("three"); - - ArrayList copy = kryo.copy(test); - assertTrue(test != copy); - assertEquals(test, copy); - } - - public void testNested () { - ArrayList test = new ArrayList(); - test.add("one"); - test.add("two"); - test.add("three"); - - ArrayList test2 = new ArrayList(); - test2.add(1); - test2.add(2f); - test2.add(3d); - test2.add((byte)4); - test2.add((short)5); - test.add(test2); - - ArrayList copy = kryo.copy(test); - assertTrue(test != copy); - assertTrue(test.get(3) != copy.get(3)); - assertEquals(test, copy); - } - - public void testReferences () { - ArrayList test = new ArrayList(); - test.add("one"); - test.add("two"); - test.add("three"); - - ArrayList test2 = new ArrayList(); - test2.add(1); - test2.add(2f); - test2.add(3d); - test2.add((byte)4); - test2.add((short)5); - test.add(test2); - test.add(test2); - test.add(test2); - - ArrayList copy = kryo.copy(test); - assertTrue(test != copy); - assertEquals(test, copy); - assertTrue(test.get(3) != copy.get(4)); - assertTrue(copy.get(3) == copy.get(4)); - assertTrue(copy.get(3) == copy.get(5)); - } - - public void testCircularReferences () { - ArrayList test = new ArrayList(); - test.add("one"); - test.add("two"); - test.add("three"); - test.add(test); - - ArrayList copy = kryo.copy(test); - assertTrue(test != copy); - assertEquals(copy.get(0), "one"); - assertEquals(copy.get(1), "two"); - assertEquals(copy.get(2), "three"); - assertTrue(copy.get(3) == copy); - - Moo root = new Moo(); - Moo moo1 = new Moo(); - Moo moo2 = new Moo(); - Moo moo3 = new Moo(); - root.moo = moo1; - moo1.moo = moo2; - moo2.moo = moo3; - moo3.moo = root; - Moo root2 = kryo.copy(root); - assertTrue(root != root2); - assertTrue(root.moo != root2.moo); - assertTrue(root.moo.moo != root2.moo.moo); - assertTrue(root.moo.moo.moo != root2.moo.moo.moo); - assertTrue(root.moo.moo.moo.moo != root2.moo.moo.moo.moo); - assertTrue(root.moo.moo.moo.moo == root); - assertTrue(root2.moo.moo.moo.moo == root2); - } - - public void testShallow () { - ArrayList test = new ArrayList(); - test.add("one"); - test.add("two"); - test.add("three"); - - ArrayList test2 = new ArrayList(); - test2.add(1); - test2.add(2f); - test2.add(3d); - test2.add((byte)4); - test2.add((short)5); - test.add(test2); - - ArrayList copy = kryo.copyShallow(test); - assertTrue(test != copy); - assertTrue(test.get(3) == copy.get(3)); - assertEquals(test, copy); - } - - static public class Moo { - Moo moo; - } -} diff --git a/test/dorkbox/network/kryo/DefaultSerializersTest.java b/test/dorkbox/network/kryo/DefaultSerializersTest.java deleted file mode 100644 index c588f35e..00000000 --- a/test/dorkbox/network/kryo/DefaultSerializersTest.java +++ /dev/null @@ -1,310 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.EnumSet; -import java.util.TimeZone; - -/** @author Nathan Sweet */ -public class DefaultSerializersTest extends KryoTestCase { - { - supportsCopy = true; - } - - public void testBoolean () { - roundTrip(2, 2, true); - roundTrip(2, 2, false); - } - - public void testByte () { - roundTrip(2, 2, (byte)1); - roundTrip(2, 2, (byte)125); - roundTrip(2, 2, (byte)-125); - } - - public void testChar () { - roundTrip(3, 3, 'a'); - roundTrip(3, 3, 'z'); - } - - public void testDouble () { - roundTrip(9, 9, 0d); - roundTrip(9, 9, 1234d); - roundTrip(9, 9, 1234.5678d); - } - - public void testFloat () { - roundTrip(5, 5, 0f); - roundTrip(5, 5, 123f); - roundTrip(5, 5, 123.456f); - } - - public void testInt () { - roundTrip(2, 5, 0); - roundTrip(2, 5, 63); - roundTrip(3, 5, 64); - roundTrip(3, 5, 127); - roundTrip(3, 5, 128); - roundTrip(3, 5, 8191); - roundTrip(4, 5, 8192); - roundTrip(4, 5, 16383); - roundTrip(4, 5, 16384); - roundTrip(5, 5, 2097151); - roundTrip(4, 5, 1048575); - roundTrip(5, 5, 134217727); - roundTrip(6, 5, 268435455); - roundTrip(6, 5, 134217728); - roundTrip(6, 5, 268435456); - roundTrip(2, 5, -64); - roundTrip(3, 5, -65); - roundTrip(3, 5, -8192); - roundTrip(4, 5, -1048576); - roundTrip(5, 5, -134217728); - roundTrip(6, 5, -134217729); - } - - public void testLong () { - roundTrip(2, 9, 0l); - roundTrip(2, 9, 63l); - roundTrip(3, 9, 64l); - roundTrip(3, 9, 127l); - roundTrip(3, 9, 128l); - roundTrip(3, 9, 8191l); - roundTrip(4, 9, 8192l); - roundTrip(4, 9, 16383l); - roundTrip(4, 9, 16384l); - roundTrip(5, 9, 2097151l); - roundTrip(4, 9, 1048575l); - roundTrip(5, 9, 134217727l); - roundTrip(6, 9, 268435455l); - roundTrip(6, 9, 134217728l); - roundTrip(6, 9, 268435456l); - roundTrip(2, 9, -64l); - roundTrip(3, 9, -65l); - roundTrip(3, 9, -8192l); - roundTrip(4, 9, -1048576l); - roundTrip(5, 9, -134217728l); - roundTrip(6, 9, -134217729l); - roundTrip(10, 9, 2368365495612416452l); - roundTrip(10, 9, -2368365495612416452l); - } - - public void testShort () { - roundTrip(3, 3, (short)0); - roundTrip(3, 3, (short)123); - roundTrip(3, 3, (short)123); - roundTrip(3, 3, (short)-123); - roundTrip(3, 3, (short)250); - roundTrip(3, 3, (short)123); - roundTrip(3, 3, (short)400); - } - - public void testString () { - kryo = new Kryo(); - kryo.setRegistrationRequired(true); - roundTrip(6, 6, "meow"); - roundTrip(70, 70, "abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef"); - - kryo.setReferences(false); - roundTrip(5, 5, "meow"); - - roundTrip(3, 3, "a"); - roundTrip(3, 3, "\n"); - roundTrip(2, 2, ""); - roundTrip(100, 100, "ABCDEFGHIJKLMNOPQRSTUVWXYZ\rabcdefghijklmnopqrstuvwxyz\n1234567890\t\"!`?'.,;:()[]{}<>|/@\\^$-%+=#_&~*"); - - roundTrip(21, 21, "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u7C9F"); - } - - public void testNull () { - kryo = new Kryo(); - kryo.setRegistrationRequired(true); - kryo.register(ArrayList.class); - roundTrip(1, 1, null); - testNull(Long.class); - testNull(ArrayList.class); - - kryo.setReferences(false); - roundTrip(1, 1, null); - testNull(Long.class); - testNull(ArrayList.class); - } - - - @SuppressWarnings({"rawtypes", "unchecked"}) - private void testNull (Class type) { - kryo.writeObjectOrNull(output, null, type); - input.setBuffer(output.toBytes()); - Object object = kryo.readObjectOrNull(input, type); - assertNull(object); - } - - public void testDateSerializer () { - kryo.register(Date.class); - roundTrip(10, 9, new Date(-1234567)); - roundTrip(2, 9, new Date(0)); - roundTrip(4, 9, new Date(1234567)); - roundTrip(10, 9, new Date(-1234567)); - } - - public void testBigDecimalSerializer () { - kryo.register(BigDecimal.class); - roundTrip(5, 8, BigDecimal.valueOf(12345, 2)); - } - - public void testBigIntegerSerializer () { - kryo.register(BigInteger.class); - roundTrip(8, 8, BigInteger.valueOf(1270507903945L)); - } - - public void testEnumSerializer () { - kryo.register(TestEnum.class); - roundTrip(2, 2, TestEnum.a); - roundTrip(2, 2, TestEnum.b); - roundTrip(2, 2, TestEnum.c); - - kryo = new Kryo(); - kryo.setRegistrationRequired(false); - // 1 byte identifying it's a class name - // 1 byte for the class name id - // 57 bytes for the class name characters - // 1 byte for the reference id - // 1 byte for the enum value - - // HACK offset by X from original because of changes in package name - roundTrip(61-packageOffset, 61-packageOffset, TestEnum.c); - } - - public void testEnumSetSerializer () { - kryo.register(EnumSet.class); - kryo.register(TestEnum.class); - roundTrip(5, 8, EnumSet.of(TestEnum.a, TestEnum.c)); - roundTrip(4, 7, EnumSet.of(TestEnum.a)); - roundTrip(6, 9, EnumSet.allOf(TestEnum.class)); - - kryo = new Kryo(); - kryo.setRegistrationRequired(false); - // HACK offset by X from original because of changes in package name - roundTrip(89-packageOffset, 92-packageOffset, EnumSet.of(TestEnum.a, TestEnum.c)); - } - - public void testEnumSerializerWithMethods () { - kryo.register(TestEnumWithMethods.class); - roundTrip(2, 2, TestEnumWithMethods.a); - roundTrip(2, 2, TestEnumWithMethods.b); - roundTrip(2, 2, TestEnumWithMethods.c); - - kryo = new Kryo(); - kryo.setRegistrationRequired(false); - // HACK offset by X from original because of changes in package name - roundTrip(76-packageOffset, 76-packageOffset, TestEnumWithMethods.c); - } - - - @SuppressWarnings({"rawtypes", "unchecked"}) - public void testCollectionsMethods () { - kryo.setRegistrationRequired(false); - ArrayList test = new ArrayList(); - test.add(Collections.EMPTY_LIST); - test.add(Collections.EMPTY_MAP); - test.add(Collections.EMPTY_SET); - test.add(Collections.singletonList("meow")); - test.add(Collections.singletonMap("moo", 1234)); - test.add(Collections.singleton(12.34)); - roundTrip(249, 251, test); - } - - public void testCalendar () { - kryo.setRegistrationRequired(false); - Calendar calendar = Calendar.getInstance(); - calendar.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); - calendar.set(1980, 7, 26, 12, 22, 46); - roundTrip(64, 73, calendar); - } - - public void testClassSerializer() { - kryo.register(Class.class); - kryo.register(ArrayList.class); - kryo.setRegistrationRequired(false); - final Output out = new Output(1024); - - kryo.writeObject(out, String.class); - kryo.writeObject(out, Integer.class); - kryo.writeObject(out, Short.class); - kryo.writeObject(out, Long.class); - kryo.writeObject(out, Double.class); - kryo.writeObject(out, Float.class); - kryo.writeObject(out, Boolean.class); - kryo.writeObject(out, Character.class); - - kryo.writeObject(out, int.class); - kryo.writeObject(out, short.class); - kryo.writeObject(out, long.class); - kryo.writeObject(out, double.class); - kryo.writeObject(out, float.class); - kryo.writeObject(out, boolean.class); - kryo.writeObject(out, char.class); - kryo.writeObject(out, ArrayList.class); - kryo.writeObject(out, TestEnum.class); - - final Input in = new Input(out.getBuffer()); - - assertEquals(String.class, kryo.readObject(in, Class.class)); - assertEquals(Integer.class, kryo.readObject(in, Class.class)); - assertEquals(Short.class, kryo.readObject(in, Class.class)); - assertEquals(Long.class, kryo.readObject(in, Class.class)); - assertEquals(Double.class, kryo.readObject(in, Class.class)); - assertEquals(Float.class, kryo.readObject(in, Class.class)); - assertEquals(Boolean.class, kryo.readObject(in, Class.class)); - assertEquals(Character.class, kryo.readObject(in, Class.class)); - assertEquals(int.class, kryo.readObject(in, Class.class)); - assertEquals(short.class, kryo.readObject(in, Class.class)); - assertEquals(long.class, kryo.readObject(in, Class.class)); - assertEquals(double.class, kryo.readObject(in, Class.class)); - assertEquals(float.class, kryo.readObject(in, Class.class)); - assertEquals(boolean.class, kryo.readObject(in, Class.class)); - assertEquals(char.class, kryo.readObject(in, Class.class)); - assertEquals(ArrayList.class, kryo.readObject(in, Class.class)); - assertEquals(TestEnum.class, kryo.readObject(in, Class.class)); - } - - public enum TestEnum { - a, b, c - } - - public enum TestEnumWithMethods { - a { - }, - b { - }, - c { - } - } -} diff --git a/test/dorkbox/network/kryo/DeflateSerializerTest.java b/test/dorkbox/network/kryo/DeflateSerializerTest.java deleted file mode 100644 index 7e8bdae0..00000000 --- a/test/dorkbox/network/kryo/DeflateSerializerTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import com.esotericsoftware.kryo.serializers.DefaultSerializers.StringSerializer; -import com.esotericsoftware.kryo.serializers.DeflateSerializer; - -/** @author Nathan Sweet */ -public class DeflateSerializerTest extends KryoTestCase { - public void testString () { - kryo.register(String.class, new DeflateSerializer(new StringSerializer())); - roundTrip(15, 15, "abcdefabcdefabcdefabcdefabcdefabcdefabcdef"); - } - - public void testGraph () { - kryo.register(Message.class); - kryo.register(MessageType.class); - kryo.register(ServerPhysicsUpdate.class, new DeflateSerializer(kryo.getDefaultSerializer(ServerPhysicsUpdate.class))); - - ServerPhysicsUpdate physicsUpdate = new ServerPhysicsUpdate(); - physicsUpdate.value = 1; - Message message = new Message(); - message.type = MessageType.SERVER_UPDATE; - message.data = physicsUpdate; - - roundTrip(8, 8, message); - } - - public static class ServerPhysicsUpdate { - public int value; - - public ServerPhysicsUpdate () { - } - - public int hashCode () { - final int prime = 31; - int result = 1; - result = prime * result + value; - return result; - } - - public boolean equals (Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - ServerPhysicsUpdate other = (ServerPhysicsUpdate)obj; - if (value != other.value) return false; - return true; - } - } - - public static enum MessageType { - SERVER_UPDATE - } - - public static class Message { - public MessageType type; - public Object data; - - public Message () { - } - - public int hashCode () { - final int prime = 31; - int result = 1; - result = prime * result + ((data == null) ? 0 : data.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - return result; - } - - public boolean equals (Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - Message other = (Message)obj; - if (data == null) { - if (other.data != null) return false; - } else if (!data.equals(other.data)) return false; - if (type != other.type) return false; - return true; - } - } -} diff --git a/test/dorkbox/network/kryo/FieldSerializerTest.java b/test/dorkbox/network/kryo/FieldSerializerTest.java deleted file mode 100644 index 127e540a..00000000 --- a/test/dorkbox/network/kryo/FieldSerializerTest.java +++ /dev/null @@ -1,1477 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import java.io.ByteArrayOutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.objenesis.strategy.StdInstantiatorStrategy; - -import com.esotericsoftware.kryo.DefaultSerializer; -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.KryoException; -import com.esotericsoftware.kryo.NotNull; -import com.esotericsoftware.kryo.Registration; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import com.esotericsoftware.kryo.serializers.CollectionSerializer; -import com.esotericsoftware.kryo.serializers.CollectionSerializer.BindCollection; -import com.esotericsoftware.kryo.serializers.DefaultArraySerializers.IntArraySerializer; -import com.esotericsoftware.kryo.serializers.DefaultArraySerializers.LongArraySerializer; -import com.esotericsoftware.kryo.serializers.DefaultSerializers.StringSerializer; -import com.esotericsoftware.kryo.serializers.FieldSerializer; -import com.esotericsoftware.kryo.serializers.FieldSerializer.Bind; -import com.esotericsoftware.kryo.serializers.FieldSerializer.Optional; -import com.esotericsoftware.kryo.serializers.MapSerializer.BindMap; - -/** @author Nathan Sweet */ - -@SuppressWarnings({"rawtypes", "unchecked"}) -public class FieldSerializerTest extends KryoTestCase { - { - this.supportsCopy = true; - } - - public void testDefaultTypes () { - this.kryo.register(DefaultTypes.class); - this.kryo.register(byte[].class); - DefaultTypes test = new DefaultTypes(); - test.booleanField = true; - test.byteField = 123; - test.charField = 'Z'; - test.shortField = 12345; - test.intField = 123456; - test.longField = 123456789; - test.floatField = 123.456f; - test.doubleField = 1.23456d; - test.BooleanField = true; - test.ByteField = -12; - test.CharacterField = 'X'; - test.ShortField = -12345; - test.IntegerField = -123456; - test.LongField = -123456789l; - test.FloatField = -123.3f; - test.DoubleField = -0.121231d; - test.StringField = "stringvalue"; - test.byteArrayField = new byte[] {2, 1, 0, -1, -2}; - roundTrip(78, 88, test); - - this.kryo.register(HasStringField.class); - test.hasStringField = new HasStringField(); - FieldSerializer serializer = (FieldSerializer)this.kryo.getSerializer(DefaultTypes.class); - serializer.getField("hasStringField").setCanBeNull(false); - roundTrip(79, 89, test); - serializer.setFixedFieldTypes(true); - serializer.getField("hasStringField").setCanBeNull(false); - roundTrip(78, 88, test); - } - - public void testFieldRemoval () { - this.kryo.register(DefaultTypes.class); - this.kryo.register(byte[].class); - this.kryo.register(HasStringField.class); - - HasStringField hasStringField = new HasStringField(); - hasStringField.text = "moo"; - roundTrip(4, 4, hasStringField); - - DefaultTypes test = new DefaultTypes(); - test.intField = 12; - test.StringField = "value"; - test.CharacterField = 'X'; - test.child = new DefaultTypes(); - roundTrip(71, 91, test); - - this.supportsCopy = false; - - test.StringField = null; - roundTrip(67, 87, test); - - FieldSerializer serializer = (FieldSerializer)this.kryo.getSerializer(DefaultTypes.class); - serializer.removeField("LongField"); - serializer.removeField("floatField"); - serializer.removeField("FloatField"); - roundTrip(55, 75, test); - - this.supportsCopy = true; - } - - public - void testFieldRemovalOnGenerics() { - kryo.register(IsGeneric.class); - kryo.register(DefaultTypes.class); - kryo.register(byte[].class); - - FieldSerializer serializer = new FieldSerializer(kryo, IsGeneric.class); - serializer.removeField("y"); - kryo.register(IsGeneric.class, serializer); - - IsGeneric> test = new IsGeneric>(); - test.item = new IsGeneric(); - - try { - roundTrip(5, 11, test); - } catch (KryoException e) { - e.printStackTrace(); - fail("Couldn't serialize generic with a removed field."); - } - } - - - public void testOptionalRegistration () { - this.kryo.setRegistrationRequired(false); - DefaultTypes test = new DefaultTypes(); - test.intField = 12; - test.StringField = "value"; - test.CharacterField = 'X'; - test.hasStringField = new HasStringField(); - test.child = new DefaultTypes(); - test.child.hasStringField = new HasStringField(); - - // HACK offset by XX from original because of changes in package name + XX because it has ANOTHER subclass - roundTrip(195-this.packageOffset-this.packageOffset, 215-this.packageOffset-this.packageOffset, test); - test.hasStringField = null; - roundTrip(193-this.packageOffset-this.packageOffset, 213-this.packageOffset-this.packageOffset, test); - - test = new DefaultTypes(); - test.booleanField = true; - test.byteField = 123; - test.charField = 1234; - test.shortField = 12345; - test.intField = 123456; - test.longField = 123456789; - test.floatField = 123.456f; - test.doubleField = 1.23456d; - test.BooleanField = true; - test.ByteField = -12; - test.CharacterField = 123; - test.ShortField = -12345; - test.IntegerField = -123456; - test.LongField = -123456789l; - test.FloatField = -123.3f; - test.DoubleField = -0.121231d; - test.StringField = "stringvalue"; - test.byteArrayField = new byte[] {2, 1, 0, -1, -2}; - - this.kryo = new Kryo(); - // HACK offset by X from original because of changes in package name - roundTrip(140-this.packageOffset, 150-this.packageOffset, test); - - C c = new C(); - c.a = new A(); - c.a.value = 123; - c.a.b = new B(); - c.a.b.value = 456; - c.d = new D(); - c.d.e = new E(); - c.d.e.f = new F(); - - // HACK offset by X from original because of changes in package name - roundTrip(63-this.packageOffset, 73-this.packageOffset, c); - } - - public void testReferences () { - C c = new C(); - c.a = new A(); - c.a.value = 123; - c.a.b = new B(); - c.a.b.value = 456; - c.d = new D(); - c.d.e = new E(); - c.d.e.f = new F(); - c.d.e.f.a = c.a; - - this.kryo = new Kryo(); - // HACK offset by X from original because of changes in package name - roundTrip(63-this.packageOffset, 73-this.packageOffset, c); - C c2 = (C)this.object2; - assertTrue(c2.a == c2.d.e.f.a); - - // Test reset clears unregistered class names. - // HACK offset by X from original because of changes in package name - roundTrip(63-this.packageOffset, 73-this.packageOffset, c); - c2 = (C)this.object2; - assertTrue(c2.a == c2.d.e.f.a); - - this.kryo = new Kryo(); - this.kryo.setRegistrationRequired(true); - this.kryo.register(A.class); - this.kryo.register(B.class); - this.kryo.register(C.class); - this.kryo.register(D.class); - this.kryo.register(E.class); - this.kryo.register(F.class); - roundTrip(15, 25, c); - c2 = (C)this.object2; - assertTrue(c2.a == c2.d.e.f.a); - } - - public void testRegistrationOrder () { - A a = new A(); - a.value = 100; - a.b = new B(); - a.b.value = 200; - a.b.a = new A(); - a.b.a.value = 300; - - this.kryo.register(A.class); - this.kryo.register(B.class); - roundTrip(10, 16, a); - - this.kryo = new Kryo(); - this.kryo.setReferences(false); - this.kryo.register(B.class); - this.kryo.register(A.class); - roundTrip(10, 16, a); - } - - public void testExceptionTrace () { - C c = new C(); - c.a = new A(); - c.a.value = 123; - c.a.b = new B(); - c.a.b.value = 456; - c.d = new D(); - c.d.e = new E(); - c.d.e.f = new F(); - - Kryo kryoWithoutF = new Kryo(); - kryoWithoutF.setReferences(false); - kryoWithoutF.setRegistrationRequired(true); - kryoWithoutF.register(A.class); - kryoWithoutF.register(B.class); - kryoWithoutF.register(C.class); - kryoWithoutF.register(D.class); - kryoWithoutF.register(E.class); - - Output output = new Output(512); - try { - kryoWithoutF.writeClassAndObject(output, c); - fail("Should have failed because F is not registered."); - } catch (KryoException ignored) { - } - - this.kryo.register(A.class); - this.kryo.register(B.class); - this.kryo.register(C.class); - this.kryo.register(D.class); - this.kryo.register(E.class); - this.kryo.register(F.class); - this.kryo.setRegistrationRequired(true); - - output.clear(); - this.kryo.writeClassAndObject(output, c); - output.flush(); - assertEquals(14, output.total()); - - Input input = new Input(output.getBuffer()); - this.kryo.readClassAndObject(input); - - try { - input.setPosition(0); - kryoWithoutF.readClassAndObject(input); - fail("Should have failed because F is not registered."); - } catch (KryoException ignored) { - } - } - - public void testNoDefaultConstructor () { - this.kryo.register(SimpleNoDefaultConstructor.class, new Serializer() { - @Override - public SimpleNoDefaultConstructor read (Kryo kryo, Input input, Class type) { - return new SimpleNoDefaultConstructor(input.readInt(true)); - } - - @Override - public void write (Kryo kryo, Output output, SimpleNoDefaultConstructor object) { - output.writeInt(object.constructorValue, true); - } - - @Override - public SimpleNoDefaultConstructor copy (Kryo kryo, SimpleNoDefaultConstructor original) { - return new SimpleNoDefaultConstructor(original.constructorValue); - } - }); - SimpleNoDefaultConstructor object1 = new SimpleNoDefaultConstructor(2); - roundTrip(2, 5, object1); - - this.kryo.register(ComplexNoDefaultConstructor.class, new FieldSerializer(this.kryo, - ComplexNoDefaultConstructor.class) { - @Override - public void write (Kryo kryo, Output output, ComplexNoDefaultConstructor object) { - output.writeString(object.name); - super.write(kryo, output, object); - } - - @Override - protected ComplexNoDefaultConstructor create (Kryo kryo, Input input, Class type) { - String name = input.readString(); - return new ComplexNoDefaultConstructor(name); - } - - @Override - protected ComplexNoDefaultConstructor createCopy (Kryo kryo, ComplexNoDefaultConstructor original) { - return new ComplexNoDefaultConstructor(original.name); - } - }); - ComplexNoDefaultConstructor object2 = new ComplexNoDefaultConstructor("has no zero arg constructor!"); - object2.anotherField1 = 1234; - object2.anotherField2 = "abcd"; - roundTrip(35, 37, object2); - } - - public void testNonNull () { - this.kryo.register(HasNonNull.class); - HasNonNull nonNullValue = new HasNonNull(); - nonNullValue.nonNullText = "moo"; - roundTrip(4, 4, nonNullValue); - } - - public void testDefaultSerializerAnnotation () { - this.kryo = new Kryo(); - // HACK offset by X from original because of changes in package name - roundTrip(82-this.packageOffset, 89-this.packageOffset, new HasDefaultSerializerAnnotation(123)); - } - - public void testOptionalAnnotation () { - this.kryo = new Kryo(); - // HACK offset by X from original because of changes in package name + 2 b/c of how optionalAnnotations works - roundTrip(72-this.packageOffset-2, 72-this.packageOffset-2, new HasOptionalAnnotation()); - this.kryo = new Kryo(); - this.kryo.getContext().put("smurf", null); - // HACK offset by X from original because of changes in package name + 2 b/c of how optionalAnnotations works - roundTrip(73-this.packageOffset-2, 76-this.packageOffset-2, new HasOptionalAnnotation()); - } - - public void testCyclicGraph () throws Exception { - this.kryo = new Kryo(); - this.kryo.setRegistrationRequired(true); - this.kryo.register(DefaultTypes.class); - this.kryo.register(byte[].class); - DefaultTypes test = new DefaultTypes(); - test.child = test; - roundTrip(35, 45, test); - } - - @SuppressWarnings("synthetic-access") - public void testInstantiatorStrategy () { - this.kryo.register(HasArgumentConstructor.class); - this.kryo.setInstantiatorStrategy(new StdInstantiatorStrategy()); - HasArgumentConstructor test = new HasArgumentConstructor("cow"); - roundTrip(4, 4, test); - - this.kryo.register(HasPrivateConstructor.class); - test = new HasPrivateConstructor(); - roundTrip(4, 4, test); - } - - /** - * This test uses StdInstantiatorStrategy and therefore requires a no-arg constructor. - **/ - @SuppressWarnings("synthetic-access") - public - void testDefaultInstantiatorStrategy() { - kryo.register(HasArgumentConstructor.class); - HasArgumentConstructor test = new HasPrivateConstructor(); - HasPrivateConstructor.invocations = 0; - - kryo.register(HasPrivateConstructor.class); - roundTrip(4, 4, test); - assertEquals("Default constructor should not be invoked with StdInstantiatorStrategy strategy", 25, - HasPrivateConstructor.invocations); - } - - /** - * This test uses StdInstantiatorStrategy and should bypass invocation of no-arg constructor, even if it is provided. - **/ - @SuppressWarnings("synthetic-access") - public - void testStdInstantiatorStrategy() { - kryo.register(HasArgumentConstructor.class); - kryo.setInstantiatorStrategy(new StdInstantiatorStrategy()); - HasArgumentConstructor test = new HasPrivateConstructor(); - HasPrivateConstructor.invocations = 0; - - kryo.register(HasPrivateConstructor.class); - roundTrip(4, 4, test); - assertEquals("Default constructor should not be invoked with StdInstantiatorStrategy strategy", 0, - HasPrivateConstructor.invocations); - } - - public - void testGenericTypesOptimized() { - testGenericTypes(true); - } - - public - void testGenericTypesNonOptimized() { - testGenericTypes(false); - } - - /** - * Check that it is OK to change the optimizedGenerics setting on the same Kryo instance multiple times. - */ - public - void testGenericTypesOptimizedAndNonOptimized() { - Kryo kryoInstance = kryo; - testGenericTypes(true); - assertEquals("The same instance of Kryo should be used", kryoInstance, kryo); - testGenericTypes(false); - assertEquals("The same instance of Kryo should be used", kryoInstance, kryo); - testGenericTypes(true); - assertEquals("The same instance of Kryo should be used", kryoInstance, kryo); - testGenericTypes(false); - assertEquals("The same instance of Kryo should be used", kryoInstance, kryo); - } - - private - void testGenericTypes(boolean optimizedGenerics) { - kryo.getFieldSerializerConfig() - .setOptimizedGenerics(optimizedGenerics); - kryo.setReferences(true); - kryo.setRegistrationRequired(true); - kryo.register(HasGenerics.class); - kryo.register(ArrayList.class); - kryo.register(ArrayList[].class); - kryo.register(HashMap.class); - - // It may happen that classes were registered already befor this function - // was called. In this case, invoke the setters on the FieldSerializer - // objects directly. - FieldSerializer fieldSerializer; - fieldSerializer = (FieldSerializer) kryo.getSerializer(HasGenerics.class); - fieldSerializer.setOptimizedGenerics(optimizedGenerics); - - HasGenerics test = new HasGenerics(); - test.list1 = new ArrayList(); - test.list1.add(1); - test.list1.add(2); - test.list1.add(3); - test.list1.add(4); - test.list1.add(5); - test.list1.add(6); - test.list1.add(7); - test.list1.add(8); - test.list2 = new ArrayList(); - test.list2.add(test.list1); - test.map1 = new HashMap(); - test.map1.put("a", test.list1); - test.list3 = new ArrayList(); - test.list3.add(null); - test.list4 = new ArrayList(); - test.list4.add(null); - test.list5 = new ArrayList(); - test.list5.add("one"); - test.list5.add("two"); - roundTrip(optimizedGenerics ? 53 : 56, optimizedGenerics ? 80 : 83, test); - ArrayList[] al = new ArrayList[1]; - al[0] = new ArrayList(Arrays.asList(new String[] {"A", "B", "S"})); - roundTrip(18, 18, al); - } - - public void testRegistration () { - int id = this.kryo.getNextRegistrationId(); - this.kryo.register(DefaultTypes.class, id); - this.kryo.register(DefaultTypes.class, id); - this.kryo.register(new Registration(byte[].class, this.kryo.getDefaultSerializer(byte[].class), id + 1)); - this.kryo.register(byte[].class, this.kryo.getDefaultSerializer(byte[].class), id + 1); - this.kryo.register(HasStringField.class, this.kryo.getDefaultSerializer(HasStringField.class)); - - DefaultTypes test = new DefaultTypes(); - test.intField = 12; - test.StringField = "meow"; - test.CharacterField = 'z'; - test.byteArrayField = new byte[] {0, 1, 2, 3, 4}; - test.child = new DefaultTypes(); - roundTrip(75, 95, test); - } - - public - void testTransients() { - kryo.register(HasTransients.class); - HasTransients objectWithTransients1 = new HasTransients(); - objectWithTransients1.transientField1 = "Test"; - objectWithTransients1.anotherField2 = 5; - objectWithTransients1.anotherField3 = "Field2"; - - FieldSerializer ser = (FieldSerializer) kryo.getSerializer(HasTransients.class); - ser.setCopyTransient(false); - - HasTransients objectWithTransients3 = kryo.copy(objectWithTransients1); - assertTrue("Objects should be different if copy does not include transient fields", - !objectWithTransients3.equals(objectWithTransients1)); - assertEquals("transient fields should be null", objectWithTransients3.transientField1, null); - - ser.setCopyTransient(true); - HasTransients objectWithTransients2 = kryo.copy(objectWithTransients1); - assertEquals("Objects should be equal if copy includes transient fields", objectWithTransients2, objectWithTransients1); - } - - public - void testTransientsUsingGlobalConfig() { - kryo.getFieldSerializerConfig() - .setCopyTransient(false); - kryo.register(HasTransients.class); - HasTransients objectWithTransients1 = new HasTransients(); - objectWithTransients1.transientField1 = "Test"; - objectWithTransients1.anotherField2 = 5; - objectWithTransients1.anotherField3 = "Field2"; - - FieldSerializer ser = (FieldSerializer) kryo.getSerializer(HasTransients.class); - HasTransients objectWithTransients3 = kryo.copy(objectWithTransients1); - assertTrue("Objects should be different if copy does not include transient fields", - !objectWithTransients3.equals(objectWithTransients1)); - assertEquals("transient fields should be null", objectWithTransients3.transientField1, null); - - ser.setCopyTransient(true); - HasTransients objectWithTransients2 = kryo.copy(objectWithTransients1); - assertEquals("Objects should be equal if copy includes transient fields", objectWithTransients2, objectWithTransients1); - } - - public - void testSerializeTransients() { - kryo.register(HasTransients.class); - HasTransients objectWithTransients1 = new HasTransients(); - objectWithTransients1.transientField1 = "Test"; - objectWithTransients1.anotherField2 = 5; - objectWithTransients1.anotherField3 = "Field2"; - - ByteArrayOutputStream outputStream; - Output output; - Input input; - byte[] outBytes; - - FieldSerializer ser = (FieldSerializer) kryo.getSerializer(HasTransients.class); - ser.setSerializeTransient(false); - - outputStream = new ByteArrayOutputStream(); - output = new Output(outputStream); - ser.write(kryo, output, objectWithTransients1); - output.flush(); - - outBytes = outputStream.toByteArray(); - input = new Input(outBytes); - HasTransients objectWithTransients3 = ser.read(kryo, input, HasTransients.class); - assertTrue("Objects should be different if write does not include transient fields", - !objectWithTransients3.equals(objectWithTransients1)); - assertEquals("transient fields should be null", objectWithTransients3.transientField1, null); - - ser.setSerializeTransient(true); - - outputStream = new ByteArrayOutputStream(); - output = new Output(outputStream); - ser.write(kryo, output, objectWithTransients1); - output.flush(); - - outBytes = outputStream.toByteArray(); - input = new Input(outBytes); - HasTransients objectWithTransients2 = ser.read(kryo, input, HasTransients.class); - assertTrue("Objects should be equal if write includes transient fields", objectWithTransients2.equals(objectWithTransients1)); - } - - public - void testSerializeTransientsUsingGlobalConfig() { - kryo.getFieldSerializerConfig() - .setSerializeTransient(false); - kryo.register(HasTransients.class); - HasTransients objectWithTransients1 = new HasTransients(); - objectWithTransients1.transientField1 = "Test"; - objectWithTransients1.anotherField2 = 5; - objectWithTransients1.anotherField3 = "Field2"; - - ByteArrayOutputStream outputStream; - Output output; - Input input; - byte[] outBytes; - - FieldSerializer ser = (FieldSerializer) kryo.getSerializer(HasTransients.class); - outputStream = new ByteArrayOutputStream(); - output = new Output(outputStream); - ser.write(kryo, output, objectWithTransients1); - output.flush(); - - outBytes = outputStream.toByteArray(); - input = new Input(outBytes); - HasTransients objectWithTransients3 = ser.read(kryo, input, HasTransients.class); - assertTrue("Objects should be different if write does not include transient fields", - !objectWithTransients3.equals(objectWithTransients1)); - assertEquals("transient fields should be null", objectWithTransients3.transientField1, null); - - ser.setSerializeTransient(true); - - outputStream = new ByteArrayOutputStream(); - output = new Output(outputStream); - ser.write(kryo, output, objectWithTransients1); - output.flush(); - - outBytes = outputStream.toByteArray(); - input = new Input(outBytes); - HasTransients objectWithTransients2 = ser.read(kryo, input, HasTransients.class); - assertTrue("Objects should be equal if write includes transient fields", objectWithTransients2.equals(objectWithTransients1)); - } - - public - void testCorrectlyAnnotatedFields() { - kryo.register(int[].class); - kryo.register(long[].class); - kryo.register(HashMap.class); - kryo.register(ArrayList.class); - kryo.register(AnnotatedFields.class); - AnnotatedFields obj1 = new AnnotatedFields(); - obj1.map = new HashMap(); - obj1.map.put("key1", new int[] {1, 2, 3}); - obj1.map.put("key2", new int[] {3, 4, 5}); - obj1.map.put("key3", null); - - obj1.collection = new ArrayList(); - obj1.collection.add(new long[] {1, 2, 3}); - - roundTrip(31, 73, obj1); - } - - public - void testWronglyAnnotatedCollectionFields() { - try { - kryo.register(WronglyAnnotatedCollectionFields.class); - WronglyAnnotatedCollectionFields obj1 = new WronglyAnnotatedCollectionFields(); - roundTrip(31, 73, obj1); - } catch (RuntimeException e) { - Throwable cause = e.getCause() - .getCause(); - assertTrue("Exception should complain about a field not implementing java.util.Collection", - cause.getMessage() - .contains("be used only with fields implementing java.util.Collection")); - return; - } - - assertFalse("Exception was expected", true); - } - - public - void testWronglyAnnotatedMapFields() { - try { - kryo.register(WronglyAnnotatedMapFields.class); - WronglyAnnotatedMapFields obj1 = new WronglyAnnotatedMapFields(); - roundTrip(31, 73, obj1); - } catch (RuntimeException e) { - Throwable cause = e.getCause() - .getCause(); - assertTrue("Exception should complain about a field not implementing java.util.Map ", - cause.getMessage() - .contains("be used only with fields implementing java.util.Map")); - return; - } - - assertFalse("Exception was expected", true); - } - - public - void testMultipleTimesAnnotatedMapFields() { - try { - kryo.register(MultipleTimesAnnotatedCollectionFields.class); - MultipleTimesAnnotatedCollectionFields obj1 = new MultipleTimesAnnotatedCollectionFields(); - roundTrip(31, 73, obj1); - } catch (RuntimeException e) { - Throwable cause = e.getCause() - .getCause(); - assertTrue("Exception should complain about a field that has a serializer already", - cause.getMessage() - .contains("already")); - return; - } - - assertFalse("Exception was expected", true); - } - - static public - class DefaultTypes { - // Primitives. - public boolean booleanField; - public byte byteField; - public char charField; - public short shortField; - public int intField; - public long longField; - public float floatField; - public double doubleField; - // Primitive wrappers. - public Boolean BooleanField; - public Byte ByteField; - public Character CharacterField; - public Short ShortField; - public Integer IntegerField; - public Long LongField; - public Float FloatField; - public Double DoubleField; - // Other. - public String StringField; - public byte[] byteArrayField; - - DefaultTypes child; - HasStringField hasStringField; - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - DefaultTypes other = (DefaultTypes) obj; - if (BooleanField == null) { - if (other.BooleanField != null) - return false; - } - else if (!BooleanField.equals(other.BooleanField)) - return false; - if (ByteField == null) { - if (other.ByteField != null) - return false; - } - else if (!ByteField.equals(other.ByteField)) - return false; - if (CharacterField == null) { - if (other.CharacterField != null) - return false; - } - else if (!CharacterField.equals(other.CharacterField)) - return false; - if (DoubleField == null) { - if (other.DoubleField != null) - return false; - } - else if (!DoubleField.equals(other.DoubleField)) - return false; - if (FloatField == null) { - if (other.FloatField != null) - return false; - } - else if (!FloatField.equals(other.FloatField)) - return false; - if (IntegerField == null) { - if (other.IntegerField != null) - return false; - } - else if (!IntegerField.equals(other.IntegerField)) - return false; - if (LongField == null) { - if (other.LongField != null) - return false; - } - else if (!LongField.equals(other.LongField)) - return false; - if (ShortField == null) { - if (other.ShortField != null) - return false; - } - else if (!ShortField.equals(other.ShortField)) - return false; - if (StringField == null) { - if (other.StringField != null) - return false; - } - else if (!StringField.equals(other.StringField)) - return false; - if (booleanField != other.booleanField) - return false; - - Object list1 = arrayToList(byteArrayField); - Object list2 = arrayToList(other.byteArrayField); - if (list1 != list2) { - if (list1 == null || list2 == null) - return false; - if (!list1.equals(list2)) - return false; - } - - if (child != other.child) { - if (child == null || other.child == null) - return false; - if (child != this && !child.equals(other.child)) - return false; - } - - if (byteField != other.byteField) - return false; - if (charField != other.charField) - return false; - if (Double.doubleToLongBits(doubleField) != Double.doubleToLongBits(other.doubleField)) - return false; - if (Float.floatToIntBits(floatField) != Float.floatToIntBits(other.floatField)) - return false; - if (intField != other.intField) - return false; - if (longField != other.longField) - return false; - if (shortField != other.shortField) - return false; - return true; - } - } - - - static public final - class A { - public int value; - public B b; - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - A other = (A) obj; - if (b == null) { - if (other.b != null) - return false; - } - else if (!b.equals(other.b)) - return false; - if (value != other.value) - return false; - return true; - } - } - - - static public final - class B { - public int value; - public A a; - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - B other = (B) obj; - if (a == null) { - if (other.a != null) - return false; - } - else if (!a.equals(other.a)) - return false; - if (value != other.value) - return false; - return true; - } - } - - - static public final - class C { - public A a; - public D d; - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - C other = (C) obj; - if (a == null) { - if (other.a != null) - return false; - } - else if (!a.equals(other.a)) - return false; - if (d == null) { - if (other.d != null) - return false; - } - else if (!d.equals(other.d)) - return false; - return true; - } - } - - - static public final - class D { - public E e; - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - D other = (D) obj; - if (e == null) { - if (other.e != null) - return false; - } - else if (!e.equals(other.e)) - return false; - return true; - } - } - - - static public final - class E { - public F f; - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - E other = (E) obj; - if (f == null) { - if (other.f != null) - return false; - } - else if (!f.equals(other.f)) - return false; - return true; - } - } - - - static public final - class F { - public int value; - public final int finalValue = 12; - public A a; - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - F other = (F) obj; - if (finalValue != other.finalValue) - return false; - if (value != other.value) - return false; - return true; - } - } - - - static public - class SimpleNoDefaultConstructor { - int constructorValue; - - public - SimpleNoDefaultConstructor(int constructorValue) { - this.constructorValue = constructorValue; - } - - public - int getConstructorValue() { - return constructorValue; - } - - public - int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + constructorValue; - return result; - } - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - SimpleNoDefaultConstructor other = (SimpleNoDefaultConstructor) obj; - if (constructorValue != other.constructorValue) - return false; - return true; - } - } - - - static public - class HasTransients { - public transient String transientField1; - public int anotherField2; - public String anotherField3; - - public - HasTransients() { - } - - public - int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + anotherField2; - result = prime * result + ((anotherField3 == null) ? 0 : anotherField3.hashCode()); - result = prime * result + ((transientField1 == null) ? 0 : transientField1.hashCode()); - return result; - } - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - HasTransients other = (HasTransients) obj; - if (anotherField2 != other.anotherField2) - return false; - if (anotherField3 == null) { - if (other.anotherField3 != null) - return false; - } - else if (!anotherField3.equals(other.anotherField3)) - return false; - if (transientField1 == null) { - if (other.transientField1 != null) - return false; - } - else if (!transientField1.equals(other.transientField1)) - return false; - return true; - } - } - - - static public - class ComplexNoDefaultConstructor { - public transient String name; - public int anotherField1; - public String anotherField2; - - public - ComplexNoDefaultConstructor(String name) { - this.name = name; - } - - public - int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + anotherField1; - result = prime * result + ((anotherField2 == null) ? 0 : anotherField2.hashCode()); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - return result; - } - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ComplexNoDefaultConstructor other = (ComplexNoDefaultConstructor) obj; - if (anotherField1 != other.anotherField1) - return false; - if (anotherField2 == null) { - if (other.anotherField2 != null) - return false; - } - else if (!anotherField2.equals(other.anotherField2)) - return false; - if (name == null) { - if (other.name != null) - return false; - } - else if (!name.equals(other.name)) - return false; - return true; - } - } - - - static public - class HasNonNull { - @NotNull - public String nonNullText; - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - HasNonNull other = (HasNonNull) obj; - if (nonNullText == null) { - if (other.nonNullText != null) - return false; - } - else if (!nonNullText.equals(other.nonNullText)) - return false; - return true; - } - } - - - static public - class HasStringField { - public String text; - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - HasStringField other = (HasStringField) obj; - if (text == null) { - if (other.text != null) - return false; - } - else if (!text.equals(other.text)) - return false; - return true; - } - } - - - static public - class HasOptionalAnnotation { - @Optional("smurf") - int moo; - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - HasOptionalAnnotation other = (HasOptionalAnnotation) obj; - if (moo != other.moo) - return false; - return true; - } - } - - - @DefaultSerializer(HasDefaultSerializerAnnotationSerializer.class) - static public - class HasDefaultSerializerAnnotation { - long time; - - public - HasDefaultSerializerAnnotation(long time) { - this.time = time; - } - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - HasDefaultSerializerAnnotation other = (HasDefaultSerializerAnnotation) obj; - if (time != other.time) - return false; - return true; - } - } - - - static public - class HasDefaultSerializerAnnotationSerializer extends Serializer { - @Override - public - void write(Kryo kryo, Output output, HasDefaultSerializerAnnotation object) { - output.writeLong(object.time, true); - } - - @Override - public - HasDefaultSerializerAnnotation read(Kryo kryo, Input input, Class type) { - return new HasDefaultSerializerAnnotation(input.readLong(true)); - } - - @Override - public - HasDefaultSerializerAnnotation copy(Kryo kryo, HasDefaultSerializerAnnotation original) { - return new HasDefaultSerializerAnnotation(original.time); - } - } - - - static public - class HasArgumentConstructor { - public String moo; - - public - HasArgumentConstructor(String moo) { - this.moo = moo; - } - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - HasArgumentConstructor other = (HasArgumentConstructor) obj; - if (moo == null) { - if (other.moo != null) - return false; - } - else if (!moo.equals(other.moo)) - return false; - return true; - } - } - - - static public - class HasPrivateConstructor extends HasArgumentConstructor { - static int invocations; - - private - HasPrivateConstructor() { - super("cow"); - HasPrivateConstructor.invocations++; - } - } - - - static public - class HasGenerics { - ArrayList list1; - List> list2 = new ArrayList>(); - List list3 = new ArrayList(); - ArrayList list4 = new ArrayList(); - ArrayList list5; - HashMap> map1; - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - HasGenerics other = (HasGenerics) obj; - if (list1 == null) { - if (other.list1 != null) - return false; - } - else if (!list1.equals(other.list1)) - return false; - if (list2 == null) { - if (other.list2 != null) - return false; - } - else if (!list2.equals(other.list2)) - return false; - if (list3 == null) { - if (other.list3 != null) - return false; - } - else if (!list3.equals(other.list3)) - return false; - if (list4 == null) { - if (other.list4 != null) - return false; - } - else if (!list4.equals(other.list4)) - return false; - if (list5 == null) { - if (other.list5 != null) - return false; - } - else if (!list5.equals(other.list5)) - return false; - if (map1 == null) { - if (other.map1 != null) - return false; - } - else if (!map1.equals(other.map1)) - return false; - return true; - } - } - - - static public - class MultipleTimesAnnotatedCollectionFields { - // This annotation should result in an exception, because - // it is applied to a non-collection field - @BindCollection(elementSerializer = LongArraySerializer.class, - elementClass = long[].class, - elementsCanBeNull = false) - @Bind(CollectionSerializer.class) - Collection collection; - } - - - static public - class WronglyAnnotatedCollectionFields { - // This annotation should result in an exception, because - // it is applied to a non-collection field - @BindCollection(elementSerializer = LongArraySerializer.class, - elementClass = long[].class, - elementsCanBeNull = false) - int collection; - } - - - static public - class WronglyAnnotatedMapFields { - // This annotation should result in an exception, because - // it is applied to a non-map field - @BindMap(valueSerializer = IntArraySerializer.class, - keySerializer = StringSerializer.class, - valueClass = int[].class, - keyClass = String.class, - keysCanBeNull = false) - Object map; - } - - - static public - class AnnotatedFields { - @Bind(StringSerializer.class) - Object stringField; - - @BindMap(valueSerializer = IntArraySerializer.class, - keySerializer = StringSerializer.class, - valueClass = int[].class, - keyClass = String.class, - keysCanBeNull = false) - Map map; - - @BindCollection(elementSerializer = LongArraySerializer.class, - elementClass = long[].class, - elementsCanBeNull = false) - Collection collection; - - public - boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - AnnotatedFields other = (AnnotatedFields) obj; - if (map == null) { - if (other.map != null) - return false; - } - else { - if (other.map == null) - return false; - if (map.size() != other.map.size()) - return false; - for (Object e : map.entrySet()) { - Map.Entry entry = (Map.Entry) e; - if (!other.map.containsKey(entry.getKey())) - return false; - Object otherValue = other.map.get(entry.getKey()); - if (entry.getValue() == null && otherValue != null) - return false; - if (!Arrays.equals((int[]) entry.getValue(), (int[]) otherValue)) - return false; - } - } - if (collection == null) { - if (other.collection != null) - return false; - } - else { - if (other.collection == null) - return false; - if (collection.size() != other.collection.size()) - return false; - Iterator it1 = collection.iterator(); - Iterator it2 = other.collection.iterator(); - while (it1.hasNext()) { - Object e1 = it1.next(); - Object e2 = it2.next(); - if (!Arrays.equals((long[]) e1, (long[]) e2)) - return false; - } - } - return true; - } - } - - - static public - class IsGeneric { - T item; - private int y; - private int z; - - @Override - public - boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof IsGeneric)) - return false; - - IsGeneric isGeneric = (IsGeneric) o; - - if (z != isGeneric.z) - return false; - if (item != null ? !item.equals(isGeneric.item) : isGeneric.item != null) - return false; - - return true; - } - } -} diff --git a/test/dorkbox/network/kryo/InputOutputByteBufTest.java b/test/dorkbox/network/kryo/InputOutputByteBufTest.java new file mode 100644 index 00000000..397a43cd --- /dev/null +++ b/test/dorkbox/network/kryo/InputOutputByteBufTest.java @@ -0,0 +1,1014 @@ +/* Copyright (c) 2008-2018, Nathan Sweet + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the distribution. + * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +package dorkbox.network.kryo; + +import static dorkbox.network.kryo.KryoAssert.assertDoubleEquals; +import static dorkbox.network.kryo.KryoAssert.assertFloatEquals; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Random; + +import org.junit.Test; + +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.Registration; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; + +import dorkbox.network.pipeline.ByteBufInput; +import dorkbox.network.pipeline.ByteBufOutput; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.buffer.Unpooled; + +/** @author Nathan Sweet */ +@SuppressWarnings("all") +public class InputOutputByteBufTest extends KryoTestCase { + @Test + public void testByteBufferInputEnd () { + Input in = new Input(new ByteArrayInputStream(new byte[] {123, 0, 0, 0})); + assertFalse(in.end()); + in.setPosition(4); + assertTrue(in.end()); + } + + @Test + public void testOutputStream () throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + Output output = new Output(buffer, 2); + output.writeBytes(new byte[] {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}); + output.writeBytes(new byte[] {31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}); + output.writeBytes(new byte[] {51, 52, 53, 54, 55, 56, 57, 58}); + output.writeBytes(new byte[] {61, 62, 63, 64, 65}); + output.flush(); + + assertArrayEquals(new byte[] { // + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, // + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, // + 51, 52, 53, 54, 55, 56, 57, 58, // + 61, 62, 63, 64, 65}, buffer.toByteArray()); + } + + @Test + public void testInputStream () throws IOException { + byte[] bytes = new byte[] { // + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, // + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, // + 51, 52, 53, 54, 55, 56, 57, 58, // + 61, 62, 63, 64, 65}; + ByteArrayInputStream buffer = new ByteArrayInputStream(bytes); + Input input = new Input(buffer, 2); + byte[] temp = new byte[1024]; + int count = input.read(temp, 512, bytes.length); + assertEquals(bytes.length, count); + byte[] temp2 = new byte[count]; + System.arraycopy(temp, 512, temp2, 0, count); + assertArrayEquals(bytes, temp2); + + input = new Input(bytes); + count = input.read(temp, 512, 512); + assertEquals(bytes.length, count); + temp2 = new byte[count]; + System.arraycopy(temp, 512, temp2, 0, count); + assertArrayEquals(bytes, temp2); + } + + @Test + public void testWriteBytes () throws IOException { + Output buffer = new Output(512); + buffer.writeBytes(new byte[] {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}); + buffer.writeBytes(new byte[] {31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}); + buffer.writeByte(51); + buffer.writeBytes(new byte[] {52, 53, 54, 55, 56, 57, 58}); + buffer.writeByte(61); + buffer.writeByte(62); + buffer.writeByte(63); + buffer.writeByte(64); + buffer.writeByte(65); + buffer.flush(); + + assertArrayEquals(new byte[] { // + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, // + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, // + 51, 52, 53, 54, 55, 56, 57, 58, // + 61, 62, 63, 64, 65}, buffer.toBytes()); + } + + @Test + public void testStrings () throws IOException { + runStringTest(new Output(4096)); + runStringTest(new Output(897)); + runStringTest(new Output(new ByteArrayOutputStream())); + + Output write = new Output(21); + String value = "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u1234"; + write.writeString(value); + Input read = new Input(write.toBytes()); + assertEquals(value, read.readString()); + + write.reset(); + write.writeString(null); + read = new Input(write.toBytes()); + assertNull(read.readString()); + + for (int i = 0; i <= 258; i++) + runStringTest(i); + runStringTest(1); + runStringTest(2); + runStringTest(127); + runStringTest(256); + runStringTest(1024 * 1023); + runStringTest(1024 * 1024); + runStringTest(1024 * 1025); + runStringTest(1024 * 1026); + runStringTest(1024 * 1024 * 2); + } + + @Test + public void testGrowingBufferForAscii () { + // Initial size of 0. + final Output output = new Output(0, 1024); + // Check that it is possible to write an ASCII string into the output buffer. + output.writeString("node/read"); + assertEquals("node/read", new Input(output.getBuffer(), 0, output.position()).readString()); + } + + private void runStringTest (int length) throws IOException { + Output write = new Output(1024, -1); + StringBuilder buffer = new StringBuilder(); + for (int i = 0; i < length; i++) + buffer.append((char)i); + + String value = buffer.toString(); + write.writeString(value); + write.writeString(value); + Input read = new Input(write.toBytes()); + assertEquals(value, read.readString()); + assertEquals(value, read.readStringBuilder().toString()); + + write.reset(); + write.writeString(buffer.toString()); + write.writeString(buffer.toString()); + read = new Input(write.toBytes()); + assertEquals(value, read.readStringBuilder().toString()); + assertEquals(value, read.readString()); + + if (length <= 127) { + write.reset(); + write.writeAscii(value); + write.writeAscii(value); + read = new Input(write.toBytes()); + assertEquals(value, read.readStringBuilder().toString()); + assertEquals(value, read.readString()); + } + } + + private void runStringTest (Output write) throws IOException { + String value1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\rabcdefghijklmnopqrstuvwxyz\n1234567890\t\"!`?'.,;:()[]{}<>|/@\\^$-%+=#_&~*"; + String value2 = "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u1234"; + + write.writeString(""); + write.writeString("1"); + write.writeString("22"); + write.writeString("uno"); + write.writeString("dos"); + write.writeString("tres"); + write.writeString(null); + write.writeString(value1); + write.writeString(value2); + for (int i = 0; i < 127; i++) + write.writeString(String.valueOf((char)i)); + for (int i = 0; i < 127; i++) + write.writeString(String.valueOf((char)i) + "abc"); + + Input read = new Input(write.toBytes()); + assertEquals("", read.readString()); + assertEquals("1", read.readString()); + assertEquals("22", read.readString()); + assertEquals("uno", read.readString()); + assertEquals("dos", read.readString()); + assertEquals("tres", read.readString()); + assertNull(read.readString()); + assertEquals(value1, read.readString()); + assertEquals(value2, read.readString()); + for (int i = 0; i < 127; i++) + assertEquals(String.valueOf((char)i), read.readString()); + for (int i = 0; i < 127; i++) + assertEquals(String.valueOf((char)i) + "abc", read.readString()); + + read.reset(); + assertEquals("", read.readStringBuilder().toString()); + assertEquals("1", read.readStringBuilder().toString()); + assertEquals("22", read.readStringBuilder().toString()); + assertEquals("uno", read.readStringBuilder().toString()); + assertEquals("dos", read.readStringBuilder().toString()); + assertEquals("tres", read.readStringBuilder().toString()); + assertNull(read.readStringBuilder()); + assertEquals(value1, read.readStringBuilder().toString()); + assertEquals(value2, read.readStringBuilder().toString()); + for (int i = 0; i < 127; i++) + assertEquals(String.valueOf((char)i), read.readStringBuilder().toString()); + for (int i = 0; i < 127; i++) + assertEquals(String.valueOf((char)i) + "abc", read.readStringBuilder().toString()); + } + + @Test + public void testCanReadInt () throws IOException { + Output write = new Output(new ByteArrayOutputStream()); + + Input read = new Input(write.toBytes()); + assertFalse(read.canReadVarInt()); + + write.writeVarInt(400, true); + + read = new Input(write.toBytes()); + assertTrue(read.canReadVarInt()); + read.setLimit(read.limit() - 1); + assertFalse(read.canReadVarInt()); + } + + @Test + public void testVarIntFlagOutput () throws IOException { + Output output = new Output(4096); + Input input = new Input(output.getBuffer()); + runVarIntFlagsTest(output, input); + } + + @Test + public void testVarIntFlagByteBufferOutput () throws IOException { + ByteBufOutput output = new ByteBufOutput(4096); + ByteBufInput input = new ByteBufInput(output.getByteBuf()); + runVarIntFlagsTest(output, input); + } + + private void runVarIntFlagsTest (Output output, Input input) throws IOException { + assertEquals(1, output.writeVarIntFlag(true, 63, true)); + assertEquals(2, output.writeVarIntFlag(true, 64, true)); + + assertEquals(1, output.writeVarIntFlag(false, 63, true)); + assertEquals(2, output.writeVarIntFlag(false, 64, true)); + + assertEquals(1, output.writeVarIntFlag(true, 31, false)); + assertEquals(2, output.writeVarIntFlag(true, 32, false)); + + assertEquals(1, output.writeVarIntFlag(false, 31, false)); + assertEquals(2, output.writeVarIntFlag(false, 32, false)); + + input.setPosition(0); + input.setLimit(output.position()); + assertTrue(input.readVarIntFlag()); + assertEquals(63, input.readVarIntFlag(true)); + assertTrue(input.readVarIntFlag()); + assertEquals(64, input.readVarIntFlag(true)); + + assertFalse(input.readVarIntFlag()); + assertEquals(63, input.readVarIntFlag(true)); + assertFalse(input.readVarIntFlag()); + assertEquals(64, input.readVarIntFlag(true)); + + assertTrue(input.readVarIntFlag()); + assertEquals(31, input.readVarIntFlag(false)); + assertTrue(input.readVarIntFlag()); + assertEquals(32, input.readVarIntFlag(false)); + + assertFalse(input.readVarIntFlag()); + assertEquals(31, input.readVarIntFlag(false)); + assertFalse(input.readVarIntFlag()); + assertEquals(32, input.readVarIntFlag(false)); + } + + @Test + public void testInts () throws IOException { + runIntTest(new Output(4096)); + runIntTest(new Output(new ByteArrayOutputStream())); + } + + private void runIntTest (Output write) throws IOException { + write.writeInt(0); + write.writeInt(63); + write.writeInt(64); + write.writeInt(127); + write.writeInt(128); + write.writeInt(8192); + write.writeInt(16384); + write.writeInt(2097151); + write.writeInt(1048575); + write.writeInt(134217727); + write.writeInt(268435455); + write.writeInt(134217728); + write.writeInt(268435456); + write.writeInt(-2097151); + write.writeInt(-1048575); + write.writeInt(-134217727); + write.writeInt(-268435455); + write.writeInt(-134217728); + write.writeInt(-268435456); + assertEquals(1, write.writeVarInt(0, true)); + assertEquals(1, write.writeVarInt(0, false)); + assertEquals(1, write.writeVarInt(63, true)); + assertEquals(1, write.writeVarInt(63, false)); + assertEquals(1, write.writeVarInt(64, true)); + assertEquals(2, write.writeVarInt(64, false)); + assertEquals(1, write.writeVarInt(127, true)); + assertEquals(2, write.writeVarInt(127, false)); + assertEquals(2, write.writeVarInt(128, true)); + assertEquals(2, write.writeVarInt(128, false)); + assertEquals(2, write.writeVarInt(8191, true)); + assertEquals(2, write.writeVarInt(8191, false)); + assertEquals(2, write.writeVarInt(8192, true)); + assertEquals(3, write.writeVarInt(8192, false)); + assertEquals(2, write.writeVarInt(16383, true)); + assertEquals(3, write.writeVarInt(16383, false)); + assertEquals(3, write.writeVarInt(16384, true)); + assertEquals(3, write.writeVarInt(16384, false)); + assertEquals(3, write.writeVarInt(2097151, true)); + assertEquals(4, write.writeVarInt(2097151, false)); + assertEquals(3, write.writeVarInt(1048575, true)); + assertEquals(3, write.writeVarInt(1048575, false)); + assertEquals(4, write.writeVarInt(134217727, true)); + assertEquals(4, write.writeVarInt(134217727, false)); + assertEquals(4, write.writeVarInt(268435455, true)); + assertEquals(5, write.writeVarInt(268435455, false)); + assertEquals(4, write.writeVarInt(134217728, true)); + assertEquals(5, write.writeVarInt(134217728, false)); + assertEquals(5, write.writeVarInt(268435456, true)); + assertEquals(5, write.writeVarInt(268435456, false)); + assertEquals(1, write.writeVarInt(-64, false)); + assertEquals(5, write.writeVarInt(-64, true)); + assertEquals(2, write.writeVarInt(-65, false)); + assertEquals(5, write.writeVarInt(-65, true)); + assertEquals(2, write.writeVarInt(-8192, false)); + assertEquals(5, write.writeVarInt(-8192, true)); + assertEquals(3, write.writeVarInt(-1048576, false)); + assertEquals(5, write.writeVarInt(-1048576, true)); + assertEquals(4, write.writeVarInt(-134217728, false)); + assertEquals(5, write.writeVarInt(-134217728, true)); + assertEquals(5, write.writeVarInt(-134217729, false)); + assertEquals(5, write.writeVarInt(-134217729, true)); + assertEquals(5, write.writeVarInt(1000000000, false)); + assertEquals(5, write.writeVarInt(1000000000, true)); + assertEquals(5, write.writeVarInt(Integer.MAX_VALUE - 1, false)); + assertEquals(5, write.writeVarInt(Integer.MAX_VALUE - 1, true)); + assertEquals(5, write.writeVarInt(Integer.MAX_VALUE, false)); + assertEquals(5, write.writeVarInt(Integer.MAX_VALUE, true)); + + Input read = new Input(write.toBytes()); + assertEquals(0, read.readInt()); + assertEquals(63, read.readInt()); + assertEquals(64, read.readInt()); + assertEquals(127, read.readInt()); + assertEquals(128, read.readInt()); + assertEquals(8192, read.readInt()); + assertEquals(16384, read.readInt()); + assertEquals(2097151, read.readInt()); + assertEquals(1048575, read.readInt()); + assertEquals(134217727, read.readInt()); + assertEquals(268435455, read.readInt()); + assertEquals(134217728, read.readInt()); + assertEquals(268435456, read.readInt()); + assertEquals(-2097151, read.readInt()); + assertEquals(-1048575, read.readInt()); + assertEquals(-134217727, read.readInt()); + assertEquals(-268435455, read.readInt()); + assertEquals(-134217728, read.readInt()); + assertEquals(-268435456, read.readInt()); + assertTrue(read.canReadVarInt()); + assertTrue(read.canReadVarInt()); + assertTrue(read.canReadVarInt()); + assertEquals(0, read.readVarInt(true)); + assertEquals(0, read.readVarInt(false)); + assertEquals(63, read.readVarInt(true)); + assertEquals(63, read.readVarInt(false)); + assertEquals(64, read.readVarInt(true)); + assertEquals(64, read.readVarInt(false)); + assertEquals(127, read.readVarInt(true)); + assertEquals(127, read.readVarInt(false)); + assertEquals(128, read.readVarInt(true)); + assertEquals(128, read.readVarInt(false)); + assertEquals(8191, read.readVarInt(true)); + assertEquals(8191, read.readVarInt(false)); + assertEquals(8192, read.readVarInt(true)); + assertEquals(8192, read.readVarInt(false)); + assertEquals(16383, read.readVarInt(true)); + assertEquals(16383, read.readVarInt(false)); + assertEquals(16384, read.readVarInt(true)); + assertEquals(16384, read.readVarInt(false)); + assertEquals(2097151, read.readVarInt(true)); + assertEquals(2097151, read.readVarInt(false)); + assertEquals(1048575, read.readVarInt(true)); + assertEquals(1048575, read.readVarInt(false)); + assertEquals(134217727, read.readVarInt(true)); + assertEquals(134217727, read.readVarInt(false)); + assertEquals(268435455, read.readVarInt(true)); + assertEquals(268435455, read.readVarInt(false)); + assertEquals(134217728, read.readVarInt(true)); + assertEquals(134217728, read.readVarInt(false)); + assertEquals(268435456, read.readVarInt(true)); + assertEquals(268435456, read.readVarInt(false)); + assertEquals(-64, read.readVarInt(false)); + assertEquals(-64, read.readVarInt(true)); + assertEquals(-65, read.readVarInt(false)); + assertEquals(-65, read.readVarInt(true)); + assertEquals(-8192, read.readVarInt(false)); + assertEquals(-8192, read.readVarInt(true)); + assertEquals(-1048576, read.readVarInt(false)); + assertEquals(-1048576, read.readVarInt(true)); + assertEquals(-134217728, read.readVarInt(false)); + assertEquals(-134217728, read.readVarInt(true)); + assertEquals(-134217729, read.readVarInt(false)); + assertEquals(-134217729, read.readVarInt(true)); + assertEquals(1000000000, read.readVarInt(false)); + assertEquals(1000000000, read.readVarInt(true)); + assertEquals(Integer.MAX_VALUE - 1, read.readVarInt(false)); + assertEquals(Integer.MAX_VALUE - 1, read.readVarInt(true)); + assertEquals(Integer.MAX_VALUE, read.readVarInt(false)); + assertEquals(Integer.MAX_VALUE, read.readVarInt(true)); + assertFalse(read.canReadVarInt()); + + Random random = new Random(); + for (int i = 0; i < 10000; i++) { + int value = random.nextInt(); + write.reset(); + write.writeInt(value); + write.writeVarInt(value, true); + write.writeVarInt(value, false); + + read.setBuffer(write.toBytes()); + assertEquals(value, read.readInt()); + assertEquals(value, read.readVarInt(true)); + assertEquals(value, read.readVarInt(false)); + } + } + + @Test + public void testLongs () throws IOException { + runLongTest(new Output(4096)); + runLongTest(new Output(new ByteArrayOutputStream())); + } + + private void runLongTest (Output write) throws IOException { + write.writeLong(0); + write.writeLong(63); + write.writeLong(64); + write.writeLong(127); + write.writeLong(128); + write.writeLong(8192); + write.writeLong(16384); + write.writeLong(2097151); + write.writeLong(1048575); + write.writeLong(134217727); + write.writeLong(268435455); + write.writeLong(134217728); + write.writeLong(268435456); + write.writeLong(-2097151); + write.writeLong(-1048575); + write.writeLong(-134217727); + write.writeLong(-268435455); + write.writeLong(-134217728); + write.writeLong(-268435456); + assertEquals(1, write.writeVarLong(0, true)); + assertEquals(1, write.writeVarLong(0, false)); + assertEquals(1, write.writeVarLong(63, true)); + assertEquals(1, write.writeVarLong(63, false)); + assertEquals(1, write.writeVarLong(64, true)); + assertEquals(2, write.writeVarLong(64, false)); + assertEquals(1, write.writeVarLong(127, true)); + assertEquals(2, write.writeVarLong(127, false)); + assertEquals(2, write.writeVarLong(128, true)); + assertEquals(2, write.writeVarLong(128, false)); + assertEquals(2, write.writeVarLong(8191, true)); + assertEquals(2, write.writeVarLong(8191, false)); + assertEquals(2, write.writeVarLong(8192, true)); + assertEquals(3, write.writeVarLong(8192, false)); + assertEquals(2, write.writeVarLong(16383, true)); + assertEquals(3, write.writeVarLong(16383, false)); + assertEquals(3, write.writeVarLong(16384, true)); + assertEquals(3, write.writeVarLong(16384, false)); + assertEquals(3, write.writeVarLong(2097151, true)); + assertEquals(4, write.writeVarLong(2097151, false)); + assertEquals(3, write.writeVarLong(1048575, true)); + assertEquals(3, write.writeVarLong(1048575, false)); + assertEquals(4, write.writeVarLong(134217727, true)); + assertEquals(4, write.writeVarLong(134217727, false)); + assertEquals(4, write.writeVarLong(268435455L, true)); + assertEquals(5, write.writeVarLong(268435455L, false)); + assertEquals(4, write.writeVarLong(134217728L, true)); + assertEquals(5, write.writeVarLong(134217728L, false)); + assertEquals(5, write.writeVarLong(268435456L, true)); + assertEquals(5, write.writeVarLong(268435456L, false)); + assertEquals(1, write.writeVarLong(-64, false)); + assertEquals(9, write.writeVarLong(-64, true)); + assertEquals(2, write.writeVarLong(-65, false)); + assertEquals(9, write.writeVarLong(-65, true)); + assertEquals(2, write.writeVarLong(-8192, false)); + assertEquals(9, write.writeVarLong(-8192, true)); + assertEquals(3, write.writeVarLong(-1048576, false)); + assertEquals(9, write.writeVarLong(-1048576, true)); + assertEquals(4, write.writeVarLong(-134217728, false)); + assertEquals(9, write.writeVarLong(-134217728, true)); + assertEquals(5, write.writeVarLong(-134217729, false)); + assertEquals(9, write.writeVarLong(-134217729, true)); + + Input read = new Input(write.toBytes()); + assertEquals(0, read.readLong()); + assertEquals(63, read.readLong()); + assertEquals(64, read.readLong()); + assertEquals(127, read.readLong()); + assertEquals(128, read.readLong()); + assertEquals(8192, read.readLong()); + assertEquals(16384, read.readLong()); + assertEquals(2097151, read.readLong()); + assertEquals(1048575, read.readLong()); + assertEquals(134217727, read.readLong()); + assertEquals(268435455, read.readLong()); + assertEquals(134217728, read.readLong()); + assertEquals(268435456, read.readLong()); + assertEquals(-2097151, read.readLong()); + assertEquals(-1048575, read.readLong()); + assertEquals(-134217727, read.readLong()); + assertEquals(-268435455, read.readLong()); + assertEquals(-134217728, read.readLong()); + assertEquals(-268435456, read.readLong()); + assertEquals(0, read.readVarLong(true)); + assertEquals(0, read.readVarLong(false)); + assertEquals(63, read.readVarLong(true)); + assertEquals(63, read.readVarLong(false)); + assertEquals(64, read.readVarLong(true)); + assertEquals(64, read.readVarLong(false)); + assertEquals(127, read.readVarLong(true)); + assertEquals(127, read.readVarLong(false)); + assertEquals(128, read.readVarLong(true)); + assertEquals(128, read.readVarLong(false)); + assertEquals(8191, read.readVarLong(true)); + assertEquals(8191, read.readVarLong(false)); + assertEquals(8192, read.readVarLong(true)); + assertEquals(8192, read.readVarLong(false)); + assertEquals(16383, read.readVarLong(true)); + assertEquals(16383, read.readVarLong(false)); + assertEquals(16384, read.readVarLong(true)); + assertEquals(16384, read.readVarLong(false)); + assertEquals(2097151, read.readVarLong(true)); + assertEquals(2097151, read.readVarLong(false)); + assertEquals(1048575, read.readVarLong(true)); + assertEquals(1048575, read.readVarLong(false)); + assertEquals(134217727, read.readVarLong(true)); + assertEquals(134217727, read.readVarLong(false)); + assertEquals(268435455, read.readVarLong(true)); + assertEquals(268435455, read.readVarLong(false)); + assertEquals(134217728, read.readVarLong(true)); + assertEquals(134217728, read.readVarLong(false)); + assertEquals(268435456, read.readVarLong(true)); + assertEquals(268435456, read.readVarLong(false)); + assertEquals(-64, read.readVarLong(false)); + assertEquals(-64, read.readVarLong(true)); + assertEquals(-65, read.readVarLong(false)); + assertEquals(-65, read.readVarLong(true)); + assertEquals(-8192, read.readVarLong(false)); + assertEquals(-8192, read.readVarLong(true)); + assertEquals(-1048576, read.readVarLong(false)); + assertEquals(-1048576, read.readVarLong(true)); + assertEquals(-134217728, read.readVarLong(false)); + assertEquals(-134217728, read.readVarLong(true)); + assertEquals(-134217729, read.readVarLong(false)); + assertEquals(-134217729, read.readVarLong(true)); + + Random random = new Random(); + for (int i = 0; i < 10000; i++) { + long value = random.nextLong(); + write.reset(); + write.writeLong(value); + write.writeVarLong(value, true); + write.writeVarLong(value, false); + + read.setBuffer(write.toBytes()); + assertEquals(value, read.readLong()); + assertEquals(value, read.readVarLong(true)); + assertEquals(value, read.readVarLong(false)); + } + } + + @Test + public void testShorts () throws IOException { + runShortTest(new Output(4096)); + runShortTest(new Output(new ByteArrayOutputStream())); + } + + private void runShortTest (Output write) throws IOException { + write.writeShort(0); + write.writeShort(63); + write.writeShort(64); + write.writeShort(127); + write.writeShort(128); + write.writeShort(8192); + write.writeShort(16384); + write.writeShort(32767); + write.writeShort(-63); + write.writeShort(-64); + write.writeShort(-127); + write.writeShort(-128); + write.writeShort(-8192); + write.writeShort(-16384); + write.writeShort(-32768); + + Input read = new Input(write.toBytes()); + assertEquals(0, read.readShort()); + assertEquals(63, read.readShort()); + assertEquals(64, read.readShort()); + assertEquals(127, read.readShort()); + assertEquals(128, read.readShort()); + assertEquals(8192, read.readShort()); + assertEquals(16384, read.readShort()); + assertEquals(32767, read.readShort()); + assertEquals(-63, read.readShort()); + assertEquals(-64, read.readShort()); + assertEquals(-127, read.readShort()); + assertEquals(-128, read.readShort()); + assertEquals(-8192, read.readShort()); + assertEquals(-16384, read.readShort()); + assertEquals(-32768, read.readShort()); + } + + @Test + public void testFloats () throws IOException { + runFloatTest(new Output(4096)); + runFloatTest(new Output(new ByteArrayOutputStream())); + } + + private void runFloatTest (Output write) throws IOException { + write.writeFloat(0); + write.writeFloat(63); + write.writeFloat(64); + write.writeFloat(127); + write.writeFloat(128); + write.writeFloat(8192); + write.writeFloat(16384); + write.writeFloat(32767); + write.writeFloat(-63); + write.writeFloat(-64); + write.writeFloat(-127); + write.writeFloat(-128); + write.writeFloat(-8192); + write.writeFloat(-16384); + write.writeFloat(-32768); + assertEquals(1, write.writeVarFloat(0, 1000, true)); + assertEquals(1, write.writeVarFloat(0, 1000, false)); + assertEquals(3, write.writeVarFloat(63, 1000, true)); + assertEquals(3, write.writeVarFloat(63, 1000, false)); + assertEquals(3, write.writeVarFloat(64, 1000, true)); + assertEquals(3, write.writeVarFloat(64, 1000, false)); + assertEquals(3, write.writeVarFloat(127, 1000, true)); + assertEquals(3, write.writeVarFloat(127, 1000, false)); + assertEquals(3, write.writeVarFloat(128, 1000, true)); + assertEquals(3, write.writeVarFloat(128, 1000, false)); + assertEquals(4, write.writeVarFloat(8191, 1000, true)); + assertEquals(4, write.writeVarFloat(8191, 1000, false)); + assertEquals(4, write.writeVarFloat(8192, 1000, true)); + assertEquals(4, write.writeVarFloat(8192, 1000, false)); + assertEquals(4, write.writeVarFloat(16383, 1000, true)); + assertEquals(4, write.writeVarFloat(16383, 1000, false)); + assertEquals(4, write.writeVarFloat(16384, 1000, true)); + assertEquals(4, write.writeVarFloat(16384, 1000, false)); + assertEquals(4, write.writeVarFloat(32767, 1000, true)); + assertEquals(4, write.writeVarFloat(32767, 1000, false)); + assertEquals(3, write.writeVarFloat(-64, 1000, false)); + assertEquals(5, write.writeVarFloat(-64, 1000, true)); + assertEquals(3, write.writeVarFloat(-65, 1000, false)); + assertEquals(5, write.writeVarFloat(-65, 1000, true)); + assertEquals(4, write.writeVarFloat(-8192, 1000, false)); + assertEquals(5, write.writeVarFloat(-8192, 1000, true)); + + Input read = new Input(write.toBytes()); + assertFloatEquals(read.readFloat(), 0f); + assertFloatEquals(read.readFloat(), 63f); + assertFloatEquals(read.readFloat(), 64f); + assertFloatEquals(read.readFloat(), 127f); + assertFloatEquals(read.readFloat(), 128f); + assertFloatEquals(read.readFloat(), 8192f); + assertFloatEquals(read.readFloat(), 16384f); + assertFloatEquals(read.readFloat(), 32767f); + assertFloatEquals(read.readFloat(), -63f); + assertFloatEquals(read.readFloat(), -64f); + assertFloatEquals(read.readFloat(), -127f); + assertFloatEquals(read.readFloat(), -128f); + assertFloatEquals(read.readFloat(), -8192f); + assertFloatEquals(read.readFloat(), -16384f); + assertFloatEquals(read.readFloat(), -32768f); + assertFloatEquals(read.readVarFloat(1000, true), 0f); + assertFloatEquals(read.readVarFloat(1000, false), 0f); + assertFloatEquals(read.readVarFloat(1000, true), 63f); + assertFloatEquals(read.readVarFloat(1000, false), 63f); + assertFloatEquals(read.readVarFloat(1000, true), 64f); + assertFloatEquals(read.readVarFloat(1000, false), 64f); + assertFloatEquals(read.readVarFloat(1000, true), 127f); + assertFloatEquals(read.readVarFloat(1000, false), 127f); + assertFloatEquals(read.readVarFloat(1000, true), 128f); + assertFloatEquals(read.readVarFloat(1000, false), 128f); + assertFloatEquals(read.readVarFloat(1000, true), 8191f); + assertFloatEquals(read.readVarFloat(1000, false), 8191f); + assertFloatEquals(read.readVarFloat(1000, true), 8192f); + assertFloatEquals(read.readVarFloat(1000, false), 8192f); + assertFloatEquals(read.readVarFloat(1000, true), 16383f); + assertFloatEquals(read.readVarFloat(1000, false), 16383f); + assertFloatEquals(read.readVarFloat(1000, true), 16384f); + assertFloatEquals(read.readVarFloat(1000, false), 16384f); + assertFloatEquals(read.readVarFloat(1000, true), 32767f); + assertFloatEquals(read.readVarFloat(1000, false), 32767f); + assertFloatEquals(read.readVarFloat(1000, false), -64f); + assertFloatEquals(read.readVarFloat(1000, true), -64f); + assertFloatEquals(read.readVarFloat(1000, false), -65f); + assertFloatEquals(read.readVarFloat(1000, true), -65f); + assertFloatEquals(read.readVarFloat(1000, false), -8192f); + assertFloatEquals(read.readVarFloat(1000, true), -8192f); + } + + @Test + public void testDoubles () throws IOException { + runDoubleTest(new Output(4096)); + runDoubleTest(new Output(new ByteArrayOutputStream())); + } + + private void runDoubleTest (Output write) throws IOException { + write.writeDouble(0); + write.writeDouble(63); + write.writeDouble(64); + write.writeDouble(127); + write.writeDouble(128); + write.writeDouble(8192); + write.writeDouble(16384); + write.writeDouble(32767); + write.writeDouble(-63); + write.writeDouble(-64); + write.writeDouble(-127); + write.writeDouble(-128); + write.writeDouble(-8192); + write.writeDouble(-16384); + write.writeDouble(-32768); + assertEquals(1, write.writeVarDouble(0, 1000, true)); + assertEquals(1, write.writeVarDouble(0, 1000, false)); + assertEquals(3, write.writeVarDouble(63, 1000, true)); + assertEquals(3, write.writeVarDouble(63, 1000, false)); + assertEquals(3, write.writeVarDouble(64, 1000, true)); + assertEquals(3, write.writeVarDouble(64, 1000, false)); + assertEquals(3, write.writeVarDouble(127, 1000, true)); + assertEquals(3, write.writeVarDouble(127, 1000, false)); + assertEquals(3, write.writeVarDouble(128, 1000, true)); + assertEquals(3, write.writeVarDouble(128, 1000, false)); + assertEquals(4, write.writeVarDouble(8191, 1000, true)); + assertEquals(4, write.writeVarDouble(8191, 1000, false)); + assertEquals(4, write.writeVarDouble(8192, 1000, true)); + assertEquals(4, write.writeVarDouble(8192, 1000, false)); + assertEquals(4, write.writeVarDouble(16383, 1000, true)); + assertEquals(4, write.writeVarDouble(16383, 1000, false)); + assertEquals(4, write.writeVarDouble(16384, 1000, true)); + assertEquals(4, write.writeVarDouble(16384, 1000, false)); + assertEquals(4, write.writeVarDouble(32767, 1000, true)); + assertEquals(4, write.writeVarDouble(32767, 1000, false)); + assertEquals(3, write.writeVarDouble(-64, 1000, false)); + assertEquals(9, write.writeVarDouble(-64, 1000, true)); + assertEquals(3, write.writeVarDouble(-65, 1000, false)); + assertEquals(9, write.writeVarDouble(-65, 1000, true)); + assertEquals(4, write.writeVarDouble(-8192, 1000, false)); + assertEquals(9, write.writeVarDouble(-8192, 1000, true)); + write.writeDouble(1.23456d); + + Input read = new Input(write.toBytes()); + assertDoubleEquals(read.readDouble(), 0d); + assertDoubleEquals(read.readDouble(), 63d); + assertDoubleEquals(read.readDouble(), 64d); + assertDoubleEquals(read.readDouble(), 127d); + assertDoubleEquals(read.readDouble(), 128d); + assertDoubleEquals(read.readDouble(), 8192d); + assertDoubleEquals(read.readDouble(), 16384d); + assertDoubleEquals(read.readDouble(), 32767d); + assertDoubleEquals(read.readDouble(), -63d); + assertDoubleEquals(read.readDouble(), -64d); + assertDoubleEquals(read.readDouble(), -127d); + assertDoubleEquals(read.readDouble(), -128d); + assertDoubleEquals(read.readDouble(), -8192d); + assertDoubleEquals(read.readDouble(), -16384d); + assertDoubleEquals(read.readDouble(), -32768d); + assertDoubleEquals(read.readVarDouble(1000, true), 0d); + assertDoubleEquals(read.readVarDouble(1000, false), 0d); + assertDoubleEquals(read.readVarDouble(1000, true), 63d); + assertDoubleEquals(read.readVarDouble(1000, false), 63d); + assertDoubleEquals(read.readVarDouble(1000, true), 64d); + assertDoubleEquals(read.readVarDouble(1000, false), 64d); + assertDoubleEquals(read.readVarDouble(1000, true), 127d); + assertDoubleEquals(read.readVarDouble(1000, false), 127d); + assertDoubleEquals(read.readVarDouble(1000, true), 128d); + assertDoubleEquals(read.readVarDouble(1000, false), 128d); + assertDoubleEquals(read.readVarDouble(1000, true), 8191d); + assertDoubleEquals(read.readVarDouble(1000, false), 8191d); + assertDoubleEquals(read.readVarDouble(1000, true), 8192d); + assertDoubleEquals(read.readVarDouble(1000, false), 8192d); + assertDoubleEquals(read.readVarDouble(1000, true), 16383d); + assertDoubleEquals(read.readVarDouble(1000, false), 16383d); + assertDoubleEquals(read.readVarDouble(1000, true), 16384d); + assertDoubleEquals(read.readVarDouble(1000, false), 16384d); + assertDoubleEquals(read.readVarDouble(1000, true), 32767d); + assertDoubleEquals(read.readVarDouble(1000, false), 32767d); + assertDoubleEquals(read.readVarDouble(1000, false), -64d); + assertDoubleEquals(read.readVarDouble(1000, true), -64d); + assertDoubleEquals(read.readVarDouble(1000, false), -65d); + assertDoubleEquals(read.readVarDouble(1000, true), -65d); + assertDoubleEquals(read.readVarDouble(1000, false), -8192d); + assertDoubleEquals(read.readVarDouble(1000, true), -8192d); + assertDoubleEquals(1.23456d, read.readDouble()); + } + + @Test + public void testBooleans () throws IOException { + runBooleanTest(new Output(4096)); + runBooleanTest(new Output(new ByteArrayOutputStream())); + } + + private void runBooleanTest (Output write) throws IOException { + for (int i = 0; i < 100; i++) { + write.writeBoolean(true); + write.writeBoolean(false); + } + + Input read = new Input(write.toBytes()); + for (int i = 0; i < 100; i++) { + assertTrue(read.readBoolean()); + assertFalse(read.readBoolean()); + } + } + + @Test + public void testChars () throws IOException { + runCharTest(new Output(4096)); + runCharTest(new Output(new ByteArrayOutputStream())); + } + + private void runCharTest (Output write) throws IOException { + write.writeChar((char)0); + write.writeChar((char)63); + write.writeChar((char)64); + write.writeChar((char)127); + write.writeChar((char)128); + write.writeChar((char)8192); + write.writeChar((char)16384); + write.writeChar((char)32767); + write.writeChar((char)65535); + + Input read = new Input(write.toBytes()); + assertEquals(0, read.readChar()); + assertEquals(63, read.readChar()); + assertEquals(64, read.readChar()); + assertEquals(127, read.readChar()); + assertEquals(128, read.readChar()); + assertEquals(8192, read.readChar()); + assertEquals(16384, read.readChar()); + assertEquals(32767, read.readChar()); + assertEquals(65535, read.readChar()); + } + + @Test + public void testInputWithOffset () throws Exception { + final byte[] buf = new byte[30]; + final Input in = new Input(buf, 10, 10); + assertEquals(10, in.available()); + } + + @Test + public void testSmallBuffers () throws Exception { + ByteBuf buf = Unpooled.buffer(1024); + ByteBufOutputStream byteBufferOutputStream = new ByteBufOutputStream(buf); + Output testOutput = new Output(byteBufferOutputStream); + testOutput.writeBytes(new byte[512]); + testOutput.writeBytes(new byte[512]); + testOutput.flush(); + + ByteBufInputStream testInputs = new ByteBufInputStream(buf); + Input input = new Input(testInputs, 512); + byte[] toRead = new byte[512]; + input.readBytes(toRead); + + input.readBytes(toRead); + } + + @Test + public void testVerySmallBuffers () throws Exception { + Output out1 = new Output(4, -1); + Output out2 = new ByteBufOutput(4, -1); + + for (int i = 0; i < 16; i++) { + out1.writeVarInt(92, false); + } + + for (int i = 0; i < 16; i++) { + out2.writeVarInt(92, false); + } + + assertArrayEquals(out1.toBytes(), out2.toBytes()); + } + + @Test + public void testZeroLengthOutputs () throws Exception { + Output output = new Output(0, 10000); + kryo.writeClassAndObject(output, "Test string"); + + Output byteBufferOutput = new ByteBufOutput(0, 10000); + kryo.writeClassAndObject(byteBufferOutput, "Test string"); + } + + @Test + public void testFlushRoundTrip () throws Exception { + + Kryo kryo = new Kryo(); + + String s1 = "12345"; + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + ObjectOutputStream objOutput = new ObjectOutputStream(os); + Output output = new Output(objOutput); + + kryo.writeClass(output, s1.getClass()); + kryo.writeObject(output, s1); + output.flush(); +// objOutput.flush(); // this layer wasn't flushed prior to this bugfix, add it for a workaround + + byte[] b = os.toByteArray(); + System.out.println("size: " + b.length); + + ByteArrayInputStream in = new ByteArrayInputStream(b); + ObjectInputStream objIn = new ObjectInputStream(in); + Input input = new Input(objIn); + + Registration r = kryo.readClass(input); + String s2 = (String)kryo.readObject(input, r.getType()); + + assertEquals(s1, s2); + + } + + @Test(expected = IllegalArgumentException.class) + public void testNewOutputMaxBufferSizeLessThanBufferSize () { + int bufferSize = 2; + int maxBufferSize = 1; + + new Output(bufferSize, maxBufferSize); + } + + @Test(expected = IllegalArgumentException.class) + public void testSetOutputMaxBufferSizeLessThanBufferSize () { + int bufferSize = 2; + int maxBufferSize = 1; + + Output output = new Output(bufferSize, bufferSize); + assertNotNull(output); + + output.setBuffer(new byte[bufferSize], maxBufferSize); + } + + @Test + public void testNewOutputMaxBufferSizeIsMinusOne () { + int bufferSize = 2; + int maxBufferSize = -1; + + Output output = new Output(bufferSize, maxBufferSize); + assertNotNull(output); + // This test should pass as long as no exception thrown + } + + @Test + public void testSetOutputMaxBufferSizeIsMinusOne () { + int bufferSize = 2; + int maxBufferSize = -1; + + Output output = new Output(bufferSize, bufferSize); + assertNotNull(output); + output.setBuffer(new byte[bufferSize], maxBufferSize); + // This test should pass as long as no exception thrown + } + +} diff --git a/test/dorkbox/network/kryo/InputOutputTest.java b/test/dorkbox/network/kryo/InputOutputTest.java deleted file mode 100644 index 14b3665c..00000000 --- a/test/dorkbox/network/kryo/InputOutputTest.java +++ /dev/null @@ -1,818 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; -import java.util.Random; - -import com.esotericsoftware.kryo.io.ByteBufferInputStream; -import com.esotericsoftware.kryo.io.ByteBufferOutputStream; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - -/** @author Nathan Sweet */ -@SuppressWarnings("resource") -public class InputOutputTest extends KryoTestCase { - public void testOutputStream () { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - Output output = new Output(buffer, 2); - output.writeBytes(new byte[] {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}); - output.writeBytes(new byte[] {31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}); - output.writeBytes(new byte[] {51, 52, 53, 54, 55, 56, 57, 58}); - output.writeBytes(new byte[] {61, 62, 63, 64, 65}); - output.flush(); - - assertEquals(new byte[] { // - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, // - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, // - 51, 52, 53, 54, 55, 56, 57, 58, // - 61, 62, 63, 64, 65}, buffer.toByteArray()); - - output.close(); - } - - public void testInputStream () { - byte[] bytes = new byte[] { // - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, // - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, // - 51, 52, 53, 54, 55, 56, 57, 58, // - 61, 62, 63, 64, 65}; - ByteArrayInputStream buffer = new ByteArrayInputStream(bytes); - Input input = new Input(buffer, 2); - byte[] temp = new byte[1024]; - int count = input.read(temp, 512, bytes.length); - assertEquals(bytes.length, count); - byte[] temp2 = new byte[count]; - System.arraycopy(temp, 512, temp2, 0, count); - assertEquals(bytes, temp2); - input.close(); - - input = new Input(bytes); - count = input.read(temp, 512, 512); - assertEquals(bytes.length, count); - temp2 = new byte[count]; - System.arraycopy(temp, 512, temp2, 0, count); - assertEquals(bytes, temp2); - - input.close(); - } - - public void testWriteBytes () { - Output buffer = new Output(512); - buffer.writeBytes(new byte[] {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}); - buffer.writeBytes(new byte[] {31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}); - buffer.writeByte(51); - buffer.writeBytes(new byte[] {52, 53, 54, 55, 56, 57, 58}); - buffer.writeByte(61); - buffer.writeByte(62); - buffer.writeByte(63); - buffer.writeByte(64); - buffer.writeByte(65); - buffer.flush(); - - assertEquals(new byte[] { // - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, // - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, // - 51, 52, 53, 54, 55, 56, 57, 58, // - 61, 62, 63, 64, 65}, buffer.toBytes()); - - buffer.close(); - } - - public void testStrings () { - runStringTest(new Output(4096)); - runStringTest(new Output(897)); - runStringTest(new Output(new ByteArrayOutputStream())); - - Output write = new Output(21); - String value = "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u1234"; - write.writeString(value); - Input read = new Input(write.toBytes()); - assertEquals(value, read.readString()); - - runStringTest(127); - runStringTest(256); - runStringTest(1024 * 1023); - runStringTest(1024 * 1024); - runStringTest(1024 * 1025); - runStringTest(1024 * 1026); - runStringTest(1024 * 1024 * 2); - - write.close(); - read.close(); - } - - public void runStringTest (int length) { - Output write = new Output(1024, -1); - StringBuilder buffer = new StringBuilder(); - for (int i = 0; i < length; i++) { - buffer.append((char)i); - } - - String value = buffer.toString(); - write.writeString(value); - write.writeString(value); - Input read = new Input(write.toBytes()); - assertEquals(value, read.readString()); - assertEquals(value, read.readStringBuilder().toString()); - read.close(); - write.close(); - write.clear(); - write.writeString(buffer); - write.writeString(buffer); - read = new Input(write.toBytes()); - assertEquals(value, read.readStringBuilder().toString()); - assertEquals(value, read.readString()); - - if (length <= 127) { - write.clear(); - write.writeAscii(value); - write.writeAscii(value); - read = new Input(write.toBytes()); - assertEquals(value, read.readStringBuilder().toString()); - assertEquals(value, read.readString()); - } - } - - public void runStringTest (Output write) { - String value1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\rabcdefghijklmnopqrstuvwxyz\n1234567890\t\"!`?'.,;:()[]{}<>|/@\\^$-%+=#_&~*"; - String value2 = "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u1234"; - - write.writeString(""); - write.writeString("1"); - write.writeString("22"); - write.writeString("uno"); - write.writeString("dos"); - write.writeString("tres"); - write.writeString(null); - write.writeString(value1); - write.writeString(value2); - for (int i = 0; i < 127; i++) { - write.writeString(String.valueOf((char)i)); - } - for (int i = 0; i < 127; i++) { - write.writeString(String.valueOf((char)i) + "abc"); - } - - Input read = new Input(write.toBytes()); - assertEquals("", read.readString()); - assertEquals("1", read.readString()); - assertEquals("22", read.readString()); - assertEquals("uno", read.readString()); - assertEquals("dos", read.readString()); - assertEquals("tres", read.readString()); - assertEquals(null, read.readString()); - assertEquals(value1, read.readString()); - assertEquals(value2, read.readString()); - for (int i = 0; i < 127; i++) { - assertEquals(String.valueOf((char)i), read.readString()); - } - for (int i = 0; i < 127; i++) { - assertEquals(String.valueOf((char)i) + "abc", read.readString()); - } - - read.rewind(); - assertEquals("", read.readStringBuilder().toString()); - assertEquals("1", read.readStringBuilder().toString()); - assertEquals("22", read.readStringBuilder().toString()); - assertEquals("uno", read.readStringBuilder().toString()); - assertEquals("dos", read.readStringBuilder().toString()); - assertEquals("tres", read.readStringBuilder().toString()); - assertEquals(null, read.readStringBuilder()); - assertEquals(value1, read.readStringBuilder().toString()); - assertEquals(value2, read.readStringBuilder().toString()); - for (int i = 0; i < 127; i++) { - assertEquals(String.valueOf((char)i), read.readStringBuilder().toString()); - } - for (int i = 0; i < 127; i++) { - assertEquals(String.valueOf((char)i) + "abc", read.readStringBuilder().toString()); - } - } - - public void testCanReadInt () { - Output write = new Output(new ByteArrayOutputStream()); - - Input read = new Input(write.toBytes()); - assertEquals(false, read.canReadInt()); - - write.writeInt(400, true); - - read = new Input(write.toBytes()); - assertEquals(true, read.canReadInt()); - read.setLimit(read.limit() - 1); - assertEquals(false, read.canReadInt()); - } - - public void testInts () { - runIntTest(new Output(4096)); - runIntTest(new Output(new ByteArrayOutputStream())); - } - - private void runIntTest (Output write) { - write.writeInt(0); - write.writeInt(63); - write.writeInt(64); - write.writeInt(127); - write.writeInt(128); - write.writeInt(8192); - write.writeInt(16384); - write.writeInt(2097151); - write.writeInt(1048575); - write.writeInt(134217727); - write.writeInt(268435455); - write.writeInt(134217728); - write.writeInt(268435456); - write.writeInt(-2097151); - write.writeInt(-1048575); - write.writeInt(-134217727); - write.writeInt(-268435455); - write.writeInt(-134217728); - write.writeInt(-268435456); - assertEquals(1, write.writeInt(0, true)); - assertEquals(1, write.writeInt(0, false)); - assertEquals(1, write.writeInt(63, true)); - assertEquals(1, write.writeInt(63, false)); - assertEquals(1, write.writeInt(64, true)); - assertEquals(2, write.writeInt(64, false)); - assertEquals(1, write.writeInt(127, true)); - assertEquals(2, write.writeInt(127, false)); - assertEquals(2, write.writeInt(128, true)); - assertEquals(2, write.writeInt(128, false)); - assertEquals(2, write.writeInt(8191, true)); - assertEquals(2, write.writeInt(8191, false)); - assertEquals(2, write.writeInt(8192, true)); - assertEquals(3, write.writeInt(8192, false)); - assertEquals(2, write.writeInt(16383, true)); - assertEquals(3, write.writeInt(16383, false)); - assertEquals(3, write.writeInt(16384, true)); - assertEquals(3, write.writeInt(16384, false)); - assertEquals(3, write.writeInt(2097151, true)); - assertEquals(4, write.writeInt(2097151, false)); - assertEquals(3, write.writeInt(1048575, true)); - assertEquals(3, write.writeInt(1048575, false)); - assertEquals(4, write.writeInt(134217727, true)); - assertEquals(4, write.writeInt(134217727, false)); - assertEquals(4, write.writeInt(268435455, true)); - assertEquals(5, write.writeInt(268435455, false)); - assertEquals(4, write.writeInt(134217728, true)); - assertEquals(5, write.writeInt(134217728, false)); - assertEquals(5, write.writeInt(268435456, true)); - assertEquals(5, write.writeInt(268435456, false)); - assertEquals(1, write.writeInt(-64, false)); - assertEquals(5, write.writeInt(-64, true)); - assertEquals(2, write.writeInt(-65, false)); - assertEquals(5, write.writeInt(-65, true)); - assertEquals(2, write.writeInt(-8192, false)); - assertEquals(5, write.writeInt(-8192, true)); - assertEquals(3, write.writeInt(-1048576, false)); - assertEquals(5, write.writeInt(-1048576, true)); - assertEquals(4, write.writeInt(-134217728, false)); - assertEquals(5, write.writeInt(-134217728, true)); - assertEquals(5, write.writeInt(-134217729, false)); - assertEquals(5, write.writeInt(-134217729, true)); - - Input read = new Input(write.toBytes()); - assertEquals(0, read.readInt()); - assertEquals(63, read.readInt()); - assertEquals(64, read.readInt()); - assertEquals(127, read.readInt()); - assertEquals(128, read.readInt()); - assertEquals(8192, read.readInt()); - assertEquals(16384, read.readInt()); - assertEquals(2097151, read.readInt()); - assertEquals(1048575, read.readInt()); - assertEquals(134217727, read.readInt()); - assertEquals(268435455, read.readInt()); - assertEquals(134217728, read.readInt()); - assertEquals(268435456, read.readInt()); - assertEquals(-2097151, read.readInt()); - assertEquals(-1048575, read.readInt()); - assertEquals(-134217727, read.readInt()); - assertEquals(-268435455, read.readInt()); - assertEquals(-134217728, read.readInt()); - assertEquals(-268435456, read.readInt()); - assertEquals(true, read.canReadInt()); - assertEquals(true, read.canReadInt()); - assertEquals(true, read.canReadInt()); - assertEquals(0, read.readInt(true)); - assertEquals(0, read.readInt(false)); - assertEquals(63, read.readInt(true)); - assertEquals(63, read.readInt(false)); - assertEquals(64, read.readInt(true)); - assertEquals(64, read.readInt(false)); - assertEquals(127, read.readInt(true)); - assertEquals(127, read.readInt(false)); - assertEquals(128, read.readInt(true)); - assertEquals(128, read.readInt(false)); - assertEquals(8191, read.readInt(true)); - assertEquals(8191, read.readInt(false)); - assertEquals(8192, read.readInt(true)); - assertEquals(8192, read.readInt(false)); - assertEquals(16383, read.readInt(true)); - assertEquals(16383, read.readInt(false)); - assertEquals(16384, read.readInt(true)); - assertEquals(16384, read.readInt(false)); - assertEquals(2097151, read.readInt(true)); - assertEquals(2097151, read.readInt(false)); - assertEquals(1048575, read.readInt(true)); - assertEquals(1048575, read.readInt(false)); - assertEquals(134217727, read.readInt(true)); - assertEquals(134217727, read.readInt(false)); - assertEquals(268435455, read.readInt(true)); - assertEquals(268435455, read.readInt(false)); - assertEquals(134217728, read.readInt(true)); - assertEquals(134217728, read.readInt(false)); - assertEquals(268435456, read.readInt(true)); - assertEquals(268435456, read.readInt(false)); - assertEquals(-64, read.readInt(false)); - assertEquals(-64, read.readInt(true)); - assertEquals(-65, read.readInt(false)); - assertEquals(-65, read.readInt(true)); - assertEquals(-8192, read.readInt(false)); - assertEquals(-8192, read.readInt(true)); - assertEquals(-1048576, read.readInt(false)); - assertEquals(-1048576, read.readInt(true)); - assertEquals(-134217728, read.readInt(false)); - assertEquals(-134217728, read.readInt(true)); - assertEquals(-134217729, read.readInt(false)); - assertEquals(-134217729, read.readInt(true)); - assertEquals(false, read.canReadInt()); - - Random random = new Random(); - for (int i = 0; i < 10000; i++) { - int value = random.nextInt(); - write.clear(); - write.writeInt(value); - write.writeInt(value, true); - write.writeInt(value, false); - read.setBuffer(write.toBytes()); - assertEquals(value, read.readInt()); - assertEquals(value, read.readInt(true)); - assertEquals(value, read.readInt(false)); - } - } - - public void testLongs () { - runLongTest(new Output(4096)); - runLongTest(new Output(new ByteArrayOutputStream())); - } - - private void runLongTest (Output write) { - write.writeLong(0); - write.writeLong(63); - write.writeLong(64); - write.writeLong(127); - write.writeLong(128); - write.writeLong(8192); - write.writeLong(16384); - write.writeLong(2097151); - write.writeLong(1048575); - write.writeLong(134217727); - write.writeLong(268435455); - write.writeLong(134217728); - write.writeLong(268435456); - write.writeLong(-2097151); - write.writeLong(-1048575); - write.writeLong(-134217727); - write.writeLong(-268435455); - write.writeLong(-134217728); - write.writeLong(-268435456); - assertEquals(1, write.writeLong(0, true)); - assertEquals(1, write.writeLong(0, false)); - assertEquals(1, write.writeLong(63, true)); - assertEquals(1, write.writeLong(63, false)); - assertEquals(1, write.writeLong(64, true)); - assertEquals(2, write.writeLong(64, false)); - assertEquals(1, write.writeLong(127, true)); - assertEquals(2, write.writeLong(127, false)); - assertEquals(2, write.writeLong(128, true)); - assertEquals(2, write.writeLong(128, false)); - assertEquals(2, write.writeLong(8191, true)); - assertEquals(2, write.writeLong(8191, false)); - assertEquals(2, write.writeLong(8192, true)); - assertEquals(3, write.writeLong(8192, false)); - assertEquals(2, write.writeLong(16383, true)); - assertEquals(3, write.writeLong(16383, false)); - assertEquals(3, write.writeLong(16384, true)); - assertEquals(3, write.writeLong(16384, false)); - assertEquals(3, write.writeLong(2097151, true)); - assertEquals(4, write.writeLong(2097151, false)); - assertEquals(3, write.writeLong(1048575, true)); - assertEquals(3, write.writeLong(1048575, false)); - assertEquals(4, write.writeLong(134217727, true)); - assertEquals(4, write.writeLong(134217727, false)); - assertEquals(4, write.writeLong(268435455l, true)); - assertEquals(5, write.writeLong(268435455l, false)); - assertEquals(4, write.writeLong(134217728l, true)); - assertEquals(5, write.writeLong(134217728l, false)); - assertEquals(5, write.writeLong(268435456l, true)); - assertEquals(5, write.writeLong(268435456l, false)); - assertEquals(1, write.writeLong(-64, false)); - assertEquals(9, write.writeLong(-64, true)); - assertEquals(2, write.writeLong(-65, false)); - assertEquals(9, write.writeLong(-65, true)); - assertEquals(2, write.writeLong(-8192, false)); - assertEquals(9, write.writeLong(-8192, true)); - assertEquals(3, write.writeLong(-1048576, false)); - assertEquals(9, write.writeLong(-1048576, true)); - assertEquals(4, write.writeLong(-134217728, false)); - assertEquals(9, write.writeLong(-134217728, true)); - assertEquals(5, write.writeLong(-134217729, false)); - assertEquals(9, write.writeLong(-134217729, true)); - - Input read = new Input(write.toBytes()); - assertEquals(0, read.readLong()); - assertEquals(63, read.readLong()); - assertEquals(64, read.readLong()); - assertEquals(127, read.readLong()); - assertEquals(128, read.readLong()); - assertEquals(8192, read.readLong()); - assertEquals(16384, read.readLong()); - assertEquals(2097151, read.readLong()); - assertEquals(1048575, read.readLong()); - assertEquals(134217727, read.readLong()); - assertEquals(268435455, read.readLong()); - assertEquals(134217728, read.readLong()); - assertEquals(268435456, read.readLong()); - assertEquals(-2097151, read.readLong()); - assertEquals(-1048575, read.readLong()); - assertEquals(-134217727, read.readLong()); - assertEquals(-268435455, read.readLong()); - assertEquals(-134217728, read.readLong()); - assertEquals(-268435456, read.readLong()); - assertEquals(0, read.readLong(true)); - assertEquals(0, read.readLong(false)); - assertEquals(63, read.readLong(true)); - assertEquals(63, read.readLong(false)); - assertEquals(64, read.readLong(true)); - assertEquals(64, read.readLong(false)); - assertEquals(127, read.readLong(true)); - assertEquals(127, read.readLong(false)); - assertEquals(128, read.readLong(true)); - assertEquals(128, read.readLong(false)); - assertEquals(8191, read.readLong(true)); - assertEquals(8191, read.readLong(false)); - assertEquals(8192, read.readLong(true)); - assertEquals(8192, read.readLong(false)); - assertEquals(16383, read.readLong(true)); - assertEquals(16383, read.readLong(false)); - assertEquals(16384, read.readLong(true)); - assertEquals(16384, read.readLong(false)); - assertEquals(2097151, read.readLong(true)); - assertEquals(2097151, read.readLong(false)); - assertEquals(1048575, read.readLong(true)); - assertEquals(1048575, read.readLong(false)); - assertEquals(134217727, read.readLong(true)); - assertEquals(134217727, read.readLong(false)); - assertEquals(268435455, read.readLong(true)); - assertEquals(268435455, read.readLong(false)); - assertEquals(134217728, read.readLong(true)); - assertEquals(134217728, read.readLong(false)); - assertEquals(268435456, read.readLong(true)); - assertEquals(268435456, read.readLong(false)); - assertEquals(-64, read.readLong(false)); - assertEquals(-64, read.readLong(true)); - assertEquals(-65, read.readLong(false)); - assertEquals(-65, read.readLong(true)); - assertEquals(-8192, read.readLong(false)); - assertEquals(-8192, read.readLong(true)); - assertEquals(-1048576, read.readLong(false)); - assertEquals(-1048576, read.readLong(true)); - assertEquals(-134217728, read.readLong(false)); - assertEquals(-134217728, read.readLong(true)); - assertEquals(-134217729, read.readLong(false)); - assertEquals(-134217729, read.readLong(true)); - - Random random = new Random(); - for (int i = 0; i < 10000; i++) { - long value = random.nextLong(); - write.clear(); - write.writeLong(value); - write.writeLong(value, true); - write.writeLong(value, false); - read.setBuffer(write.toBytes()); - assertEquals(value, read.readLong()); - assertEquals(value, read.readLong(true)); - assertEquals(value, read.readLong(false)); - } - } - - public void testShorts () { - runShortTest(new Output(4096)); - runShortTest(new Output(new ByteArrayOutputStream())); - } - - private void runShortTest (Output write) { - write.writeShort(0); - write.writeShort(63); - write.writeShort(64); - write.writeShort(127); - write.writeShort(128); - write.writeShort(8192); - write.writeShort(16384); - write.writeShort(32767); - write.writeShort(-63); - write.writeShort(-64); - write.writeShort(-127); - write.writeShort(-128); - write.writeShort(-8192); - write.writeShort(-16384); - write.writeShort(-32768); - - Input read = new Input(write.toBytes()); - assertEquals(0, read.readShort()); - assertEquals(63, read.readShort()); - assertEquals(64, read.readShort()); - assertEquals(127, read.readShort()); - assertEquals(128, read.readShort()); - assertEquals(8192, read.readShort()); - assertEquals(16384, read.readShort()); - assertEquals(32767, read.readShort()); - assertEquals(-63, read.readShort()); - assertEquals(-64, read.readShort()); - assertEquals(-127, read.readShort()); - assertEquals(-128, read.readShort()); - assertEquals(-8192, read.readShort()); - assertEquals(-16384, read.readShort()); - assertEquals(-32768, read.readShort()); - } - - public void testFloats () { - runFloatTest(new Output(4096)); - runFloatTest(new Output(new ByteArrayOutputStream())); - } - - private void runFloatTest (Output write) { - write.writeFloat(0); - write.writeFloat(63); - write.writeFloat(64); - write.writeFloat(127); - write.writeFloat(128); - write.writeFloat(8192); - write.writeFloat(16384); - write.writeFloat(32767); - write.writeFloat(-63); - write.writeFloat(-64); - write.writeFloat(-127); - write.writeFloat(-128); - write.writeFloat(-8192); - write.writeFloat(-16384); - write.writeFloat(-32768); - assertEquals(1, write.writeFloat(0, 1000, true)); - assertEquals(1, write.writeFloat(0, 1000, false)); - assertEquals(3, write.writeFloat(63, 1000, true)); - assertEquals(3, write.writeFloat(63, 1000, false)); - assertEquals(3, write.writeFloat(64, 1000, true)); - assertEquals(3, write.writeFloat(64, 1000, false)); - assertEquals(3, write.writeFloat(127, 1000, true)); - assertEquals(3, write.writeFloat(127, 1000, false)); - assertEquals(3, write.writeFloat(128, 1000, true)); - assertEquals(3, write.writeFloat(128, 1000, false)); - assertEquals(4, write.writeFloat(8191, 1000, true)); - assertEquals(4, write.writeFloat(8191, 1000, false)); - assertEquals(4, write.writeFloat(8192, 1000, true)); - assertEquals(4, write.writeFloat(8192, 1000, false)); - assertEquals(4, write.writeFloat(16383, 1000, true)); - assertEquals(4, write.writeFloat(16383, 1000, false)); - assertEquals(4, write.writeFloat(16384, 1000, true)); - assertEquals(4, write.writeFloat(16384, 1000, false)); - assertEquals(4, write.writeFloat(32767, 1000, true)); - assertEquals(4, write.writeFloat(32767, 1000, false)); - assertEquals(3, write.writeFloat(-64, 1000, false)); - assertEquals(5, write.writeFloat(-64, 1000, true)); - assertEquals(3, write.writeFloat(-65, 1000, false)); - assertEquals(5, write.writeFloat(-65, 1000, true)); - assertEquals(4, write.writeFloat(-8192, 1000, false)); - assertEquals(5, write.writeFloat(-8192, 1000, true)); - - Input read = new Input(write.toBytes()); - assertEquals(read.readFloat(), 0f); - assertEquals(read.readFloat(), 63f); - assertEquals(read.readFloat(), 64f); - assertEquals(read.readFloat(), 127f); - assertEquals(read.readFloat(), 128f); - assertEquals(read.readFloat(), 8192f); - assertEquals(read.readFloat(), 16384f); - assertEquals(read.readFloat(), 32767f); - assertEquals(read.readFloat(), -63f); - assertEquals(read.readFloat(), -64f); - assertEquals(read.readFloat(), -127f); - assertEquals(read.readFloat(), -128f); - assertEquals(read.readFloat(), -8192f); - assertEquals(read.readFloat(), -16384f); - assertEquals(read.readFloat(), -32768f); - assertEquals(read.readFloat(1000, true), 0f); - assertEquals(read.readFloat(1000, false), 0f); - assertEquals(read.readFloat(1000, true), 63f); - assertEquals(read.readFloat(1000, false), 63f); - assertEquals(read.readFloat(1000, true), 64f); - assertEquals(read.readFloat(1000, false), 64f); - assertEquals(read.readFloat(1000, true), 127f); - assertEquals(read.readFloat(1000, false), 127f); - assertEquals(read.readFloat(1000, true), 128f); - assertEquals(read.readFloat(1000, false), 128f); - assertEquals(read.readFloat(1000, true), 8191f); - assertEquals(read.readFloat(1000, false), 8191f); - assertEquals(read.readFloat(1000, true), 8192f); - assertEquals(read.readFloat(1000, false), 8192f); - assertEquals(read.readFloat(1000, true), 16383f); - assertEquals(read.readFloat(1000, false), 16383f); - assertEquals(read.readFloat(1000, true), 16384f); - assertEquals(read.readFloat(1000, false), 16384f); - assertEquals(read.readFloat(1000, true), 32767f); - assertEquals(read.readFloat(1000, false), 32767f); - assertEquals(read.readFloat(1000, false), -64f); - assertEquals(read.readFloat(1000, true), -64f); - assertEquals(read.readFloat(1000, false), -65f); - assertEquals(read.readFloat(1000, true), -65f); - assertEquals(read.readFloat(1000, false), -8192f); - assertEquals(read.readFloat(1000, true), -8192f); - } - - public void testDoubles () { - runDoubleTest(new Output(4096)); - runDoubleTest(new Output(new ByteArrayOutputStream())); - } - - private void runDoubleTest (Output write) { - write.writeDouble(0); - write.writeDouble(63); - write.writeDouble(64); - write.writeDouble(127); - write.writeDouble(128); - write.writeDouble(8192); - write.writeDouble(16384); - write.writeDouble(32767); - write.writeDouble(-63); - write.writeDouble(-64); - write.writeDouble(-127); - write.writeDouble(-128); - write.writeDouble(-8192); - write.writeDouble(-16384); - write.writeDouble(-32768); - assertEquals(1, write.writeDouble(0, 1000, true)); - assertEquals(1, write.writeDouble(0, 1000, false)); - assertEquals(3, write.writeDouble(63, 1000, true)); - assertEquals(3, write.writeDouble(63, 1000, false)); - assertEquals(3, write.writeDouble(64, 1000, true)); - assertEquals(3, write.writeDouble(64, 1000, false)); - assertEquals(3, write.writeDouble(127, 1000, true)); - assertEquals(3, write.writeDouble(127, 1000, false)); - assertEquals(3, write.writeDouble(128, 1000, true)); - assertEquals(3, write.writeDouble(128, 1000, false)); - assertEquals(4, write.writeDouble(8191, 1000, true)); - assertEquals(4, write.writeDouble(8191, 1000, false)); - assertEquals(4, write.writeDouble(8192, 1000, true)); - assertEquals(4, write.writeDouble(8192, 1000, false)); - assertEquals(4, write.writeDouble(16383, 1000, true)); - assertEquals(4, write.writeDouble(16383, 1000, false)); - assertEquals(4, write.writeDouble(16384, 1000, true)); - assertEquals(4, write.writeDouble(16384, 1000, false)); - assertEquals(4, write.writeDouble(32767, 1000, true)); - assertEquals(4, write.writeDouble(32767, 1000, false)); - assertEquals(3, write.writeDouble(-64, 1000, false)); - assertEquals(9, write.writeDouble(-64, 1000, true)); - assertEquals(3, write.writeDouble(-65, 1000, false)); - assertEquals(9, write.writeDouble(-65, 1000, true)); - assertEquals(4, write.writeDouble(-8192, 1000, false)); - assertEquals(9, write.writeDouble(-8192, 1000, true)); - write.writeDouble(1.23456d); - - Input read = new Input(write.toBytes()); - assertEquals(read.readDouble(), 0d); - assertEquals(read.readDouble(), 63d); - assertEquals(read.readDouble(), 64d); - assertEquals(read.readDouble(), 127d); - assertEquals(read.readDouble(), 128d); - assertEquals(read.readDouble(), 8192d); - assertEquals(read.readDouble(), 16384d); - assertEquals(read.readDouble(), 32767d); - assertEquals(read.readDouble(), -63d); - assertEquals(read.readDouble(), -64d); - assertEquals(read.readDouble(), -127d); - assertEquals(read.readDouble(), -128d); - assertEquals(read.readDouble(), -8192d); - assertEquals(read.readDouble(), -16384d); - assertEquals(read.readDouble(), -32768d); - assertEquals(read.readDouble(1000, true), 0d); - assertEquals(read.readDouble(1000, false), 0d); - assertEquals(read.readDouble(1000, true), 63d); - assertEquals(read.readDouble(1000, false), 63d); - assertEquals(read.readDouble(1000, true), 64d); - assertEquals(read.readDouble(1000, false), 64d); - assertEquals(read.readDouble(1000, true), 127d); - assertEquals(read.readDouble(1000, false), 127d); - assertEquals(read.readDouble(1000, true), 128d); - assertEquals(read.readDouble(1000, false), 128d); - assertEquals(read.readDouble(1000, true), 8191d); - assertEquals(read.readDouble(1000, false), 8191d); - assertEquals(read.readDouble(1000, true), 8192d); - assertEquals(read.readDouble(1000, false), 8192d); - assertEquals(read.readDouble(1000, true), 16383d); - assertEquals(read.readDouble(1000, false), 16383d); - assertEquals(read.readDouble(1000, true), 16384d); - assertEquals(read.readDouble(1000, false), 16384d); - assertEquals(read.readDouble(1000, true), 32767d); - assertEquals(read.readDouble(1000, false), 32767d); - assertEquals(read.readDouble(1000, false), -64d); - assertEquals(read.readDouble(1000, true), -64d); - assertEquals(read.readDouble(1000, false), -65d); - assertEquals(read.readDouble(1000, true), -65d); - assertEquals(read.readDouble(1000, false), -8192d); - assertEquals(read.readDouble(1000, true), -8192d); - assertEquals(1.23456d, read.readDouble()); - } - - public void testBooleans () { - runBooleanTest(new Output(4096)); - runBooleanTest(new Output(new ByteArrayOutputStream())); - } - - private void runBooleanTest (Output write) { - for (int i = 0; i < 100; i++) { - write.writeBoolean(true); - write.writeBoolean(false); - } - - Input read = new Input(write.toBytes()); - for (int i = 0; i < 100; i++) { - assertEquals(true, read.readBoolean()); - assertEquals(false, read.readBoolean()); - } - } - - public void testChars () { - runCharTest(new Output(4096)); - runCharTest(new Output(new ByteArrayOutputStream())); - } - - private void runCharTest (Output write) { - write.writeChar((char)0); - write.writeChar((char)63); - write.writeChar((char)64); - write.writeChar((char)127); - write.writeChar((char)128); - write.writeChar((char)8192); - write.writeChar((char)16384); - write.writeChar((char)32767); - write.writeChar((char)65535); - - Input read = new Input(write.toBytes()); - assertEquals(0, read.readChar()); - assertEquals(63, read.readChar()); - assertEquals(64, read.readChar()); - assertEquals(127, read.readChar()); - assertEquals(128, read.readChar()); - assertEquals(8192, read.readChar()); - assertEquals(16384, read.readChar()); - assertEquals(32767, read.readChar()); - assertEquals(65535, read.readChar()); - } - - public void testInputWithOffset () throws Exception { - final byte[] buf = new byte[30]; - final Input in = new Input(buf, 10, 10); - assertEquals(10, in.available()); - in.close(); - } - - public void testSmallBuffers() throws Exception { - ByteBuffer buf = ByteBuffer.allocate(1024); - ByteBufferOutputStream byteBufferOutputStream = new ByteBufferOutputStream(buf); - Output testOutput = new Output(byteBufferOutputStream); - testOutput.writeBytes(new byte[512]); - testOutput.writeBytes(new byte[512]); - testOutput.flush(); - - ByteBufferInputStream testInputs = new ByteBufferInputStream(); - buf.flip(); - testInputs.setByteBuffer(buf); - Input input = new Input(testInputs, 512); - byte[] toRead = new byte[512]; - input.readBytes(toRead); - - input.readBytes(toRead); - - testOutput.close(); - input.close(); - } -} diff --git a/test/dorkbox/network/kryo/JavaSerializerTest.java b/test/dorkbox/network/kryo/JavaSerializerTest.java deleted file mode 100644 index 16de2fe6..00000000 --- a/test/dorkbox/network/kryo/JavaSerializerTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import com.esotericsoftware.kryo.serializers.JavaSerializer; - -import java.io.Serializable; - -/** @author Nathan Sweet */ -public class JavaSerializerTest extends KryoTestCase { - public void testJavaSerializer () { - kryo.register(String.class, new JavaSerializer()); - roundTrip(50, 50, "abcdefabcdefabcdefabcdefabcdefabcdefabcdef"); - roundTrip(12, 12, "meow"); - - kryo.register(TestClass.class, new JavaSerializer()); - TestClass test = new TestClass(); - test.stringField = "fubar"; - test.intField = 54321; - // HACK offset by ? from original because of changes in package name - roundTrip(134-packageOffset, 134-packageOffset, test); - roundTrip(134-packageOffset, 134-packageOffset, test); - roundTrip(134-packageOffset, 134-packageOffset, test); - } - - @SuppressWarnings("serial") - static public class TestClass implements Serializable { - String stringField; - int intField; - - @Override - public boolean equals (Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - TestClass other = (TestClass)obj; - if (intField != other.intField) { - return false; - } - if (stringField == null) { - if (other.stringField != null) { - return false; - } - } else if (!stringField.equals(other.stringField)) { - return false; - } - return true; - } - - @Override - public int hashCode() { - return super.hashCode(); - } - } -} diff --git a/test/dorkbox/network/kryo/KryoAssert.java b/test/dorkbox/network/kryo/KryoAssert.java new file mode 100644 index 00000000..8cbc5eca --- /dev/null +++ b/test/dorkbox/network/kryo/KryoAssert.java @@ -0,0 +1,21 @@ +package dorkbox.network.kryo; + +import static org.junit.Assert.*; + +/** + * Junit Assert wrapper methods class + */ +public class KryoAssert { + + private KryoAssert() { + + } + + public static void assertDoubleEquals(double expected, double actual) { + assertEquals(expected, actual, 0.0); + } + + public static void assertFloatEquals(float expected, double actual) { + assertEquals(expected, actual, 0.0); + } +} diff --git a/test/dorkbox/network/kryo/KryoTestCase.java b/test/dorkbox/network/kryo/KryoTestCase.java index b1ff9f2f..78c7db35 100644 --- a/test/dorkbox/network/kryo/KryoTestCase.java +++ b/test/dorkbox/network/kryo/KryoTestCase.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Nathan Sweet +/* Copyright (c) 2008-2018, Nathan Sweet * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following @@ -15,40 +15,41 @@ * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */package dorkbox.network.kryo; + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.*; -import junit.framework.TestCase; -import org.junit.Assert; -import org.slf4j.LoggerFactory; +package dorkbox.network.kryo; + +import static com.esotericsoftware.minlog.Log.WARN; +import static com.esotericsoftware.minlog.Log.warn; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; +import java.nio.ByteBuffer; import java.util.ArrayList; -/** - * Convenience methods for round tripping objects. - * - * @author Nathan Sweet - */ +import org.junit.Before; -@SuppressWarnings({"rawtypes", "unchecked"}) -abstract public class KryoTestCase extends TestCase { +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.Serializer; +import com.esotericsoftware.kryo.io.ByteBufferInput; +import com.esotericsoftware.kryo.io.ByteBufferOutput; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; +import com.esotericsoftware.kryo.unsafe.UnsafeByteBufferInput; +import com.esotericsoftware.kryo.unsafe.UnsafeByteBufferOutput; +import com.esotericsoftware.kryo.unsafe.UnsafeInput; +import com.esotericsoftware.kryo.unsafe.UnsafeOutput; - public static final int ORIGINAL_PACKAGE_LENGTH = "com.esotericsoftware.kryo".length(); - - // HACK offset by 5 from original because of changes in package name + 5 because it has ANOTHER subclass - protected int packageOffset = ORIGINAL_PACKAGE_LENGTH - this.getClass().getPackage().getName().length(); +/** Convenience methods for round tripping objects. + * @author Nathan Sweet */ +abstract public class KryoTestCase { + // When true, roundTrip will only do a single write/read to make debugging easier (breaks some tests). + static private final boolean debug = false; protected Kryo kryo; protected Output output; @@ -56,175 +57,128 @@ abstract public class KryoTestCase extends TestCase { protected Object object1, object2; protected boolean supportsCopy; - static interface StreamFactory { - Output createOutput(OutputStream os); + static interface BufferFactory { + public Output createOutput(OutputStream os); - Output createOutput(OutputStream os, int size); + public Output createOutput(OutputStream os, int size); - Output createOutput(int size, int limit); + public Output createOutput(int size, int limit); - Input createInput(InputStream os, int size); + public Input createInput(InputStream os, int size); - Input createInput(byte[] buffer); + public Input createInput(byte[] buffer); } - @Override - protected void setUp() throws Exception { - // assume SLF4J is bound to logback in the current environment - Logger rootLogger = (Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); - LoggerContext context = rootLogger.getLoggerContext(); - - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(context); - context.reset(); // override default configuration - - rootLogger.setLevel(Level.TRACE); + @Before + public void setUp () throws Exception { + if (debug && WARN) warn("*** DEBUG TEST ***"); kryo = new Kryo(); - kryo.setReferences(false); - kryo.setRegistrationRequired(true); -// kryo.setAsmEnabled(false); } - public T roundTrip(int length, int unsafeLength, T object1) { - roundTripWithStreamFactory(unsafeLength, object1, new StreamFactory() { - @Override - public Output createOutput(OutputStream os) { - return new UnsafeMemoryOutput(os); + /** @param length Pass Integer.MIN_VALUE to disable checking the length. */ + public T roundTrip (int length, T object1) { + T object2 = roundTripWithBufferFactory(length, object1, new BufferFactory() { + public Output createOutput (OutputStream os) { + return new Output(os); } - @Override - public Output createOutput(OutputStream os, int size) { - return new UnsafeMemoryOutput(os, size); + public Output createOutput (OutputStream os, int size) { + return new Output(os, size); } - @Override - public Output createOutput(int size, int limit) { - return new UnsafeMemoryOutput(size, limit); + public Output createOutput (int size, int limit) { + return new Output(size, limit); } - @Override - public Input createInput(InputStream os, int size) { - return new UnsafeMemoryInput(os, size); + public Input createInput (InputStream os, int size) { + return new Input(os, size); } - @Override - public Input createInput(byte[] buffer) { - return new UnsafeMemoryInput(buffer); + public Input createInput (byte[] buffer) { + return new Input(buffer); } }); - roundTripWithStreamFactory(unsafeLength, object1, new StreamFactory() { - @Override - public Output createOutput(OutputStream os) { + if (debug) return object2; + + roundTripWithBufferFactory(length, object1, new BufferFactory() { + public Output createOutput (OutputStream os) { + return new ByteBufferOutput(os); + } + + public Output createOutput (OutputStream os, int size) { + return new ByteBufferOutput(os, size); + } + + public Output createOutput (int size, int limit) { + return new ByteBufferOutput(size, limit); + } + + public Input createInput (InputStream os, int size) { + return new ByteBufferInput(os, size); + } + + public Input createInput (byte[] buffer) { + ByteBuffer byteBuffer = ByteBuffer.allocateDirect(buffer.length); + byteBuffer.put(buffer).flip(); + return new ByteBufferInput(byteBuffer); + } + }); + + roundTripWithBufferFactory(length, object1, new BufferFactory() { + public Output createOutput (OutputStream os) { return new UnsafeOutput(os); } - @Override - public Output createOutput(OutputStream os, int size) { + public Output createOutput (OutputStream os, int size) { return new UnsafeOutput(os, size); } - @Override - public Output createOutput(int size, int limit) { + public Output createOutput (int size, int limit) { return new UnsafeOutput(size, limit); } - @Override - public Input createInput(InputStream os, int size) { + public Input createInput (InputStream os, int size) { return new UnsafeInput(os, size); } - @Override - public Input createInput(byte[] buffer) { + public Input createInput (byte[] buffer) { return new UnsafeInput(buffer); } }); - roundTripWithStreamFactory(length, object1, new StreamFactory() { - @Override - public Output createOutput(OutputStream os) { - return new ByteBufferOutput(os); + roundTripWithBufferFactory(length, object1, new BufferFactory() { + public Output createOutput (OutputStream os) { + return new UnsafeByteBufferOutput(os); } - @Override - public Output createOutput(OutputStream os, int size) { - return new ByteBufferOutput(os, size); + public Output createOutput (OutputStream os, int size) { + return new UnsafeByteBufferOutput(os, size); } - @Override - public Output createOutput(int size, int limit) { - return new ByteBufferOutput(size, limit); + public Output createOutput (int size, int limit) { + return new UnsafeByteBufferOutput(size, limit); } - @Override - public Input createInput(InputStream os, int size) { - return new ByteBufferInput(os, size); + public Input createInput (InputStream os, int size) { + return new UnsafeByteBufferInput(os, size); } - @Override - public Input createInput(byte[] buffer) { - return new ByteBufferInput(buffer); + public Input createInput (byte[] buffer) { + ByteBuffer byteBuffer = ByteBuffer.allocateDirect(buffer.length); + byteBuffer.put(buffer).flip(); + return new UnsafeByteBufferInput(byteBuffer); } }); - roundTripWithStreamFactory(unsafeLength, object1, new StreamFactory() { - @Override - public Output createOutput(OutputStream os) { - return new FastOutput(os); - } - - @Override - public Output createOutput(OutputStream os, int size) { - return new FastOutput(os, size); - } - - @Override - public Output createOutput(int size, int limit) { - return new FastOutput(size, limit); - } - - @Override - public Input createInput(InputStream os, int size) { - return new FastInput(os, size); - } - - @Override - public Input createInput(byte[] buffer) { - return new FastInput(buffer); - } - }); - - return roundTripWithStreamFactory(length, object1, new StreamFactory() { - @Override - public Output createOutput(OutputStream os) { - return new Output(os); - } - - @Override - public Output createOutput(OutputStream os, int size) { - return new Output(os, size); - } - - @Override - public Output createOutput(int size, int limit) { - return new Output(size, limit); - } - - @Override - public Input createInput(InputStream os, int size) { - return new Input(os, size); - } - - @Override - public Input createInput(byte[] buffer) { - return new Input(buffer); - } - }); + return object2; } - public T roundTripWithStreamFactory(int length, T object1, - StreamFactory sf) { + /** @param length Pass Integer.MIN_VALUE to disable checking the length. */ + public T roundTripWithBufferFactory (int length, T object1, BufferFactory sf) { + boolean checkLength = length != Integer.MIN_VALUE; + this.object1 = object1; // Test output to stream, large buffer. @@ -233,15 +187,19 @@ abstract public class KryoTestCase extends TestCase { kryo.writeClassAndObject(output, object1); output.flush(); + if (debug) System.out.println(); + // Test input from stream, large buffer. - @SuppressWarnings("unused") - byte[] out = outStream.toByteArray(); - input = sf.createInput( - new ByteArrayInputStream(outStream.toByteArray()), 4096); + byte[] out = outStream.toByteArray(); + input = sf.createInput(new ByteArrayInputStream(outStream.toByteArray()), 4096); object2 = kryo.readClassAndObject(input); - assertEquals("Incorrect number of bytes read.", length, input.total()); - assertEquals("Incorrect number of bytes written.", length, output.total()); - assertEquals(object1, object2); + doAssertEquals(object1, object2); + if (checkLength) { + assertEquals("Incorrect number of bytes read.", length, input.total()); + assertEquals("Incorrect number of bytes written.", length, output.total()); + } + + if (debug) return (T)object2; // Test output to stream, small buffer. outStream = new ByteArrayOutputStream(); @@ -250,30 +208,25 @@ abstract public class KryoTestCase extends TestCase { output.flush(); // Test input from stream, small buffer. - input = sf.createInput( - new ByteArrayInputStream(outStream.toByteArray()), 10); + input = sf.createInput(new ByteArrayInputStream(outStream.toByteArray()), 10); object2 = kryo.readClassAndObject(input); - assertEquals("Incorrect number of bytes read.", length, input.total()); - assertEquals(object1, object2); + doAssertEquals(object1, object2); + if (checkLength) assertEquals("Incorrect number of bytes read.", length, input.total()); if (object1 != null) { // Test null with serializer. - Serializer serializer = kryo.getRegistration(object1.getClass()) - .getSerializer(); - output.clear(); + Serializer serializer = kryo.getRegistration(object1.getClass()).getSerializer(); + output.reset(); outStream.reset(); kryo.writeObjectOrNull(output, null, serializer); output.flush(); // Test null from byte array with and without serializer. - input = sf.createInput( - new ByteArrayInputStream(outStream.toByteArray()), 10); - assertEquals(null, kryo.readObjectOrNull(input, object1.getClass(), - serializer)); + input = sf.createInput(new ByteArrayInputStream(outStream.toByteArray()), 10); + assertNull(kryo.readObjectOrNull(input, object1.getClass(), serializer)); - input = sf.createInput( - new ByteArrayInputStream(outStream.toByteArray()), 10); - assertEquals(null, kryo.readObjectOrNull(input, object1.getClass())); + input = sf.createInput(new ByteArrayInputStream(outStream.toByteArray()), 10); + assertNull(kryo.readObjectOrNull(input, object1.getClass())); } // Test output to byte array. @@ -284,42 +237,40 @@ abstract public class KryoTestCase extends TestCase { // Test input from byte array. input = sf.createInput(output.toBytes()); object2 = kryo.readClassAndObject(input); - assertEquals(object1, object2); - assertEquals("Incorrect length.", length, output.total()); - assertEquals("Incorrect number of bytes read.", length, input.total()); - input.rewind(); + doAssertEquals(object1, object2); + if (checkLength) { + assertEquals("Incorrect length.", length, output.total()); + assertEquals("Incorrect number of bytes read.", length, input.total()); + } + input.reset(); if (supportsCopy) { // Test copy. T copy = kryo.copy(object1); - assertEquals(object1, copy); + doAssertEquals(object1, copy); copy = kryo.copyShallow(object1); - assertEquals(object1, copy); + doAssertEquals(object1, copy); } - return (T) object2; + return (T)object2; } - static public void assertEquals(Object object1, Object object2) { - Assert.assertEquals(arrayToList(object1), arrayToList(object2)); + protected void doAssertEquals (Object object1, Object object2) { + assertEquals(arrayToList(object1), arrayToList(object2)); } - static public Object arrayToList(Object array) { - if (array == null || !array.getClass().isArray()) { - return array; - } + static public Object arrayToList (Object array) { + if (array == null || !array.getClass().isArray()) return array; ArrayList list = new ArrayList(Array.getLength(array)); - for (int i = 0, n = Array.getLength(array); i < n; i++) { - list.add(arrayToList(Array.get(array, i))); - } + for (int i = 0, n = Array.getLength(array); i < n; i++) + list.add(arrayToList(Array.get(array, i))); return list; } - static public ArrayList list(Object... items) { + static public ArrayList list (Object... items) { ArrayList list = new ArrayList(); - for (Object item : items) { - list.add(item); - } + for (Object item : items) + list.add(item); return list; } } diff --git a/test/dorkbox/network/kryo/MapSerializerTest.java b/test/dorkbox/network/kryo/MapSerializerTest.java deleted file mode 100644 index 0c898bf2..00000000 --- a/test/dorkbox/network/kryo/MapSerializerTest.java +++ /dev/null @@ -1,151 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import com.esotericsoftware.kryo.serializers.MapSerializer; -import org.junit.Assert; - -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Random; -import java.util.TreeMap; -import java.util.concurrent.ConcurrentHashMap; - -/** @author Nathan Sweet */ -public class MapSerializerTest extends KryoTestCase { - { - supportsCopy = true; - } - - @SuppressWarnings({"rawtypes","unchecked"}) - public void testMaps () { - kryo.register(HashMap.class); - kryo.register(LinkedHashMap.class); - HashMap map = new HashMap(); - map.put("123", "456"); - map.put("789", "abc"); - roundTrip(18, 21, map); - roundTrip(2, 5, new LinkedHashMap()); - roundTrip(18, 21, new LinkedHashMap(map)); - - MapSerializer serializer = new MapSerializer(); - kryo.register(HashMap.class, serializer); - kryo.register(LinkedHashMap.class, serializer); - serializer.setKeyClass(String.class, kryo.getSerializer(String.class)); - serializer.setKeysCanBeNull(false); - serializer.setValueClass(String.class, kryo.getSerializer(String.class)); - roundTrip(14, 17, map); - serializer.setValuesCanBeNull(false); - roundTrip(14, 17, map); - } - - public void testEmptyHashMap () { - execute(new HashMap(), 0); - } - - public void testNotEmptyHashMap () { - execute(new HashMap(), 1000); - } - - public void testEmptyConcurrentHashMap () { - execute(new ConcurrentHashMap(), 0); - } - - public void testNotEmptyConcurrentHashMap () { - execute(new ConcurrentHashMap(), 1000); - } - - public void testGenerics () { - kryo.register(HasGenerics.class); - kryo.register(Integer[].class); - kryo.register(HashMap.class); - - HasGenerics test = new HasGenerics(); - test.map.put("moo", new Integer[] {1, 2}); - - output = new Output(4096); - kryo.writeClassAndObject(output, test); - output.flush(); - - input = new Input(output.toBytes()); - HasGenerics test2 = (HasGenerics)kryo.readClassAndObject(input); - assertEquals(test.map.get("moo"), test2.map.get("moo")); - } - - private void execute (Map map, int inserts) { - Random random = new Random(); - for (int i = 0; i < inserts; i++) { - map.put(random.nextLong(), random.nextBoolean()); - } - - Kryo kryo = new Kryo(); - kryo.register(HashMap.class, new MapSerializer()); - kryo.register(ConcurrentHashMap.class, new MapSerializer()); - - Output output = new Output(2048, -1); - kryo.writeClassAndObject(output, map); - output.close(); - - Input input = new Input(output.toBytes()); - Object deserialized = kryo.readClassAndObject(input); - input.close(); - - Assert.assertEquals(map, deserialized); - } - - @SuppressWarnings({"unchecked","rawtypes"}) - public void testTreeMap () { - kryo.register(TreeMap.class); - TreeMap map = new TreeMap(); - map.put("123", "456"); - map.put("789", "abc"); - roundTrip(19, 22, map); - - kryo.register(KeyThatIsntComparable.class); - kryo.register(KeyComparator.class); - map = new TreeMap(new KeyComparator()); - KeyThatIsntComparable key = new KeyThatIsntComparable(); - key.value = "123"; - map.put(key, "456"); - roundTrip(11, 14, map); - } - - @SuppressWarnings({"unchecked","rawtypes"}) - static public class HasGenerics { - public HashMap map = new HashMap(); - public HashMap map2 = new HashMap(); - } - - static public class KeyComparator implements Comparator { - @Override - public int compare (KeyThatIsntComparable o1, KeyThatIsntComparable o2) { - return o1.value.compareTo(o2.value); - } - } - - static public class KeyThatIsntComparable { - public String value; - } -} diff --git a/test/dorkbox/network/kryo/ReferenceTest.java b/test/dorkbox/network/kryo/ReferenceTest.java deleted file mode 100644 index c8cf4c0e..00000000 --- a/test/dorkbox/network/kryo/ReferenceTest.java +++ /dev/null @@ -1,184 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.Serializer; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import com.esotericsoftware.kryo.serializers.MapSerializer; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - - -@SuppressWarnings({"rawtypes", "unchecked"}) -public class ReferenceTest extends KryoTestCase { - static public class Ordering { - public String order; - } - - @SuppressWarnings("serial") - static public class Stuff extends TreeMap { - public Ordering ordering; - - public Stuff (Ordering ordering) { - this.ordering = ordering; - } - } - - public void testChildObjectBeforeReference () { - Ordering ordering = new Ordering(); - ordering.order = "assbackwards"; - Stuff stuff = new Stuff(ordering); - stuff.put("key", "value"); - stuff.put("something", 456); - stuff.put("self", stuff); - - Kryo kryo = new Kryo(); - kryo.addDefaultSerializer(Stuff.class, new MapSerializer() { - @Override - public void write (Kryo kryo, Output output, Map object) { - kryo.writeObjectOrNull(output, ((Stuff)object).ordering, Ordering.class); - super.write(kryo, output, object); - } - - @Override - protected Map create (Kryo kryo, Input input, Class type) { - Ordering ordering = kryo.readObjectOrNull(input, Ordering.class); - return new Stuff(ordering); - } - }); - - Output output = new Output(512, -1); - kryo.writeObject(output, stuff); - - Input input = new Input(output.getBuffer(), 0, output.position()); - Stuff stuff2 = kryo.readObject(input, Stuff.class); - - assertEquals(stuff.ordering.order, stuff2.ordering.order); - assertEquals(stuff.get("key"), stuff2.get("key")); - assertEquals(stuff.get("something"), stuff2.get("something")); - assertTrue(stuff.get("self") == stuff); - assertTrue(stuff2.get("self") == stuff2); - } - - public void testReadingNestedObjectsFirst () { - ArrayList list = new ArrayList(); - list.add("1"); - list.add("1"); - list.add("2"); - list.add("1"); - list.add("1"); - List subList = list.subList(0, 5); - - kryo.setRegistrationRequired(false); - kryo.register(ArrayList.class); - Class subListClass = (Class)subList.getClass(); - if(subListClass.getName().equals("java.util.ArrayList$SubList")) { - // This is JDK > = 1.7 - kryo.register(subList.getClass(), new ArraySubListSerializer()); - } else { - kryo.register(subList.getClass(), new SubListSerializer()); - } - roundTrip(26, 26, subList); - } - - static public class SubListSerializer extends Serializer { - private Field listField, offsetField, sizeField; - - public SubListSerializer () { - try { - Class sublistClass = Class.forName("java.util.SubList"); - listField = sublistClass.getDeclaredField("l"); - offsetField = sublistClass.getDeclaredField("offset"); - sizeField = sublistClass.getDeclaredField("size"); - listField.setAccessible(true); - offsetField.setAccessible(true); - sizeField.setAccessible(true); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - @Override - public void write (Kryo kryo, Output output, List list) { - try { - kryo.writeClassAndObject(output, listField.get(list)); - int fromIndex = offsetField.getInt(list); - int count = sizeField.getInt(list); - output.writeInt(fromIndex); - output.writeInt(count); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - @Override - public List read (Kryo kryo, Input input, Class type) { - List list = (List)kryo.readClassAndObject(input); - int fromIndex = input.readInt(); - int count = input.readInt(); - return list.subList(fromIndex, fromIndex + count); - } - } - - static public class ArraySubListSerializer extends Serializer { - private Field parentField, offsetField, sizeField; - - public ArraySubListSerializer () { - try { - Class sublistClass = Class.forName("java.util.ArrayList$SubList"); - parentField = sublistClass.getDeclaredField("parent"); - offsetField = sublistClass.getDeclaredField("offset"); - sizeField = sublistClass.getDeclaredField("size"); - parentField.setAccessible(true); - offsetField.setAccessible(true); - sizeField.setAccessible(true); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - @Override - public void write (Kryo kryo, Output output, List list) { - try { - kryo.writeClassAndObject(output, parentField.get(list)); - int offset = offsetField.getInt(list); - int size = sizeField.getInt(list); - output.writeInt(offset); - output.writeInt(size); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - @Override - public List read (Kryo kryo, Input input, Class type) { - List list = (List)kryo.readClassAndObject(input); - int offset = input.readInt(); - int size = input.readInt(); - return list.subList(offset, offset + size); - } - } -} diff --git a/test/dorkbox/network/kryo/SerializationBenchmarkTest.java b/test/dorkbox/network/kryo/SerializationBenchmarkTest.java deleted file mode 100644 index efbade73..00000000 --- a/test/dorkbox/network/kryo/SerializationBenchmarkTest.java +++ /dev/null @@ -1,877 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.KryoSerializable; -import com.esotericsoftware.kryo.io.FastInput; -import com.esotericsoftware.kryo.io.FastOutput; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import com.esotericsoftware.kryo.io.UnsafeInput; -import com.esotericsoftware.kryo.io.UnsafeOutput; -import com.esotericsoftware.kryo.serializers.FieldSerializer; -import org.slf4j.LoggerFactory; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectInputStream; -import java.io.ObjectOutput; -import java.io.ObjectOutputStream; -import java.util.Arrays; -import java.util.concurrent.TimeUnit; - -/*** This test was originally taken from a GridGain blog. It is a compares the speed of serialization using Java serialization, - * Kryo, Kryo with Unsafe patches and GridGain's serialization. - * - * @author Roman Levenstein */ - -@SuppressWarnings({"unchecked","unused"}) -public class SerializationBenchmarkTest extends KryoTestCase { - private static final int WARMUP_ITERATIONS = 1000; - - /** Number of runs. */ - private static final int RUN_CNT = 1; - - /** Number of iterations. Set it to something rather big for obtaining meaningful results */ -// private static final int ITER_CNT = 200000; - private static final int ITER_CNT = 100; - - private static final int SLEEP_BETWEEN_RUNS = 100; - - private static final int OUTPUT_BUFFER_SIZE = 4096 * 10 * 4; - - SampleObject obj = createObject(); - - private static SampleObject createObject () { - long[] longArr = new long[3000]; - - for (int i = 0; i < longArr.length; i++) { - longArr[i] = i; - } - - double[] dblArr = new double[3000]; - - for (int i = 0; i < dblArr.length; i++) { - dblArr[i] = 0.1 * i; - } - - return new SampleObject(123, 123.456f, (short)321, longArr, dblArr); - } - -// public static void main(String[] args) throws Exception { -// // Create sample object. -// SampleObject obj = createObject(); -// -// SerializationBenchmarkTest benchmark = new SerializationBenchmarkTest(); -// -// // Run Java serialization test. -// // benchmark.testJavaSerialization(obj); -// // benchmark.testJavaSerializationWithoutTryCatch(obj); -// -// // Run Kryo serialization test. -// // benchmark.kryoSerialization(obj); -// benchmark.testKryoSerializationUmodified(obj); -// benchmark.testKryoSerializationWithoutTryCatch(obj); -// benchmark.testKryoUnsafeSerializationWithoutTryCatch(obj); -// -// // Run GridGain serialization test. -// // benchmark.gridGainSerialization(obj); -// } - - - public void testDummyEntry() { - System.err.println("Edit the " + SerializationBenchmarkTest.class.getName() + " file to display benchmark metrics."); - } - -// public void testJavaSerialization () throws Exception { -// // Warm-up phase: Perform 100000 iterations -// runJavaSerialization(1, WARMUP_ITERATIONS, false); -// runJavaSerialization(RUN_CNT, ITER_CNT, true); -// } -// -// public void testJavaSerializationWithoutTryCatch () throws Exception { -// // Warm-up phase: Perform 100000 iterations -// runJavaSerializationWithoutTryCatch(1, WARMUP_ITERATIONS, false); -// runJavaSerializationWithoutTryCatch(RUN_CNT, ITER_CNT, true); -// } -// -// public void testKryoSerialization () throws Exception { -// // Warm-up phase: Perform 100000 iterations -// runKryoSerialization(1, WARMUP_ITERATIONS, false); -// runKryoSerialization(RUN_CNT, ITER_CNT, true); -// } -// -// public void testKryoSerializationUnmodified () throws Exception { -// // Warm-up phase: Perform 100000 iterations -// runKryoSerializationUmodified(1, WARMUP_ITERATIONS, false); -// runKryoSerializationUmodified(RUN_CNT, ITER_CNT, true); -// } -// -// public void testKryoSerializationWithoutTryCatch () throws Exception { -// // Warm-up phase: Perform 100000 iterations -// runKryoSerializationWithoutTryCatch(1, WARMUP_ITERATIONS, false); -// runKryoSerializationWithoutTryCatch(RUN_CNT, ITER_CNT, true); -// } -// -// public void testKryoSerializationWithoutTryCatchWithFastStreams () throws Exception { -// // Warm-up phase: Perform 100000 iterations -// runKryoSerializationWithoutTryCatchWithFastStreams(1, WARMUP_ITERATIONS, false); -// runKryoSerializationWithoutTryCatchWithFastStreams(RUN_CNT, ITER_CNT, true); -// } -// -// public void testKryoUnsafeSerializationWithoutTryCatch () throws Exception { -// // Warm-up phase: Perform 100000 iterations -// runKryoUnsafeSerializationWithoutTryCatch(1, WARMUP_ITERATIONS, false); -// runKryoUnsafeSerializationWithoutTryCatch(RUN_CNT, ITER_CNT, true); -// } -// -// public void testKryoUnsafeSerializationWithoutTryCatchWithoutAsm () throws Exception { -// // Warm-up phase: Perform 100000 iterations -// runKryoUnsafeSerializationWithoutTryCatchWithoutAsm(1, WARMUP_ITERATIONS, false); -// runKryoUnsafeSerializationWithoutTryCatchWithoutAsm(RUN_CNT, ITER_CNT, true); -// } -// -// public void testKryoUnsafeSerializationWithoutTryCatchWithoutReferences () throws Exception { -// // Warm-up phase: Perform 100000 iterations -// runKryoUnsafeSerializationWithoutTryCatchWithoutReferences(1, WARMUP_ITERATIONS, false); -// runKryoUnsafeSerializationWithoutTryCatchWithoutReferences(RUN_CNT, ITER_CNT, true); -// } - - - - @SuppressWarnings("null") - private void runJavaSerialization (final int RUN_CNT, final int ITER_CNT, boolean outputResults) throws Exception { - long avgDur = 0; - long bestTime = Long.MAX_VALUE; - - for (int i = 0; i < RUN_CNT; i++) { - SampleObject newObj = null; - - long start = System.nanoTime(); - - for (int j = 0; j < ITER_CNT; j++) { - ByteArrayOutputStream out = new ByteArrayOutputStream(OUTPUT_BUFFER_SIZE); - - ObjectOutputStream objOut = null; - - try { - objOut = new ObjectOutputStream(out); - - objOut.writeObject(obj); - } finally { - objOut.close(); - // U.close(objOut, null); - } - - ObjectInputStream objIn = null; - - try { - objIn = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())); - - newObj = (SampleObject)objIn.readObject(); - } finally { - objIn.close(); - // U.close(objIn, null); - } - } - - long dur = System.nanoTime() - start; - dur = TimeUnit.NANOSECONDS.toMillis(dur); - // Check that unmarshalled object is equal to original one (should - // never fail). - if (!obj.equals(newObj)) { - throw new RuntimeException("Unmarshalled object is not equal to original object."); - } - - if (outputResults) { - System.out.format(">>> Java serialization via Externalizable (run %d): %,d ms\n", i + 1, dur); - } - avgDur += dur; - bestTime = Math.min(bestTime, dur); - systemCleanupAfterRun(); - } - - avgDur /= RUN_CNT; - - if (outputResults) { - System.out.format("\n>>> Java serialization via Externalizable (average): %,d ms\n\n", avgDur); - System.out.format("\n>>> Java serialization via Externalizable (best time): %,d ms\n\n", bestTime); - } - - } - - private void systemCleanupAfterRun () throws InterruptedException { - System.gc(); - Thread.sleep(SLEEP_BETWEEN_RUNS); - System.gc(); - } - - private void runJavaSerializationWithoutTryCatch (final int RUN_CNT, final int ITER_CNT, boolean outputResults) - throws Exception { - long avgDur = 0; - long bestTime = Long.MAX_VALUE; - - for (int i = 0; i < RUN_CNT; i++) { - SampleObject newObj = null; - - long start = System.nanoTime(); - - for (int j = 0; j < ITER_CNT; j++) { - ByteArrayOutputStream out = new ByteArrayOutputStream(OUTPUT_BUFFER_SIZE); - - ObjectOutputStream objOut = null; - - objOut = new ObjectOutputStream(out); - - objOut.writeObject(obj); - objOut.close(); - // U.close(objOut, null); - - ObjectInputStream objIn = null; - - objIn = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())); - - newObj = (SampleObject)objIn.readObject(); - objIn.close(); - // U.close(objIn, null); - } - - long dur = System.nanoTime() - start; - dur = TimeUnit.NANOSECONDS.toMillis(dur); - // Check that unmarshalled object is equal to original one (should - // never fail). - if (!obj.equals(newObj)) { - throw new RuntimeException("Unmarshalled object is not equal to original object."); - } - if (outputResults) { - System.out.format(">>> Java serialization without try-catch (run %d): %,d ms\n", i + 1, dur); - } - - avgDur += dur; - bestTime = Math.min(bestTime, dur); - systemCleanupAfterRun(); - } - - avgDur /= RUN_CNT; - - if (outputResults) { - System.out.format("\n>>> Java serialization without try-catch via Externalizable (average): %,d ms\n\n", avgDur); - System.out.format("\n>>> Java serialization without try-catch via Externalizable (best time): %,d ms\n\n", bestTime); - } - } - - @SuppressWarnings("null") - private void runKryoSerialization (final int RUN_CNT, final int ITER_CNT, boolean outputResults) throws Exception { - Kryo marsh = new Kryo(); - marsh.register(SampleObject.class, 40); - - long avgDur = 0; - long bestTime = Long.MAX_VALUE; - byte[] out = new byte[OUTPUT_BUFFER_SIZE]; - - for (int i = 0; i < RUN_CNT; i++) { - SampleObject newObj = null; - - long start = System.nanoTime(); - - for (int j = 0; j < ITER_CNT; j++) { - - Output kryoOut = null; - - try { - kryoOut = new Output(out); - marsh.writeObject(kryoOut, obj); - } finally { - kryoOut.close(); - // U.close(kryoOut, null); - } - - Input kryoIn = null; - - try { - kryoIn = new Input(kryoOut.getBuffer(), 0, kryoOut.position()); - newObj = marsh.readObject(kryoIn, SampleObject.class); - } finally { - kryoIn.close(); - // U.close(kryoIn, null); - } - } - - long dur = System.nanoTime() - start; - dur = TimeUnit.NANOSECONDS.toMillis(dur); - // Check that unmarshalled object is equal to original one (should - // never fail). - if (!obj.equals(newObj)) { - throw new RuntimeException("Unmarshalled object is not equal to original object."); - } - - if (outputResults) { - System.out.format(">>> Kryo serialization (run %d): %,d ms\n", i + 1, dur); - } - avgDur += dur; - bestTime = Math.min(bestTime, dur); - systemCleanupAfterRun(); - } - - avgDur /= RUN_CNT; - - if (outputResults) { - System.out.format("\n>>> Kryo serialization (average): %,d ms\n\n", avgDur); - System.out.format("\n>>> Kryo serialization (best time): %,d ms\n\n", bestTime); - } - - } - - @SuppressWarnings("null") - private void runKryoSerializationUmodified (final int RUN_CNT, final int ITER_CNT, boolean outputResults) throws Exception { - Kryo marsh = new Kryo(); - - long avgDur = 0; - long bestTime = Long.MAX_VALUE; - - for (int i = 0; i < RUN_CNT; i++) { - SampleObject newObj = null; - - long start = System.nanoTime(); - - for (int j = 0; j < ITER_CNT; j++) { - - Output kryoOut = null; - - try { - kryoOut = new Output(OUTPUT_BUFFER_SIZE); - - marsh.writeObject(kryoOut, obj); - } finally { - // U.close(kryoOut, null); - kryoOut.close(); - } - - Input kryoIn = null; - - try { - kryoIn = new Input(kryoOut.getBuffer(), 0, kryoOut.position()); - newObj = marsh.readObject(kryoIn, SampleObject.class); - } finally { - // U.close(kryoIn, null); - kryoIn.close(); - } - } - - long dur = System.nanoTime() - start; - dur = TimeUnit.NANOSECONDS.toMillis(dur); - - // Check that unmarshalled object is equal to original one (should - // never fail). - if (!obj.equals(newObj)) { - throw new RuntimeException("Unmarshalled object is not equal to original object."); - } - - if (outputResults) { - System.out.format(">>> Kryo unmodified serialization (run %d): %,d ms\n", i + 1, dur); - } - - avgDur += dur; - bestTime = Math.min(bestTime, dur); - systemCleanupAfterRun(); - } - - avgDur /= RUN_CNT; - - if (outputResults) { - System.out.format("\n>>> Kryo unmodified serialization (average): %,d ms\n\n", avgDur); - System.out.format("\n>>> Kryo unmodified serialization (best time): %,d ms\n\n", bestTime); - } - } - - private void runKryoSerializationWithoutTryCatch (final int RUN_CNT, final int ITER_CNT, boolean outputResults) - throws Exception { - Kryo marsh = new Kryo(); - marsh.register(SampleObject.class, 40); - - long avgDur = 0; - long bestTime = Long.MAX_VALUE; - - byte[] out = new byte[OUTPUT_BUFFER_SIZE]; - - for (int i = 0; i < RUN_CNT; i++) { - SampleObject newObj = null; - - long start = System.nanoTime(); - - for (int j = 0; j < ITER_CNT; j++) { - - Output kryoOut = null; - - kryoOut = new Output(out); - - marsh.writeObject(kryoOut, obj); - kryoOut.close(); - // U.close(kryoOut, null); - - Input kryoIn = null; - - kryoIn = new Input(kryoOut.getBuffer(), 0, kryoOut.position()); - - newObj = marsh.readObject(kryoIn, SampleObject.class); - kryoIn.close(); - // U.close(kryoIn, null); - } - - long dur = System.nanoTime() - start; - dur = TimeUnit.NANOSECONDS.toMillis(dur); - // Check that unmarshalled object is equal to original one (should - // never fail). - if (!obj.equals(newObj)) { - throw new RuntimeException("Unmarshalled object is not equal to original object."); - } - if (outputResults) { - System.out.format(">>> Kryo serialization without try-catch (run %d): %,d ms\n", i + 1, dur); - } - - avgDur += dur; - bestTime = Math.min(bestTime, dur); - systemCleanupAfterRun(); - } - - avgDur /= RUN_CNT; - - if (outputResults) { - System.out.format("\n>>> Kryo serialization without try-catch (average): %,d ms\n\n", avgDur); - System.out.format("\n>>> Kryo serialization without try-catch (best time): %,d ms\n\n", bestTime); - } - } - - private void runKryoSerializationWithoutTryCatchWithFastStreams (final int RUN_CNT, final int ITER_CNT, boolean outputResults) - throws Exception { - Kryo marsh = new Kryo(); - marsh.register(SampleObject.class, 40); - - long avgDur = 0; - long bestTime = Long.MAX_VALUE; - - byte[] out = new byte[OUTPUT_BUFFER_SIZE]; - - for (int i = 0; i < RUN_CNT; i++) { - SampleObject newObj = null; - - long start = System.nanoTime(); - - for (int j = 0; j < ITER_CNT; j++) { - - Output kryoOut = null; - - kryoOut = new FastOutput(out); - - marsh.writeObject(kryoOut, obj); - kryoOut.close(); - // U.close(kryoOut, null); - - Input kryoIn = null; - - kryoIn = new FastInput(kryoOut.getBuffer(), 0, kryoOut.position()); - - newObj = marsh.readObject(kryoIn, SampleObject.class); - kryoIn.close(); - // U.close(kryoIn, null); - } - - long dur = System.nanoTime() - start; - dur = TimeUnit.NANOSECONDS.toMillis(dur); - // Check that unmarshalled object is equal to original one (should - // never fail). - if (!obj.equals(newObj)) { - throw new RuntimeException("Unmarshalled object is not equal to original object."); - } - if (outputResults) { - System.out.format(">>> Kryo serialization without try-catch with fast streams (run %d): %,d ms\n", i + 1, dur); - } - - avgDur += dur; - bestTime = Math.min(bestTime, dur); - systemCleanupAfterRun(); - } - - avgDur /= RUN_CNT; - - if (outputResults) { - System.out.format("\n>>> Kryo serialization without try-catch with fast streams (average): %,d ms\n\n", avgDur); - System.out.format("\n>>> Kryo serialization without try-catch with fast streams (best time): %,d ms\n\n", bestTime); - } - } - - private void runKryoUnsafeSerializationWithoutTryCatch (final int RUN_CNT, final int ITER_CNT, boolean outputResults) - throws Exception { - Kryo marsh = new Kryo(); - marsh.setRegistrationRequired(true); - marsh.register(double[].class, 30); - marsh.register(long[].class, 31); - // Explicitly tell to use Unsafe-based serializer - marsh.register(SampleObject.class, new FieldSerializer(marsh, SampleObject.class), 40); - - // Use fastest possible serialization of object fields - FieldSerializer ser = (FieldSerializer)marsh.getRegistration(SampleObject.class) - .getSerializer(); - ser.setUseAsm(true); - - long avgDur = 0; - long bestTime = Long.MAX_VALUE; - - byte[] out = new byte[OUTPUT_BUFFER_SIZE]; - for (int i = 0; i < RUN_CNT; i++) { - SampleObject newObj = null; - - long start = System.nanoTime(); - - for (int j = 0; j < ITER_CNT; j++) { - - Output kryoOut = null; - - kryoOut = new UnsafeOutput(out); - - marsh.writeObject(kryoOut, obj); - kryoOut.close(); - // U.close(kryoOut, null); - - Input kryoIn = null; - - kryoIn = new UnsafeInput(kryoOut.getBuffer(), 0, kryoOut.position()); - - newObj = marsh.readObject(kryoIn, SampleObject.class); - kryoIn.close(); - // U.close(kryoIn, null); - } - - long dur = System.nanoTime() - start; - dur = TimeUnit.NANOSECONDS.toMillis(dur); - // Check that unmarshalled object is equal to original one (should - // never fail). - if (!obj.equals(newObj)) { - throw new RuntimeException("Unmarshalled object is not equal to original object."); - } - - if (outputResults) { - System.out.format(">>> Kryo unsafe serialization without try-catch (run %d): %,d ms\n", i + 1, dur); - } - - avgDur += dur; - bestTime = Math.min(bestTime, dur); - systemCleanupAfterRun(); - } - - avgDur /= RUN_CNT; - - if (outputResults) { - System.out.format("\n>>> Kryo unsafe serialization without try-catch (average): %,d ms\n\n", avgDur); - System.out.format("\n>>> Kryo unsafe serialization without try-catch (best time): %,d ms\n\n", bestTime); - } - } - - private void runKryoUnsafeSerializationWithoutTryCatchWithoutAsm (final int RUN_CNT, final int ITER_CNT, boolean outputResults) - throws Exception { - Kryo marsh = new Kryo(); - marsh.setRegistrationRequired(true); - marsh.register(double[].class, 30); - marsh.register(long[].class, 31); - // Explicitly tell to use Unsafe-based serializer - marsh.register(SampleObject.class, new FieldSerializer(marsh, SampleObject.class), 40); - -// // Use fastest possible serialization of object fields -// FieldSerializer ser = (FieldSerializer) marsh.getRegistration(SampleObject.class).getSerializer(); -// ser.setUseAsm(false); - - long avgDur = 0; - long bestTime = Long.MAX_VALUE; - - byte[] out = new byte[OUTPUT_BUFFER_SIZE]; - for (int i = 0; i < RUN_CNT; i++) { - SampleObject newObj = null; - - long start = System.nanoTime(); - - for (int j = 0; j < ITER_CNT; j++) { - - Output kryoOut = null; - - kryoOut = new UnsafeOutput(out); - - marsh.writeObject(kryoOut, obj); - kryoOut.close(); - // U.close(kryoOut, null); - - Input kryoIn = null; - - kryoIn = new UnsafeInput(kryoOut.getBuffer(), 0, kryoOut.position()); - - newObj = marsh.readObject(kryoIn, SampleObject.class); - kryoIn.close(); - // U.close(kryoIn, null); - } - - long dur = System.nanoTime() - start; - dur = TimeUnit.NANOSECONDS.toMillis(dur); - // Check that unmarshalled object is equal to original one (should - // never fail). - if (!obj.equals(newObj)) { - throw new RuntimeException("Unmarshalled object is not equal to original object."); - } - - if (outputResults) { - System.out.format(">>> Kryo unsafe serialization without try-catch, without ASM (run %d): %,d ms\n", i + 1, dur); - } - - avgDur += dur; - bestTime = Math.min(bestTime, dur); - systemCleanupAfterRun(); - } - - avgDur /= RUN_CNT; - - if (outputResults) { - System.out.format("\n>>> Kryo unsafe serialization without try-catch, without ASM (average): %,d ms\n\n", avgDur); - System.out.format("\n>>> Kryo unsafe serialization without try-catch, without ASM (best time): %,d ms\n\n", bestTime); - } - - } - - private void runKryoUnsafeSerializationWithoutTryCatchWithoutReferences (final int RUN_CNT, final int ITER_CNT, - boolean outputResults) throws Exception { - Kryo marsh = new Kryo(); - kryo.setReferences(false); - marsh.setRegistrationRequired(true); - marsh.register(double[].class, 30); - marsh.register(long[].class, 31); - // Explicitly tell to use Unsafe-based serializer - marsh.register(SampleObject.class, new FieldSerializer(marsh, SampleObject.class), 40); - - // Use fastest possible serialization of object fields - FieldSerializer ser = (FieldSerializer)marsh.getRegistration(SampleObject.class) - .getSerializer(); - ser.setUseAsm(false); - - long avgDur = 0; - long bestTime = Long.MAX_VALUE; - - for (int i = 0; i < RUN_CNT; i++) { - SampleObject newObj = null; - byte[] out = new byte[OUTPUT_BUFFER_SIZE]; - - long start = System.nanoTime(); - - for (int j = 0; j < ITER_CNT; j++) { - - Output kryoOut = null; - - kryoOut = new UnsafeOutput(out); - - marsh.writeObject(kryoOut, obj); - kryoOut.close(); - // U.close(kryoOut, null); - - Input kryoIn = null; - - kryoIn = new UnsafeInput(kryoOut.getBuffer(), 0, kryoOut.position()); - - newObj = marsh.readObject(kryoIn, SampleObject.class); - kryoIn.close(); - // U.close(kryoIn, null); - } - - long dur = System.nanoTime() - start; - dur = TimeUnit.NANOSECONDS.toMillis(dur); - // Check that unmarshalled object is equal to original one (should - // never fail). - if (!obj.equals(newObj)) { - throw new RuntimeException("Unmarshalled object is not equal to original object."); - } - - if (outputResults) { - System.out.format( - ">>> Kryo unsafe serialization without try-catch, without ASM, without references (run %d): %,d ms\n", i + 1, dur); - } - - avgDur += dur; - bestTime = Math.min(bestTime, dur); - systemCleanupAfterRun(); - } - - avgDur /= RUN_CNT; - - if (outputResults) { - System.out.format( - "\n>>> Kryo unsafe serialization without try-catch, without ASM, without references (average): %,d ms\n\n", avgDur); - System.out.format( - "\n>>> Kryo unsafe serialization without try-catch, without ASM, without references (best time): %,d ms\n\n", - bestTime); - } - - } - -// private static long gridGainSerialization() -// throws Exception { -// GridMarshaller marsh = new GridOptimizedMarshaller(false, -// Arrays.asList(SampleObject.class.getName()), null); -// -// long avgDur = 0; -// -// for (int i = 0; i < RUN_CNT; i++) { -// SampleObject newObj = null; -// -// long start = System.currentTimeMillis(); -// -// for (int j = 0; j < ITER_CNT; j++) -// newObj = marsh.unmarshal(marsh.marshal(obj), null); -// -// long dur = System.currentTimeMillis() - start; -// -// // Check that unmarshalled object is equal to original one (should -// // never fail). -// if (!obj.equals(newObj)) -// throw new RuntimeException( -// "Unmarshalled object is not equal to original object."); -// -// System.out.format(">>> GridGain serialization (run %d): %,d ms\n", -// i + 1, dur); -// -// avgDur += dur; -// } -// -// avgDur /= RUN_CNT; -// -// System.out.format("\n>>> GridGain serialization (average): %,d ms\n\n", -// avgDur); -// -// return avgDur; -// } - - @Override - protected void setUp () throws Exception { - super.setUp(); - - // assume SLF4J is bound to logback in the current environment - Logger rootLogger = (Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); - LoggerContext context = rootLogger.getLoggerContext(); - - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(context); - context.reset(); // override default configuration - - rootLogger.setLevel(Level.WARN); - } - - private static class SampleObject implements Externalizable, KryoSerializable { - private int intVal; - private float floatVal; - private Short shortVal; - private long[] longArr; - private double[] dblArr; - private SampleObject selfRef; - - public SampleObject () { - } - - SampleObject (int intVal, float floatVal, Short shortVal, long[] longArr, double[] dblArr) { - this.intVal = intVal; - this.floatVal = floatVal; - this.shortVal = shortVal; - this.longArr = longArr; - this.dblArr = dblArr; - - selfRef = this; - } - - /** {@inheritDoc} */ - @Override - public boolean equals (Object other) { - if (this == other) { - return true; - } - - if (other == null || getClass() != other.getClass()) { - return false; - } - - SampleObject obj = (SampleObject)other; - - assert this == selfRef; - assert obj == obj.selfRef; - - return intVal == obj.intVal && floatVal == obj.floatVal && shortVal.equals(obj.shortVal) - && Arrays.equals(dblArr, obj.dblArr) && Arrays.equals(longArr, obj.longArr); - } - - // Required by Kryo serialization. - @Override - public void read (Kryo kryo, Input in) { - intVal = kryo.readObject(in, Integer.class); - floatVal = kryo.readObject(in, Float.class); - shortVal = kryo.readObject(in, Short.class); - longArr = kryo.readObject(in, long[].class); - dblArr = kryo.readObject(in, double[].class); - selfRef = kryo.readObject(in, SampleObject.class); - } - - // Required by Java Externalizable. - @Override - public void readExternal (ObjectInput in) throws IOException, ClassNotFoundException { - intVal = in.readInt(); - floatVal = in.readFloat(); - shortVal = in.readShort(); - longArr = (long[])in.readObject(); - dblArr = (double[])in.readObject(); - selfRef = (SampleObject)in.readObject(); - } - - // Required by Kryo serialization. - @Override - public void write (Kryo kryo, Output out) { - kryo.writeObject(out, intVal); - kryo.writeObject(out, floatVal); - kryo.writeObject(out, shortVal); - kryo.writeObject(out, longArr); - kryo.writeObject(out, dblArr); - kryo.writeObject(out, selfRef); - } - - // Required by Java Externalizable. - @Override - public void writeExternal (ObjectOutput out) throws IOException { - out.writeInt(intVal); - out.writeFloat(floatVal); - out.writeShort(shortVal); - out.writeObject(longArr); - out.writeObject(dblArr); - out.writeObject(selfRef); - } - - @Override - public int hashCode() { - return super.hashCode(); - } - } -} diff --git a/test/dorkbox/network/kryo/TaggedFieldSerializerTest.java b/test/dorkbox/network/kryo/TaggedFieldSerializerTest.java deleted file mode 100644 index a374c790..00000000 --- a/test/dorkbox/network/kryo/TaggedFieldSerializerTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import com.esotericsoftware.kryo.serializers.TaggedFieldSerializer; -import com.esotericsoftware.kryo.serializers.TaggedFieldSerializer.Tag; - - -@SuppressWarnings({"rawtypes"}) -public class TaggedFieldSerializerTest extends KryoTestCase { - { - this.supportsCopy = true; - } - - public void testTaggedFieldSerializer() { - TestClass object1 = new TestClass(); - object1.moo = 2; - object1.child = new TestClass(); - object1.child.moo = 5; - object1.other = new AnotherClass(); - object1.other.value = "meow"; - object1.ignored = 32; - this.kryo.setDefaultSerializer(TaggedFieldSerializer.class); - this.kryo.register(TestClass.class); - this.kryo.register(AnotherClass.class); - TestClass object2 = roundTrip(57, 75, object1); - assertTrue(object2.ignored == 0); - } - - public void testAddedField() { - TestClass object1 = new TestClass(); - object1.child = new TestClass(); - object1.other = new AnotherClass(); - object1.other.value = "meow"; - - TaggedFieldSerializer serializer = new TaggedFieldSerializer(this.kryo, TestClass.class); - serializer.removeField("text"); - this.kryo.register(TestClass.class, serializer); - this.kryo.register(AnotherClass.class, new TaggedFieldSerializer(this.kryo, AnotherClass.class)); - roundTrip(39, 55, object1); - - this.kryo.register(TestClass.class, new TaggedFieldSerializer(this.kryo, TestClass.class)); - Object object2 = this.kryo.readClassAndObject(this.input); - assertEquals(object1, object2); - } - - static public class TestClass { - @Tag(0) public String text = "something"; - @Tag(1) public int moo = 120; - @Tag(2) public long moo2 = 1234120; - @Tag(3) public TestClass child; - @Tag(4) public int zzz = 123; - @Tag(5) public AnotherClass other; - @Tag(6) @Deprecated public int ignored; - - @Override - public boolean equals (Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - TestClass other = (TestClass)obj; - if (this.child == null) { - if (other.child != null) { - return false; - } - } else if (!this.child.equals(other.child)) { - return false; - } - if (this.moo != other.moo) { - return false; - } - if (this.moo2 != other.moo2) { - return false; - } - if (this.text == null) { - if (other.text != null) { - return false; - } - } else if (!this.text.equals(other.text)) { - return false; - } - if (this.zzz != other.zzz) { - return false; - } - return true; - } - - @Override - public int hashCode() { - return super.hashCode(); - } - } - - static public class AnotherClass { - @Tag(1) String value; - } -} diff --git a/test/dorkbox/network/kryo/UnsafeInputOutputTest.java b/test/dorkbox/network/kryo/UnsafeInputOutputTest.java deleted file mode 100644 index e527f3dd..00000000 --- a/test/dorkbox/network/kryo/UnsafeInputOutputTest.java +++ /dev/null @@ -1,824 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.util.Random; - -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; -import com.esotericsoftware.kryo.io.UnsafeInput; -import com.esotericsoftware.kryo.io.UnsafeOutput; - -/** @author Nathan Sweet */ -@SuppressWarnings("resource") -public class UnsafeInputOutputTest extends KryoTestCase { - public void testOutputStream () { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - UnsafeOutput output = new UnsafeOutput(buffer, 2); - output.writeBytes(new byte[] {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}); - output.writeBytes(new byte[] {31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}); - output.writeBytes(new byte[] {51, 52, 53, 54, 55, 56, 57, 58}); - output.writeBytes(new byte[] {61, 62, 63, 64, 65}); - output.flush(); - - assertEquals(new byte[] { // - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, // - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, // - 51, 52, 53, 54, 55, 56, 57, 58, // - 61, 62, 63, 64, 65}, buffer.toByteArray()); - - output.close(); - } - - public void testInputStream () { - byte[] bytes = new byte[] { // - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, // - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, // - 51, 52, 53, 54, 55, 56, 57, 58, // - 61, 62, 63, 64, 65}; - ByteArrayInputStream buffer = new ByteArrayInputStream(bytes); - Input input = new UnsafeInput(buffer, 2); - byte[] temp = new byte[1024]; - int count = input.read(temp, 512, bytes.length); - assertEquals(bytes.length, count); - byte[] temp2 = new byte[count]; - System.arraycopy(temp, 512, temp2, 0, count); - assertEquals(bytes, temp2); - - input.close(); - - input = new UnsafeInput(bytes); - count = input.read(temp, 512, 512); - assertEquals(bytes.length, count); - temp2 = new byte[count]; - System.arraycopy(temp, 512, temp2, 0, count); - assertEquals(bytes, temp2); - - input.close(); - } - - public void testWriteBytes () { - UnsafeOutput buffer = new UnsafeOutput(512); - buffer.writeBytes(new byte[] {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}); - buffer.writeBytes(new byte[] {31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}); - buffer.writeByte(51); - buffer.writeBytes(new byte[] {52, 53, 54, 55, 56, 57, 58}); - buffer.writeByte(61); - buffer.writeByte(62); - buffer.writeByte(63); - buffer.writeByte(64); - buffer.writeByte(65); - buffer.flush(); - - assertEquals(new byte[] { // - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, // - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, // - 51, 52, 53, 54, 55, 56, 57, 58, // - 61, 62, 63, 64, 65}, buffer.toBytes()); - - buffer.close(); - } - - public void testStrings () { - runStringTest(new UnsafeOutput(4096)); - runStringTest(new UnsafeOutput(897)); - runStringTest(new UnsafeOutput(new ByteArrayOutputStream())); - - UnsafeOutput write = new UnsafeOutput(21); - String value = "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u1234"; - write.writeString(value); - Input read = new UnsafeInput(write.toBytes()); - assertEquals(value, read.readString()); - - runStringTest(127); - runStringTest(256); - runStringTest(1024 * 1023); - runStringTest(1024 * 1024); - runStringTest(1024 * 1025); - runStringTest(1024 * 1026); - runStringTest(1024 * 1024 * 2); - } - - public void runStringTest (int length) { - UnsafeOutput write = new UnsafeOutput(1024, -1); - StringBuilder buffer = new StringBuilder(); - for (int i = 0; i < length; i++) { - buffer.append((char)i); - } - - String value = buffer.toString(); - write.writeString(value); - write.writeString(value); - Input read = new UnsafeInput(write.toBytes()); - assertEquals(value, read.readString()); - assertEquals(value, read.readStringBuilder().toString()); - - write.clear(); - write.writeString(buffer); - write.writeString(buffer); - read = new UnsafeInput(write.toBytes()); - assertEquals(value, read.readStringBuilder().toString()); - assertEquals(value, read.readString()); - - if (length <= 127) { - write.clear(); - write.writeAscii(value); - write.writeAscii(value); - read = new UnsafeInput(write.toBytes()); - assertEquals(value, read.readStringBuilder().toString()); - assertEquals(value, read.readString()); - } - } - - public void runStringTest (UnsafeOutput write) { - String value1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\rabcdefghijklmnopqrstuvwxyz\n1234567890\t\"!`?'.,;:()[]{}<>|/@\\^$-%+=#_&~*"; - String value2 = "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u1234"; - - write.writeString(""); - write.writeString("1"); - write.writeString("22"); - write.writeString("uno"); - write.writeString("dos"); - write.writeString("tres"); - write.writeString(null); - write.writeString(value1); - write.writeString(value2); - for (int i = 0; i < 127; i++) { - write.writeString(String.valueOf((char)i)); - } - for (int i = 0; i < 127; i++) { - write.writeString(String.valueOf((char)i) + "abc"); - } - - Input read = new UnsafeInput(write.toBytes()); - assertEquals("", read.readString()); - assertEquals("1", read.readString()); - assertEquals("22", read.readString()); - assertEquals("uno", read.readString()); - assertEquals("dos", read.readString()); - assertEquals("tres", read.readString()); - assertEquals(null, read.readString()); - assertEquals(value1, read.readString()); - assertEquals(value2, read.readString()); - for (int i = 0; i < 127; i++) { - assertEquals(String.valueOf((char)i), read.readString()); - } - for (int i = 0; i < 127; i++) { - assertEquals(String.valueOf((char)i) + "abc", read.readString()); - } - - read.rewind(); - assertEquals("", read.readStringBuilder().toString()); - assertEquals("1", read.readStringBuilder().toString()); - assertEquals("22", read.readStringBuilder().toString()); - assertEquals("uno", read.readStringBuilder().toString()); - assertEquals("dos", read.readStringBuilder().toString()); - assertEquals("tres", read.readStringBuilder().toString()); - assertEquals(null, read.readStringBuilder()); - assertEquals(value1, read.readStringBuilder().toString()); - assertEquals(value2, read.readStringBuilder().toString()); - for (int i = 0; i < 127; i++) { - assertEquals(String.valueOf((char)i), read.readStringBuilder().toString()); - } - for (int i = 0; i < 127; i++) { - assertEquals(String.valueOf((char)i) + "abc", read.readStringBuilder().toString()); - } - } - - public void testCanReadInt () { - UnsafeOutput write = new UnsafeOutput(new ByteArrayOutputStream()); - - Input read = new UnsafeInput(write.toBytes()); - assertEquals(false, read.canReadInt()); - - write.writeVarInt(400, true); - - read = new UnsafeInput(write.toBytes()); - assertEquals(true, read.canReadInt()); - read.setLimit(read.limit() - 1); - assertEquals(false, read.canReadInt()); - } - - public void testInts () { - runIntTest(new UnsafeOutput(4096)); - runIntTest(new UnsafeOutput(new ByteArrayOutputStream())); - } - - private void runIntTest (UnsafeOutput write) { - write.writeInt(0); - write.writeInt(63); - write.writeInt(64); - write.writeInt(127); - write.writeInt(128); - write.writeInt(8192); - write.writeInt(16384); - write.writeInt(2097151); - write.writeInt(1048575); - write.writeInt(134217727); - write.writeInt(268435455); - write.writeInt(134217728); - write.writeInt(268435456); - write.writeInt(-2097151); - write.writeInt(-1048575); - write.writeInt(-134217727); - write.writeInt(-268435455); - write.writeInt(-134217728); - write.writeInt(-268435456); - assertEquals(4, write.writeInt(0, true)); - assertEquals(4, write.writeInt(0, false)); - assertEquals(4, write.writeInt(63, true)); - assertEquals(4, write.writeInt(63, false)); - assertEquals(4, write.writeInt(64, true)); - assertEquals(4, write.writeInt(64, false)); - assertEquals(4, write.writeInt(127, true)); - assertEquals(4, write.writeInt(127, false)); - assertEquals(4, write.writeInt(128, true)); - assertEquals(4, write.writeInt(128, false)); - assertEquals(4, write.writeInt(8191, true)); - assertEquals(4, write.writeInt(8191, false)); - assertEquals(4, write.writeInt(8192, true)); - assertEquals(4, write.writeInt(8192, false)); - assertEquals(4, write.writeInt(16383, true)); - assertEquals(4, write.writeInt(16383, false)); - assertEquals(4, write.writeInt(16384, true)); - assertEquals(4, write.writeInt(16384, false)); - assertEquals(4, write.writeInt(2097151, true)); - assertEquals(4, write.writeInt(2097151, false)); - assertEquals(4, write.writeInt(1048575, true)); - assertEquals(4, write.writeInt(1048575, false)); - assertEquals(4, write.writeInt(134217727, true)); - assertEquals(4, write.writeInt(134217727, false)); - assertEquals(4, write.writeInt(268435455, true)); - assertEquals(4, write.writeInt(268435455, false)); - assertEquals(4, write.writeInt(134217728, true)); - assertEquals(4, write.writeInt(134217728, false)); - assertEquals(4, write.writeInt(268435456, true)); - assertEquals(4, write.writeInt(268435456, false)); - assertEquals(4, write.writeInt(-64, false)); - assertEquals(4, write.writeInt(-64, true)); - assertEquals(4, write.writeInt(-65, false)); - assertEquals(4, write.writeInt(-65, true)); - assertEquals(4, write.writeInt(-8192, false)); - assertEquals(4, write.writeInt(-8192, true)); - assertEquals(4, write.writeInt(-1048576, false)); - assertEquals(4, write.writeInt(-1048576, true)); - assertEquals(4, write.writeInt(-134217728, false)); - assertEquals(4, write.writeInt(-134217728, true)); - assertEquals(4, write.writeInt(-134217729, false)); - assertEquals(4, write.writeInt(-134217729, true)); - - Input read = new UnsafeInput(write.toBytes()); - assertEquals(0, read.readInt()); - assertEquals(63, read.readInt()); - assertEquals(64, read.readInt()); - assertEquals(127, read.readInt()); - assertEquals(128, read.readInt()); - assertEquals(8192, read.readInt()); - assertEquals(16384, read.readInt()); - assertEquals(2097151, read.readInt()); - assertEquals(1048575, read.readInt()); - assertEquals(134217727, read.readInt()); - assertEquals(268435455, read.readInt()); - assertEquals(134217728, read.readInt()); - assertEquals(268435456, read.readInt()); - assertEquals(-2097151, read.readInt()); - assertEquals(-1048575, read.readInt()); - assertEquals(-134217727, read.readInt()); - assertEquals(-268435455, read.readInt()); - assertEquals(-134217728, read.readInt()); - assertEquals(-268435456, read.readInt()); - assertEquals(true, read.canReadInt()); - assertEquals(true, read.canReadInt()); - assertEquals(true, read.canReadInt()); - assertEquals(0, read.readInt(true)); - assertEquals(0, read.readInt(false)); - assertEquals(63, read.readInt(true)); - assertEquals(63, read.readInt(false)); - assertEquals(64, read.readInt(true)); - assertEquals(64, read.readInt(false)); - assertEquals(127, read.readInt(true)); - assertEquals(127, read.readInt(false)); - assertEquals(128, read.readInt(true)); - assertEquals(128, read.readInt(false)); - assertEquals(8191, read.readInt(true)); - assertEquals(8191, read.readInt(false)); - assertEquals(8192, read.readInt(true)); - assertEquals(8192, read.readInt(false)); - assertEquals(16383, read.readInt(true)); - assertEquals(16383, read.readInt(false)); - assertEquals(16384, read.readInt(true)); - assertEquals(16384, read.readInt(false)); - assertEquals(2097151, read.readInt(true)); - assertEquals(2097151, read.readInt(false)); - assertEquals(1048575, read.readInt(true)); - assertEquals(1048575, read.readInt(false)); - assertEquals(134217727, read.readInt(true)); - assertEquals(134217727, read.readInt(false)); - assertEquals(268435455, read.readInt(true)); - assertEquals(268435455, read.readInt(false)); - assertEquals(134217728, read.readInt(true)); - assertEquals(134217728, read.readInt(false)); - assertEquals(268435456, read.readInt(true)); - assertEquals(268435456, read.readInt(false)); - assertEquals(-64, read.readInt(false)); - assertEquals(-64, read.readInt(true)); - assertEquals(-65, read.readInt(false)); - assertEquals(-65, read.readInt(true)); - assertEquals(-8192, read.readInt(false)); - assertEquals(-8192, read.readInt(true)); - assertEquals(-1048576, read.readInt(false)); - assertEquals(-1048576, read.readInt(true)); - assertEquals(-134217728, read.readInt(false)); - assertEquals(-134217728, read.readInt(true)); - assertEquals(-134217729, read.readInt(false)); - assertEquals(-134217729, read.readInt(true)); - assertEquals(false, read.canReadInt()); - - Random random = new Random(); - for (int i = 0; i < 10000; i++) { - int value = random.nextInt(); - write.clear(); - write.writeInt(value); - write.writeInt(value, true); - write.writeInt(value, false); - read.setBuffer(write.toBytes()); - assertEquals(value, read.readInt()); - assertEquals(value, read.readInt(true)); - assertEquals(value, read.readInt(false)); - } - } - - public void testLongs () { - runLongTest(new UnsafeOutput(4096)); - runLongTest(new UnsafeOutput(new ByteArrayOutputStream())); - } - - private void runLongTest (UnsafeOutput write) { - write.writeLong(0); - write.writeLong(63); - write.writeLong(64); - write.writeLong(127); - write.writeLong(128); - write.writeLong(8192); - write.writeLong(16384); - write.writeLong(2097151); - write.writeLong(1048575); - write.writeLong(134217727); - write.writeLong(268435455); - write.writeLong(134217728); - write.writeLong(268435456); - write.writeLong(-2097151); - write.writeLong(-1048575); - write.writeLong(-134217727); - write.writeLong(-268435455); - write.writeLong(-134217728); - write.writeLong(-268435456); - assertEquals(8, write.writeLong(0, true)); - assertEquals(8, write.writeLong(0, false)); - assertEquals(8, write.writeLong(63, true)); - assertEquals(8, write.writeLong(63, false)); - assertEquals(8, write.writeLong(64, true)); - assertEquals(8, write.writeLong(64, false)); - assertEquals(8, write.writeLong(127, true)); - assertEquals(8, write.writeLong(127, false)); - assertEquals(8, write.writeLong(128, true)); - assertEquals(8, write.writeLong(128, false)); - assertEquals(8, write.writeLong(8191, true)); - assertEquals(8, write.writeLong(8191, false)); - assertEquals(8, write.writeLong(8192, true)); - assertEquals(8, write.writeLong(8192, false)); - assertEquals(8, write.writeLong(16383, true)); - assertEquals(8, write.writeLong(16383, false)); - assertEquals(8, write.writeLong(16384, true)); - assertEquals(8, write.writeLong(16384, false)); - assertEquals(8, write.writeLong(2097151, true)); - assertEquals(8, write.writeLong(2097151, false)); - assertEquals(8, write.writeLong(1048575, true)); - assertEquals(8, write.writeLong(1048575, false)); - assertEquals(8, write.writeLong(134217727, true)); - assertEquals(8, write.writeLong(134217727, false)); - assertEquals(8, write.writeLong(268435455l, true)); - assertEquals(8, write.writeLong(268435455l, false)); - assertEquals(8, write.writeLong(134217728l, true)); - assertEquals(8, write.writeLong(134217728l, false)); - assertEquals(8, write.writeLong(268435456l, true)); - assertEquals(8, write.writeLong(268435456l, false)); - assertEquals(8, write.writeLong(-64, false)); - assertEquals(8, write.writeLong(-64, true)); - assertEquals(8, write.writeLong(-65, false)); - assertEquals(8, write.writeLong(-65, true)); - assertEquals(8, write.writeLong(-8192, false)); - assertEquals(8, write.writeLong(-8192, true)); - assertEquals(8, write.writeLong(-1048576, false)); - assertEquals(8, write.writeLong(-1048576, true)); - assertEquals(8, write.writeLong(-134217728, false)); - assertEquals(8, write.writeLong(-134217728, true)); - assertEquals(8, write.writeLong(-134217729, false)); - assertEquals(8, write.writeLong(-134217729, true)); - - Input read = new UnsafeInput(write.toBytes()); - assertEquals(0, read.readLong()); - assertEquals(63, read.readLong()); - assertEquals(64, read.readLong()); - assertEquals(127, read.readLong()); - assertEquals(128, read.readLong()); - assertEquals(8192, read.readLong()); - assertEquals(16384, read.readLong()); - assertEquals(2097151, read.readLong()); - assertEquals(1048575, read.readLong()); - assertEquals(134217727, read.readLong()); - assertEquals(268435455, read.readLong()); - assertEquals(134217728, read.readLong()); - assertEquals(268435456, read.readLong()); - assertEquals(-2097151, read.readLong()); - assertEquals(-1048575, read.readLong()); - assertEquals(-134217727, read.readLong()); - assertEquals(-268435455, read.readLong()); - assertEquals(-134217728, read.readLong()); - assertEquals(-268435456, read.readLong()); - assertEquals(0, read.readLong(true)); - assertEquals(0, read.readLong(false)); - assertEquals(63, read.readLong(true)); - assertEquals(63, read.readLong(false)); - assertEquals(64, read.readLong(true)); - assertEquals(64, read.readLong(false)); - assertEquals(127, read.readLong(true)); - assertEquals(127, read.readLong(false)); - assertEquals(128, read.readLong(true)); - assertEquals(128, read.readLong(false)); - assertEquals(8191, read.readLong(true)); - assertEquals(8191, read.readLong(false)); - assertEquals(8192, read.readLong(true)); - assertEquals(8192, read.readLong(false)); - assertEquals(16383, read.readLong(true)); - assertEquals(16383, read.readLong(false)); - assertEquals(16384, read.readLong(true)); - assertEquals(16384, read.readLong(false)); - assertEquals(2097151, read.readLong(true)); - assertEquals(2097151, read.readLong(false)); - assertEquals(1048575, read.readLong(true)); - assertEquals(1048575, read.readLong(false)); - assertEquals(134217727, read.readLong(true)); - assertEquals(134217727, read.readLong(false)); - assertEquals(268435455, read.readLong(true)); - assertEquals(268435455, read.readLong(false)); - assertEquals(134217728, read.readLong(true)); - assertEquals(134217728, read.readLong(false)); - assertEquals(268435456, read.readLong(true)); - assertEquals(268435456, read.readLong(false)); - assertEquals(-64, read.readLong(false)); - assertEquals(-64, read.readLong(true)); - assertEquals(-65, read.readLong(false)); - assertEquals(-65, read.readLong(true)); - assertEquals(-8192, read.readLong(false)); - assertEquals(-8192, read.readLong(true)); - assertEquals(-1048576, read.readLong(false)); - assertEquals(-1048576, read.readLong(true)); - assertEquals(-134217728, read.readLong(false)); - assertEquals(-134217728, read.readLong(true)); - assertEquals(-134217729, read.readLong(false)); - assertEquals(-134217729, read.readLong(true)); - - Random random = new Random(); - for (int i = 0; i < 10000; i++) { - long value = random.nextLong(); - write.clear(); - write.writeLong(value); - write.writeLong(value, true); - write.writeLong(value, false); - read.setBuffer(write.toBytes()); - assertEquals("Element " + i, value, read.readLong()); - assertEquals("Element " + i, value, read.readLong(true)); - assertEquals("Element " + i, value, read.readLong(false)); - } - } - - public void testShorts () { - runShortTest(new UnsafeOutput(4096)); - runShortTest(new UnsafeOutput(new ByteArrayOutputStream())); - } - - private void runShortTest (UnsafeOutput write) { - write.writeShort(0); - write.writeShort(63); - write.writeShort(64); - write.writeShort(127); - write.writeShort(128); - write.writeShort(8192); - write.writeShort(16384); - write.writeShort(32767); - write.writeShort(-63); - write.writeShort(-64); - write.writeShort(-127); - write.writeShort(-128); - write.writeShort(-8192); - write.writeShort(-16384); - write.writeShort(-32768); - - Input read = new UnsafeInput(write.toBytes()); - assertEquals(0, read.readShort()); - assertEquals(63, read.readShort()); - assertEquals(64, read.readShort()); - assertEquals(127, read.readShort()); - assertEquals(128, read.readShort()); - assertEquals(8192, read.readShort()); - assertEquals(16384, read.readShort()); - assertEquals(32767, read.readShort()); - assertEquals(-63, read.readShort()); - assertEquals(-64, read.readShort()); - assertEquals(-127, read.readShort()); - assertEquals(-128, read.readShort()); - assertEquals(-8192, read.readShort()); - assertEquals(-16384, read.readShort()); - assertEquals(-32768, read.readShort()); - } - - public void testFloats () { - runFloatTest(new UnsafeOutput(4096)); - runFloatTest(new UnsafeOutput(new ByteArrayOutputStream())); - } - - private void runFloatTest (UnsafeOutput write) { - write.writeFloat(0); - write.writeFloat(63); - write.writeFloat(64); - write.writeFloat(127); - write.writeFloat(128); - write.writeFloat(8192); - write.writeFloat(16384); - write.writeFloat(32767); - write.writeFloat(-63); - write.writeFloat(-64); - write.writeFloat(-127); - write.writeFloat(-128); - write.writeFloat(-8192); - write.writeFloat(-16384); - write.writeFloat(-32768); - assertEquals(4, write.writeFloat(0, 1000, true)); - assertEquals(4, write.writeFloat(0, 1000, false)); - assertEquals(4, write.writeFloat(63, 1000, true)); - assertEquals(4, write.writeFloat(63, 1000, false)); - assertEquals(4, write.writeFloat(64, 1000, true)); - assertEquals(4, write.writeFloat(64, 1000, false)); - assertEquals(4, write.writeFloat(127, 1000, true)); - assertEquals(4, write.writeFloat(127, 1000, false)); - assertEquals(4, write.writeFloat(128, 1000, true)); - assertEquals(4, write.writeFloat(128, 1000, false)); - assertEquals(4, write.writeFloat(8191, 1000, true)); - assertEquals(4, write.writeFloat(8191, 1000, false)); - assertEquals(4, write.writeFloat(8192, 1000, true)); - assertEquals(4, write.writeFloat(8192, 1000, false)); - assertEquals(4, write.writeFloat(16383, 1000, true)); - assertEquals(4, write.writeFloat(16383, 1000, false)); - assertEquals(4, write.writeFloat(16384, 1000, true)); - assertEquals(4, write.writeFloat(16384, 1000, false)); - assertEquals(4, write.writeFloat(32767, 1000, true)); - assertEquals(4, write.writeFloat(32767, 1000, false)); - assertEquals(4, write.writeFloat(-64, 1000, false)); - assertEquals(4, write.writeFloat(-64, 1000, true)); - assertEquals(4, write.writeFloat(-65, 1000, false)); - assertEquals(4, write.writeFloat(-65, 1000, true)); - assertEquals(4, write.writeFloat(-8192, 1000, false)); - assertEquals(4, write.writeFloat(-8192, 1000, true)); - - Input read = new UnsafeInput(write.toBytes()); - assertEquals(read.readFloat(), 0f); - assertEquals(read.readFloat(), 63f); - assertEquals(read.readFloat(), 64f); - assertEquals(read.readFloat(), 127f); - assertEquals(read.readFloat(), 128f); - assertEquals(read.readFloat(), 8192f); - assertEquals(read.readFloat(), 16384f); - assertEquals(read.readFloat(), 32767f); - assertEquals(read.readFloat(), -63f); - assertEquals(read.readFloat(), -64f); - assertEquals(read.readFloat(), -127f); - assertEquals(read.readFloat(), -128f); - assertEquals(read.readFloat(), -8192f); - assertEquals(read.readFloat(), -16384f); - assertEquals(read.readFloat(), -32768f); - assertEquals(read.readFloat(1000, true), 0f); - assertEquals(read.readFloat(1000, false), 0f); - assertEquals(read.readFloat(1000, true), 63f); - assertEquals(read.readFloat(1000, false), 63f); - assertEquals(read.readFloat(1000, true), 64f); - assertEquals(read.readFloat(1000, false), 64f); - assertEquals(read.readFloat(1000, true), 127f); - assertEquals(read.readFloat(1000, false), 127f); - assertEquals(read.readFloat(1000, true), 128f); - assertEquals(read.readFloat(1000, false), 128f); - assertEquals(read.readFloat(1000, true), 8191f); - assertEquals(read.readFloat(1000, false), 8191f); - assertEquals(read.readFloat(1000, true), 8192f); - assertEquals(read.readFloat(1000, false), 8192f); - assertEquals(read.readFloat(1000, true), 16383f); - assertEquals(read.readFloat(1000, false), 16383f); - assertEquals(read.readFloat(1000, true), 16384f); - assertEquals(read.readFloat(1000, false), 16384f); - assertEquals(read.readFloat(1000, true), 32767f); - assertEquals(read.readFloat(1000, false), 32767f); - assertEquals(read.readFloat(1000, false), -64f); - assertEquals(read.readFloat(1000, true), -64f); - assertEquals(read.readFloat(1000, false), -65f); - assertEquals(read.readFloat(1000, true), -65f); - assertEquals(read.readFloat(1000, false), -8192f); - assertEquals(read.readFloat(1000, true), -8192f); - } - - public void testDoubles () { - runDoubleTest(new UnsafeOutput(4096)); - runDoubleTest(new UnsafeOutput(new ByteArrayOutputStream())); - } - - private void runDoubleTest (UnsafeOutput write) { - write.writeDouble(0); - write.writeDouble(63); - write.writeDouble(64); - write.writeDouble(127); - write.writeDouble(128); - write.writeDouble(8192); - write.writeDouble(16384); - write.writeDouble(32767); - write.writeDouble(-63); - write.writeDouble(-64); - write.writeDouble(-127); - write.writeDouble(-128); - write.writeDouble(-8192); - write.writeDouble(-16384); - write.writeDouble(-32768); - assertEquals(8, write.writeDouble(0, 1000, true)); - assertEquals(8, write.writeDouble(0, 1000, false)); - assertEquals(8, write.writeDouble(63, 1000, true)); - assertEquals(8, write.writeDouble(63, 1000, false)); - assertEquals(8, write.writeDouble(64, 1000, true)); - assertEquals(8, write.writeDouble(64, 1000, false)); - assertEquals(8, write.writeDouble(127, 1000, true)); - assertEquals(8, write.writeDouble(127, 1000, false)); - assertEquals(8, write.writeDouble(128, 1000, true)); - assertEquals(8, write.writeDouble(128, 1000, false)); - assertEquals(8, write.writeDouble(8191, 1000, true)); - assertEquals(8, write.writeDouble(8191, 1000, false)); - assertEquals(8, write.writeDouble(8192, 1000, true)); - assertEquals(8, write.writeDouble(8192, 1000, false)); - assertEquals(8, write.writeDouble(16383, 1000, true)); - assertEquals(8, write.writeDouble(16383, 1000, false)); - assertEquals(8, write.writeDouble(16384, 1000, true)); - assertEquals(8, write.writeDouble(16384, 1000, false)); - assertEquals(8, write.writeDouble(32767, 1000, true)); - assertEquals(8, write.writeDouble(32767, 1000, false)); - assertEquals(8, write.writeDouble(-64, 1000, false)); - assertEquals(8, write.writeDouble(-64, 1000, true)); - assertEquals(8, write.writeDouble(-65, 1000, false)); - assertEquals(8, write.writeDouble(-65, 1000, true)); - assertEquals(8, write.writeDouble(-8192, 1000, false)); - assertEquals(8, write.writeDouble(-8192, 1000, true)); - write.writeDouble(1.23456d); - - Input read = new UnsafeInput(write.toBytes()); - assertEquals(read.readDouble(), 0d); - assertEquals(read.readDouble(), 63d); - assertEquals(read.readDouble(), 64d); - assertEquals(read.readDouble(), 127d); - assertEquals(read.readDouble(), 128d); - assertEquals(read.readDouble(), 8192d); - assertEquals(read.readDouble(), 16384d); - assertEquals(read.readDouble(), 32767d); - assertEquals(read.readDouble(), -63d); - assertEquals(read.readDouble(), -64d); - assertEquals(read.readDouble(), -127d); - assertEquals(read.readDouble(), -128d); - assertEquals(read.readDouble(), -8192d); - assertEquals(read.readDouble(), -16384d); - assertEquals(read.readDouble(), -32768d); - assertEquals(read.readDouble(1000, true), 0d); - assertEquals(read.readDouble(1000, false), 0d); - assertEquals(read.readDouble(1000, true), 63d); - assertEquals(read.readDouble(1000, false), 63d); - assertEquals(read.readDouble(1000, true), 64d); - assertEquals(read.readDouble(1000, false), 64d); - assertEquals(read.readDouble(1000, true), 127d); - assertEquals(read.readDouble(1000, false), 127d); - assertEquals(read.readDouble(1000, true), 128d); - assertEquals(read.readDouble(1000, false), 128d); - assertEquals(read.readDouble(1000, true), 8191d); - assertEquals(read.readDouble(1000, false), 8191d); - assertEquals(read.readDouble(1000, true), 8192d); - assertEquals(read.readDouble(1000, false), 8192d); - assertEquals(read.readDouble(1000, true), 16383d); - assertEquals(read.readDouble(1000, false), 16383d); - assertEquals(read.readDouble(1000, true), 16384d); - assertEquals(read.readDouble(1000, false), 16384d); - assertEquals(read.readDouble(1000, true), 32767d); - assertEquals(read.readDouble(1000, false), 32767d); - assertEquals(read.readDouble(1000, false), -64d); - assertEquals(read.readDouble(1000, true), -64d); - assertEquals(read.readDouble(1000, false), -65d); - assertEquals(read.readDouble(1000, true), -65d); - assertEquals(read.readDouble(1000, false), -8192d); - assertEquals(read.readDouble(1000, true), -8192d); - assertEquals(1.23456d, read.readDouble()); - } - - public void testBooleans () { - runBooleanTest(new UnsafeOutput(4096)); - runBooleanTest(new UnsafeOutput(new ByteArrayOutputStream())); - } - - private void runBooleanTest (UnsafeOutput write) { - for (int i = 0; i < 100; i++) { - write.writeBoolean(true); - write.writeBoolean(false); - } - - Input read = new UnsafeInput(write.toBytes()); - for (int i = 0; i < 100; i++) { - assertEquals(true, read.readBoolean()); - assertEquals(false, read.readBoolean()); - } - } - - public void testChars () { - runCharTest(new UnsafeOutput(4096)); - runCharTest(new UnsafeOutput(new ByteArrayOutputStream())); - } - - private void runCharTest (UnsafeOutput write) { - write.writeChar((char)0); - write.writeChar((char)63); - write.writeChar((char)64); - write.writeChar((char)127); - write.writeChar((char)128); - write.writeChar((char)8192); - write.writeChar((char)16384); - write.writeChar((char)32767); - write.writeChar((char)65535); - - Input read = new UnsafeInput(write.toBytes()); - assertEquals(0, read.readChar()); - assertEquals(63, read.readChar()); - assertEquals(64, read.readChar()); - assertEquals(127, read.readChar()); - assertEquals(128, read.readChar()); - assertEquals(8192, read.readChar()); - assertEquals(16384, read.readChar()); - assertEquals(32767, read.readChar()); - assertEquals(65535, read.readChar()); - } - - // Check if writing varInts may produce more bytes than expected - public void testWriteTooManyBytes () { - ByteArrayOutputStream os = new ByteArrayOutputStream(1); - runVarIntTest(new UnsafeOutput(os, 4), os); - } - - private void runVarIntTest (UnsafeOutput write, ByteArrayOutputStream os) { - write.writeVarInt(0, true); - write.writeVarInt(63, true); - write.writeVarInt(64, true); - write.writeVarInt(65535, true); - assertEquals(6, write.total()); - write.flush(); - assertEquals(6, os.size()); - - Input read = new UnsafeInput(os.toByteArray()); - assertEquals(0, read.readVarInt(true)); - assertEquals(63, read.readVarInt(true)); - assertEquals(64, read.readVarInt(true)); - assertEquals(65535, read.readVarInt(true)); - assertEquals(true, read.eof()); - - read.close(); - } - - public void testSimpleVarInt() { - final int value = 39117; - final Output out = new UnsafeOutput(1024); - out.writeVarInt(value, true); - out.flush(); - final Input in = new UnsafeInput(out.toBytes()); - final int actualValue = in.readVarInt(true); - assertEquals(value, actualValue); - - out.close(); - in.close(); - } -} diff --git a/test/dorkbox/network/kryo/UnsafeMemoryInputOutputTest.java b/test/dorkbox/network/kryo/UnsafeMemoryInputOutputTest.java deleted file mode 100644 index 7b9f851d..00000000 --- a/test/dorkbox/network/kryo/UnsafeMemoryInputOutputTest.java +++ /dev/null @@ -1,829 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.util.Random; - -import com.esotericsoftware.kryo.io.ByteBufferInput; -import com.esotericsoftware.kryo.io.ByteBufferOutput; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.UnsafeMemoryInput; -import com.esotericsoftware.kryo.io.UnsafeMemoryOutput; -import com.esotericsoftware.kryo.util.UnsafeUtil; - -/** @author Roman Levenstein */ -@SuppressWarnings("resource") -public class UnsafeMemoryInputOutputTest extends KryoTestCase { - - public void testByteBufferOutputWithPreallocatedMemory () { - long bufAddress = UnsafeUtil.unsafe().allocateMemory(4096); - try { - ByteBufferOutput outputBuffer = new ByteBufferOutput(bufAddress, 4096); - outputBuffer.writeInt(10); - - ByteBufferInput inputBuffer = new ByteBufferInput(outputBuffer.getByteBuffer()); - inputBuffer.readInt(); - inputBuffer.release(); - - inputBuffer.close(); - outputBuffer.close(); - - outputBuffer.release(); - outputBuffer = new UnsafeMemoryOutput(bufAddress, 4096); - outputBuffer.writeInt(10); - - inputBuffer = new UnsafeMemoryInput(outputBuffer.getByteBuffer()); - inputBuffer.readInt(); - inputBuffer.release(); - outputBuffer.release(); - - outputBuffer.close(); - } catch (Throwable t) { - System.err.println("Streams with preallocated direct memory are not supported on this JVM"); - t.printStackTrace(); - } finally { - UnsafeUtil.unsafe().freeMemory(bufAddress); - } - } - - public void testOutputStream () { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - UnsafeMemoryOutput output = new UnsafeMemoryOutput(buffer, 2); - output.writeBytes(new byte[] {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}); - output.writeBytes(new byte[] {31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}); - output.writeBytes(new byte[] {51, 52, 53, 54, 55, 56, 57, 58}); - output.writeBytes(new byte[] {61, 62, 63, 64, 65}); - output.flush(); - - assertEquals(new byte[] { // - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, // - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, // - 51, 52, 53, 54, 55, 56, 57, 58, // - 61, 62, 63, 64, 65}, buffer.toByteArray()); - - output.close(); - } - - public void testInputStream () { - byte[] bytes = new byte[] { // - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, // - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, // - 51, 52, 53, 54, 55, 56, 57, 58, // - 61, 62, 63, 64, 65}; - ByteArrayInputStream buffer = new ByteArrayInputStream(bytes); - Input input = new UnsafeMemoryInput(buffer, 2); - byte[] temp = new byte[1024]; - int count = input.read(temp, 512, bytes.length); - assertEquals(bytes.length, count); - byte[] temp2 = new byte[count]; - System.arraycopy(temp, 512, temp2, 0, count); - assertEquals(bytes, temp2); - - input.close(); - - input = new UnsafeMemoryInput(bytes); - count = input.read(temp, 512, 512); - assertEquals(bytes.length, count); - temp2 = new byte[count]; - System.arraycopy(temp, 512, temp2, 0, count); - assertEquals(bytes, temp2); - - input.close(); - } - - public void testWriteBytes () { - UnsafeMemoryOutput buffer = new UnsafeMemoryOutput(512); - buffer.writeBytes(new byte[] {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}); - buffer.writeBytes(new byte[] {31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46}); - buffer.writeByte(51); - buffer.writeBytes(new byte[] {52, 53, 54, 55, 56, 57, 58}); - buffer.writeByte(61); - buffer.writeByte(62); - buffer.writeByte(63); - buffer.writeByte(64); - buffer.writeByte(65); - buffer.flush(); - - assertEquals(new byte[] { // - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, // - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, // - 51, 52, 53, 54, 55, 56, 57, 58, // - 61, 62, 63, 64, 65}, buffer.toBytes()); - - buffer.close(); - } - - public void testStrings () { - runStringTest(new UnsafeMemoryOutput(4096)); - runStringTest(new UnsafeMemoryOutput(897)); - runStringTest(new UnsafeMemoryOutput(new ByteArrayOutputStream())); - - UnsafeMemoryOutput write = new UnsafeMemoryOutput(21); - String value = "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u1234"; - write.writeString(value); - Input read = new UnsafeMemoryInput(write.toBytes()); - assertEquals(value, read.readString()); - - runStringTest(127); - runStringTest(256); - runStringTest(1024 * 1023); - runStringTest(1024 * 1024); - runStringTest(1024 * 1025); - runStringTest(1024 * 1026); - runStringTest(1024 * 1024 * 2); - - write.close(); - read.close(); - } - - public void runStringTest (int length) { - UnsafeMemoryOutput write = new UnsafeMemoryOutput(1024, -1); - StringBuilder buffer = new StringBuilder(); - for (int i = 0; i < length; i++) { - buffer.append((char)i); - } - - String value = buffer.toString(); - write.writeString(value); - write.writeString(value); - Input read = new UnsafeMemoryInput(write.toBytes()); - assertEquals(value, read.readString()); - assertEquals(value, read.readStringBuilder().toString()); - - write.clear(); - write.writeString(buffer); - write.writeString(buffer); - read = new UnsafeMemoryInput(write.toBytes()); - assertEquals(value, read.readStringBuilder().toString()); - assertEquals(value, read.readString()); - - if (length <= 127) { - write.clear(); - write.writeAscii(value); - write.writeAscii(value); - read = new UnsafeMemoryInput(write.toBytes()); - assertEquals(value, read.readStringBuilder().toString()); - assertEquals(value, read.readString()); - } - } - - public void runStringTest (UnsafeMemoryOutput write) { - String value1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\rabcdefghijklmnopqrstuvwxyz\n1234567890\t\"!`?'.,;:()[]{}<>|/@\\^$-%+=#_&~*"; - String value2 = "abcdef\u00E1\u00E9\u00ED\u00F3\u00FA\u1234"; - - write.writeString(""); - write.writeString("1"); - write.writeString("22"); - write.writeString("uno"); - write.writeString("dos"); - write.writeString("tres"); - write.writeString(null); - write.writeString(value1); - write.writeString(value2); - for (int i = 0; i < 127; i++) { - write.writeString(String.valueOf((char)i)); - } - for (int i = 0; i < 127; i++) { - write.writeString(String.valueOf((char)i) + "abc"); - } - - Input read = new UnsafeMemoryInput(write.toBytes()); - assertEquals("", read.readString()); - assertEquals("1", read.readString()); - assertEquals("22", read.readString()); - assertEquals("uno", read.readString()); - assertEquals("dos", read.readString()); - assertEquals("tres", read.readString()); - assertEquals(null, read.readString()); - assertEquals(value1, read.readString()); - assertEquals(value2, read.readString()); - for (int i = 0; i < 127; i++) { - assertEquals(String.valueOf((char)i), read.readString()); - } - for (int i = 0; i < 127; i++) { - assertEquals(String.valueOf((char)i) + "abc", read.readString()); - } - - read.rewind(); - assertEquals("", read.readStringBuilder().toString()); - assertEquals("1", read.readStringBuilder().toString()); - assertEquals("22", read.readStringBuilder().toString()); - assertEquals("uno", read.readStringBuilder().toString()); - assertEquals("dos", read.readStringBuilder().toString()); - assertEquals("tres", read.readStringBuilder().toString()); - assertEquals(null, read.readStringBuilder()); - assertEquals(value1, read.readStringBuilder().toString()); - assertEquals(value2, read.readStringBuilder().toString()); - for (int i = 0; i < 127; i++) { - assertEquals(String.valueOf((char)i), read.readStringBuilder().toString()); - } - for (int i = 0; i < 127; i++) { - assertEquals(String.valueOf((char)i) + "abc", read.readStringBuilder().toString()); - } - } - - public void testCanReadInt () { - UnsafeMemoryOutput write = new UnsafeMemoryOutput(new ByteArrayOutputStream()); - - Input read = new UnsafeMemoryInput(write.toBytes()); - assertEquals(false, read.canReadInt()); - - write.writeVarInt(400, true); - - read = new UnsafeMemoryInput(write.toBytes()); - assertEquals(true, read.canReadInt()); - read.setLimit(read.limit() - 1); - assertEquals(false, read.canReadInt()); - } - - public void testInts () { - runIntTest(new UnsafeMemoryOutput(4096)); - runIntTest(new UnsafeMemoryOutput(new ByteArrayOutputStream())); - } - - private void runIntTest (UnsafeMemoryOutput write) { - write.writeInt(0); - write.writeInt(63); - write.writeInt(64); - write.writeInt(127); - write.writeInt(128); - write.writeInt(8192); - write.writeInt(16384); - write.writeInt(2097151); - write.writeInt(1048575); - write.writeInt(134217727); - write.writeInt(268435455); - write.writeInt(134217728); - write.writeInt(268435456); - write.writeInt(-2097151); - write.writeInt(-1048575); - write.writeInt(-134217727); - write.writeInt(-268435455); - write.writeInt(-134217728); - write.writeInt(-268435456); - assertEquals(4, write.writeInt(0, true)); - assertEquals(4, write.writeInt(0, false)); - assertEquals(4, write.writeInt(63, true)); - assertEquals(4, write.writeInt(63, false)); - assertEquals(4, write.writeInt(64, true)); - assertEquals(4, write.writeInt(64, false)); - assertEquals(4, write.writeInt(127, true)); - assertEquals(4, write.writeInt(127, false)); - assertEquals(4, write.writeInt(128, true)); - assertEquals(4, write.writeInt(128, false)); - assertEquals(4, write.writeInt(8191, true)); - assertEquals(4, write.writeInt(8191, false)); - assertEquals(4, write.writeInt(8192, true)); - assertEquals(4, write.writeInt(8192, false)); - assertEquals(4, write.writeInt(16383, true)); - assertEquals(4, write.writeInt(16383, false)); - assertEquals(4, write.writeInt(16384, true)); - assertEquals(4, write.writeInt(16384, false)); - assertEquals(4, write.writeInt(2097151, true)); - assertEquals(4, write.writeInt(2097151, false)); - assertEquals(4, write.writeInt(1048575, true)); - assertEquals(4, write.writeInt(1048575, false)); - assertEquals(4, write.writeInt(134217727, true)); - assertEquals(4, write.writeInt(134217727, false)); - assertEquals(4, write.writeInt(268435455, true)); - assertEquals(4, write.writeInt(268435455, false)); - assertEquals(4, write.writeInt(134217728, true)); - assertEquals(4, write.writeInt(134217728, false)); - assertEquals(4, write.writeInt(268435456, true)); - assertEquals(4, write.writeInt(268435456, false)); - assertEquals(4, write.writeInt(-64, false)); - assertEquals(4, write.writeInt(-64, true)); - assertEquals(4, write.writeInt(-65, false)); - assertEquals(4, write.writeInt(-65, true)); - assertEquals(4, write.writeInt(-8192, false)); - assertEquals(4, write.writeInt(-8192, true)); - assertEquals(4, write.writeInt(-1048576, false)); - assertEquals(4, write.writeInt(-1048576, true)); - assertEquals(4, write.writeInt(-134217728, false)); - assertEquals(4, write.writeInt(-134217728, true)); - assertEquals(4, write.writeInt(-134217729, false)); - assertEquals(4, write.writeInt(-134217729, true)); - - Input read = new UnsafeMemoryInput(write.toBytes()); - assertEquals(0, read.readInt()); - assertEquals(63, read.readInt()); - assertEquals(64, read.readInt()); - assertEquals(127, read.readInt()); - assertEquals(128, read.readInt()); - assertEquals(8192, read.readInt()); - assertEquals(16384, read.readInt()); - assertEquals(2097151, read.readInt()); - assertEquals(1048575, read.readInt()); - assertEquals(134217727, read.readInt()); - assertEquals(268435455, read.readInt()); - assertEquals(134217728, read.readInt()); - assertEquals(268435456, read.readInt()); - assertEquals(-2097151, read.readInt()); - assertEquals(-1048575, read.readInt()); - assertEquals(-134217727, read.readInt()); - assertEquals(-268435455, read.readInt()); - assertEquals(-134217728, read.readInt()); - assertEquals(-268435456, read.readInt()); - assertEquals(true, read.canReadInt()); - assertEquals(true, read.canReadInt()); - assertEquals(true, read.canReadInt()); - assertEquals(0, read.readInt(true)); - assertEquals(0, read.readInt(false)); - assertEquals(63, read.readInt(true)); - assertEquals(63, read.readInt(false)); - assertEquals(64, read.readInt(true)); - assertEquals(64, read.readInt(false)); - assertEquals(127, read.readInt(true)); - assertEquals(127, read.readInt(false)); - assertEquals(128, read.readInt(true)); - assertEquals(128, read.readInt(false)); - assertEquals(8191, read.readInt(true)); - assertEquals(8191, read.readInt(false)); - assertEquals(8192, read.readInt(true)); - assertEquals(8192, read.readInt(false)); - assertEquals(16383, read.readInt(true)); - assertEquals(16383, read.readInt(false)); - assertEquals(16384, read.readInt(true)); - assertEquals(16384, read.readInt(false)); - assertEquals(2097151, read.readInt(true)); - assertEquals(2097151, read.readInt(false)); - assertEquals(1048575, read.readInt(true)); - assertEquals(1048575, read.readInt(false)); - assertEquals(134217727, read.readInt(true)); - assertEquals(134217727, read.readInt(false)); - assertEquals(268435455, read.readInt(true)); - assertEquals(268435455, read.readInt(false)); - assertEquals(134217728, read.readInt(true)); - assertEquals(134217728, read.readInt(false)); - assertEquals(268435456, read.readInt(true)); - assertEquals(268435456, read.readInt(false)); - assertEquals(-64, read.readInt(false)); - assertEquals(-64, read.readInt(true)); - assertEquals(-65, read.readInt(false)); - assertEquals(-65, read.readInt(true)); - assertEquals(-8192, read.readInt(false)); - assertEquals(-8192, read.readInt(true)); - assertEquals(-1048576, read.readInt(false)); - assertEquals(-1048576, read.readInt(true)); - assertEquals(-134217728, read.readInt(false)); - assertEquals(-134217728, read.readInt(true)); - assertEquals(-134217729, read.readInt(false)); - assertEquals(-134217729, read.readInt(true)); - assertEquals(false, read.canReadInt()); - - Random random = new Random(); - for (int i = 0; i < 10000; i++) { - int value = random.nextInt(); - write.clear(); - write.writeInt(value); - write.writeInt(value, true); - write.writeInt(value, false); - read.setBuffer(write.toBytes()); - assertEquals(value, read.readInt()); - assertEquals(value, read.readInt(true)); - assertEquals(value, read.readInt(false)); - } - } - - public void testLongs () { - runLongTest(new UnsafeMemoryOutput(4096)); - runLongTest(new UnsafeMemoryOutput(new ByteArrayOutputStream())); - } - - private void runLongTest (UnsafeMemoryOutput write) { - write.writeLong(0); - write.writeLong(63); - write.writeLong(64); - write.writeLong(127); - write.writeLong(128); - write.writeLong(8192); - write.writeLong(16384); - write.writeLong(2097151); - write.writeLong(1048575); - write.writeLong(134217727); - write.writeLong(268435455); - write.writeLong(134217728); - write.writeLong(268435456); - write.writeLong(-2097151); - write.writeLong(-1048575); - write.writeLong(-134217727); - write.writeLong(-268435455); - write.writeLong(-134217728); - write.writeLong(-268435456); - assertEquals(8, write.writeLong(0, true)); - assertEquals(8, write.writeLong(0, false)); - assertEquals(8, write.writeLong(63, true)); - assertEquals(8, write.writeLong(63, false)); - assertEquals(8, write.writeLong(64, true)); - assertEquals(8, write.writeLong(64, false)); - assertEquals(8, write.writeLong(127, true)); - assertEquals(8, write.writeLong(127, false)); - assertEquals(8, write.writeLong(128, true)); - assertEquals(8, write.writeLong(128, false)); - assertEquals(8, write.writeLong(8191, true)); - assertEquals(8, write.writeLong(8191, false)); - assertEquals(8, write.writeLong(8192, true)); - assertEquals(8, write.writeLong(8192, false)); - assertEquals(8, write.writeLong(16383, true)); - assertEquals(8, write.writeLong(16383, false)); - assertEquals(8, write.writeLong(16384, true)); - assertEquals(8, write.writeLong(16384, false)); - assertEquals(8, write.writeLong(2097151, true)); - assertEquals(8, write.writeLong(2097151, false)); - assertEquals(8, write.writeLong(1048575, true)); - assertEquals(8, write.writeLong(1048575, false)); - assertEquals(8, write.writeLong(134217727, true)); - assertEquals(8, write.writeLong(134217727, false)); - assertEquals(8, write.writeLong(268435455l, true)); - assertEquals(8, write.writeLong(268435455l, false)); - assertEquals(8, write.writeLong(134217728l, true)); - assertEquals(8, write.writeLong(134217728l, false)); - assertEquals(8, write.writeLong(268435456l, true)); - assertEquals(8, write.writeLong(268435456l, false)); - assertEquals(8, write.writeLong(-64, false)); - assertEquals(8, write.writeLong(-64, true)); - assertEquals(8, write.writeLong(-65, false)); - assertEquals(8, write.writeLong(-65, true)); - assertEquals(8, write.writeLong(-8192, false)); - assertEquals(8, write.writeLong(-8192, true)); - assertEquals(8, write.writeLong(-1048576, false)); - assertEquals(8, write.writeLong(-1048576, true)); - assertEquals(8, write.writeLong(-134217728, false)); - assertEquals(8, write.writeLong(-134217728, true)); - assertEquals(8, write.writeLong(-134217729, false)); - assertEquals(8, write.writeLong(-134217729, true)); - - Input read = new UnsafeMemoryInput(write.toBytes()); - assertEquals(0, read.readLong()); - assertEquals(63, read.readLong()); - assertEquals(64, read.readLong()); - assertEquals(127, read.readLong()); - assertEquals(128, read.readLong()); - assertEquals(8192, read.readLong()); - assertEquals(16384, read.readLong()); - assertEquals(2097151, read.readLong()); - assertEquals(1048575, read.readLong()); - assertEquals(134217727, read.readLong()); - assertEquals(268435455, read.readLong()); - assertEquals(134217728, read.readLong()); - assertEquals(268435456, read.readLong()); - assertEquals(-2097151, read.readLong()); - assertEquals(-1048575, read.readLong()); - assertEquals(-134217727, read.readLong()); - assertEquals(-268435455, read.readLong()); - assertEquals(-134217728, read.readLong()); - assertEquals(-268435456, read.readLong()); - assertEquals(0, read.readLong(true)); - assertEquals(0, read.readLong(false)); - assertEquals(63, read.readLong(true)); - assertEquals(63, read.readLong(false)); - assertEquals(64, read.readLong(true)); - assertEquals(64, read.readLong(false)); - assertEquals(127, read.readLong(true)); - assertEquals(127, read.readLong(false)); - assertEquals(128, read.readLong(true)); - assertEquals(128, read.readLong(false)); - assertEquals(8191, read.readLong(true)); - assertEquals(8191, read.readLong(false)); - assertEquals(8192, read.readLong(true)); - assertEquals(8192, read.readLong(false)); - assertEquals(16383, read.readLong(true)); - assertEquals(16383, read.readLong(false)); - assertEquals(16384, read.readLong(true)); - assertEquals(16384, read.readLong(false)); - assertEquals(2097151, read.readLong(true)); - assertEquals(2097151, read.readLong(false)); - assertEquals(1048575, read.readLong(true)); - assertEquals(1048575, read.readLong(false)); - assertEquals(134217727, read.readLong(true)); - assertEquals(134217727, read.readLong(false)); - assertEquals(268435455, read.readLong(true)); - assertEquals(268435455, read.readLong(false)); - assertEquals(134217728, read.readLong(true)); - assertEquals(134217728, read.readLong(false)); - assertEquals(268435456, read.readLong(true)); - assertEquals(268435456, read.readLong(false)); - assertEquals(-64, read.readLong(false)); - assertEquals(-64, read.readLong(true)); - assertEquals(-65, read.readLong(false)); - assertEquals(-65, read.readLong(true)); - assertEquals(-8192, read.readLong(false)); - assertEquals(-8192, read.readLong(true)); - assertEquals(-1048576, read.readLong(false)); - assertEquals(-1048576, read.readLong(true)); - assertEquals(-134217728, read.readLong(false)); - assertEquals(-134217728, read.readLong(true)); - assertEquals(-134217729, read.readLong(false)); - assertEquals(-134217729, read.readLong(true)); - - Random random = new Random(); - for (int i = 0; i < 10000; i++) { - long value = random.nextLong(); - write.clear(); - write.writeLong(value); - write.writeLong(value, true); - write.writeLong(value, false); - read.setBuffer(write.toBytes()); - assertEquals("Element " + i, value, read.readLong()); - assertEquals("Element " + i, value, read.readLong(true)); - assertEquals("Element " + i, value, read.readLong(false)); - } - } - - public void testShorts () { - runShortTest(new UnsafeMemoryOutput(4096)); - runShortTest(new UnsafeMemoryOutput(new ByteArrayOutputStream())); - } - - private void runShortTest (UnsafeMemoryOutput write) { - write.writeShort(0); - write.writeShort(63); - write.writeShort(64); - write.writeShort(127); - write.writeShort(128); - write.writeShort(8192); - write.writeShort(16384); - write.writeShort(32767); - write.writeShort(-63); - write.writeShort(-64); - write.writeShort(-127); - write.writeShort(-128); - write.writeShort(-8192); - write.writeShort(-16384); - write.writeShort(-32768); - - Input read = new UnsafeMemoryInput(write.toBytes()); - assertEquals(0, read.readShort()); - assertEquals(63, read.readShort()); - assertEquals(64, read.readShort()); - assertEquals(127, read.readShort()); - assertEquals(128, read.readShort()); - assertEquals(8192, read.readShort()); - assertEquals(16384, read.readShort()); - assertEquals(32767, read.readShort()); - assertEquals(-63, read.readShort()); - assertEquals(-64, read.readShort()); - assertEquals(-127, read.readShort()); - assertEquals(-128, read.readShort()); - assertEquals(-8192, read.readShort()); - assertEquals(-16384, read.readShort()); - assertEquals(-32768, read.readShort()); - } - - public void testFloats () { - runFloatTest(new UnsafeMemoryOutput(4096)); - runFloatTest(new UnsafeMemoryOutput(new ByteArrayOutputStream())); - } - - private void runFloatTest (UnsafeMemoryOutput write) { - write.writeFloat(0); - write.writeFloat(63); - write.writeFloat(64); - write.writeFloat(127); - write.writeFloat(128); - write.writeFloat(8192); - write.writeFloat(16384); - write.writeFloat(32767); - write.writeFloat(-63); - write.writeFloat(-64); - write.writeFloat(-127); - write.writeFloat(-128); - write.writeFloat(-8192); - write.writeFloat(-16384); - write.writeFloat(-32768); - assertEquals(4, write.writeFloat(0, 1000, true)); - assertEquals(4, write.writeFloat(0, 1000, false)); - assertEquals(4, write.writeFloat(63, 1000, true)); - assertEquals(4, write.writeFloat(63, 1000, false)); - assertEquals(4, write.writeFloat(64, 1000, true)); - assertEquals(4, write.writeFloat(64, 1000, false)); - assertEquals(4, write.writeFloat(127, 1000, true)); - assertEquals(4, write.writeFloat(127, 1000, false)); - assertEquals(4, write.writeFloat(128, 1000, true)); - assertEquals(4, write.writeFloat(128, 1000, false)); - assertEquals(4, write.writeFloat(8191, 1000, true)); - assertEquals(4, write.writeFloat(8191, 1000, false)); - assertEquals(4, write.writeFloat(8192, 1000, true)); - assertEquals(4, write.writeFloat(8192, 1000, false)); - assertEquals(4, write.writeFloat(16383, 1000, true)); - assertEquals(4, write.writeFloat(16383, 1000, false)); - assertEquals(4, write.writeFloat(16384, 1000, true)); - assertEquals(4, write.writeFloat(16384, 1000, false)); - assertEquals(4, write.writeFloat(32767, 1000, true)); - assertEquals(4, write.writeFloat(32767, 1000, false)); - assertEquals(4, write.writeFloat(-64, 1000, false)); - assertEquals(4, write.writeFloat(-64, 1000, true)); - assertEquals(4, write.writeFloat(-65, 1000, false)); - assertEquals(4, write.writeFloat(-65, 1000, true)); - assertEquals(4, write.writeFloat(-8192, 1000, false)); - assertEquals(4, write.writeFloat(-8192, 1000, true)); - - Input read = new UnsafeMemoryInput(write.toBytes()); - assertEquals(read.readFloat(), 0f); - assertEquals(read.readFloat(), 63f); - assertEquals(read.readFloat(), 64f); - assertEquals(read.readFloat(), 127f); - assertEquals(read.readFloat(), 128f); - assertEquals(read.readFloat(), 8192f); - assertEquals(read.readFloat(), 16384f); - assertEquals(read.readFloat(), 32767f); - assertEquals(read.readFloat(), -63f); - assertEquals(read.readFloat(), -64f); - assertEquals(read.readFloat(), -127f); - assertEquals(read.readFloat(), -128f); - assertEquals(read.readFloat(), -8192f); - assertEquals(read.readFloat(), -16384f); - assertEquals(read.readFloat(), -32768f); - assertEquals(read.readFloat(1000, true), 0f); - assertEquals(read.readFloat(1000, false), 0f); - assertEquals(read.readFloat(1000, true), 63f); - assertEquals(read.readFloat(1000, false), 63f); - assertEquals(read.readFloat(1000, true), 64f); - assertEquals(read.readFloat(1000, false), 64f); - assertEquals(read.readFloat(1000, true), 127f); - assertEquals(read.readFloat(1000, false), 127f); - assertEquals(read.readFloat(1000, true), 128f); - assertEquals(read.readFloat(1000, false), 128f); - assertEquals(read.readFloat(1000, true), 8191f); - assertEquals(read.readFloat(1000, false), 8191f); - assertEquals(read.readFloat(1000, true), 8192f); - assertEquals(read.readFloat(1000, false), 8192f); - assertEquals(read.readFloat(1000, true), 16383f); - assertEquals(read.readFloat(1000, false), 16383f); - assertEquals(read.readFloat(1000, true), 16384f); - assertEquals(read.readFloat(1000, false), 16384f); - assertEquals(read.readFloat(1000, true), 32767f); - assertEquals(read.readFloat(1000, false), 32767f); - assertEquals(read.readFloat(1000, false), -64f); - assertEquals(read.readFloat(1000, true), -64f); - assertEquals(read.readFloat(1000, false), -65f); - assertEquals(read.readFloat(1000, true), -65f); - assertEquals(read.readFloat(1000, false), -8192f); - assertEquals(read.readFloat(1000, true), -8192f); - } - - public void testDoubles () { - runDoubleTest(new UnsafeMemoryOutput(4096)); - runDoubleTest(new UnsafeMemoryOutput(new ByteArrayOutputStream())); - } - - private void runDoubleTest (UnsafeMemoryOutput write) { - write.writeDouble(0); - write.writeDouble(63); - write.writeDouble(64); - write.writeDouble(127); - write.writeDouble(128); - write.writeDouble(8192); - write.writeDouble(16384); - write.writeDouble(32767); - write.writeDouble(-63); - write.writeDouble(-64); - write.writeDouble(-127); - write.writeDouble(-128); - write.writeDouble(-8192); - write.writeDouble(-16384); - write.writeDouble(-32768); - assertEquals(8, write.writeDouble(0, 1000, true)); - assertEquals(8, write.writeDouble(0, 1000, false)); - assertEquals(8, write.writeDouble(63, 1000, true)); - assertEquals(8, write.writeDouble(63, 1000, false)); - assertEquals(8, write.writeDouble(64, 1000, true)); - assertEquals(8, write.writeDouble(64, 1000, false)); - assertEquals(8, write.writeDouble(127, 1000, true)); - assertEquals(8, write.writeDouble(127, 1000, false)); - assertEquals(8, write.writeDouble(128, 1000, true)); - assertEquals(8, write.writeDouble(128, 1000, false)); - assertEquals(8, write.writeDouble(8191, 1000, true)); - assertEquals(8, write.writeDouble(8191, 1000, false)); - assertEquals(8, write.writeDouble(8192, 1000, true)); - assertEquals(8, write.writeDouble(8192, 1000, false)); - assertEquals(8, write.writeDouble(16383, 1000, true)); - assertEquals(8, write.writeDouble(16383, 1000, false)); - assertEquals(8, write.writeDouble(16384, 1000, true)); - assertEquals(8, write.writeDouble(16384, 1000, false)); - assertEquals(8, write.writeDouble(32767, 1000, true)); - assertEquals(8, write.writeDouble(32767, 1000, false)); - assertEquals(8, write.writeDouble(-64, 1000, false)); - assertEquals(8, write.writeDouble(-64, 1000, true)); - assertEquals(8, write.writeDouble(-65, 1000, false)); - assertEquals(8, write.writeDouble(-65, 1000, true)); - assertEquals(8, write.writeDouble(-8192, 1000, false)); - assertEquals(8, write.writeDouble(-8192, 1000, true)); - write.writeDouble(1.23456d); - - Input read = new UnsafeMemoryInput(write.toBytes()); - assertEquals(read.readDouble(), 0d); - assertEquals(read.readDouble(), 63d); - assertEquals(read.readDouble(), 64d); - assertEquals(read.readDouble(), 127d); - assertEquals(read.readDouble(), 128d); - assertEquals(read.readDouble(), 8192d); - assertEquals(read.readDouble(), 16384d); - assertEquals(read.readDouble(), 32767d); - assertEquals(read.readDouble(), -63d); - assertEquals(read.readDouble(), -64d); - assertEquals(read.readDouble(), -127d); - assertEquals(read.readDouble(), -128d); - assertEquals(read.readDouble(), -8192d); - assertEquals(read.readDouble(), -16384d); - assertEquals(read.readDouble(), -32768d); - assertEquals(read.readDouble(1000, true), 0d); - assertEquals(read.readDouble(1000, false), 0d); - assertEquals(read.readDouble(1000, true), 63d); - assertEquals(read.readDouble(1000, false), 63d); - assertEquals(read.readDouble(1000, true), 64d); - assertEquals(read.readDouble(1000, false), 64d); - assertEquals(read.readDouble(1000, true), 127d); - assertEquals(read.readDouble(1000, false), 127d); - assertEquals(read.readDouble(1000, true), 128d); - assertEquals(read.readDouble(1000, false), 128d); - assertEquals(read.readDouble(1000, true), 8191d); - assertEquals(read.readDouble(1000, false), 8191d); - assertEquals(read.readDouble(1000, true), 8192d); - assertEquals(read.readDouble(1000, false), 8192d); - assertEquals(read.readDouble(1000, true), 16383d); - assertEquals(read.readDouble(1000, false), 16383d); - assertEquals(read.readDouble(1000, true), 16384d); - assertEquals(read.readDouble(1000, false), 16384d); - assertEquals(read.readDouble(1000, true), 32767d); - assertEquals(read.readDouble(1000, false), 32767d); - assertEquals(read.readDouble(1000, false), -64d); - assertEquals(read.readDouble(1000, true), -64d); - assertEquals(read.readDouble(1000, false), -65d); - assertEquals(read.readDouble(1000, true), -65d); - assertEquals(read.readDouble(1000, false), -8192d); - assertEquals(read.readDouble(1000, true), -8192d); - assertEquals(1.23456d, read.readDouble()); - - read.close(); - } - - public void testBooleans () { - runBooleanTest(new UnsafeMemoryOutput(4096)); - runBooleanTest(new UnsafeMemoryOutput(new ByteArrayOutputStream())); - } - - private void runBooleanTest (UnsafeMemoryOutput write) { - for (int i = 0; i < 100; i++) { - write.writeBoolean(true); - write.writeBoolean(false); - } - - Input read = new UnsafeMemoryInput(write.toBytes()); - for (int i = 0; i < 100; i++) { - assertEquals(true, read.readBoolean()); - assertEquals(false, read.readBoolean()); - } - - read.close(); - } - - public void testChars () { - runCharTest(new UnsafeMemoryOutput(4096)); - runCharTest(new UnsafeMemoryOutput(new ByteArrayOutputStream())); - } - - private void runCharTest (UnsafeMemoryOutput write) { - write.writeChar((char)0); - write.writeChar((char)63); - write.writeChar((char)64); - write.writeChar((char)127); - write.writeChar((char)128); - write.writeChar((char)8192); - write.writeChar((char)16384); - write.writeChar((char)32767); - write.writeChar((char)65535); - - Input read = new UnsafeMemoryInput(write.toBytes()); - assertEquals(0, read.readChar()); - assertEquals(63, read.readChar()); - assertEquals(64, read.readChar()); - assertEquals(127, read.readChar()); - assertEquals(128, read.readChar()); - assertEquals(8192, read.readChar()); - assertEquals(16384, read.readChar()); - assertEquals(32767, read.readChar()); - assertEquals(65535, read.readChar()); - - read.close(); - } -} diff --git a/test/dorkbox/network/kryo/pool/KryoPoolBenchmarkTest.java b/test/dorkbox/network/kryo/pool/KryoPoolBenchmarkTest.java deleted file mode 100644 index a68ab0b1..00000000 --- a/test/dorkbox/network/kryo/pool/KryoPoolBenchmarkTest.java +++ /dev/null @@ -1,188 +0,0 @@ -/* Copyright (c) 2008, Nathan Sweet - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided with the distribution. - * - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package dorkbox.network.kryo.pool; - -import java.util.Arrays; -import java.util.concurrent.TimeUnit; - -import org.junit.Test; - -import com.esotericsoftware.kryo.Kryo; - -import dorkbox.network.kryo.FieldSerializerTest; -import dorkbox.objectPool.ObjectPool; -import dorkbox.objectPool.PoolableObject; - -public -class KryoPoolBenchmarkTest { - - private static final int WARMUP_ITERATIONS = 10000; - - /** - * Number of runs. - */ - private static final int RUN_CNT = 10; - - /** - * Number of iterations. Set it to something rather big for obtaining meaningful results - */ -// private static final int ITER_CNT = 200000; - private static final int ITER_CNT = 10000; - private static final int SLEEP_BETWEEN_RUNS = 100; - - // not private to prevent the synthetic accessor method - static PoolableObject poolableObject = new PoolableObject() { - @Override - public - Kryo create() { - Kryo kryo = new Kryo(); - kryo.register(FieldSerializerTest.DefaultTypes.class); - kryo.register(SampleObject.class); - return kryo; - } - }; - - @Test - public - void testWithoutPool() throws Exception { - // Warm-up phase: Perform 100000 iterations - runWithoutPool(1, WARMUP_ITERATIONS, false); - runWithoutPool(RUN_CNT, ITER_CNT, true); - } - - @Test - public - void testWithPool() throws Exception { - // Warm-up phase: Perform 100000 iterations - runWithPool(ObjectPool.NonBlocking(poolableObject), 1, WARMUP_ITERATIONS, false); - runWithPool(ObjectPool.NonBlocking(poolableObject), RUN_CNT, ITER_CNT, true); - } - - @Test - public - void testWithPoolWithSoftReferences() throws Exception { - // Warm-up phase: Perform 100000 iterations - runWithPool(ObjectPool.NonBlockingSoftReference(poolableObject), 1, WARMUP_ITERATIONS, false); - runWithPool(ObjectPool.NonBlockingSoftReference(poolableObject), RUN_CNT, ITER_CNT, true); - } - - private - void run(String description, Runnable runnable, final int runCount, final int iterCount, boolean outputResults) throws Exception { - long avgDur = 0; - long bestTime = Long.MAX_VALUE; - - for (int i = 0; i < runCount; i++) { - long start = System.nanoTime(); - - for (int j = 0; j < iterCount; j++) { - runnable.run(); - } - - long dur = System.nanoTime() - start; - dur = TimeUnit.NANOSECONDS.toMillis(dur); - - if (outputResults) - System.out.format(">>> %s (run %d): %,d ms\n", description, i + 1, dur); - avgDur += dur; - bestTime = Math.min(bestTime, dur); - systemCleanupAfterRun(); - } - - avgDur /= runCount; - - if (outputResults) { - System.out.format("\n>>> %s (average): %,d ms", description, avgDur); - System.out.format("\n>>> %s (best time): %,d ms\n\n", description, bestTime); - } - - } - - private - void runWithoutPool(final int runCount, final int iterCount, boolean outputResults) throws Exception { - run("Without pool", new Runnable() { - @Override - public - void run() { - poolableObject.create(); - } - }, runCount, iterCount, outputResults); - } - - private - void runWithPool(final ObjectPool pool, final int runCount, final int iterCount, boolean outputResults) throws Exception { - run("With pool " + pool.toString(), new Runnable() { - @Override - public - void run() { - Kryo kryo = pool.take(); - pool.put(kryo); - } - }, runCount, iterCount, outputResults); - } - - private - void systemCleanupAfterRun() throws InterruptedException { - System.gc(); - Thread.sleep(SLEEP_BETWEEN_RUNS); - System.gc(); - } - - private static - class SampleObject { - private int intVal; - private float floatVal; - private Short shortVal; - private long[] longArr; - private double[] dblArr; - private String str; - - public - SampleObject() { - } - - SampleObject(int intVal, float floatVal, Short shortVal, long[] longArr, double[] dblArr, String str) { - this.intVal = intVal; - this.floatVal = floatVal; - this.shortVal = shortVal; - this.longArr = longArr; - this.dblArr = dblArr; - this.str = str; - } - - /** - * {@inheritDoc} - */ - @Override - public - boolean equals(Object other) { - if (this == other) - return true; - - if (other == null || getClass() != other.getClass()) - return false; - - SampleObject obj = (SampleObject) other; - - return intVal == obj.intVal && floatVal == obj.floatVal && shortVal.equals(obj.shortVal) && Arrays.equals(dblArr, obj.dblArr) && - Arrays.equals(longArr, obj.longArr) && (str == null ? obj.str == null : str.equals(obj.str)); - } - } - -}