More tests

This commit is contained in:
Andrea Cavalli 2023-04-20 01:26:17 +02:00
parent 1eb4b0334c
commit c22d6719d9
16 changed files with 523 additions and 171 deletions

View File

@ -1,5 +1,6 @@
package it.cavallium.buffer;
import it.cavallium.data.generator.nativedata.Int52;
import it.cavallium.stream.SafeByteArrayInputStream;
import it.cavallium.stream.SafeByteArrayOutputStream;
import it.cavallium.stream.SafeDataOutput;
@ -99,6 +100,49 @@ public interface Buf extends ByteList, RandomAccess {
void writeTo(SafeDataOutput dataOutput);
/**
* @param i byte offset
*/
default float getFloat(int i) {
return Float.intBitsToFloat(getInt(i));
}
/**
* @param i byte offset
*/
default double getDouble(int i) {
return Double.longBitsToDouble(getLong(i));
}
/**
* @param i byte offset
*/
default char getChar(int i) {
byte b1 = getByte(i);
byte b2 = getByte(i + 1);
return (char) ((b1 & 0xFF) << 8 | (b2 & 0xFF));
}
/**
* @param i byte offset
*/
default short getShort(int i) {
byte b1 = getByte(i);
byte b2 = getByte(i + 1);
return (short) ((b1 & 0xFF) << 8 | (b2 & 0xFF));
}
/**
* @param i byte offset
*/
default int getInt(int i) {
byte b1 = getByte(i);
byte b2 = getByte(i + 1);
byte b3 = getByte(i + 2);
byte b4 = getByte(i + 3);
return b1 << 24 | (b2 & 0xFF) << 16 | (b3 & 0xFF) << 8 | (b4 & 0xFF);
}
/**
* @param i byte offset
*/
@ -124,26 +168,21 @@ public interface Buf extends ByteList, RandomAccess {
/**
* @param i byte offset
*/
default int getInt(int i) {
default long getInt52(int i) {
byte b1 = getByte(i);
byte b2 = getByte(i + 1);
byte b3 = getByte(i + 2);
byte b4 = getByte(i + 3);
return b1 << 24 | (b2 & 0xFF) << 16 | (b3 & 0xFF) << 8 | (b4 & 0xFF);
}
/**
* @param i byte offset
*/
default float getFloat(int i) {
return Float.intBitsToFloat(getInt(i));
}
/**
* @param i byte offset
*/
default double getDouble(int i) {
return Double.longBitsToDouble(getLong(i));
byte b5 = getByte(i + 4);
byte b6 = getByte(i + 5);
byte b7 = getByte(i + 6);
return (b1 & 0xFFL) << 48
| (b2 & 0xFFL) << 40
| (b3 & 0xFFL) << 32
| (b4 & 0xFFL) << 24
| (b5 & 0xFFL) << 16
| (b6 & 0xFFL) << 8
| (b7 & 0xFFL);
}
/**
@ -153,6 +192,27 @@ public interface Buf extends ByteList, RandomAccess {
return getByte(i) != 0;
}
/**
* @param i byte offset
*/
default String getShortText(int i, Charset charset) {
var len = getShort(i);
return getString(i + Short.BYTES, len, charset);
}
/**
* @param i byte offset
*/
default String getMediumText(int i, Charset charset) {
var len = getInt(i);
return getString(i + Integer.BYTES, len, charset);
}
/**
* @param i byte offset
*/
String getString(int i, int length, Charset charset);
/**
* @param i byte offset
*/
@ -167,6 +227,22 @@ public interface Buf extends ByteList, RandomAccess {
set(i, val);
}
/**
* @param i byte offset
*/
default void setChar(int i, char val) {
set(i, (byte) (val >> 8));
set(i + 1, (byte) val);
}
/**
* @param i byte offset
*/
default void setShort(int i, short val) {
set(i, (byte) (val >> 8));
set(i + 1, (byte) val);
}
/**
* @param i byte offset
*/
@ -191,6 +267,20 @@ public interface Buf extends ByteList, RandomAccess {
set(i + 7, (byte) val);
}
/**
* @param i byte offset
*/
default void setInt52(int i, long val) {
Int52.checkValidity(val);
set(i, (byte) (val >> 48));
set(i + 1, (byte) (val >> 40));
set(i + 2, (byte) (val >> 32));
set(i + 3, (byte) (val >> 24));
set(i + 4, (byte) (val >> 16));
set(i + 5, (byte) (val >> 8));
set(i + 6, (byte) val);
}
/**
* @param i byte offset
*/

View File

@ -1,17 +1,17 @@
package it.cavallium.buffer;
import static java.util.Objects.checkFromToIndex;
import it.cavallium.stream.SafeByteArrayOutputStream;
import it.cavallium.stream.SafeDataOutput;
import it.cavallium.stream.SafeDataOutputStream;
import it.unimi.dsi.fastutil.Arrays;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Objects;
import org.jetbrains.annotations.NotNull;
import static java.util.Objects.checkFromToIndex;
public class BufDataOutput implements SafeDataOutput {
private final SafeByteArrayOutputStream buf;
@ -62,6 +62,8 @@ public class BufDataOutput implements SafeDataOutput {
}
}
@IgnoreCoverage
@Deprecated(forRemoval = true)
public static BufDataOutput wrap(Buf buf, int from, int to) {
checkFromToIndex(from, to, buf.size());
if (buf.isEmpty()) {
@ -71,6 +73,8 @@ public class BufDataOutput implements SafeDataOutput {
}
}
@IgnoreCoverage
@Deprecated(forRemoval = true)
public static BufDataOutput wrap(Buf buf) {
if (buf.isEmpty()) {
return createLimited(0);
@ -234,6 +238,11 @@ public class BufDataOutput implements SafeDataOutput {
return Buf.wrap(this.buf.array, this.buf.length);
}
public Buf toList() {
dOut.flush();
return Buf.wrap(Arrays.copyOf(this.buf.array, this.buf.length));
}
@Override
public String toString() {
return dOut.toString();

View File

@ -1,21 +1,35 @@
package it.cavallium.buffer;
import static it.unimi.dsi.fastutil.Arrays.ensureFromTo;
import static java.util.Objects.checkFromIndexSize;
import static java.util.Objects.checkFromToIndex;
import it.cavallium.stream.SafeByteArrayInputStream;
import it.cavallium.stream.SafeByteArrayOutputStream;
import it.cavallium.stream.SafeDataOutput;
import it.unimi.dsi.fastutil.bytes.*;
import it.unimi.dsi.fastutil.bytes.AbstractByteList;
import it.unimi.dsi.fastutil.bytes.ByteArrayList;
import it.unimi.dsi.fastutil.bytes.ByteArrays;
import it.unimi.dsi.fastutil.bytes.ByteCollection;
import it.unimi.dsi.fastutil.bytes.ByteConsumer;
import it.unimi.dsi.fastutil.bytes.ByteIterator;
import it.unimi.dsi.fastutil.bytes.ByteIterators;
import it.unimi.dsi.fastutil.bytes.ByteList;
import it.unimi.dsi.fastutil.bytes.ByteListIterator;
import it.unimi.dsi.fastutil.bytes.BytePredicate;
import it.unimi.dsi.fastutil.bytes.ByteSpliterator;
import it.unimi.dsi.fastutil.bytes.ByteSpliterators;
import it.unimi.dsi.fastutil.bytes.ByteUnaryOperator;
import java.io.Serial;
import java.nio.charset.Charset;
import java.util.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.IntPredicate;
import java.util.function.IntUnaryOperator;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.VisibleForTesting;
@ -220,7 +234,12 @@ class ByteListBuf extends ByteArrayList implements Buf {
@Override
public String toString(Charset charset) {
return new String(a, 0, size, charset);
return getString(0, size, charset);
}
@Override
public String getString(int i, int length, Charset charset) {
return new String(a, i, length, charset);
}
class SubList extends AbstractByteList.ByteRandomAccessSubList implements Buf {
@ -509,6 +528,12 @@ class ByteListBuf extends ByteArrayList implements Buf {
public String toString(Charset charset) {
return new String(a, from, size(), charset);
}
@Override
public String getString(int i, int length, Charset charset) {
checkFromIndexSize(i, length, to - from);
return new String(a, from + i, length, charset);
}
}
@IgnoreCoverage

View File

@ -14,7 +14,7 @@ public class ArrayStringSerializer implements DataSerializer<List<String>> {
public void serialize(SafeDataOutput dataOutput, @NotNull List<String> data) {
dataOutput.writeInt(data.size());
for (String item : data) {
dataOutput.writeUTF(item);
dataOutput.writeShortText(item, StandardCharsets.UTF_8);
}
}

View File

@ -1,7 +1,6 @@
package it.cavallium.data.generator.nativedata;
import java.lang.annotation.Native;
import java.util.Objects;
import org.jetbrains.annotations.NotNull;
public class Int52 extends Number implements Comparable<Int52> {
@ -23,6 +22,10 @@ public class Int52 extends Number implements Comparable<Int52> {
public static final Int52 ONE = new Int52(1L);
public static final Int52 TWO = new Int52(2L);
public static final Int52 TEN = new Int52(10L);
public static final long MAX_VALUE_L = 0x0F_FF_FF_FF_FF_FF_FFL;
public static final long MIN_VALUE_L = 0;
public static final Int52 MAX_VALUE = fromLongSafe(MAX_VALUE_L);
public static final Int52 MIN_VALUE = ZERO;
private final long value;
@ -30,7 +33,18 @@ public class Int52 extends Number implements Comparable<Int52> {
this.value = value;
}
public static void checkValidity(long value) {
if (value < 0 || value > MAX_VALUE_L) {
throw new IllegalArgumentException("Only positive values below or equal to " + MAX_VALUE_L + " are supported: " + value);
}
}
public static Int52 fromLong(long value) {
checkValidity(value);
return fromLongSafe(value);
}
private static Int52 fromLongSafe(long value) {
if (value == 0) {
return ZERO;
} else if (value == 1) {
@ -39,15 +53,33 @@ public class Int52 extends Number implements Comparable<Int52> {
return TWO;
} else if (value == 10) {
return TEN;
} else if (value <= 0) {
throw new IllegalArgumentException("Only positive values are supported");
} else if (value > 0x0F_FF_FF_FF_FF_FF_FFL) {
throw new IllegalArgumentException("Only values below or equal to " + 0xFFFFFFFFFFFFFL + " are supported");
} else {
return new Int52(value);
}
}
public static Int52 fromByteArray(byte[] bytes) {
return fromLongSafe(fromByteArrayL(bytes));
}
public static Int52 fromBytes(byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7) {
return fromLongSafe(fromBytesL(b1, b2, b3, b4, b5, b6, b7));
}
public static long fromByteArrayL(byte[] bytes) {
return fromBytesL(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6]);
}
public static long fromBytesL(byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7) {
return (b1 & 0xFFL) << 48
| (b2 & 0xFFL) << 40
| (b3 & 0xFFL) << 32
| (b4 & 0xFFL) << 24
| (b5 & 0xFFL) << 16
| (b6 & 0xFFL) << 8
| (b7 & 0xFFL);
}
long getValue() {
return value;
}

View File

@ -18,7 +18,7 @@ public class NullableStringSerializer implements DataSerializer<NullableString>
} else {
dataOutput.writeBoolean(true);
String dataContent = data.get();
dataOutput.writeUTF(dataContent);
dataOutput.writeShortText(dataContent, StandardCharsets.UTF_8);
}
}

View File

@ -0,0 +1,36 @@
package it.cavallium.stream;
import it.cavallium.buffer.IgnoreCoverage;
import java.util.Objects;
import org.jetbrains.annotations.NotNull;
class NullOutputStream extends SafeOutputStream {
private volatile boolean closed;
@IgnoreCoverage
private void ensureOpen() {
if (closed) {
throw new IllegalStateException("Stream closed");
}
}
@IgnoreCoverage
@Override
public void write(int b) {
ensureOpen();
}
@IgnoreCoverage
@Override
public void write(byte @NotNull [] b, int off, int len) {
Objects.checkFromIndexSize(off, len, b.length);
ensureOpen();
}
@IgnoreCoverage
@Override
public void close() {
closed = true;
}
}

View File

@ -16,15 +16,14 @@
package it.cavallium.stream;
import static java.util.Objects.checkFromToIndex;
import it.cavallium.buffer.IgnoreCoverage;
import it.unimi.dsi.fastutil.bytes.ByteArrays;
import java.util.Arrays;
import java.util.HexFormat;
import java.util.Objects;
import static java.util.Objects.checkFromToIndex;
/** Simple, fast byte-array output stream that exposes the backing array.
*
* <p>{@link java.io.ByteArrayOutputStream} is nice, but to get its content you
@ -143,32 +142,19 @@ public class SafeByteArrayOutputStream extends SafeMeasurableOutputStream implem
private void growBy(int len) {
if (wrapped) {
ensureWrappedBounds(arrayPosition, arrayPosition + len);
}
if (arrayPosition + len > array.length) {
if (wrapped) {
throw new ArrayIndexOutOfBoundsException(arrayPosition + len - 1);
} else {
array = ByteArrays.grow(array, arrayPosition + len, arrayPosition);
}
} else if (arrayPosition + len > array.length) {
array = ByteArrays.grow(array, arrayPosition + len, arrayPosition);
}
}
@Override
public void position(final long newPosition) {
if (wrapped) {
arrayPosition = (int) (newPosition + wrappedFrom);
} else {
arrayPosition = (int)newPosition;
}
arrayPosition = (int) (newPosition + wrappedFrom);
}
@Override
public long position() {
if (wrapped) {
return arrayPosition - wrappedFrom;
} else {
return arrayPosition;
}
return arrayPosition - wrappedFrom;
}
@Override

View File

@ -25,8 +25,6 @@
package it.cavallium.stream;
import org.jetbrains.annotations.NotNull;
import java.nio.charset.Charset;
/**
@ -291,6 +289,7 @@ public interface SafeDataOutput {
*
* @param s the string of bytes to be written.
*/
@Deprecated
void writeBytes(String s);
/**
@ -310,6 +309,7 @@ public interface SafeDataOutput {
*
* @param s the string value to be written.
*/
@Deprecated
void writeChars(String s);
/**

View File

@ -25,7 +25,7 @@
package it.cavallium.stream;
import java.io.DataOutputStream;
import it.cavallium.buffer.IgnoreCoverage;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
@ -63,11 +63,7 @@ public class SafeDataOutputStream extends SafeFilterOutputStream implements Safe
* until it reaches Integer.MAX_VALUE.
*/
private void incCount(int value) {
int temp = written + value;
if (temp < 0) {
temp = Integer.MAX_VALUE;
}
written = temp;
written = Math.addExact(written, value);
}
/**
@ -113,6 +109,7 @@ public class SafeDataOutputStream extends SafeFilterOutputStream implements Safe
* @see SafeFilterOutputStream#out
* @see java.io.OutputStream#flush()
*/
@IgnoreCoverage
public void flush() {
out.flush();
}
@ -274,6 +271,8 @@ public class SafeDataOutputStream extends SafeFilterOutputStream implements Safe
* @param s a string of bytes to be written.
* @see SafeFilterOutputStream#out
*/
@Deprecated
@IgnoreCoverage
public final void writeBytes(String s) {
int len = s.length();
for (int i = 0 ; i < len ; i++) {
@ -293,6 +292,8 @@ public class SafeDataOutputStream extends SafeFilterOutputStream implements Safe
* @see SafeDataOutputStream#writeChar(int)
* @see SafeFilterOutputStream#out
*/
@Deprecated
@IgnoreCoverage
public final void writeChars(String s) {
int len = s.length();
for (int i = 0 ; i < len ; i++) {
@ -322,6 +323,7 @@ public class SafeDataOutputStream extends SafeFilterOutputStream implements Safe
* @param str a string to be written.
* @see #writeChars(String)
*/
@IgnoreCoverage
@Deprecated
public final void writeUTF(String str) {
writeShortText(str, StandardCharsets.UTF_8);
@ -363,8 +365,4 @@ public class SafeDataOutputStream extends SafeFilterOutputStream implements Safe
public final int size() {
return written;
}
public DataOutputStream asDataOutputStream() {
return new DataOutputStream(this.out);
}
}

View File

@ -1,6 +1,9 @@
package it.cavallium.stream;
import it.cavallium.buffer.IgnoreCoverage;
import org.jetbrains.annotations.NotNull;
/**
* This class is the superclass of all classes that filter output
* streams. These streams sit on top of an already existing output
@ -21,17 +24,7 @@ public class SafeFilterOutputStream extends SafeOutputStream {
/**
* The underlying output stream to be filtered.
*/
protected SafeOutputStream out;
/**
* Whether the stream is closed; implicitly initialized to false.
*/
private volatile boolean closed;
/**
* Object used to prevent a race on the 'closed' instance variable.
*/
private final Object closeLock = new Object();
protected final SafeOutputStream out;
/**
* Creates an output stream filter built on top of the specified
@ -58,6 +51,7 @@ public class SafeFilterOutputStream extends SafeOutputStream {
* @param b the {@code byte}.
*/
@Override
@IgnoreCoverage
public void write(int b) {
out.write(b);
}
@ -77,9 +71,10 @@ public class SafeFilterOutputStream extends SafeOutputStream {
* @param b the data to be written.
* @see SafeFilterOutputStream#write(byte[], int, int)
*/
@IgnoreCoverage
@Override
public void write(byte b[]) {
write(b, 0, b.length);
public void write(byte @NotNull [] b) {
out.write(b);
}
/**
@ -101,14 +96,10 @@ public class SafeFilterOutputStream extends SafeOutputStream {
* @param len the number of bytes to write.
* @see SafeFilterOutputStream#write(int)
*/
@IgnoreCoverage
@Override
public void write(byte b[], int off, int len) {
if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
throw new IndexOutOfBoundsException();
for (int i = 0 ; i < len ; i++) {
write(b[off + i]);
}
public void write(byte[] b, int off, int len) {
out.write(b, off, len);
}
/**
@ -120,6 +111,7 @@ public class SafeFilterOutputStream extends SafeOutputStream {
*
* @see SafeFilterOutputStream#out
*/
@IgnoreCoverage
@Override
public void flush() {
out.flush();
@ -136,45 +128,9 @@ public class SafeFilterOutputStream extends SafeOutputStream {
* @see SafeFilterOutputStream#flush()
* @see SafeFilterOutputStream#out
*/
@IgnoreCoverage
@Override
public void close() {
if (closed) {
return;
}
synchronized (closeLock) {
if (closed) {
return;
}
closed = true;
}
Throwable flushException = null;
try {
flush();
} catch (Throwable e) {
flushException = e;
throw e;
} finally {
if (flushException == null) {
out.close();
} else {
try {
out.close();
} catch (Throwable closeException) {
// evaluate possible precedence of flushException over closeException
if ((flushException instanceof ThreadDeath) &&
!(closeException instanceof ThreadDeath)) {
flushException.addSuppressed(closeException);
throw (ThreadDeath) flushException;
}
if (flushException != closeException) {
closeException.addSuppressed(flushException);
}
throw closeException;
}
}
}
out.close();
}
}

View File

@ -52,6 +52,7 @@ public abstract class SafeInputStream extends InputStream {
return i;
}
@IgnoreCoverage
public byte[] readAllBytes() {
return readNBytes(Integer.MAX_VALUE);
}
@ -121,6 +122,7 @@ public abstract class SafeInputStream extends InputStream {
return result;
}
@IgnoreCoverage
public int readNBytes(byte[] b, int off, int len) {
Objects.checkFromIndexSize(off, len, b.length);
@ -134,10 +136,12 @@ public abstract class SafeInputStream extends InputStream {
return n;
}
@IgnoreCoverage
public String readString(int length, Charset charset) {
return new String(readNBytes(length), charset);
}
@IgnoreCoverage
public long skip(long n) {
long remaining = n;
int nr;
@ -159,6 +163,7 @@ public abstract class SafeInputStream extends InputStream {
return n - remaining;
}
@IgnoreCoverage
public void skipNBytes(long n) {
if (n > 0) {
long ns = skip(n);
@ -193,6 +198,7 @@ public abstract class SafeInputStream extends InputStream {
throw new UnsupportedOperationException("mark/reset not supported");
}
@IgnoreCoverage
public long transferTo(OutputStream out) {
Objects.requireNonNull(out, "out");
long transferred = 0;

View File

@ -17,12 +17,13 @@ package it.cavallium.stream;
*/
import it.cavallium.buffer.IgnoreCoverage;
import java.io.InputStream;
/** An {@link InputStream} that implements also the {@link SafeMeasurableStream} interface.
*
* @since 5.0.4
*/
@IgnoreCoverage
public abstract class SafeMeasurableInputStream extends SafeInputStream implements SafeMeasurableStream {
}

View File

@ -1,5 +1,6 @@
package it.cavallium.stream;
import it.cavallium.buffer.IgnoreCoverage;
import java.io.Closeable;
import java.io.Flushable;
import java.io.OutputStream;
@ -47,32 +48,8 @@ public abstract class SafeOutputStream extends OutputStream implements Closeable
*
* @since 11
*/
public static OutputStream nullOutputStream() {
return new OutputStream() {
private volatile boolean closed;
private void ensureOpen() {
if (closed) {
throw new IllegalStateException("Stream closed");
}
}
@Override
public void write(int b) {
ensureOpen();
}
@Override
public void write(byte @NotNull [] b, int off, int len) {
Objects.checkFromIndexSize(off, len, b.length);
ensureOpen();
}
@Override
public void close() {
closed = true;
}
};
public static SafeOutputStream nullOutputStream() {
return new NullOutputStream();
}
/**
@ -127,6 +104,7 @@ public abstract class SafeOutputStream extends OutputStream implements Closeable
* @param off the start offset in the data.
* @param len the number of bytes to write.
*/
@IgnoreCoverage
public void write(byte[] b, int off, int len) {
Objects.checkFromIndexSize(off, len, b.length);
// len == 0 condition implicitly handled by loop bounds
@ -152,6 +130,7 @@ public abstract class SafeOutputStream extends OutputStream implements Closeable
* The {@code flush} method of {@code OutputStream} does nothing.
*
*/
@IgnoreCoverage
public void flush() {
}
@ -166,4 +145,5 @@ public abstract class SafeOutputStream extends OutputStream implements Closeable
*/
public void close() {
}
}

View File

@ -1,20 +1,31 @@
package it.cavallium.buffer;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.google.common.primitives.Chars;
import com.google.common.primitives.Longs;
import com.google.common.primitives.Shorts;
import it.cavallium.data.generator.nativedata.Int52;
import it.cavallium.stream.SafeByteArrayInputStream;
import it.cavallium.stream.SafeByteArrayOutputStream;
import it.cavallium.stream.SafeDataOutputStream;
import it.unimi.dsi.fastutil.bytes.*;
import it.unimi.dsi.fastutil.bytes.ByteArrayList;
import it.unimi.dsi.fastutil.bytes.ByteCollections;
import it.unimi.dsi.fastutil.bytes.ByteList;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HexFormat;
import java.util.List;
import java.util.Spliterators;
import java.util.concurrent.atomic.LongAdder;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
@ -109,12 +120,14 @@ public class TestBuffer {
var wrapSmallByteArrayListCappedRangeOffsetAndLen = new BufArg("wrap(small byte array list, 5, same-3)", Buf.wrap(ByteArrayList.of(small.clone()), 5, small.length - 3), small.length - 5 - 3, Arrays.copyOfRange(small, 5, small.length - 3));
var wrapSmallByteListCappedRangeOffsetAndLen = new BufArg("wrap(small byte list, 5, same-3)", Buf.wrap(ByteList.of(small.clone()), 5, small.length - 3), small.length - 5 - 3, Arrays.copyOfRange(small, 5, small.length - 3));
return List.of(emptyBuf, byteListBuf, byteListBufOf, def0Buf, def10Buf, def10000Buf, zeroedBuf, zeroed10Buf, zeroed10000Buf, copyOfEmpty,
copyOfSmall, copyOfBig, wrapByteArrayList, wrapBufSmall, wrapSmallArray, wrapBigArray, wrapSmallByteList, wrapBigByteList,
wrapSmallCapped, wrapBigCapped, wrapSmallCappedSame, wrapBigCappedSame, wrapSmallCappedMinusOne,
wrapBigCappedMinusOne, wrapSmallCappedRangeSame, wrapBigCappedRangeSame, wrapSmallCappedRangeOffset,
wrapBigCappedRangeOffset, wrapSmallCappedRangeOffsetAndLen, wrapBigCappedRangeOffsetAndLen,
wrapSmallCappedRangeLen, wrapBigCappedRangeLen, wrapSmallByteArrayListCappedRangeOffsetAndLen, wrapSmallByteListCappedRangeOffsetAndLen);
return List.of(emptyBuf, byteListBuf, byteListBufOf, def0Buf, def10Buf, def10000Buf, zeroedBuf, zeroed10Buf,
zeroed10000Buf, copyOfEmpty, copyOfSmall, copyOfBig, wrapByteArrayList, wrapBufSmall, wrapSmallArray,
wrapBigArray, wrapSmallByteList, wrapBigByteList, wrapSmallCapped, wrapBigCapped, wrapSmallCappedSame,
wrapBigCappedSame, wrapSmallCappedMinusOne, wrapBigCappedMinusOne, wrapSmallCappedRangeSame,
wrapBigCappedRangeSame, wrapSmallCappedRangeOffset, wrapBigCappedRangeOffset,
wrapSmallCappedRangeOffsetAndLen, wrapBigCappedRangeOffsetAndLen, wrapSmallCappedRangeLen,
wrapBigCappedRangeLen, wrapSmallBufCappedRangeOffsetAndLen, wrapSmallByteArrayListCappedRangeOffsetAndLen,
wrapSmallByteListCappedRangeOffsetAndLen);
}
public static List<BufArg> createSubListBufs() {
@ -275,6 +288,46 @@ public class TestBuffer {
return provideBufs().filter(ba -> ba.initialSize >= Long.BYTES * 2);
}
@ParameterizedTest
@MethodSource
public void testShorts(BufArg bufArg) {
var short1 = bufArg.b.getShort(0);
assertEquals(Shorts.fromByteArray(bufArg.initialContent), short1);
var short2 = bufArg.b.getShort(Short.BYTES);
assertEquals(Shorts.fromByteArray(Arrays.copyOfRange(bufArg.initialContent, Short.BYTES, Short.BYTES * 2)), short2);
var expected1 = (short) (short1 + 1);
bufArg.b.setShort(0, expected1);
var expected2 = (short) (short2 + 1);
bufArg.b.setShort(Short.BYTES, expected2);
assertEquals(expected1, bufArg.b.getShort(0));
assertEquals(expected2, bufArg.b.getShort(Short.BYTES));
}
public static Stream<BufArg> testShorts() {
return provideBufs().filter(ba -> ba.initialSize >= Short.BYTES * 2);
}
@ParameterizedTest
@MethodSource
public void testChars(BufArg bufArg) {
var char1 = bufArg.b.getChar(0);
assertEquals(Chars.fromByteArray(bufArg.initialContent), char1);
var char2 = bufArg.b.getChar(Character.BYTES);
assertEquals(Chars.fromByteArray(Arrays.copyOfRange(bufArg.initialContent, Character.BYTES, Character.BYTES * 2)), char2);
var expected1 = (char) (char1 + 1);
bufArg.b.setChar(0, expected1);
var expected2 = (char) (char2 + 1);
bufArg.b.setChar(Character.BYTES, expected2);
assertEquals(expected1, bufArg.b.getChar(0));
assertEquals(expected2, bufArg.b.getChar(Character.BYTES));
}
public static Stream<BufArg> testChars() {
return provideBufs().filter(ba -> ba.initialSize >= Character.BYTES * 2);
}
@ParameterizedTest
@MethodSource
public void testInts(BufArg bufArg) {
@ -383,6 +436,26 @@ public class TestBuffer {
return provideBufs().filter(ba -> ba.initialSize >= 2);
}
@ParameterizedTest
@MethodSource
public void testInt52s(BufArg bufArg) {
var int521 = bufArg.b.getInt52(0);
assertEquals(Int52.fromByteArrayL(bufArg.initialContent), int521);
var int522 = bufArg.b.getInt52(Int52.BYTES);
assertEquals(Int52.fromByteArrayL(Arrays.copyOf(Arrays.copyOfRange(bufArg.initialContent, Int52.BYTES, Int52.BYTES * 2), Long.BYTES)), int522);
var expected1 = (int521 * 3) % Int52.MAX_VALUE_L;
bufArg.b.setInt52(0, expected1);
var expected2 = (int522 * 3) % Int52.MAX_VALUE_L;
bufArg.b.setInt52(Int52.BYTES, expected2);
assertEquals(expected1, bufArg.b.getInt52(0));
assertEquals(expected2, bufArg.b.getInt52(Int52.BYTES));
}
public static Stream<BufArg> testInt52s() {
return provideBufs().filter(ba -> ba.initialSize >= Int52.BYTES * 2);
}
@ParameterizedTest
@MethodSource("provideBufs")
public void testString(BufArg bufArg) {

View File

@ -1,44 +1,74 @@
package it.cavallium.stream;
import it.cavallium.buffer.Buf;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import it.cavallium.buffer.Buf;
import it.cavallium.buffer.BufDataOutput;
import it.cavallium.data.generator.nativedata.Int52;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
public class TestOutput {
@Test
public void testBufOutputStream() throws IOException {
var buf = Buf.createZeroes(Integer.BYTES * 3);
var buf = Buf.createZeroes(Integer.BYTES * 3 + Short.BYTES + Character.BYTES + 4);
var subMiddleBuf = buf.subList(Integer.BYTES, Integer.BYTES * 2);
buf.setInt(0, 0);
buf.setInt(Integer.BYTES, 5);
buf.setInt(Integer.BYTES * 2, 4);
var subBuf = buf.subList(Integer.BYTES, Integer.BYTES * 3);
var subBuf = buf.subList(Integer.BYTES, Integer.BYTES * 3 + Short.BYTES + Character.BYTES + 4);
var subBufOut = subBuf.binaryOutputStream();
var subBufOutData = new SafeDataOutputStream(subBufOut);
assertEquals(0, subBufOutData.size());
subBufOutData.writeInt(9);
subBufOut.position(0);
subBufOutData.writeInt(1);
subBufOutData.writeInt(2);
subBufOutData.writeShort(1);
subBufOutData.writeChar(1);
subBufOutData.write(new byte[] {1, 2});
subBufOutData.write(new byte[] {0, 0, 3, 4, 0, 0}, 2, 2);
assertEquals(Integer.BYTES, Integer.BYTES * 3 + Short.BYTES + Character.BYTES + 4, subBufOutData.size());
assertDoesNotThrow(subBufOutData::toString);
assertDoesNotThrow(subBufOut::toString);
assertThrows(Exception.class, () -> subBufOutData.writeByte(1));
assertThrows(Exception.class, () -> subBufOut.ensureWritable(1));
var i0 = buf.getInt(0);
var i1 = buf.getInt(Integer.BYTES);
var i2 = buf.getInt(Integer.BYTES * 2);
var s1 = (buf.getByte(Integer.BYTES * 3) << 8) | buf.getByte(Integer.BYTES * 3 + 1);
var c1 = (buf.getByte(Integer.BYTES * 3 + Short.BYTES) << 8) | buf.getByte(Integer.BYTES * 3 + Short.BYTES + 1);
var b1 = buf.getByte(Integer.BYTES * 3 + Short.BYTES + Character.BYTES);
var b2 = buf.getByte(Integer.BYTES * 3 + Short.BYTES + Character.BYTES + 1);
var b3 = buf.getByte(Integer.BYTES * 3 + Short.BYTES + Character.BYTES + 2);
var b4 = buf.getByte(Integer.BYTES * 3 + Short.BYTES + Character.BYTES + 3);
assertEquals(List.of(0, 1, 2), List.of(i0, i1, i2));
assertEquals(1, s1);
assertEquals(1, c1);
assertEquals(List.of(1, 2, 3, 4), List.of((int) b1, (int) b2, (int) b3, (int) b4));
{
var baos = new ByteArrayOutputStream();
var dos = new DataOutputStream(baos);
dos.writeInt(1);
dos.writeInt(2);
dos.writeShort(1);
dos.writeChar(1);
dos.writeByte(1);
dos.writeByte(2);
dos.writeByte(3);
dos.writeByte(4);
assertArrayEquals(baos.toByteArray(), subBufOut.toByteArray());
}
{
@ -47,6 +77,12 @@ public class TestOutput {
dos.writeInt(0);
dos.writeInt(1);
dos.writeInt(2);
dos.writeShort(1);
dos.writeChar(1);
dos.writeByte(1);
dos.writeByte(2);
dos.writeByte(3);
dos.writeByte(4);
assertArrayEquals(baos.toByteArray(), buf.toByteArray());
}
{
@ -55,6 +91,104 @@ public class TestOutput {
dos.writeInt(1);
assertArrayEquals(baos.toByteArray(), subMiddleBuf.toByteArray());
}
{
var b = Buf.createZeroes(Long.BYTES * 4);
var os = b.binaryOutputStream();
var ds = new SafeDataOutputStream(os);
ds.writeBoolean(true);
assertTrue(b.getBoolean(0));
os.reset();
ds.writeByte(Byte.MAX_VALUE - 1);
assertEquals(Byte.MAX_VALUE - 1, b.getByte(0));
os.reset();
ds.writeShort(Short.MAX_VALUE - 1);
assertEquals(Short.MAX_VALUE - 1, b.getShort(0));
os.reset();
ds.writeChar(Character.MAX_VALUE - 1);
assertEquals(Character.MAX_VALUE - 1, b.getChar(0));
os.reset();
ds.writeInt(Integer.MAX_VALUE - 1);
assertEquals(Integer.MAX_VALUE - 1, b.getInt(0));
os.reset();
ds.writeLong(Long.MAX_VALUE - 1);
assertEquals(Long.MAX_VALUE - 1, b.getLong(0));
os.reset();
ds.writeInt52(Int52.MAX_VALUE_L - 1);
assertEquals(Int52.MAX_VALUE_L - 1, b.getInt52(0));
os.reset();
ds.writeFloat(Float.MAX_VALUE - 1);
assertEquals(Float.MAX_VALUE - 1, b.getFloat(0));
os.reset();
ds.writeDouble(Double.MAX_VALUE - 1);
assertEquals(Double.MAX_VALUE - 1, b.getDouble(0));
os.reset();
ds.write(10);
ds.write(10);
ds.writeShortText("Ciao", StandardCharsets.UTF_8);
assertEquals("Ciao", b.getShortText(2, StandardCharsets.UTF_8));
assertEquals("Ciao", b.subList(1, b.size()).getShortText(1, StandardCharsets.UTF_8));
assertThrows(Exception.class, () -> ds.writeShortText("1".repeat(Short.MAX_VALUE + 1), StandardCharsets.UTF_8));
os.reset();
ds.write(10);
ds.write(10);
ds.writeMediumText("Ciao", StandardCharsets.UTF_8);
assertEquals("Ciao", b.getMediumText(2, StandardCharsets.UTF_8));
assertEquals("Ciao", b.subList(1, b.size()).getMediumText(1, StandardCharsets.UTF_8));
os.reset();
}
}
@Test
public void testWrappedBufDataOutput() throws IOException {
var sz = Long.BYTES * 4;
BufDataOutput bdo;
Buf buf;
{
bdo = BufDataOutput.createLimited(sz);
bdo.writeBoolean(true);
buf = bdo.asList();
assertTrue(buf.getBoolean(0));
}
{
bdo = BufDataOutput.createLimited(sz);
bdo.writeByte(Byte.MAX_VALUE - 1);
buf = bdo.asList();
assertEquals(Byte.MAX_VALUE - 1, buf.getByte(0));
}
{
bdo = BufDataOutput.createLimited(sz);
bdo.writeShort(Short.MAX_VALUE - 1);
buf = bdo.asList();
assertEquals(Short.MAX_VALUE - 1, buf.getShort(0));
}
{
bdo = BufDataOutput.createLimited(sz);
bdo.writeChar(Character.MAX_VALUE - 1);
buf = bdo.asList();
assertEquals(Character.MAX_VALUE - 1, buf.getChar(0));
}
{
bdo = BufDataOutput.createLimited(sz);
bdo.writeInt(Integer.MAX_VALUE - 1);
buf = bdo.asList();
assertEquals(Integer.MAX_VALUE - 1, buf.getInt(0));
}
{
bdo = BufDataOutput.createLimited(sz);
bdo.writeLong(Long.MAX_VALUE - 1);
buf = bdo.asList();
assertEquals(Long.MAX_VALUE - 1, buf.getLong(0));
}
}
@ParameterizedTest
@ -64,12 +198,15 @@ public class TestOutput {
baos.write(0);
baos.write(0);
baos.write(0);
assertArrayEquals(new byte[3], baos.toByteArray());
var x = new byte[] {1, 2, 3, 4};
baos.write(x);
baos.write(x, 1, 2);
assertArrayEquals(new byte[] {0, 0, 0, 1, 2, 3, 4, 2, 3}, baos.toByteArray());
}
@ParameterizedTest
@MethodSource("provideByteArrayOutputStreams")
public void testTrim(SafeByteArrayOutputStream baos) {
public void testTrimAndGrow(SafeByteArrayOutputStream baos) {
baos.trim();
assertEquals(0, baos.array.length);
baos.write(10);
@ -81,6 +218,21 @@ public class TestOutput {
assertArrayEquals(new byte[] {10, 0, 0}, baos.array);
}
@ParameterizedTest
@MethodSource("provideByteArrayOutputStreams")
public void testReset(SafeByteArrayOutputStream baos) {
baos.trim();
baos.write(10);
baos.write(10);
assertEquals(2, baos.position());
assertEquals(2, baos.length());
assertEquals(2, baos.array.length);
baos.reset();
assertEquals(0, baos.position());
assertEquals(0, baos.length());
assertEquals(2, baos.array.length);
}
public static Stream<SafeByteArrayOutputStream> provideByteArrayOutputStreams() {
return Stream.of(new SafeByteArrayOutputStream(),
new SafeByteArrayOutputStream(10),
@ -89,4 +241,12 @@ public class TestOutput {
new SafeByteArrayOutputStream()
);
}
@Test
public void testNOS() {
try (var nos = SafeDataOutputStream.nullOutputStream()) {
nos.write(0);
nos.flush();
}
}
}