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

View File

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

View File

@ -1,21 +1,35 @@
package it.cavallium.buffer; 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 static java.util.Objects.checkFromToIndex;
import it.cavallium.stream.SafeByteArrayInputStream; import it.cavallium.stream.SafeByteArrayInputStream;
import it.cavallium.stream.SafeByteArrayOutputStream; import it.cavallium.stream.SafeByteArrayOutputStream;
import it.cavallium.stream.SafeDataOutput; 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.io.Serial;
import java.nio.charset.Charset; 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.IntPredicate;
import java.util.function.IntUnaryOperator; import java.util.function.IntUnaryOperator;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.VisibleForTesting; import org.jetbrains.annotations.VisibleForTesting;
@ -220,7 +234,12 @@ class ByteListBuf extends ByteArrayList implements Buf {
@Override @Override
public String toString(Charset charset) { 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 { class SubList extends AbstractByteList.ByteRandomAccessSubList implements Buf {
@ -509,6 +528,12 @@ class ByteListBuf extends ByteArrayList implements Buf {
public String toString(Charset charset) { public String toString(Charset charset) {
return new String(a, from, size(), 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 @IgnoreCoverage

View File

@ -14,7 +14,7 @@ public class ArrayStringSerializer implements DataSerializer<List<String>> {
public void serialize(SafeDataOutput dataOutput, @NotNull List<String> data) { public void serialize(SafeDataOutput dataOutput, @NotNull List<String> data) {
dataOutput.writeInt(data.size()); dataOutput.writeInt(data.size());
for (String item : data) { 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; package it.cavallium.data.generator.nativedata;
import java.lang.annotation.Native; import java.lang.annotation.Native;
import java.util.Objects;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class Int52 extends Number implements Comparable<Int52> { 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 ONE = new Int52(1L);
public static final Int52 TWO = new Int52(2L); public static final Int52 TWO = new Int52(2L);
public static final Int52 TEN = new Int52(10L); 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; private final long value;
@ -30,7 +33,18 @@ public class Int52 extends Number implements Comparable<Int52> {
this.value = value; 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) { public static Int52 fromLong(long value) {
checkValidity(value);
return fromLongSafe(value);
}
private static Int52 fromLongSafe(long value) {
if (value == 0) { if (value == 0) {
return ZERO; return ZERO;
} else if (value == 1) { } else if (value == 1) {
@ -39,15 +53,33 @@ public class Int52 extends Number implements Comparable<Int52> {
return TWO; return TWO;
} else if (value == 10) { } else if (value == 10) {
return TEN; 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 { } else {
return new Int52(value); 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() { long getValue() {
return value; return value;
} }

View File

@ -18,7 +18,7 @@ public class NullableStringSerializer implements DataSerializer<NullableString>
} else { } else {
dataOutput.writeBoolean(true); dataOutput.writeBoolean(true);
String dataContent = data.get(); 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; package it.cavallium.stream;
import static java.util.Objects.checkFromToIndex;
import it.cavallium.buffer.IgnoreCoverage; import it.cavallium.buffer.IgnoreCoverage;
import it.unimi.dsi.fastutil.bytes.ByteArrays; import it.unimi.dsi.fastutil.bytes.ByteArrays;
import java.util.Arrays; import java.util.Arrays;
import java.util.HexFormat; import java.util.HexFormat;
import java.util.Objects; import java.util.Objects;
import static java.util.Objects.checkFromToIndex;
/** Simple, fast byte-array output stream that exposes the backing array. /** Simple, fast byte-array output stream that exposes the backing array.
* *
* <p>{@link java.io.ByteArrayOutputStream} is nice, but to get its content you * <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) { private void growBy(int len) {
if (wrapped) { if (wrapped) {
ensureWrappedBounds(arrayPosition, arrayPosition + len); ensureWrappedBounds(arrayPosition, arrayPosition + len);
} } else if (arrayPosition + len > array.length) {
if (arrayPosition + len > array.length) { array = ByteArrays.grow(array, arrayPosition + len, arrayPosition);
if (wrapped) {
throw new ArrayIndexOutOfBoundsException(arrayPosition + len - 1);
} else {
array = ByteArrays.grow(array, arrayPosition + len, arrayPosition);
}
} }
} }
@Override @Override
public void position(final long newPosition) { public void position(final long newPosition) {
if (wrapped) { arrayPosition = (int) (newPosition + wrappedFrom);
arrayPosition = (int) (newPosition + wrappedFrom);
} else {
arrayPosition = (int)newPosition;
}
} }
@Override @Override
public long position() { public long position() {
if (wrapped) { return arrayPosition - wrappedFrom;
return arrayPosition - wrappedFrom;
} else {
return arrayPosition;
}
} }
@Override @Override

View File

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

View File

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

View File

@ -1,6 +1,9 @@
package it.cavallium.stream; 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 * This class is the superclass of all classes that filter output
* streams. These streams sit on top of an already existing 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. * The underlying output stream to be filtered.
*/ */
protected SafeOutputStream out; protected final 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();
/** /**
* Creates an output stream filter built on top of the specified * 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}. * @param b the {@code byte}.
*/ */
@Override @Override
@IgnoreCoverage
public void write(int b) { public void write(int b) {
out.write(b); out.write(b);
} }
@ -77,9 +71,10 @@ public class SafeFilterOutputStream extends SafeOutputStream {
* @param b the data to be written. * @param b the data to be written.
* @see SafeFilterOutputStream#write(byte[], int, int) * @see SafeFilterOutputStream#write(byte[], int, int)
*/ */
@IgnoreCoverage
@Override @Override
public void write(byte b[]) { public void write(byte @NotNull [] b) {
write(b, 0, b.length); out.write(b);
} }
/** /**
@ -101,14 +96,10 @@ public class SafeFilterOutputStream extends SafeOutputStream {
* @param len the number of bytes to write. * @param len the number of bytes to write.
* @see SafeFilterOutputStream#write(int) * @see SafeFilterOutputStream#write(int)
*/ */
@IgnoreCoverage
@Override @Override
public void write(byte b[], int off, int len) { public void write(byte[] b, int off, int len) {
if ((off | len | (b.length - (len + off)) | (off + len)) < 0) out.write(b, off, len);
throw new IndexOutOfBoundsException();
for (int i = 0 ; i < len ; i++) {
write(b[off + i]);
}
} }
/** /**
@ -120,6 +111,7 @@ public class SafeFilterOutputStream extends SafeOutputStream {
* *
* @see SafeFilterOutputStream#out * @see SafeFilterOutputStream#out
*/ */
@IgnoreCoverage
@Override @Override
public void flush() { public void flush() {
out.flush(); out.flush();
@ -136,45 +128,9 @@ public class SafeFilterOutputStream extends SafeOutputStream {
* @see SafeFilterOutputStream#flush() * @see SafeFilterOutputStream#flush()
* @see SafeFilterOutputStream#out * @see SafeFilterOutputStream#out
*/ */
@IgnoreCoverage
@Override @Override
public void close() { public void close() {
if (closed) { out.close();
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;
}
}
}
} }
} }

View File

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

View File

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

View File

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

View File

@ -1,20 +1,31 @@
package it.cavallium.buffer; 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.Longs;
import com.google.common.primitives.Shorts;
import it.cavallium.data.generator.nativedata.Int52;
import it.cavallium.stream.SafeByteArrayInputStream; import it.cavallium.stream.SafeByteArrayInputStream;
import it.cavallium.stream.SafeByteArrayOutputStream; import it.cavallium.stream.SafeByteArrayOutputStream;
import it.cavallium.stream.SafeDataOutputStream; 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.ByteBuffer;
import java.nio.charset.StandardCharsets; 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.concurrent.atomic.LongAdder;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource; 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 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)); 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, return List.of(emptyBuf, byteListBuf, byteListBufOf, def0Buf, def10Buf, def10000Buf, zeroedBuf, zeroed10Buf,
copyOfSmall, copyOfBig, wrapByteArrayList, wrapBufSmall, wrapSmallArray, wrapBigArray, wrapSmallByteList, wrapBigByteList, zeroed10000Buf, copyOfEmpty, copyOfSmall, copyOfBig, wrapByteArrayList, wrapBufSmall, wrapSmallArray,
wrapSmallCapped, wrapBigCapped, wrapSmallCappedSame, wrapBigCappedSame, wrapSmallCappedMinusOne, wrapBigArray, wrapSmallByteList, wrapBigByteList, wrapSmallCapped, wrapBigCapped, wrapSmallCappedSame,
wrapBigCappedMinusOne, wrapSmallCappedRangeSame, wrapBigCappedRangeSame, wrapSmallCappedRangeOffset, wrapBigCappedSame, wrapSmallCappedMinusOne, wrapBigCappedMinusOne, wrapSmallCappedRangeSame,
wrapBigCappedRangeOffset, wrapSmallCappedRangeOffsetAndLen, wrapBigCappedRangeOffsetAndLen, wrapBigCappedRangeSame, wrapSmallCappedRangeOffset, wrapBigCappedRangeOffset,
wrapSmallCappedRangeLen, wrapBigCappedRangeLen, wrapSmallByteArrayListCappedRangeOffsetAndLen, wrapSmallByteListCappedRangeOffsetAndLen); wrapSmallCappedRangeOffsetAndLen, wrapBigCappedRangeOffsetAndLen, wrapSmallCappedRangeLen,
wrapBigCappedRangeLen, wrapSmallBufCappedRangeOffsetAndLen, wrapSmallByteArrayListCappedRangeOffsetAndLen,
wrapSmallByteListCappedRangeOffsetAndLen);
} }
public static List<BufArg> createSubListBufs() { public static List<BufArg> createSubListBufs() {
@ -275,6 +288,46 @@ public class TestBuffer {
return provideBufs().filter(ba -> ba.initialSize >= Long.BYTES * 2); 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 @ParameterizedTest
@MethodSource @MethodSource
public void testInts(BufArg bufArg) { public void testInts(BufArg bufArg) {
@ -383,6 +436,26 @@ public class TestBuffer {
return provideBufs().filter(ba -> ba.initialSize >= 2); 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 @ParameterizedTest
@MethodSource("provideBufs") @MethodSource("provideBufs")
public void testString(BufArg bufArg) { public void testString(BufArg bufArg) {

View File

@ -1,44 +1,74 @@
package it.cavallium.stream; package it.cavallium.stream;
import it.cavallium.buffer.Buf; import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import org.junit.jupiter.params.ParameterizedTest; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.params.provider.MethodSource; 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.ByteArrayOutputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertArrayEquals; import org.junit.jupiter.params.ParameterizedTest;
import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.params.provider.MethodSource;
public class TestOutput { public class TestOutput {
@Test @Test
public void testBufOutputStream() throws IOException { 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); var subMiddleBuf = buf.subList(Integer.BYTES, Integer.BYTES * 2);
buf.setInt(0, 0); buf.setInt(0, 0);
buf.setInt(Integer.BYTES, 5); buf.setInt(Integer.BYTES, 5);
buf.setInt(Integer.BYTES * 2, 4); 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 subBufOut = subBuf.binaryOutputStream();
var subBufOutData = new SafeDataOutputStream(subBufOut); var subBufOutData = new SafeDataOutputStream(subBufOut);
assertEquals(0, subBufOutData.size());
subBufOutData.writeInt(9); subBufOutData.writeInt(9);
subBufOut.position(0); subBufOut.position(0);
subBufOutData.writeInt(1); subBufOutData.writeInt(1);
subBufOutData.writeInt(2); 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 i0 = buf.getInt(0);
var i1 = buf.getInt(Integer.BYTES); var i1 = buf.getInt(Integer.BYTES);
var i2 = buf.getInt(Integer.BYTES * 2); 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(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 baos = new ByteArrayOutputStream();
var dos = new DataOutputStream(baos); var dos = new DataOutputStream(baos);
dos.writeInt(1); dos.writeInt(1);
dos.writeInt(2); 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()); assertArrayEquals(baos.toByteArray(), subBufOut.toByteArray());
} }
{ {
@ -47,6 +77,12 @@ public class TestOutput {
dos.writeInt(0); dos.writeInt(0);
dos.writeInt(1); dos.writeInt(1);
dos.writeInt(2); 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()); assertArrayEquals(baos.toByteArray(), buf.toByteArray());
} }
{ {
@ -55,6 +91,104 @@ public class TestOutput {
dos.writeInt(1); dos.writeInt(1);
assertArrayEquals(baos.toByteArray(), subMiddleBuf.toByteArray()); 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 @ParameterizedTest
@ -64,12 +198,15 @@ public class TestOutput {
baos.write(0); baos.write(0);
baos.write(0); 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 @ParameterizedTest
@MethodSource("provideByteArrayOutputStreams") @MethodSource("provideByteArrayOutputStreams")
public void testTrim(SafeByteArrayOutputStream baos) { public void testTrimAndGrow(SafeByteArrayOutputStream baos) {
baos.trim(); baos.trim();
assertEquals(0, baos.array.length); assertEquals(0, baos.array.length);
baos.write(10); baos.write(10);
@ -81,6 +218,21 @@ public class TestOutput {
assertArrayEquals(new byte[] {10, 0, 0}, baos.array); 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() { public static Stream<SafeByteArrayOutputStream> provideByteArrayOutputStreams() {
return Stream.of(new SafeByteArrayOutputStream(), return Stream.of(new SafeByteArrayOutputStream(),
new SafeByteArrayOutputStream(10), new SafeByteArrayOutputStream(10),
@ -89,4 +241,12 @@ public class TestOutput {
new SafeByteArrayOutputStream() new SafeByteArrayOutputStream()
); );
} }
@Test
public void testNOS() {
try (var nos = SafeDataOutputStream.nullOutputStream()) {
nos.write(0);
nos.flush();
}
}
} }