diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index f4db232..99b60f1 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -16,10 +16,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v2 with: - java-version: '11' + java-version: '17' distribution: 'adopt' cache: maven - name: Run all unit test cases and verify the GPG key diff --git a/CHANGELOG.md b/CHANGELOG.md index 13257b5..746563a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,3 +21,12 @@ ## 0.4.0 2022-11-20 Feature release - Moved annotations management to the [tenio-core](https://github.com/congcoi123/tenio-core) module + +## 0.5.0 2023-08-30 Feature release +- Upgraded to JDK 17 +- Upgraded dependencies +- Allowed checking logging configuration before writing logs +- Added some utility methods to work with custom data types +- Changed some methods' names +- Fixed test cases' issues +- Bugs fixed diff --git a/CHECKLIST.md b/CHECKLIST.md index 2711ff7..2f87270 100644 --- a/CHECKLIST.md +++ b/CHECKLIST.md @@ -6,14 +6,14 @@ - [x] Executes command *mvn clean install* to run the *checkstyle* process ### Before updating to new version -- [x] Makes sure the current branch is *develop* branch +- [x] Makes sure the current branch is *develop* branch +- [x] Creates a Pull Request (PR) from develop to master branch - [x] All new methods should be annotated by the *@since* annotation - [x] Changes version in *pom.xml* file - [x] Updates new changes in the *CHANGELOG.md* file - [x] Updates the *VERSION* file - [x] Updates the *README.md* file -- [x] Executes command *mvn clean install* to run the *checkstyle* process -- [x] Creates a Pull Request (PR) from develop to master branch +- [x] Executes command *mvn clean install* to run the *checkstyle* process ### Creating a new release - [x] Makes sure the current branch is *master* branch diff --git a/README.md b/README.md index 6ab39d1..e170b38 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,8 @@ - - + +

@@ -41,7 +41,7 @@ This module provides common methods, classes for other modules to use. It suppor mechanism and supplies the self-defined serialized and deserialized processes for transferring data through the network. ## Requirements -- Java 11 +- Java 17 ## License The [`TenIO`](https://github.com/congcoi123/tenio) project is currently available under the [MIT](LICENSE) License. diff --git a/VERSION b/VERSION index b62841e..bb58c40 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -20221120.0.4.0 \ No newline at end of file +20230830.0.5.0 \ No newline at end of file diff --git a/pom.xml b/pom.xml index 995617e..165fcda 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.github.congcoi123 tenio-common - 0.4.0 + 0.5.0 jar ${project.groupId}:${project.artifactId} @@ -41,14 +41,14 @@ 31.1-jre 0.6.12 - 2.17.2 + 2.20.0 0.10.2 UTF-8 - 5.8.2 - 1.8.2 - 4.4.0 + 5.9.2 + 1.9.2 + 5.2.0 3.8.0 11 @@ -56,13 +56,13 @@ 3.1.2 3.2.0 - 3.2.0 + 3.5.0 1.6 0.8.7 4.3.0 - 11 - 11 + 17 + 17 @@ -147,6 +147,12 @@ ${org.mockito.core.version} test + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven.javadoc.plugin.version} + maven-plugin + @@ -233,18 +239,19 @@ org.apache.maven.plugins maven-javadoc-plugin ${maven.javadoc.plugin.version} - attach-javadocs + compile jar + javadoc - ${java.home}/bin/javadoc + false diff --git a/src/main/java/com/tenio/common/configuration/CommonConfiguration.java b/src/main/java/com/tenio/common/configuration/CommonConfiguration.java index 2cf8025..d70cbfd 100644 --- a/src/main/java/com/tenio/common/configuration/CommonConfiguration.java +++ b/src/main/java/com/tenio/common/configuration/CommonConfiguration.java @@ -101,9 +101,11 @@ protected void push(ConfigurationType key, Object value) { } if (configuration.containsKey(key)) { - info("CONFIGURATION", - buildgen("Configuration key [", key, "] attempted to replace the old value ", - configuration.get(key), " by the new one ", value)); + if (isInfoEnabled()) { + info("CONFIGURATION", + buildgen("Configuration key [", key, "] attempted to replace the old value ", + configuration.get(key), " by the new one ", value)); + } return; } diff --git a/src/main/java/com/tenio/common/data/DataUtility.java b/src/main/java/com/tenio/common/data/DataUtility.java index 82a3db1..8102972 100644 --- a/src/main/java/com/tenio/common/data/DataUtility.java +++ b/src/main/java/com/tenio/common/data/DataUtility.java @@ -86,16 +86,9 @@ public static MsgPackMap newMsgMap() { * @return a new collection instance */ public static DataCollection binaryToCollection(DataType type, byte[] binary) { - switch (type) { - case ZERO: - return ZeroUtility.binaryToCollection(binary); - - case MSG_PACK: - return MsgPackUtility.deserialize(binary); - - default: - throw new UnsupportedOperationException(String.format("Unsupported serialization type: " + - "%s", type)); - } + return switch (type) { + case ZERO -> ZeroUtility.binaryToCollection(binary); + case MSG_PACK -> MsgPackUtility.deserialize(binary); + }; } } diff --git a/src/main/java/com/tenio/common/data/msgpack/ByteArrayInputStream.java b/src/main/java/com/tenio/common/data/msgpack/ByteArrayInputStream.java index 16b48ab..fe25699 100644 --- a/src/main/java/com/tenio/common/data/msgpack/ByteArrayInputStream.java +++ b/src/main/java/com/tenio/common/data/msgpack/ByteArrayInputStream.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.io.InputStream; +import java.io.Serial; import java.io.Serializable; /** @@ -25,6 +26,7 @@ */ public final class ByteArrayInputStream extends InputStream implements Serializable { + @Serial private static final long serialVersionUID = -5334077014767018880L; private int offset; diff --git a/src/main/java/com/tenio/common/data/msgpack/MsgPackUtility.java b/src/main/java/com/tenio/common/data/msgpack/MsgPackUtility.java index b2265df..4c07c60 100644 --- a/src/main/java/com/tenio/common/data/msgpack/MsgPackUtility.java +++ b/src/main/java/com/tenio/common/data/msgpack/MsgPackUtility.java @@ -45,6 +45,10 @@ of this software and associated documentation files (the "Software"), to deal */ public final class MsgPackUtility { + private MsgPackUtility() { + throw new UnsupportedOperationException("This class does not support creating a new instance"); + } + /** * Serialize an object to an array of bytes data. * @@ -55,31 +59,6 @@ public static byte[] serialize(MsgPackMap msgPackMap) { return MsgPackConverter.pack(msgPackMap); } - /** - * Deserialize an array of bytes data to a {@link MsgPackMap} object. - * - * @param msgPackMap the message container which is using in the system - * @param byteArrayInput the object for converting raw binaries' data to msgpack - * using one - * @param binaries an array of bytes data - * @return an message object in {@link MsgPackMap} type - */ - public static MsgPackMap deserialize(MsgPackMap msgPackMap, ByteArrayInputStream byteArrayInput, - byte[] binaries) { - var dstMap = MsgPackConverter.unpack(byteArrayInput, binaries); - if (dstMap == null || dstMap.isEmpty()) { - return null; - } - dstMap.forEach((key, value) -> { - try { - msgPackMap.put(key, MsgPackConverter.valueToObject(value)); - } catch (IOException e) { - e.printStackTrace(); - } - }); - return msgPackMap; - } - /** * Deserialize an array of bytes data to a {@link MsgPackMap} object. * @@ -96,12 +75,30 @@ public static MsgPackMap deserialize(byte[] binaries) { dstMap.forEach((key, value) -> { try { msgObject.put(key, MsgPackConverter.valueToObject(value)); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException exception) { + exception.printStackTrace(); } }); return msgObject; } + + /** + * Retrieves new instance of the {@link MsgPackMap} class. + * + * @return an instance + */ + public static MsgPackMap newMsgPackMap() { + return MsgPackMap.newInstance(); + } + + /** + * Retrieves new instance of the {@link MsgPackArray} class. + * + * @return an instance + */ + public static MsgPackArray newMsgPackArray() { + return MsgPackArray.newInstance(); + } } class MsgPackConverter { @@ -120,8 +117,8 @@ class MsgPackConverter { public static byte[] pack(Map map) { try { return PACKER.write(map); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException exception) { + exception.printStackTrace(); return null; } } @@ -139,8 +136,8 @@ public static Map unpack(ByteArrayInputStream byteArrayInput, byt byteArrayInput.reset(binaries); var unpacker = PACKER.createUnpacker(byteArrayInput); return unpacker.read(mapTmpl); - } catch (IOException | IllegalArgumentException e) { - e.printStackTrace(); + } catch (IOException | IllegalArgumentException exception) { + exception.printStackTrace(); return null; } } @@ -172,8 +169,8 @@ public static Object valueToObject(Value value) throws IOException { arrayValue.forEach(element -> { try { array.add(valueToObject(element)); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException exception) { + exception.printStackTrace(); } }); return array; diff --git a/src/main/java/com/tenio/common/data/msgpack/element/MsgPackArray.java b/src/main/java/com/tenio/common/data/msgpack/element/MsgPackArray.java index 59abf48..13c5607 100644 --- a/src/main/java/com/tenio/common/data/msgpack/element/MsgPackArray.java +++ b/src/main/java/com/tenio/common/data/msgpack/element/MsgPackArray.java @@ -24,6 +24,7 @@ of this software and associated documentation files (the "Software"), to deal package com.tenio.common.data.msgpack.element; +import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -34,6 +35,7 @@ of this software and associated documentation files (the "Software"), to deal */ public final class MsgPackArray extends ArrayList implements Serializable { + @Serial private static final long serialVersionUID = -2718756636745901607L; /** diff --git a/src/main/java/com/tenio/common/data/msgpack/element/MsgPackMap.java b/src/main/java/com/tenio/common/data/msgpack/element/MsgPackMap.java index 4fe30f8..1140cf4 100644 --- a/src/main/java/com/tenio/common/data/msgpack/element/MsgPackMap.java +++ b/src/main/java/com/tenio/common/data/msgpack/element/MsgPackMap.java @@ -26,6 +26,7 @@ of this software and associated documentation files (the "Software"), to deal import com.tenio.common.data.DataCollection; import com.tenio.common.data.msgpack.MsgPackUtility; +import java.io.Serial; import java.io.Serializable; import java.util.HashMap; import java.util.Map; @@ -37,6 +38,7 @@ of this software and associated documentation files (the "Software"), to deal public final class MsgPackMap extends HashMap implements DataCollection, Serializable { + @Serial private static final long serialVersionUID = 6697372748701824069L; /** @@ -54,6 +56,16 @@ public static MsgPackMap newInstance() { return new MsgPackMap(); } + /** + * Determines whether the data can be fetched by its key in the map. + * + * @param key the {@link String} key needs to be checked + * @return true if a value is available, otherwise false + */ + public boolean contains(String key) { + return containsKey(key); + } + /** * Retrieves value in the map by its key. * @@ -105,23 +117,35 @@ public MsgPackArray getMsgPackArray(String key) { } /** - * Determines whether the data can be fetched by its key in the map. + * Adds new data into the map with its key. * - * @param key the {@link String} key needs to be checked - * @return true if a value is available, otherwise false + * @param key the {@link String} key of data + * @param value the {@link MsgPackArray} value needs to be inserted + * @return the pointer of this instance */ - public boolean contains(String key) { - return containsKey(key); + public MsgPackMap putMsgPackArray(String key, MsgPackArray value) { + put(key, value); + return this; + } + + /** + * Retrieves value in the map by its key. + * + * @param key the {@link String} key in the map + * @return the value converted in {@link MsgPackMap} type fetched by its key in the map + */ + public MsgPackMap getMsgPackMap(String key) { + return (MsgPackMap) get(key); } /** * Adds new data into the map with its key. * * @param key the {@link String} key of data - * @param value the {@link MsgPackArray} value needs to be inserted + * @param value the {@link MsgPackMap} value needs to be inserted * @return the pointer of this instance */ - public MsgPackMap putMsgPackArray(String key, MsgPackArray value) { + public MsgPackMap putMsgPackMap(String key, MsgPackMap value) { put(key, value); return this; } diff --git a/src/main/java/com/tenio/common/data/zero/ReadonlyZeroArray.java b/src/main/java/com/tenio/common/data/zero/ReadonlyZeroArray.java index b5a3254..288b73b 100644 --- a/src/main/java/com/tenio/common/data/zero/ReadonlyZeroArray.java +++ b/src/main/java/com/tenio/common/data/zero/ReadonlyZeroArray.java @@ -40,6 +40,15 @@ public interface ReadonlyZeroArray extends DataCollection { */ boolean contains(Object element); + /** + * Determines whether a value is present at the index or not. + * + * @param index the array's index + * @return true if the value is existed, otherwise false + * @since 0.5.0 + */ + boolean containsValueAt(int index); + /** * Retrieves the data of element at index in the array. * diff --git a/src/main/java/com/tenio/common/data/zero/ReadonlyZeroMap.java b/src/main/java/com/tenio/common/data/zero/ReadonlyZeroMap.java index 7ad2b48..aadb49b 100644 --- a/src/main/java/com/tenio/common/data/zero/ReadonlyZeroMap.java +++ b/src/main/java/com/tenio/common/data/zero/ReadonlyZeroMap.java @@ -129,6 +129,15 @@ public interface ReadonlyZeroMap extends DataCollection { */ String getString(String key); + /** + * Retrieves the data of element by its key in the generic data collection type. + * + * @param key the {@link String} key needs to be checked + * @return the value held fetched by its key in {@link DataCollection} type + * @since 0.5.0 + */ + DataCollection getDataCollection(String key); + /** * Retrieves the data of element by its key in the map. * diff --git a/src/main/java/com/tenio/common/data/zero/ZeroArray.java b/src/main/java/com/tenio/common/data/zero/ZeroArray.java index 73c6870..e1501b9 100644 --- a/src/main/java/com/tenio/common/data/zero/ZeroArray.java +++ b/src/main/java/com/tenio/common/data/zero/ZeroArray.java @@ -61,6 +61,15 @@ public interface ZeroArray extends ReadonlyZeroArray, Iterable { */ ZeroArray addByte(byte data); + /** + * Sets a byte value at index in the array. + * + * @param index the element's index + * @param data the appended data + * @return the pointer of this instance + */ + ZeroArray setByte(int index, byte data); + /** * Appends a short value into the array. * @@ -85,6 +94,15 @@ public interface ZeroArray extends ReadonlyZeroArray, Iterable { */ ZeroArray addLong(long data); + /** + * Sets a long value at index in the array. + * + * @param index the element's index + * @param data the appended data + * @return the pointer of this instance + */ + ZeroArray setLong(int index, long data); + /** * Appends a float value into the array. * diff --git a/src/main/java/com/tenio/common/data/zero/implement/ZeroArrayImpl.java b/src/main/java/com/tenio/common/data/zero/implement/ZeroArrayImpl.java index df16051..0360125 100644 --- a/src/main/java/com/tenio/common/data/zero/implement/ZeroArrayImpl.java +++ b/src/main/java/com/tenio/common/data/zero/implement/ZeroArrayImpl.java @@ -62,11 +62,24 @@ public byte[] toBinary() { @Override public boolean contains(Object data) { + if (Objects.isNull(data)) { + return array.stream().anyMatch(element -> Objects.isNull(element.getData())); + } var match = - array.stream().filter(element -> element.getData().equals(data)).findFirst(); + array.stream() + .filter(element -> Objects.nonNull(element.getData()) && element.getData().equals(data)) + .findFirst(); return match.orElse(null) != null; } + @Override + public boolean containsValueAt(int index) { + if (index < 0 || index >= size()) { + return false; + } + return Objects.nonNull(array.get(index)); + } + /** * This method potentially creates an issue called "escape references". Please be aware of * using it @@ -183,6 +196,12 @@ public ZeroArray addByte(byte data) { return addElement(ZeroType.BYTE, data); } + @Override + public ZeroArray setByte(int index, byte data) { + array.set(index, ZeroUtility.newZeroElement(ZeroType.BYTE, data)); + return this; + } + @Override public ZeroArray addShort(short data) { return addElement(ZeroType.SHORT, data); @@ -198,6 +217,12 @@ public ZeroArray addLong(long data) { return addElement(ZeroType.LONG, data); } + @Override + public ZeroArray setLong(int index, long data) { + array.set(index, ZeroUtility.newZeroElement(ZeroType.LONG, data)); + return this; + } + @Override public ZeroArray addFloat(float data) { return addElement(ZeroType.FLOAT, data); @@ -347,7 +372,8 @@ public String toString() { } else if (zeroElement.getType() == ZeroType.BYTE_ARRAY) { toString = String.format("byte[%d]", ((byte[]) zeroElement.getData()).length); } else { - toString = zeroElement.getData().toString(); + toString = Objects.nonNull(zeroElement.getData()) ? zeroElement.getData().toString() : + "null"; } } diff --git a/src/main/java/com/tenio/common/data/zero/implement/ZeroElementImpl.java b/src/main/java/com/tenio/common/data/zero/implement/ZeroElementImpl.java index c74421b..3e447b6 100644 --- a/src/main/java/com/tenio/common/data/zero/implement/ZeroElementImpl.java +++ b/src/main/java/com/tenio/common/data/zero/implement/ZeroElementImpl.java @@ -26,26 +26,11 @@ of this software and associated documentation files (the "Software"), to deal import com.tenio.common.data.zero.ZeroElement; import com.tenio.common.data.zero.ZeroType; -import java.util.Objects; /** * This class holds a relationship between a self-definition data type and its value. */ -public final class ZeroElementImpl implements ZeroElement { - - private final ZeroType type; - private final Object data; - - /** - * Creates a new instance. - * - * @param type the {@link ZeroType} - * @param data the {@link Object} value - */ - public ZeroElementImpl(ZeroType type, Object data) { - this.type = type; - this.data = data; - } +public record ZeroElementImpl(ZeroType type, Object data) implements ZeroElement { @Override public ZeroType getType() { @@ -57,23 +42,6 @@ public Object getData() { return data; } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ZeroElementImpl zeroDataImpl = (ZeroElementImpl) o; - return type == zeroDataImpl.type && Objects.equals(data, zeroDataImpl.data); - } - - @Override - public int hashCode() { - return Objects.hash(type, data); - } - @Override public String toString() { return "ZeroElement{" + diff --git a/src/main/java/com/tenio/common/data/zero/implement/ZeroMapImpl.java b/src/main/java/com/tenio/common/data/zero/implement/ZeroMapImpl.java index 4d59194..4eadc8f 100644 --- a/src/main/java/com/tenio/common/data/zero/implement/ZeroMapImpl.java +++ b/src/main/java/com/tenio/common/data/zero/implement/ZeroMapImpl.java @@ -24,6 +24,7 @@ of this software and associated documentation files (the "Software"), to deal package com.tenio.common.data.zero.implement; +import com.tenio.common.data.DataCollection; import com.tenio.common.data.zero.ReadonlyZeroMap; import com.tenio.common.data.zero.ZeroArray; import com.tenio.common.data.zero.ZeroElement; @@ -155,6 +156,12 @@ public String getString(String key) { return Objects.isNull(element) ? null : (String) element.getData(); } + @Override + public DataCollection getDataCollection(String key) { + var element = getZeroElement(key); + return Objects.isNull(element) ? null : (DataCollection) element.getData(); + } + @Override public ZeroArray getZeroArray(String key) { var element = getZeroElement(key); @@ -351,7 +358,8 @@ public String toString() { } else if (zeroElement.getType() == ZeroType.BYTE_ARRAY) { builder.append(String.format("byte[%d]", ((byte[]) zeroElement.getData()).length)); } else { - builder.append(zeroElement.getData().toString()); + builder.append(Objects.nonNull(zeroElement.getData()) ? zeroElement.getData().toString() + : "null"); } } diff --git a/src/main/java/com/tenio/common/data/zero/utility/ZeroUtility.java b/src/main/java/com/tenio/common/data/zero/utility/ZeroUtility.java index d7674a5..2c91112 100644 --- a/src/main/java/com/tenio/common/data/zero/utility/ZeroUtility.java +++ b/src/main/java/com/tenio/common/data/zero/utility/ZeroUtility.java @@ -106,17 +106,12 @@ public static ZeroMap newZeroMap() { * @return a new zero collection instance */ public static DataCollection binaryToCollection(byte[] binary) { - switch (ZeroType.getByValue(binary[0])) { - case ZERO_MAP: - return binaryToMap(binary); - - case ZERO_ARRAY: - return binaryToArray(binary); - - default: - throw new UnsupportedOperationException( - String.format("Unsupported value: %s", ZeroType.getByValue(binary[0]))); - } + return switch (ZeroType.getByValue(binary[0])) { + case ZERO_MAP -> binaryToMap(binary); + case ZERO_ARRAY -> binaryToArray(binary); + default -> throw new UnsupportedOperationException( + String.format("Unsupported value: %s", ZeroType.getByValue(binary[0]))); + }; } /** @@ -231,6 +226,9 @@ private static byte[] arrayToBinary(ZeroArray array, ByteBuffer buffer) { private static ZeroElement decodeElement(ByteBuffer buffer) throws RuntimeException { var headerByte = buffer.get(); var type = ZeroType.getByValue(headerByte); + if (Objects.isNull(type)) { + return null; + } switch (type) { case NULL: @@ -273,74 +271,32 @@ private static ZeroElement decodeElement(ByteBuffer buffer) throws RuntimeExcept case ZERO_MAP: buffer.position(buffer.position() - Byte.BYTES); return newZeroElement(ZeroType.ZERO_MAP, decodeZeroMap(buffer)); - default: - return null; } + return null; } @SuppressWarnings("unchecked") private static ByteBuffer encodeElement(ByteBuffer buffer, ZeroType type, Object data) { switch (type) { - case NULL: - buffer = encodeNull(buffer); - break; - case BOOLEAN: - buffer = encodeBoolean(buffer, (Boolean) data); - break; - case BYTE: - buffer = encodeByte(buffer, (Byte) data); - break; - case SHORT: - buffer = encodeShort(buffer, (Short) data); - break; - case INTEGER: - buffer = encodeInteger(buffer, (Integer) data); - break; - case LONG: - buffer = encodeLong(buffer, (Long) data); - break; - case FLOAT: - buffer = encodeFloat(buffer, (Float) data); - break; - case DOUBLE: - buffer = encodeDouble(buffer, (Double) data); - break; - case STRING: - buffer = encodeString(buffer, (String) data); - break; - case BOOLEAN_ARRAY: - buffer = encodeBooleanArray(buffer, (Collection) data); - break; - case BYTE_ARRAY: - buffer = encodeByteArray(buffer, (byte[]) data); - break; - case SHORT_ARRAY: - buffer = encodeShortArray(buffer, (Collection) data); - break; - case INTEGER_ARRAY: - buffer = encodeIntegerArray(buffer, (Collection) data); - break; - case LONG_ARRAY: - buffer = encodeLongArray(buffer, (Collection) data); - break; - case FLOAT_ARRAY: - buffer = encodeFloatArray(buffer, (Collection) data); - break; - case DOUBLE_ARRAY: - buffer = encodeDoubleArray(buffer, (Collection) data); - break; - case STRING_ARRAY: - buffer = encodeStringArray(buffer, (Collection) data); - break; - case ZERO_ARRAY: - buffer = appendBinaryToBuffer(buffer, arrayToBinary((ZeroArray) data)); - break; - case ZERO_MAP: - buffer = appendBinaryToBuffer(buffer, mapToBinary((ZeroMap) data)); - break; - default: - throw new IllegalArgumentException( - String.format("Unsupported data type: %s", type)); + case NULL -> buffer = encodeNull(buffer); + case BOOLEAN -> buffer = encodeBoolean(buffer, (Boolean) data); + case BYTE -> buffer = encodeByte(buffer, (Byte) data); + case SHORT -> buffer = encodeShort(buffer, (Short) data); + case INTEGER -> buffer = encodeInteger(buffer, (Integer) data); + case LONG -> buffer = encodeLong(buffer, (Long) data); + case FLOAT -> buffer = encodeFloat(buffer, (Float) data); + case DOUBLE -> buffer = encodeDouble(buffer, (Double) data); + case STRING -> buffer = encodeString(buffer, (String) data); + case BOOLEAN_ARRAY -> buffer = encodeBooleanArray(buffer, (Collection) data); + case BYTE_ARRAY -> buffer = encodeByteArray(buffer, (byte[]) data); + case SHORT_ARRAY -> buffer = encodeShortArray(buffer, (Collection) data); + case INTEGER_ARRAY -> buffer = encodeIntegerArray(buffer, (Collection) data); + case LONG_ARRAY -> buffer = encodeLongArray(buffer, (Collection) data); + case FLOAT_ARRAY -> buffer = encodeFloatArray(buffer, (Collection) data); + case DOUBLE_ARRAY -> buffer = encodeDoubleArray(buffer, (Collection) data); + case STRING_ARRAY -> buffer = encodeStringArray(buffer, (Collection) data); + case ZERO_ARRAY -> buffer = appendBinaryToBuffer(buffer, arrayToBinary((ZeroArray) data)); + case ZERO_MAP -> buffer = appendBinaryToBuffer(buffer, mapToBinary((ZeroMap) data)); } return buffer; @@ -535,7 +491,8 @@ private static ZeroArray decodeZeroArray(ByteBuffer buffer) { throw new IllegalStateException( String.format("Invalid ZeroType. Expected: %s, value: %d, but found: %s, value: %d", ZeroType.ZERO_ARRAY, ZeroType.ZERO_ARRAY.getValue(), - ZeroType.getByValue(headerByte).toString(), headerByte)); + Objects.nonNull(ZeroType.getByValue(headerByte)) ? + ZeroType.getByValue(headerByte).toString() : "null", headerByte)); } var arraySize = buffer.getShort(); @@ -709,7 +666,6 @@ private static ByteBuffer encodeShortArray(ByteBuffer buffer, Collection } private static ByteBuffer encodeIntegerArray(ByteBuffer buffer, Collection data) { - var buf = ByteBuffer.allocate(ENCODE_HEADER_NUMERIC_ARRAY_BYTES + Integer.BYTES * data.size()); buf.put((byte) ZeroType.INTEGER_ARRAY.getValue()); buf.putShort((short) data.size()); diff --git a/src/main/java/com/tenio/common/logger/AbstractLogger.java b/src/main/java/com/tenio/common/logger/AbstractLogger.java index 8fd5755..b798c19 100644 --- a/src/main/java/com/tenio/common/logger/AbstractLogger.java +++ b/src/main/java/com/tenio/common/logger/AbstractLogger.java @@ -213,6 +213,26 @@ public void info(String tag, Object msg) { stringPool.repay(builder); } + /** + * Only use for errors/issues detection in the server system. Be careful when using + * it yourself. You are warned! + * + * @param info the information + */ + public void error(Object... info) { + if (!logger.isErrorEnabled()) { + return; + } + var builder = stringPool.get(); + builder.append("\n=========== BEGIN ERROR INFORMATION ===========\n"); + for (var e : info) { + builder.append(e); + } + builder.append("\n============ END ERROR INFORMATION ============\n"); + logger.error(builder.toString()); + stringPool.repay(builder); + } + /** * Only use for EXCEPTION detection in the server system. Be careful when using * it yourself. You are warned! @@ -277,4 +297,12 @@ public StringBuilder buildgen(Object... objects) { } return builder; } + + public boolean isErrorEnabled() { + return logger.isErrorEnabled(); + } + + public boolean isInfoEnabled() { + return logger.isInfoEnabled(); + } } diff --git a/src/main/java/com/tenio/common/logger/SystemLogger.java b/src/main/java/com/tenio/common/logger/SystemLogger.java index 3f698c2..18fce15 100644 --- a/src/main/java/com/tenio/common/logger/SystemLogger.java +++ b/src/main/java/com/tenio/common/logger/SystemLogger.java @@ -40,7 +40,7 @@ public abstract class SystemLogger extends AbstractLogger { * @param type the event's type * @param msg the extra information for "type" */ - public void debug(String type, Object... msg) { + public void debugEvent(String type, Object... msg) { if (!logger.isDebugEnabled()) { return; } @@ -59,6 +59,27 @@ public void debug(String type, Object... msg) { stringPool.repay(builder); } + /** + * Prints out debugging logs. + * + * @param type the debug title + * @param msg the debug content + * @since 0.5.0 + */ + public void debug(String type, Object... msg) { + if (!logger.isDebugEnabled()) { + return; + } + + var builder = stringPool.get(); + builder.append("{").append(type).append("} "); + for (var m : msg) { + builder.append(m); + } + logger.debug(builder.toString()); + stringPool.repay(builder); + } + /** * Only use for debugging EVENTS in the server system. Be careful when using it * yourself. You are warned! @@ -107,4 +128,11 @@ public void trace(String where, Object subWhere, String tag, String msg) { stringPool.repay(builder); } + public boolean isTraceEnabled() { + return logger.isTraceEnabled(); + } + + public boolean isDebugEnabled() { + return logger.isDebugEnabled(); + } } diff --git a/src/main/java/com/tenio/common/logger/pool/StringBuilderPool.java b/src/main/java/com/tenio/common/logger/pool/StringBuilderPool.java index f6efcf8..b2cfb0a 100644 --- a/src/main/java/com/tenio/common/logger/pool/StringBuilderPool.java +++ b/src/main/java/com/tenio/common/logger/pool/StringBuilderPool.java @@ -104,8 +104,10 @@ public synchronized StringBuilder get() { used[i] = false; } - infoWithoutPool(strgen("Increased the number of elements by ", - CommonConstant.ADDITIONAL_NUMBER_ELEMENTS_POOL, " to ", used.length)); + if (logger.isInfoEnabled()) { + infoWithoutPool(strgen("Increased the number of elements by ", + CommonConstant.ADDITIONAL_NUMBER_ELEMENTS_POOL, " to ", used.length)); + } // and allocate the last old element used[oldPool.length - 1] = true; @@ -125,9 +127,11 @@ public synchronized void repay(StringBuilder element) { } } if (!flagFound) { - var e = new NullElementPoolException(element.toString()); - errorWithoutPool(e); - throw e; + var exception = new NullElementPoolException(element.toString()); + if (logger.isErrorEnabled()) { + errorWithoutPool(exception); + } + throw exception; } } @@ -165,9 +169,6 @@ public synchronized int getAvailableSlot() { * @param msg the message content */ private void infoWithoutPool(String msg) { - if (!logger.isInfoEnabled()) { - return; - } logger.info("[STRINGBUILDER POOL] " + msg); } @@ -178,9 +179,6 @@ private void infoWithoutPool(String msg) { * @param cause the throwable */ private void errorWithoutPool(Throwable cause) { - if (!logger.isErrorEnabled()) { - return; - } logger.error(Throwables.getStackTraceAsString(cause)); } diff --git a/src/main/java/com/tenio/common/task/implement/TaskManagerImpl.java b/src/main/java/com/tenio/common/task/implement/TaskManagerImpl.java index d9dd24d..3a39643 100644 --- a/src/main/java/com/tenio/common/task/implement/TaskManagerImpl.java +++ b/src/main/java/com/tenio/common/task/implement/TaskManagerImpl.java @@ -71,20 +71,26 @@ public void create(String id, ScheduledFuture task) { if (!tasks.get(id).isDone() || !tasks.get(id).isCancelled()) { throw new RunningScheduledTaskException(); } - } catch (RunningScheduledTaskException e) { - error(e, "task id: ", id); + } catch (RunningScheduledTaskException exception) { + if (isErrorEnabled()) { + error(exception, "task id: ", id); + } return; } } tasks.put(id, task); - info("RUN TASK", buildgen(id, " >Time left> ", task.getDelay(TimeUnit.SECONDS), " seconds")); + if (isInfoEnabled()) { + info("RUN TASK", buildgen(id, " >Time left> ", task.getDelay(TimeUnit.SECONDS), " seconds")); + } } @Override public void kill(String id) { if (tasks.containsKey(id)) { - info("KILLED TASK", id); + if (isInfoEnabled()) { + info("KILLED TASK", id); + } tasks.remove(id); var task = tasks.get(id); if (Objects.nonNull(task) && (!task.isDone() || !task.isCancelled())) { @@ -96,7 +102,9 @@ public void kill(String id) { @Override public void clear() { tasks.forEach((id, task) -> { - info("KILLED TASK", id); + if (isInfoEnabled()) { + info("KILLED TASK", id); + } if (Objects.nonNull(task) && (!task.isDone() || !task.isCancelled())) { task.cancel(true); } diff --git a/src/main/java/com/tenio/common/utility/StringUtility.java b/src/main/java/com/tenio/common/utility/StringUtility.java index 652f433..5c5b731 100644 --- a/src/main/java/com/tenio/common/utility/StringUtility.java +++ b/src/main/java/com/tenio/common/utility/StringUtility.java @@ -76,7 +76,7 @@ public static String getRandomTextByLength(int length) { // generate a random number between // 0 to AlphaNumericString variable length - int index = (int) (ALPHA_NUMERIC_STRING.length() * Math.random()); + int index = MathUtility.randInt(0, ALPHA_NUMERIC_STRING.length() - 1); // add Character one by one in end of sb builder.append(ALPHA_NUMERIC_STRING.charAt(index)); @@ -84,4 +84,26 @@ public static String getRandomTextByLength(int length) { return builder.toString(); } + + /** + * * + * @param text + * @param trimBy + * @return + * @since 0.5.0 + */ + public static String trimStringByString(String text, String trimBy) { + int beginIndex = 0; + int endIndex = text.length(); + + while (text.substring(beginIndex, endIndex).startsWith(trimBy)) { + beginIndex += trimBy.length(); + } + + while (text.substring(beginIndex, endIndex).endsWith(trimBy)) { + endIndex -= trimBy.length(); + } + + return text.substring(beginIndex, endIndex); + } } diff --git a/src/main/java/com/tenio/common/worker/WorkerPool.java b/src/main/java/com/tenio/common/worker/WorkerPool.java index e064345..59c2ac3 100644 --- a/src/main/java/com/tenio/common/worker/WorkerPool.java +++ b/src/main/java/com/tenio/common/worker/WorkerPool.java @@ -51,14 +51,18 @@ public WorkerPool(String name, int noOfThreads, int maxNoOfTasks) { runnableWorkerPools = new ArrayList<>(); isStopped = false; - info("CREATED NEW WORKERS", - buildgen("Number of threads: ", noOfThreads, ", Max number of tasks: ", maxNoOfTasks)); + if (isInfoEnabled()) { + info("CREATED NEW WORKERS", + buildgen("Number of threads: ", noOfThreads, ", Max number of tasks: ", maxNoOfTasks)); + } for (int i = 0; i < noOfThreads; i++) { runnableWorkerPools.add(new WorkerPoolRunnable(name, i, taskQueue)); } for (WorkerPoolRunnable runnable : runnableWorkerPools) { - new Thread(runnable).start(); + Thread thread = new Thread(runnable); + thread.setDaemon(true); + thread.start(); } } @@ -74,7 +78,9 @@ public synchronized void execute(Runnable task, String debugText) throws Illegal throw new IllegalStateException("WorkersPool is stopped"); } - trace("EXECUTED A TASK", debugText); + if (isTraceEnabled()) { + trace("EXECUTED A TASK", debugText); + } taskQueue.offer(task); } @@ -95,8 +101,10 @@ public synchronized void waitUntilAllTasksFinished() { while (taskQueue.size() > 0) { try { Thread.sleep(1); - } catch (InterruptedException e) { - error(e); + } catch (InterruptedException exception) { + if (isErrorEnabled()) { + error(exception); + } } } } diff --git a/src/main/java/com/tenio/common/worker/WorkerPoolRunnable.java b/src/main/java/com/tenio/common/worker/WorkerPoolRunnable.java index 8328986..0071399 100644 --- a/src/main/java/com/tenio/common/worker/WorkerPoolRunnable.java +++ b/src/main/java/com/tenio/common/worker/WorkerPoolRunnable.java @@ -35,7 +35,7 @@ public final class WorkerPoolRunnable extends AbstractLogger implements Runnable private final BlockingQueue taskQueue; private final String name; private final int index; - private Thread thread; + private Thread currentThread; private boolean isStopped; /** @@ -56,17 +56,24 @@ public WorkerPoolRunnable(String name, int index, BlockingQueue taskQu * Starts a new thread for a worker pool. */ public void run() { - thread = Thread.currentThread(); - thread.setName(String.format("worker-%s-%d", name, index)); + currentThread = Thread.currentThread(); + currentThread.setName(String.format("worker-%s-%d", name, index)); + currentThread.setUncaughtExceptionHandler((thread, cause) -> { + if (isErrorEnabled()) { + error(cause, thread.getName()); + } + }); while (!isStopped()) { try { Runnable runnable = taskQueue.take(); runnable.run(); - } catch (Exception e) { + } catch (Throwable cause) { // log or otherwise report exception, // but keep pool thread alive. - error(e); + if (isErrorEnabled()) { + error(cause); + } } } } @@ -77,7 +84,7 @@ public void run() { public synchronized void doStop() { isStopped = true; // break pool thread out of dequeue() call. - thread.interrupt(); + currentThread.interrupt(); } /** diff --git a/src/test/java/com/tenio/common/TenIOCommonTest.java b/src/test/java/com/tenio/common/TenIOCommonTest.java index 279f8b7..27dc6bb 100644 --- a/src/test/java/com/tenio/common/TenIOCommonTest.java +++ b/src/test/java/com/tenio/common/TenIOCommonTest.java @@ -34,6 +34,7 @@ of this software and associated documentation files (the "Software"), to deal @SuiteDisplayName("Test all unit test cases for tenio-common module") @SelectPackages({ "com.tenio.common.configuration", + "com.tenio.common.constant", "com.tenio.common.data", "com.tenio.common.pool", "com.tenio.common.task", diff --git a/src/test/java/com/tenio/common/bootstrap/loader/TestClassA.java b/src/test/java/com/tenio/common/bootstrap/loader/TestClassA.java new file mode 100644 index 0000000..60ecfea --- /dev/null +++ b/src/test/java/com/tenio/common/bootstrap/loader/TestClassA.java @@ -0,0 +1,28 @@ +/* +The MIT License + +Copyright (c) 2016-2022 kong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +package com.tenio.common.bootstrap.loader; + +public class TestClassA { +} diff --git a/src/test/java/com/tenio/common/bootstrap/loader/TestClassB.java b/src/test/java/com/tenio/common/bootstrap/loader/TestClassB.java new file mode 100644 index 0000000..fa181ff --- /dev/null +++ b/src/test/java/com/tenio/common/bootstrap/loader/TestClassB.java @@ -0,0 +1,28 @@ +/* +The MIT License + +Copyright (c) 2016-2022 kong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +package com.tenio.common.bootstrap.loader; + +public class TestClassB { +} diff --git a/src/test/java/com/tenio/common/bootstrap/loader/TestClassC.java b/src/test/java/com/tenio/common/bootstrap/loader/TestClassC.java new file mode 100644 index 0000000..1e69da4 --- /dev/null +++ b/src/test/java/com/tenio/common/bootstrap/loader/TestClassC.java @@ -0,0 +1,29 @@ +/* +The MIT License + +Copyright (c) 2016-2022 kong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +package com.tenio.common.bootstrap.loader; + +public class TestClassC { +} + diff --git a/src/test/java/com/tenio/common/configuration/ConfigurationTest.java b/src/test/java/com/tenio/common/configuration/ConfigurationTest.java index 69b6569..e04cd23 100644 --- a/src/test/java/com/tenio/common/configuration/ConfigurationTest.java +++ b/src/test/java/com/tenio/common/configuration/ConfigurationTest.java @@ -49,11 +49,11 @@ void initialization() { void shouldRetrieveImportedData() { assertAll("shouldRetrieveImportedData", () -> assertTrue(configuration.getBoolean(DefaultConfigurationType.BOOLEAN)), - () -> assertEquals(configuration.getFloat(DefaultConfigurationType.FLOAT), 100F), - () -> assertEquals(configuration.getInt(DefaultConfigurationType.INTEGER), 99), - () -> assertEquals(configuration.getString(DefaultConfigurationType.STRING), "test"), - () -> assertEquals(configuration.get(DefaultConfigurationType.OBJECT), - configuration.dummyObject) + () -> assertEquals(100F, configuration.getFloat(DefaultConfigurationType.FLOAT)), + () -> assertEquals(99, configuration.getInt(DefaultConfigurationType.INTEGER)), + () -> assertEquals("test", configuration.getString(DefaultConfigurationType.STRING)), + () -> assertEquals(configuration.dummyObject, + configuration.get(DefaultConfigurationType.OBJECT)) ); } @@ -69,6 +69,6 @@ void checkNonDefinedConfiguredTypeShouldReturnTrue() { @DisplayName("To be able to clear all configuration data") void clearAllConfigurationsShouldWork() { configuration.clear(); - assertEquals(configuration.toString(), "{}"); + assertEquals("{}", configuration.toString()); } } diff --git a/src/test/java/com/tenio/common/configuration/DefaultConfigurationType.java b/src/test/java/com/tenio/common/configuration/DefaultConfigurationType.java index 414b526..8252f1a 100644 --- a/src/test/java/com/tenio/common/configuration/DefaultConfigurationType.java +++ b/src/test/java/com/tenio/common/configuration/DefaultConfigurationType.java @@ -37,8 +37,7 @@ enum DefaultConfigurationType implements ConfigurationType { NULL_DEFINED("NULL_DEFINED"); // Reverse-lookup map for getting a type from a value - private static final Map lookup = - new HashMap(); + private static final Map lookup = new HashMap<>(); static { for (var configurationType : DefaultConfigurationType.values()) { diff --git a/src/test/java/com/tenio/common/constant/ConstantTest.java b/src/test/java/com/tenio/common/constant/ConstantTest.java new file mode 100644 index 0000000..5ec67e0 --- /dev/null +++ b/src/test/java/com/tenio/common/constant/ConstantTest.java @@ -0,0 +1,50 @@ +/* +The MIT License + +Copyright (c) 2016-2022 kong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +package com.tenio.common.constant; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("Unit Test Cases For Constant") +class ConstantTest { + + @Test + @DisplayName("Throw an exception when the class's instance is attempted creating") + void createNewInstanceShouldThrowException() throws NoSuchMethodException { + var constructor = CommonConstant.class.getDeclaredConstructor(); + assertTrue(Modifier.isPrivate(constructor.getModifiers())); + assertThrows(InvocationTargetException.class, () -> { + constructor.setAccessible(true); + constructor.newInstance(); + }); + } +} diff --git a/src/test/java/com/tenio/common/data/DataTypeTest.java b/src/test/java/com/tenio/common/data/DataTypeTest.java new file mode 100644 index 0000000..5beffbb --- /dev/null +++ b/src/test/java/com/tenio/common/data/DataTypeTest.java @@ -0,0 +1,50 @@ +/* +The MIT License + +Copyright (c) 2016-2022 kong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +package com.tenio.common.data; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +@DisplayName("Unit Test Cases For Data Type") +class DataTypeTest { + + @ParameterizedTest + @CsvSource({ + "ZERO, zero", + "MSG_PACK, msgpack" + }) + @DisplayName("Test All Enumerated Values") + void testAllEnumValues(String name, String value) { + DataType dataType = DataType.valueOf(name); + DataType dataTypeByValue = DataType.getByValue(value); + assertEquals(dataTypeByValue, dataType); + assertEquals(value, dataType.getValue()); + assertEquals(value, dataType.toString()); + assertEquals(name, dataType.name()); + } +} diff --git a/src/test/java/com/tenio/common/data/DataUtilityTest.java b/src/test/java/com/tenio/common/data/DataUtilityTest.java new file mode 100644 index 0000000..111bfd4 --- /dev/null +++ b/src/test/java/com/tenio/common/data/DataUtilityTest.java @@ -0,0 +1,72 @@ +/* +The MIT License + +Copyright (c) 2016-2022 kong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +package com.tenio.common.data; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.tenio.common.data.msgpack.MsgPackUtility; +import com.tenio.common.data.msgpack.element.MsgPackArray; +import com.tenio.common.data.msgpack.element.MsgPackMap; +import com.tenio.common.data.zero.ZeroArray; +import com.tenio.common.data.zero.ZeroMap; +import com.tenio.common.data.zero.utility.ZeroUtility; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("Unit Test Cases For Data Utility") +class DataUtilityTest { + + @Test + @DisplayName("Throw an exception when the class's instance is attempted creating") + void createNewInstanceShouldThrowException() throws NoSuchMethodException { + var constructor = DataUtility.class.getDeclaredConstructor(); + assertTrue(Modifier.isPrivate(constructor.getModifiers())); + assertThrows(InvocationTargetException.class, () -> { + constructor.setAccessible(true); + constructor.newInstance(); + }); + } + + @Test + @DisplayName("Provided creation methods should work properly") + void instancesCreationShouldWork() { + assertAll("instancesCreationShouldWork", + () -> assertInstanceOf(ZeroArray.class, DataUtility.newZeroArray()), + () -> assertInstanceOf(ZeroMap.class, DataUtility.newZeroMap()), + () -> assertInstanceOf(MsgPackArray.class, DataUtility.newMsgArray()), + () -> assertInstanceOf(MsgPackMap.class, DataUtility.newMsgMap())); + + var zeroMapBinaries = ZeroUtility.mapToBinary(ZeroUtility.newZeroMap()); + var msgPackBinaries = MsgPackUtility.serialize(MsgPackMap.newInstance().putBoolean("a", true)); + assertInstanceOf(ZeroMap.class, DataUtility.binaryToCollection(DataType.ZERO, zeroMapBinaries)); + assertInstanceOf(MsgPackMap.class, DataUtility.binaryToCollection(DataType.MSG_PACK, + msgPackBinaries)); + } +} diff --git a/src/test/java/com/tenio/common/data/MsgPackUtilityTest.java b/src/test/java/com/tenio/common/data/MsgPackUtilityTest.java new file mode 100644 index 0000000..9f31005 --- /dev/null +++ b/src/test/java/com/tenio/common/data/MsgPackUtilityTest.java @@ -0,0 +1,152 @@ +/* +The MIT License + +Copyright (c) 2016-2022 kong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +package com.tenio.common.data; + +import static org.junit.jupiter.api.Assertions.assertAll; +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.tenio.common.data.msgpack.MsgPackUtility; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("Unit Test Cases For MsgPack Utility") +class MsgPackUtilityTest { + + @Test + @DisplayName("Throw an exception when the class's instance is attempted creating") + void createNewInstanceShouldThrowException() throws NoSuchMethodException { + var constructor = MsgPackUtility.class.getDeclaredConstructor(); + assertTrue(Modifier.isPrivate(constructor.getModifiers())); + assertThrows(InvocationTargetException.class, () -> { + constructor.setAccessible(true); + constructor.newInstance(); + }); + } + + @Test + @DisplayName("Checking whether binaries data is a collection should work") + void itShouldReturnCorrectDataCollection() { + var msgpackMap = MsgPackUtility.newMsgPackMap().putBoolean("a", true).putMsgPackArray("b", + MsgPackUtility.newMsgPackArray().addBoolean(true)); + var checkMsgPackMap = MsgPackUtility.deserialize(msgpackMap.toBinary()); + + assert checkMsgPackMap != null; + assertEquals(msgpackMap.toString(), checkMsgPackMap.toString()); + } + + @Test + @DisplayName("Allow adding and fetching data to/from MsgPackArray") + void addedDataInArrayShouldMatch() { + var origin = MsgPackUtility.newMsgPackArray(); + origin.addBoolean(true).addInteger(1000).addFloat(101.1f).addString("msgpack") + .addBoolean(false).addMsgPackArray(MsgPackUtility.newMsgPackArray().addBoolean(true)); + var carry = MsgPackUtility.newMsgPackMap().putMsgPackArray("k", origin); + var binary = carry.toBinary(); + var newOne = MsgPackUtility.deserialize(binary); + + assert newOne != null; + assertAll("addedDataInArrayShouldMatch", + () -> assertTrue(newOne.getMsgPackArray("k").getBoolean(0)), + () -> assertEquals(1000, newOne.getMsgPackArray("k").getInteger(1)), + () -> assertEquals(101.1f, newOne.getMsgPackArray("k").getFloat(2)), + () -> assertEquals("msgpack", newOne.getMsgPackArray("k").getString(3)), + () -> assertFalse(newOne.getMsgPackArray("k").getBoolean(4)), + () -> assertEquals(MsgPackUtility.newMsgPackArray().addBoolean(true).toString(), + newOne.getMsgPackArray("k").getMsgPackArray(5).toString()) + ); + + var readonlyArray = origin.getReadonlyList(); + assertAll("readonlyDataInArrayShouldMatch", + () -> assertTrue((boolean) readonlyArray.get(0)), + () -> assertEquals(1000, (int) readonlyArray.get(1)), + () -> assertEquals(101.1f, (float) readonlyArray.get(2)), + () -> assertEquals("msgpack", readonlyArray.get(3)), + () -> assertFalse((boolean) readonlyArray.get(4)), + () -> assertEquals(MsgPackUtility.newMsgPackArray().addBoolean(true).toString(), + readonlyArray.get(5).toString()) + ); + } + + @Test + @DisplayName("Allow adding and fetching MsgPackArray data to/from MsgPackArray") + void zeroMapInArrayShouldMatch() { + var origin = MsgPackUtility.newMsgPackArray(); + var msgPackArray = MsgPackUtility.newMsgPackArray(); + msgPackArray.addBoolean(true) + .addInteger(100) + .addString("msgpack"); + origin.addMsgPackArray(msgPackArray); + var carry = MsgPackUtility.newMsgPackMap().putMsgPackArray("k", origin); + var binary = carry.toBinary(); + var newOne = MsgPackUtility.deserialize(binary); + + assert newOne != null; + assertEquals(newOne.getMsgPackArray("k").toString(), carry.getMsgPackArray("k").toString()); + } + + @Test + @DisplayName("Allow adding and fetching data to/from MsgPackMap") + void putDataInMapShouldMatch() { + var origin = MsgPackUtility.newMsgPackMap(); + origin.putBoolean("b", true) + .putInteger("i", 1000) + .putFloat("f", 101.1f) + .putString("s", "msgpack") + .putMsgPackArray("ma", MsgPackUtility.newMsgPackArray().addBoolean(true)) + .putMsgPackMap("mm", MsgPackUtility.newMsgPackMap().putBoolean("b", true)); + var binary = origin.toBinary(); + var newOne = MsgPackUtility.deserialize(binary); + + assert newOne != null; + assertAll("putDataInMapShouldMatch", + () -> assertFalse(newOne.contains("out")), + () -> assertTrue(newOne.getBoolean("b")), + () -> assertEquals(1000, newOne.getInteger("i")), + () -> assertEquals(101.1f, newOne.getFloat("f")), + () -> assertEquals("msgpack", newOne.getString("s")), + () -> assertEquals(MsgPackUtility.newMsgPackArray().addBoolean(true).toString(), + newOne.getMsgPackArray("ma").toString()), + () -> assertEquals(MsgPackUtility.newMsgPackMap().putBoolean("b", true).toString(), + newOne.getMsgPackMap("mm").toString()) + ); + + var readonlyMap = origin.getReadonlyMap(); + assertAll("readonlyDataInMapShouldMatch", + () -> assertTrue((boolean) readonlyMap.get("b")), + () -> assertEquals(1000, (int) readonlyMap.get("i")), + () -> assertEquals(101.1f, (float) readonlyMap.get("f")), + () -> assertEquals("msgpack", readonlyMap.get("s")), + () -> assertEquals(MsgPackUtility.newMsgPackArray().addBoolean(true).toString(), + newOne.get("ma").toString()), + () -> assertEquals(MsgPackUtility.newMsgPackMap().putBoolean("b", true).toString(), + newOne.get("mm").toString()) + ); + } +} diff --git a/src/test/java/com/tenio/common/data/common/ZeroElementTest.java b/src/test/java/com/tenio/common/data/ZeroElementTest.java similarity index 97% rename from src/test/java/com/tenio/common/data/common/ZeroElementTest.java rename to src/test/java/com/tenio/common/data/ZeroElementTest.java index 0e6bce0..114761b 100644 --- a/src/test/java/com/tenio/common/data/common/ZeroElementTest.java +++ b/src/test/java/com/tenio/common/data/ZeroElementTest.java @@ -22,7 +22,7 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. */ -package com.tenio.common.data.common; +package com.tenio.common.data; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/src/test/java/com/tenio/common/data/ZeroUtilityTest.java b/src/test/java/com/tenio/common/data/ZeroUtilityTest.java index 75a60f5..c68439a 100644 --- a/src/test/java/com/tenio/common/data/ZeroUtilityTest.java +++ b/src/test/java/com/tenio/common/data/ZeroUtilityTest.java @@ -27,10 +27,15 @@ of this software and associated documentation files (the "Software"), to deal import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.tenio.common.data.zero.utility.ZeroUtility; import com.tenio.common.data.zero.ZeroType; +import com.tenio.common.data.zero.utility.ZeroUtility; +import com.tenio.common.utility.ByteUtility; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; import org.junit.jupiter.api.AfterAll; @@ -42,6 +47,7 @@ of this software and associated documentation files (the "Software"), to deal class ZeroUtilityTest { private static Collection booleans; + private static byte[] binaries; private static Collection shorts; private static Collection integers; private static Collection longs; @@ -51,12 +57,17 @@ class ZeroUtilityTest { @BeforeAll static void initialization() { - booleans = new ArrayList<>(); + booleans = new ArrayList<>(3); booleans.add(true); booleans.add(false); booleans.add(true); - shorts = new ArrayList<>(); + binaries = new byte[3]; + binaries[0] = (byte) 1; + binaries[1] = (byte) 2; + binaries[2] = (byte) 3; + + shorts = new ArrayList<>(6); shorts.add((short) 10); shorts.add((short) 11); shorts.add((short) 12); @@ -64,17 +75,17 @@ static void initialization() { shorts.add((short) 14); shorts.add((short) 15); - integers = new ArrayList<>(); + integers = new ArrayList<>(4); integers.add(100); integers.add(101); integers.add(102); integers.add(103); - longs = new ArrayList<>(); + longs = new ArrayList<>(2); longs.add(1000L); longs.add(2000L); - floats = new ArrayList<>(); + floats = new ArrayList<>(6); floats.add(1001.1f); floats.add(1002.2f); floats.add(1003.3f); @@ -82,10 +93,10 @@ static void initialization() { floats.add(1005.5f); floats.add(1006.6f); - doubles = new ArrayList<>(); + doubles = new ArrayList<>(1); doubles.add(1000000.11111); - strings = new ArrayList<>(); + strings = new ArrayList<>(5); strings.add("zero"); strings.add("data"); strings.add("testing"); @@ -104,22 +115,49 @@ static void finish() { strings.clear(); } + @Test + @DisplayName("Throw an exception when the class's instance is attempted creating") + void createNewInstanceShouldThrowException() throws NoSuchMethodException { + var constructor = ZeroUtility.class.getDeclaredConstructor(); + assertTrue(Modifier.isPrivate(constructor.getModifiers())); + assertThrows(InvocationTargetException.class, () -> { + constructor.setAccessible(true); + constructor.newInstance(); + }); + } + + @Test + @DisplayName("Checking whether binaries data is a collection should work") + void itShouldReturnCorrectDataCollection() { + var zeroMap = ZeroUtility.newZeroMap().putBoolean("a", true); + var checkZeroMap = ZeroUtility.binaryToCollection(zeroMap.toBinary()); + assertEquals(zeroMap.toString(), checkZeroMap.toString()); + + var zeroArray = ZeroUtility.newZeroArray().addBoolean(true); + var checkZeroArray = ZeroUtility.binaryToCollection(zeroArray.toBinary()); + + assertEquals(zeroArray.toString(), checkZeroArray.toString()); + assertThrows(UnsupportedOperationException.class, + () -> ZeroUtility.binaryToCollection(new byte[] {(byte) 1})); + } + @Test @DisplayName("Allow adding and fetching primitive data to/from ZeroArray") void primitiveDataInArrayShouldMatch() { var origin = ZeroUtility.newZeroArray(); - origin.addBoolean(true).addShort((short) 11).addInteger(1000).addFloat(101.1f).addLong(1000L) - .addDouble(1010101.101); + origin.addBoolean(true).addByte((byte) 1).addShort((short) 11).addInteger(1000).addFloat(101.1f) + .addLong(1000L).addDouble(1010101.101); var binary = origin.toBinary(); var newOne = ZeroUtility.binaryToArray(binary); assertAll("primitiveDataInArrayShouldMatch", () -> assertTrue(newOne.getBoolean(0)), - () -> assertEquals(newOne.getShort(1), (short) 11), - () -> assertEquals(newOne.getInteger(2), 1000), - () -> assertEquals(newOne.getFloat(3), 101.1f), - () -> assertEquals(newOne.getLong(4), 1000L), - () -> assertEquals(newOne.getDouble(5), 1010101.101) + () -> assertEquals((byte) 1, newOne.getByte(1)), + () -> assertEquals((short) 11, newOne.getShort(2)), + () -> assertEquals(1000, newOne.getInteger(3)), + () -> assertEquals(101.1f, newOne.getFloat(4)), + () -> assertEquals(1000L, newOne.getLong(5)), + () -> assertEquals(1010101.101, newOne.getDouble(6)) ); } @@ -135,10 +173,10 @@ void instanceDataInArrayShouldMatch() { assertAll("instanceDataInArrayShouldMatch", () -> assertTrue(newOne.isNull(0)), () -> assertAll("zeroDataShouldMatch", - () -> assertEquals(newOne.getZeroElement(1).getType(), ZeroType.BOOLEAN), + () -> assertEquals(ZeroType.BOOLEAN, newOne.getZeroElement(1).getType()), () -> assertFalse((boolean) newOne.getZeroElement(1).getData()) ), - () -> assertEquals(newOne.getString(2), "test") + () -> assertEquals("test", newOne.getString(2)) ); } @@ -146,19 +184,24 @@ void instanceDataInArrayShouldMatch() { @DisplayName("Allow adding and fetching arrays of primitive data to/from ZeroArray") void collectionDataInArrayShouldMatch() { var origin = ZeroUtility.newZeroArray(); - origin.addBooleanArray(booleans).addShortArray(shorts).addIntegerArray(integers) - .addLongArray(longs).addFloatArray(floats).addDoubleArray(doubles).addStringArray(strings); + var zeroArray = ZeroUtility.newZeroArray().addString("newZeroArray"); + origin.addBooleanArray(booleans).addByteArray(binaries).addShortArray(shorts) + .addIntegerArray(integers) + .addLongArray(longs).addFloatArray(floats).addDoubleArray(doubles).addStringArray(strings) + .addZeroArray(zeroArray); var binary = origin.toBinary(); var newOne = ZeroUtility.binaryToArray(binary); assertAll("collectionDataInArrayShouldMatch", - () -> assertEquals(newOne.getBooleanArray(0).toString(), booleans.toString()), - () -> assertEquals(newOne.getShortArray(1).toString(), shorts.toString()), - () -> assertEquals(newOne.getIntegerArray(2).toString(), integers.toString()), - () -> assertEquals(newOne.getLongArray(3).toString(), longs.toString()), - () -> assertEquals(newOne.getFloatArray(4).toString(), floats.toString()), - () -> assertEquals(newOne.getDoubleArray(5).toString(), doubles.toString()), - () -> assertEquals(newOne.getStringArray(6).toString(), strings.toString()) + () -> assertEquals(booleans.toString(), newOne.getBooleanArray(0).toString()), + () -> assertEquals(binaries.length, newOne.getByteArray(1).length), + () -> assertEquals(shorts.toString(), newOne.getShortArray(2).toString()), + () -> assertEquals(integers.toString(), newOne.getIntegerArray(3).toString()), + () -> assertEquals(longs.toString(), newOne.getLongArray(4).toString()), + () -> assertEquals(floats.toString(), newOne.getFloatArray(5).toString()), + () -> assertEquals(doubles.toString(), newOne.getDoubleArray(6).toString()), + () -> assertEquals(strings.toString(), newOne.getStringArray(7).toString()), + () -> assertEquals(zeroArray.toString(), newOne.getZeroArray(8).toString()) ); } @@ -172,10 +215,10 @@ void duplicatedValueInArrayShouldWork() { var newOne = ZeroUtility.binaryToArray(binary); assertAll("duplicatedValueInArrayShouldWork", - () -> assertEquals(newOne.getBooleanArray(0).toString(), booleans.toString()), - () -> assertEquals(newOne.getShortArray(1).toString(), shorts.toString()), - () -> assertEquals(newOne.getBooleanArray(2).toString(), booleans.toString()), - () -> assertEquals(newOne.getShortArray(3).toString(), shorts.toString()) + () -> assertEquals(booleans.toString(), newOne.getBooleanArray(0).toString()), + () -> assertEquals(shorts.toString(), newOne.getShortArray(1).toString()), + () -> assertEquals(booleans.toString(), newOne.getBooleanArray(2).toString()), + () -> assertEquals(shorts.toString(), newOne.getShortArray(3).toString()) ); } @@ -211,11 +254,11 @@ void primitiveDataInMapShouldMatch() { assertAll("primitiveDataInObjectShouldMatch", () -> assertTrue(newOne.getBoolean("b")), - () -> assertEquals(newOne.getShort("s"), (short) 11), - () -> assertEquals(newOne.getInteger("i"), 1000), - () -> assertEquals(newOne.getFloat("f"), 101.1f), - () -> assertEquals(newOne.getLong("l"), 1000L), - () -> assertEquals(newOne.getDouble("d"), 1010101.101) + () -> assertEquals((short) 11, newOne.getShort("s")), + () -> assertEquals(1000, newOne.getInteger("i")), + () -> assertEquals(101.1f, newOne.getFloat("f")), + () -> assertEquals(1000L, newOne.getLong("l")), + () -> assertEquals(1010101.101, newOne.getDouble("d")) ); } @@ -232,10 +275,10 @@ void instanceDataInMapShouldMatch() { assertAll("instanceDataInObjectShouldMatch", () -> assertTrue(newOne.isNull("n")), () -> assertAll("zeroDataShouldMatch", - () -> assertEquals(newOne.getZeroElement("z").getType(), ZeroType.BOOLEAN), + () -> assertEquals(ZeroType.BOOLEAN, newOne.getZeroElement("z").getType()), () -> assertFalse((boolean) newOne.getZeroElement("z").getData()) ), - () -> assertEquals(newOne.getString("s"), "test") + () -> assertEquals("test", newOne.getString("s")) ); } @@ -243,24 +286,27 @@ void instanceDataInMapShouldMatch() { @DisplayName("Allow adding and fetching arrays of primitive data to/from ZeroMap") void collectionDataInMapShouldMatch() { var origin = ZeroUtility.newZeroMap(); + var zeroArray = ZeroUtility.newZeroArray().addString("newZeroArray"); origin.putBooleanArray("b", booleans) .putShortArray("s", shorts) .putIntegerArray("i", integers) .putLongArray("l", longs) .putFloatArray("f", floats) .putDoubleArray("d", doubles) - .putStringArray("ss", strings); + .putStringArray("ss", strings) + .putZeroArray("za", zeroArray); var binary = origin.toBinary(); var newOne = ZeroUtility.binaryToMap(binary); assertAll("collectionDataInObjectShouldMatch", - () -> assertEquals(newOne.getBooleanArray("b").toString(), booleans.toString()), - () -> assertEquals(newOne.getShortArray("s").toString(), shorts.toString()), - () -> assertEquals(newOne.getIntegerArray("i").toString(), integers.toString()), - () -> assertEquals(newOne.getLongArray("l").toString(), longs.toString()), - () -> assertEquals(newOne.getFloatArray("f").toString(), floats.toString()), - () -> assertEquals(newOne.getDoubleArray("d").toString(), doubles.toString()), - () -> assertEquals(newOne.getStringArray("ss").toString(), strings.toString()) + () -> assertEquals(booleans.toString(), newOne.getBooleanArray("b").toString()), + () -> assertEquals(shorts.toString(), newOne.getShortArray("s").toString()), + () -> assertEquals(integers.toString(), newOne.getIntegerArray("i").toString()), + () -> assertEquals(longs.toString(), newOne.getLongArray("l").toString()), + () -> assertEquals(floats.toString(), newOne.getFloatArray("f").toString()), + () -> assertEquals(doubles.toString(), newOne.getDoubleArray("d").toString()), + () -> assertEquals(strings.toString(), newOne.getStringArray("ss").toString()), + () -> assertEquals(zeroArray.toString(), newOne.getZeroArray("za").toString()) ); } @@ -274,10 +320,10 @@ void duplicatedValueInMapShouldWork() { var newOne = ZeroUtility.binaryToMap(binary); assertAll("duplicatedValueInObjectShouldWork", - () -> assertEquals(newOne.getBooleanArray("b1").toString(), booleans.toString()), - () -> assertEquals(newOne.getShortArray("s1").toString(), shorts.toString()), - () -> assertEquals(newOne.getBooleanArray("b2").toString(), booleans.toString()), - () -> assertEquals(newOne.getShortArray("s2").toString(), shorts.toString()) + () -> assertEquals(booleans.toString(), newOne.getBooleanArray("b1").toString()), + () -> assertEquals(shorts.toString(), newOne.getShortArray("s1").toString()), + () -> assertEquals(booleans.toString(), newOne.getBooleanArray("b2").toString()), + () -> assertEquals(shorts.toString(), newOne.getShortArray("s2").toString()) ); } @@ -297,4 +343,283 @@ void zeroMapInMapShouldMatch() { assertEquals(zeroMap.toString(), newOne.getZeroMap("z").toString()); } + + @Test + @DisplayName("The list of elements when using getReadonlyZeroArray() method should be correct") + void getReadonlyZeroArrayShouldReturnTheSameElements() { + var origin = ZeroUtility.newZeroArray(); + origin.addInteger(10).addInteger(20).addInteger(30); + var readonlyOrigin = origin.getReadonlyZeroArray(); + + assertAll("getReadonlyZeroArrayShouldReturnTheSameElements", + () -> assertEquals(origin.getInteger(0), readonlyOrigin.getInteger(0)), + () -> assertEquals(origin.getInteger(1), readonlyOrigin.getInteger(1)), + () -> assertEquals(origin.getInteger(2), readonlyOrigin.getInteger(2))); + } + + @Test + @DisplayName("Fetching elements from a zero array should give expected results") + void fetchElementsFromZeroArrayShouldHaveExpectedResults() { + var origin = ZeroUtility.newZeroArray(); + origin.addInteger(10).addInteger(20).addInteger(30).addNull(); + + assertAll("fetchElementsFromZeroArrayShouldHaveExpectedResults", + () -> assertEquals(10, (int) origin.getDataForElementAt(0)), + () -> assertNull(origin.getDataForElementAt(3)), + () -> assertTrue(origin.contains(20)), + () -> assertFalse(origin.contains(40)), + () -> assertTrue(origin.contains(null))); + + origin.removeElementAt(3); + assertEquals(3, origin.size()); + origin.removeElementAt(0); + assertFalse(origin.contains(10)); + } + + @Test + @DisplayName("Working with binaries in ZeroArray should deliver expected results") + void workingWithBinariesInZeroArrayShouldReturnExpectedResults() { + var origin = ZeroUtility.newZeroArray(); + origin.addByte((byte) 1).addByteArray(new byte[] {(byte) 1, (byte) 2, (byte) 3}); + + assertAll("workingWithBinariesInZeroArrayShouldReturnExpectedResults", + () -> assertEquals((byte) 1, origin.getByte(0)), + () -> assertEquals((byte) 1, origin.getByteArray(1)[0]), + () -> assertEquals((byte) 2, origin.getByteArray(1)[1]), + () -> assertEquals((byte) 3, origin.getByteArray(1)[2])); + + var iterator = origin.iterator(); + while (iterator.hasNext()) { + var element = iterator.next(); + if (element.getType() == ZeroType.BYTE) { + assertEquals((byte) 1, element.getData()); + } else { + assertEquals(3, ((byte[]) element.getData()).length); + } + } + } + + @Test + @DisplayName("The map of elements when using getReadonlyZeroMap() method should be correct") + void getReadonlyZeroMapShouldReturnTheSameElements() { + var origin = ZeroUtility.newZeroMap(); + origin.putInteger("a", 10).putInteger("b", 20).putInteger("c", 30); + var readonlyOrigin = origin.getReadonlyZeroMap(); + var readonlyKeyOrigin = origin.getReadonlyKeys(); + + assertAll("getReadonlyZeroMapShouldReturnTheSameElements", + () -> assertEquals(origin.getInteger("a"), readonlyOrigin.getInteger("a")), + () -> assertEquals(origin.getInteger("b"), readonlyOrigin.getInteger("b")), + () -> assertEquals(origin.getInteger("c"), readonlyOrigin.getInteger("c"))); + + assertTrue(readonlyKeyOrigin.contains("a")); + assertTrue(readonlyKeyOrigin.contains("b")); + assertTrue(readonlyKeyOrigin.contains("c")); + assertFalse(readonlyKeyOrigin.contains("d")); + } + + @Test + @DisplayName("Fetching elements from a zero map should give expected results") + void fetchElementsFromZeroMapShouldHaveExpectedResults() { + var origin = ZeroUtility.newZeroMap(); + origin.putInteger("a", 10).putInteger("b", 20).putInteger("c", 30) + .putNull("d"); + + assertAll("fetchElementsFromZeroMapShouldHaveExpectedResults", + () -> assertEquals(10, (int) origin.getZeroElement("a").getData()), + () -> assertNull(origin.getZeroElement("d").getData()), + () -> assertTrue(origin.containsKey("a")), + () -> assertFalse(origin.containsKey("f"))); + + origin.removeElement("d"); + assertEquals(3, origin.size()); + origin.removeElement("a"); + assertFalse(origin.containsKey("a")); + } + + @Test + @DisplayName("Working with binaries in ZeroMap should deliver expected results") + void workingWithBinariesInZeroMapShouldReturnExpectedResults() { + var origin = ZeroUtility.newZeroMap(); + origin.putByte("a", (byte) 1).putByteArray("b", new byte[] {(byte) 1, (byte) 2, (byte) 3}); + assertAll("workingWithBinariesInZeroMapShouldReturnExpectedResults", + () -> assertEquals((byte) 1, origin.getByte("a")), + () -> assertEquals((byte) 1, origin.getByteArray("b")[0]), + () -> assertEquals((byte) 2, origin.getByteArray("b")[1]), + () -> assertEquals((byte) 3, origin.getByteArray("b")[2])); + + var iterator = origin.iterator(); + while (iterator.hasNext()) { + var element = iterator.next(); + if (element.getKey().equals("a")) { + assertEquals((byte) 1, element.getValue().getData()); + } else { + assertEquals(3, ((byte[]) element.getValue().getData()).length); + } + } + } + + @Test + @DisplayName("Test ZeroArray toString()") + void testZeroArrayToStringShouldGiveExpectedResult() { + var origin = ZeroUtility.newZeroArray(); + var zeroArray = ZeroUtility.newZeroArray(); + zeroArray.addString("newZeroArray"); + var zeroMap = ZeroUtility.newZeroMap(); + zeroMap.putBoolean("b", true) + .putShort("s", (short) 10) + .putInteger("i", 100) + .putBooleanArray("ba", booleans) + .putZeroArray("za", ZeroUtility.newZeroArray().addDoubleArray(doubles)); + + origin.addBoolean(true).addByte((byte) 1).addShort((short) 2).addInteger(3).addLong(4L) + .addFloat(5.0f).addDouble(6.0).addString("7").addNull(); + origin.addBooleanArray(booleans).addByteArray(binaries).addShortArray(shorts) + .addIntegerArray(integers).addLongArray(longs).addFloatArray(floats).addDoubleArray(doubles) + .addStringArray(strings); + origin.addZeroArray(zeroArray); + origin.addZeroMap(zeroMap); + + assertEquals(""" + ZeroArray{ (boolean) true; (byte) 1; (short) 2; (integer) 3; (long) 4; (float) 5.0; (double) 6.0; (string) 7; (null) null; (boolean_array) [true, false, true]; (byte_array) byte[3]; (short_array) [10, 11, 12, 13, 14, 15]; (integer_array) [100, 101, 102, 103]; (long_array) [1000, 2000]; (float_array) [1001.1, 1002.2, 1003.3, 1004.4, 1005.5, 1006.6]; (double_array) [1000000.11111]; (string_array) [zero, data, testing, is, awesome]; (zero_array) ZeroArray{ (string) newZeroArray }; (zero_map) ZeroMap{ (boolean) b: true; (short) s: 10; (zero_array) za: ZeroArray{ (double_array) [1000000.11111] }; (integer) i: 100; (boolean_array) ba: [true, false, true] } } + """.trim(), origin.toString()); + } + + @Test + @DisplayName("Test ZeroMap toString()") + void testZeroMapToStringShouldGiveExpectedResult() { + var origin = ZeroUtility.newZeroMap(); + var zeroArray = ZeroUtility.newZeroArray(); + zeroArray.addString("newZeroArray"); + var zeroMap = ZeroUtility.newZeroMap(); + zeroMap.putBoolean("b", true) + .putShort("s", (short) 10) + .putInteger("i", 100) + .putBooleanArray("ba", booleans) + .putZeroArray("za", ZeroUtility.newZeroArray().addDoubleArray(doubles)); + + origin.putBoolean("a", true).putByte("b", (byte) 1).putShort("c", (short) 2).putInteger("d", + 3).putLong("e", 4L).putFloat("f", 5.0f).putDouble("g", 6.0).putString("h", "7") + .putNull("i"); + origin.putBooleanArray("k", booleans).putByteArray("l", binaries).putShortArray("m", shorts) + .putIntegerArray("n", integers).putLongArray("o", longs).putFloatArray("p", floats) + .putDoubleArray("q", doubles).putStringArray("r", strings); + origin.putZeroArray("r", zeroArray); + origin.putZeroMap("s", zeroMap); + + assertEquals(""" + ZeroMap{ (boolean) a: true; (byte) b: 1; (short) c: 2; (integer) d: 3; (long) e: 4; (float) f: 5.0; (double) g: 6.0; (string) h: 7; (null) i: null; (boolean_array) k: [true, false, true]; (byte_array) l: byte[3]; (short_array) m: [10, 11, 12, 13, 14, 15]; (integer_array) n: [100, 101, 102, 103]; (long_array) o: [1000, 2000]; (float_array) p: [1001.1, 1002.2, 1003.3, 1004.4, 1005.5, 1006.6]; (double_array) q: [1000000.11111]; (zero_array) r: ZeroArray{ (string) newZeroArray }; (zero_map) s: ZeroMap{ (boolean) b: true; (short) s: 10; (zero_array) za: ZeroArray{ (double_array) [1000000.11111] }; (integer) i: 100; (boolean_array) ba: [true, false, true] } } + """.trim(), origin.toString()); + } + + @Test + @DisplayName("It should throw exceptions when invalid conversions were called") + void itShouldThrowExceptionsWhenInvalidConversionCalled() { + // array size is insufficient + assertThrows(IllegalStateException.class, + () -> ZeroUtility.binaryToArray(new byte[] {(byte) 1})); + // it is not the zero array + assertThrows(IllegalStateException.class, + () -> ZeroUtility.binaryToArray(new byte[] {(byte) 1, (byte) 2, (byte) 3})); + // an array with negative size + var negativeArraySizeInShort = ByteUtility.shortToBytes((short) -2); + assertThrows(NegativeArraySizeException.class, + () -> ZeroUtility.binaryToArray( + new byte[] {(byte) ZeroType.ZERO_ARRAY.getValue(), negativeArraySizeInShort[0], + negativeArraySizeInShort[1]})); + // unrecognized zero type + var arraySizeInShort = ByteUtility.shortToBytes((short) 2); + assertThrows(IllegalArgumentException.class, + () -> ZeroUtility.binaryToArray( + new byte[] {(byte) ZeroType.ZERO_ARRAY.getValue(), arraySizeInShort[0], + arraySizeInShort[1], (byte) 19, (byte) 1})); + // failed to decode boolean + assertThrows(IllegalArgumentException.class, + () -> ZeroUtility.binaryToArray( + new byte[] {(byte) ZeroType.ZERO_ARRAY.getValue(), arraySizeInShort[0], + arraySizeInShort[1], + (byte) ZeroType.BOOLEAN.getValue(), (byte) 2})); + // failed to decode string + assertThrows(IllegalArgumentException.class, + () -> ZeroUtility.binaryToArray( + new byte[] {(byte) ZeroType.ZERO_ARRAY.getValue(), arraySizeInShort[0], + arraySizeInShort[1], + (byte) ZeroType.STRING.getValue(), negativeArraySizeInShort[0], + negativeArraySizeInShort[1]})); + // failed to decode collection + assertThrows(IllegalArgumentException.class, + () -> ZeroUtility.binaryToArray( + new byte[] {(byte) ZeroType.ZERO_ARRAY.getValue(), arraySizeInShort[0], + arraySizeInShort[1], + (byte) ZeroType.BOOLEAN_ARRAY.getValue(), negativeArraySizeInShort[0], + negativeArraySizeInShort[1]})); + // failed to decode boolean array + assertThrows(IllegalArgumentException.class, + () -> ZeroUtility.binaryToArray( + new byte[] {(byte) ZeroType.ZERO_ARRAY.getValue(), arraySizeInShort[0], + arraySizeInShort[1], + (byte) ZeroType.BOOLEAN_ARRAY.getValue(), arraySizeInShort[0], arraySizeInShort[1], + (byte) 2})); + // failed to decode byte array + var negativeArraySizeInInteger = ByteUtility.intToBytes((short) -1); + assertThrows(IllegalArgumentException.class, + () -> ZeroUtility.binaryToArray( + new byte[] {(byte) ZeroType.ZERO_ARRAY.getValue(), arraySizeInShort[0], + arraySizeInShort[1], + (byte) ZeroType.BYTE_ARRAY.getValue(), negativeArraySizeInInteger[0], + negativeArraySizeInInteger[1], negativeArraySizeInInteger[2], + negativeArraySizeInInteger[3]})); + // failed to decode string array + assertThrows(IllegalArgumentException.class, + () -> ZeroUtility.binaryToArray( + new byte[] {(byte) ZeroType.ZERO_ARRAY.getValue(), arraySizeInShort[0], + arraySizeInShort[1], + (byte) ZeroType.STRING_ARRAY.getValue(), negativeArraySizeInShort[0], + negativeArraySizeInShort[1]})); + + assertThrows(IllegalStateException.class, () -> ZeroUtility.binaryToMap(new byte[] {(byte) 1})); + // it is not the zero map + assertThrows(IllegalStateException.class, + () -> ZeroUtility.binaryToMap(new byte[] {(byte) 1, (byte) 2, (byte) 3})); + // a map with negative size + assertThrows(NegativeArraySizeException.class, + () -> ZeroUtility.binaryToMap( + new byte[] {(byte) ZeroType.ZERO_MAP.getValue(), negativeArraySizeInShort[0], + negativeArraySizeInShort[1]})); + // unrecognized zero type + assertThrows(IllegalStateException.class, + () -> ZeroUtility.binaryToMap( + new byte[] {(byte) ZeroType.ZERO_ARRAY.getValue(), arraySizeInShort[0], + arraySizeInShort[1], (byte) 19, (byte) 1})); + // failed to decode boolean + assertThrows(IllegalArgumentException.class, + () -> ZeroUtility.binaryToMap( + new byte[] {(byte) ZeroType.ZERO_MAP.getValue(), arraySizeInShort[0], + arraySizeInShort[1], arraySizeInShort[0], arraySizeInShort[1], (byte) 61, + (byte) ZeroType.BOOLEAN.getValue(), (byte) 2})); + // failed to decode unrecognized element + assertThrows(IllegalArgumentException.class, + () -> ZeroUtility.binaryToMap( + new byte[] {(byte) ZeroType.ZERO_MAP.getValue(), arraySizeInShort[0], + arraySizeInShort[1], arraySizeInShort[0], arraySizeInShort[1], (byte) 61, + (byte) 0, (byte) 19})); + } + + @Test + @DisplayName("Insufficient ByteBuffer should be appended") + void insufficientByteBufferShouldBeAppended() { + var origin = ZeroUtility.newZeroMap(); + var zeroMap = ZeroUtility.newZeroMap(); + zeroMap.putBoolean("b", true) + .putShort("s", (short) 10) + .putInteger("i", 100) + .putFloat("f", 10.0f) + .putShortArray("sa", shorts); + var binaryMap = zeroMap.toBinary(); + for (char i = 'a'; i <= 'z'; i++) { + origin.putZeroMap(String.valueOf(i), ZeroUtility.binaryToMap(binaryMap)); + } + + origin.toBinary(); + } } diff --git a/src/test/java/com/tenio/common/data/common/CommonArrayTest.java b/src/test/java/com/tenio/common/data/common/CommonArrayTest.java index a2973d0..2a2e941 100644 --- a/src/test/java/com/tenio/common/data/common/CommonArrayTest.java +++ b/src/test/java/com/tenio/common/data/common/CommonArrayTest.java @@ -26,6 +26,7 @@ of this software and associated documentation files (the "Software"), to deal import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Assertions; @@ -49,14 +50,14 @@ void initialization() { @DisplayName("Allow fetching all inserted data from the array") void itShouldFetchAllInsertedData() { assertAll("itShouldFetchAllInsertedData", - () -> assertEquals(commonArray.getDouble(0), 100.0), - () -> assertEquals(commonArray.getFloat(1), 100.0F), - () -> assertEquals(commonArray.getLong(2), 100L), - () -> assertEquals(commonArray.getInt(3), 100), + () -> assertEquals(100.0, commonArray.getDouble(0)), + () -> assertEquals(100.0f, commonArray.getFloat(1)), + () -> assertEquals(100L, commonArray.getLong(2)), + () -> assertEquals(100, commonArray.getInt(3)), () -> assertTrue(commonArray.getBoolean(4)), - () -> assertEquals(commonArray.getString(5), "test"), - () -> assertEquals(commonArray.getCommonObjectArray(6), dummyArray), - () -> assertTrue(commonArray.getObject(7) instanceof CommonArray) + () -> assertEquals("test", commonArray.getString(5)), + () -> assertEquals(dummyArray, commonArray.getCommonObjectArray(6)), + () -> assertInstanceOf(CommonArray.class, commonArray.getObject(7)) ); } diff --git a/src/test/java/com/tenio/common/data/common/CommonMapTest.java b/src/test/java/com/tenio/common/data/common/CommonMapTest.java index 2eeb42d..fcff2c8 100644 --- a/src/test/java/com/tenio/common/data/common/CommonMapTest.java +++ b/src/test/java/com/tenio/common/data/common/CommonMapTest.java @@ -52,16 +52,15 @@ void initialization() { @DisplayName("Allow fetching all inserted data") void itShouldFetchAllInsertedData() { assertAll("itShouldFetchAllInsertedData", - () -> assertEquals(commonMap.getDouble("double"), 100.0), - () -> assertEquals(commonMap.getFloat("float"), 100.0F), - () -> assertEquals(commonMap.getLong("long"), 100L), - () -> assertEquals(commonMap.getInt("integer"), 100), - () -> assertEquals(commonMap.getString("string"), "test"), + () -> assertEquals(100.0, commonMap.getDouble("double")), + () -> assertEquals(100.0f, commonMap.getFloat("float")), + () -> assertEquals(100L, commonMap.getLong("long")), + () -> assertEquals(100, commonMap.getInt("integer")), + () -> assertEquals("test", commonMap.getString("string")), () -> assertTrue(commonMap.getBoolean("boolean")), - () -> assertEquals(commonMap.getCommonObject("common object"), dummyMap), - () -> assertEquals(commonMap.getCommonObjectArray("common object array"), - dummyArray), - () -> assertEquals(commonMap.getObject("object"), dummyMap)); + () -> assertEquals(dummyMap, commonMap.getCommonObject("common object")), + () -> assertEquals(dummyArray, commonMap.getCommonObjectArray("common object array")), + () -> assertEquals(dummyMap, commonMap.getObject("object"))); } @Test diff --git a/src/test/java/com/tenio/common/pool/StringBuilderPoolTest.java b/src/test/java/com/tenio/common/pool/StringBuilderPoolTest.java index 686f056..65b93cf 100644 --- a/src/test/java/com/tenio/common/pool/StringBuilderPoolTest.java +++ b/src/test/java/com/tenio/common/pool/StringBuilderPoolTest.java @@ -24,13 +24,13 @@ of this software and associated documentation files (the "Software"), to deal package com.tenio.common.pool; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; import com.tenio.common.constant.CommonConstant; import com.tenio.common.exception.NullElementPoolException; import com.tenio.common.logger.pool.StringBuilderPool; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -47,7 +47,7 @@ void initialization() { @DisplayName("To be able to get a builder instance from pool") void getBuilderFromPoolShouldWork() { var builder = StringBuilderPool.getInstance().get(); - assertTrue(builder instanceof StringBuilder); + assertNotNull(builder); } @Test @@ -59,7 +59,7 @@ void getAndRePayBuilderShouldWork() { pool.repay(builder); var sizeAfter = pool.getAvailableSlot(); - assertTrue(sizeBefore == sizeAfter); + assertEquals(sizeBefore, sizeAfter); } @Test @@ -72,8 +72,8 @@ void poolSizeDecreaseShouldBeAsExpected() { pool.get(); } var sizeAfter = pool.getAvailableSlot(); - - assertTrue(sizeAfter == (sizeBefore - takenNumber)); + var sizeExpected = sizeBefore - takenNumber; + assertEquals(sizeExpected, sizeAfter); } @Test @@ -87,9 +87,10 @@ void poolSizeIncreaseShouldBeAsExpected() { } var sizeAfter = pool.getPoolSize(); var sizeExpected = - CommonConstant.DEFAULT_NUMBER_ELEMENTS_POOL + CommonConstant.ADDITIONAL_NUMBER_ELEMENTS_POOL; + CommonConstant.DEFAULT_NUMBER_ELEMENTS_POOL + + CommonConstant.ADDITIONAL_NUMBER_ELEMENTS_POOL; - assertTrue(sizeAfter == sizeExpected); + assertEquals(sizeExpected, sizeAfter); } @Test @@ -102,7 +103,7 @@ void clearPoolShouldReturnTheAvailableSlotsEqualsSize() { } pool.cleanup(); - assertTrue(pool.getAvailableSlot() == pool.getPoolSize()); + assertEquals(pool.getAvailableSlot(), pool.getPoolSize()); } @Test diff --git a/src/test/java/com/tenio/common/task/DefaultTask.java b/src/test/java/com/tenio/common/task/DefaultTask.java index 802e1b6..ebd490c 100644 --- a/src/test/java/com/tenio/common/task/DefaultTask.java +++ b/src/test/java/com/tenio/common/task/DefaultTask.java @@ -34,8 +34,7 @@ class DefaultTask implements Task { @Override public ScheduledFuture run() { - return Executors.newSingleThreadScheduledExecutor().schedule(() -> { - System.out.println("test task"); - }, DELAY_SECOND, TimeUnit.SECONDS); + return Executors.newSingleThreadScheduledExecutor() + .schedule(() -> System.out.println("test task"), DELAY_SECOND, TimeUnit.SECONDS); } } diff --git a/src/test/java/com/tenio/common/task/TaskManagerTest.java b/src/test/java/com/tenio/common/task/TaskManagerTest.java index 8e550a8..e1ae120 100644 --- a/src/test/java/com/tenio/common/task/TaskManagerTest.java +++ b/src/test/java/com/tenio/common/task/TaskManagerTest.java @@ -40,7 +40,7 @@ void createNewTaskShouldWork() { var taskManager = TaskManagerImpl.newInstance(); taskManager.create("test-task", new DefaultTask().run()); - assertEquals(taskManager.getRemainTime("test-task"), DefaultTask.DELAY_SECOND - 1); + assertEquals(DefaultTask.DELAY_SECOND - 1, taskManager.getRemainTime("test-task")); } @Test @@ -50,7 +50,7 @@ void killATaskShouldWork() { taskManager.create("test-task", new DefaultTask().run()); taskManager.kill("test-task"); - assertEquals(taskManager.getRemainTime("test-task"), -1); + assertEquals(-1, taskManager.getRemainTime("test-task")); } @Test diff --git a/src/test/java/com/tenio/common/utility/ByteUtilityTest.java b/src/test/java/com/tenio/common/utility/ByteUtilityTest.java index f3c3fd9..b94de34 100644 --- a/src/test/java/com/tenio/common/utility/ByteUtilityTest.java +++ b/src/test/java/com/tenio/common/utility/ByteUtilityTest.java @@ -26,9 +26,12 @@ of this software and associated documentation files (the "Software"), to deal 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 com.tenio.common.custom.StringArrayConverter; -import java.io.UnsupportedEncodingException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -38,6 +41,17 @@ of this software and associated documentation files (the "Software"), to deal @DisplayName("Unit Test Cases For Byte Utility") class ByteUtilityTest { + @Test + @DisplayName("Throw an exception when the class's instance is attempted creating") + void createNewInstanceShouldThrowException() throws NoSuchMethodException { + var constructor = ByteUtility.class.getDeclaredConstructor(); + assertTrue(Modifier.isPrivate(constructor.getModifiers())); + assertThrows(InvocationTargetException.class, () -> { + constructor.setAccessible(true); + constructor.newInstance(); + }); + } + @ParameterizedTest @CsvSource({ "1695609641, '101, 16, -13, 41'", @@ -53,8 +67,8 @@ void testIntToBytes(int intValue, @ConvertWith(StringArrayConverter.class) Strin } @Test - void testBytesToInt() throws UnsupportedEncodingException { - assertEquals(1094795585, ByteUtility.bytesToInt("AAAAAAAA".getBytes("UTF-8"))); + void testBytesToInt() { + assertEquals(1094795585, ByteUtility.bytesToInt("AAAAAAAA" .getBytes(StandardCharsets.UTF_8))); } @Test @@ -66,14 +80,15 @@ void testShortToBytes() { } @Test - void testBytesToShort() throws UnsupportedEncodingException { - assertEquals((short) 16705, ByteUtility.bytesToShort("AAAAAAAA".getBytes("UTF-8"))); + void testBytesToShort() { + assertEquals((short) 16705, + ByteUtility.bytesToShort("AAAAAAAA" .getBytes(StandardCharsets.UTF_8))); } @Test - void testResizeBytesArray() throws UnsupportedEncodingException { + void testResizeBytesArray() { byte[] actualResizeBytesArrayResult = - ByteUtility.resizeBytesArray("AAAAAAAA".getBytes("UTF-8"), 1, 3); + ByteUtility.resizeBytesArray("AAAAAAAA" .getBytes(StandardCharsets.UTF_8), 1, 3); assertEquals(3, actualResizeBytesArrayResult.length); assertEquals('A', actualResizeBytesArrayResult[0]); assertEquals('A', actualResizeBytesArrayResult[1]); @@ -81,8 +96,8 @@ void testResizeBytesArray() throws UnsupportedEncodingException { } @Test - void testResizeBytesArray2() throws UnsupportedEncodingException { + void testResizeBytesArray2() { assertThrows(NegativeArraySizeException.class, - () -> ByteUtility.resizeBytesArray("AAAAAAAA".getBytes("UTF-8"), 1, -1)); + () -> ByteUtility.resizeBytesArray("AAAAAAAA" .getBytes(StandardCharsets.UTF_8), 1, -1)); } } diff --git a/src/test/java/com/tenio/common/utility/ClassLoaderUtilityTest.java b/src/test/java/com/tenio/common/utility/ClassLoaderUtilityTest.java new file mode 100644 index 0000000..edccb52 --- /dev/null +++ b/src/test/java/com/tenio/common/utility/ClassLoaderUtilityTest.java @@ -0,0 +1,95 @@ +/* +The MIT License + +Copyright (c) 2016-2022 kong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +package com.tenio.common.utility; + +import static org.junit.jupiter.api.Assertions.assertAll; +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 com.tenio.common.custom.DisabledTestFindingSolution; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("Unit Test Cases For Class Loader Utility") +class ClassLoaderUtilityTest { + + @Test + @DisplayName("Throw an exception when the class's instance is attempted creating") + void createNewInstanceShouldThrowException() throws NoSuchMethodException { + var constructor = ClassLoaderUtility.class.getDeclaredConstructor(); + assertTrue(Modifier.isPrivate(constructor.getModifiers())); + assertThrows(InvocationTargetException.class, () -> { + constructor.setAccessible(true); + constructor.newInstance(); + }); + } + + @Test + @DisplayName("Scanning a package should return a list of classes inside it") + void scanPackageShouldReturnListOfClasses() throws ClassNotFoundException { + var listClasses = ClassLoaderUtility.getClasses("com.tenio.common.bootstrap.loader"); + assertAll("scanPackageShouldReturnListOfClasses", + () -> assertEquals(3, listClasses.size()), + () -> assertTrue( + listClasses.stream().map(clazz -> clazz.getName()).anyMatch(name -> name.equals( + "com.tenio.common.bootstrap.loader.TestClassA"))), + () -> assertTrue( + listClasses.stream().map(clazz -> clazz.getName()).anyMatch(name -> name.equals( + "com.tenio.common.bootstrap.loader.TestClassB"))), + () -> assertTrue( + listClasses.stream().map(clazz -> clazz.getName()).anyMatch(name -> name.equals( + "com.tenio.common.bootstrap.loader.TestClassC"))) + ); + } + + @Test + @DisplayName("Scanning a non-existed package should return an empty list of classes") + void scanNonExistedPackageShouldReturnEmptyArray() throws ClassNotFoundException { + var listClasses = ClassLoaderUtility.getClasses("com.tenio.common.bootstrap.null"); + assertTrue(listClasses.isEmpty()); + } + + @Test + @DisplayName("To be able to scan a package of a jar file and return a list of classes inside it") + void scanExternalLibraryShouldReturnListOfClasses() throws ClassNotFoundException { + var listClasses = ClassLoaderUtility.getClasses("com.google.common.annotations"); + assertTrue(listClasses.size() > 0); + } + + + @DisabledTestFindingSolution + @DisplayName("Attempt to recall the private constructor in order to create an instance should " + + "throw an exception") + void tryToReCreateClassLoaderShouldThrowException() { + } + + @DisabledTestFindingSolution + @DisplayName("Try to procedure throwable exception cases") + void getClassesInInvalidWaysShouldThrowException() { + } +} diff --git a/src/test/java/com/tenio/common/utility/MathUtilityTest.java b/src/test/java/com/tenio/common/utility/MathUtilityTest.java index b0982a6..39681c3 100644 --- a/src/test/java/com/tenio/common/utility/MathUtilityTest.java +++ b/src/test/java/com/tenio/common/utility/MathUtilityTest.java @@ -26,16 +26,26 @@ of this software and associated documentation files (the "Software"), to deal 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 java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +@DisplayName("Unit Test Cases For Math Utility") class MathUtilityTest { @Test - void testIsNaN() { - assertFalse(MathUtility.isNaN("Val")); - assertTrue(MathUtility.isNaN(null)); + @DisplayName("Throw an exception when the class's instance is attempted creating") + void createNewInstanceShouldThrowException() throws NoSuchMethodException { + var constructor = MathUtility.class.getDeclaredConstructor(); + assertTrue(Modifier.isPrivate(constructor.getModifiers())); + assertThrows(InvocationTargetException.class, () -> { + constructor.setAccessible(true); + constructor.newInstance(); + }); } @Test @@ -49,249 +59,13 @@ void testIsEqual() { assertFalse(MathUtility.isEqual(0.0f, 10.0f)); } - @Test - void testSetSeed() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by setSeed(long) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.setSeed(42L); - } - - @Test - void testRandInt() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by randInt(int, int) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.randInt(2, 3); - } - @Test void testRandInt2() { assertEquals(1, MathUtility.randInt(1, 1)); } - @Test - void testRandInt3() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by randInt(int, int) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.randInt(0, 3); - } - - @Test - void testRandInt4() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by randInt(int, int) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.randInt(1, 3); - } - - @Test - void testRandFloat() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by randFloat() - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.randFloat(); - } - @Test void testRandInRange() { assertEquals(10.0f, MathUtility.randInRange(10.0f, 10.0f)); } - - @Test - void testRandInRange2() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by randInRange(float, float) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.randInRange(0.0f, 10.0f); - } - - @Test - void testRandInRange3() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by randInRange(float, float) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.randInRange(0.5f, 10.0f); - } - - @Test - void testRandInRange4() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by randInRange(float, float) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.randInRange(-0.5f, 10.0f); - } - - @Test - void testRandBool() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by randBool() - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.randBool(); - } - - @Test - void testRandomClamped() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by randomClamped() - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.randomClamped(); - } - - @Test - void testRandGaussian() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by randGaussian() - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.randGaussian(); - } - - @Test - void testRandGaussian2() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by randGaussian(float, float) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.randGaussian(10.0f, 10.0f); - } - - @Test - void testRandGaussian3() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by randGaussian(float, float) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.randGaussian(2.0f, 10.0f); - } - - @Test - void testRandGaussian4() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by randGaussian(float, float) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.randGaussian(1.0f, 10.0f); - } - - @Test - void testRandGaussian5() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by randGaussian(float, float) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - MathUtility.randGaussian(0.0f, 10.0f); - } - - @Test - void testClamp() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by clamp(Number, Number, Number) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - Integer arg = Integer.valueOf(1); - Integer minVal = Integer.valueOf(1); - MathUtility.clamp(arg, minVal, Integer.valueOf(1)); - } - - @Test - void testClamp2() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by clamp(Number, Number, Number) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - Integer arg = Integer.valueOf(0); - Integer minVal = Integer.valueOf(1); - MathUtility.clamp(arg, minVal, Integer.valueOf(1)); - } - - @Test - void testClamp3() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by clamp(Number, Number, Number) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - Integer arg = Integer.valueOf(3); - Integer minVal = Integer.valueOf(1); - MathUtility.clamp(arg, minVal, Integer.valueOf(1)); - } - - @Test - void testClamp4() { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by clamp(Number, Number, Number) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - Integer arg = Integer.valueOf(-1); - Integer minVal = Integer.valueOf(1); - MathUtility.clamp(arg, minVal, Integer.valueOf(1)); - } } diff --git a/src/test/java/com/tenio/common/utility/OsUtilityTest.java b/src/test/java/com/tenio/common/utility/OsUtilityTest.java index 323a06c..1cbbdc2 100644 --- a/src/test/java/com/tenio/common/utility/OsUtilityTest.java +++ b/src/test/java/com/tenio/common/utility/OsUtilityTest.java @@ -25,7 +25,11 @@ of this software and associated documentation files (the "Software"), to deal package com.tenio.common.utility; 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 java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfSystemProperty; @@ -36,7 +40,35 @@ of this software and associated documentation files (the "Software"), to deal class OsUtilityTest { @Test - @EnabledOnOs(OS.MAC) + @DisplayName("Throw an exception when the class's instance is attempted creating") + void createNewInstanceShouldThrowException() throws NoSuchMethodException { + var constructor = OsUtility.class.getDeclaredConstructor(); + assertTrue(Modifier.isPrivate(constructor.getModifiers())); + assertThrows(InvocationTargetException.class, () -> { + constructor.setAccessible(true); + constructor.newInstance(); + }); + } + + @Test + @DisplayName("Test all system types should work") + void testAllSystemTypesShouldWork() { + System.setProperty("os.name", "mac"); + assertEquals(OsUtility.OsType.MAC, OsUtility.getOperatingSystemType()); + System.setProperty("os.name", "darwin"); + assertEquals(OsUtility.OsType.MAC, OsUtility.getOperatingSystemType()); + System.setProperty("os.name", "win"); + assertEquals(OsUtility.OsType.WINDOWS, OsUtility.getOperatingSystemType()); + System.setProperty("os.name", "nux"); + assertEquals(OsUtility.OsType.LINUX, OsUtility.getOperatingSystemType()); + System.setProperty("os.name", "other"); + assertEquals(OsUtility.OsType.OTHER, OsUtility.getOperatingSystemType()); + + assertEquals("MAC", OsUtility.OsType.MAC.toString()); + } + + @Test + @EnabledIfSystemProperty(named = "os.name", matches = "mac") @DisplayName("Fetch operation system type should return MAC") void getOperatingSystemTypeMac() { assertEquals(OsUtility.OsType.MAC, OsUtility.getOperatingSystemType()); diff --git a/src/test/java/com/tenio/common/utility/StringUtilityTest.java b/src/test/java/com/tenio/common/utility/StringUtilityTest.java new file mode 100644 index 0000000..7b1c170 --- /dev/null +++ b/src/test/java/com/tenio/common/utility/StringUtilityTest.java @@ -0,0 +1,74 @@ +/* +The MIT License + +Copyright (c) 2016-2022 kong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +package com.tenio.common.utility; + +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 java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.util.UUID; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +@DisplayName("Unit Test Cases For String Utility") +class StringUtilityTest { + + @Test + @DisplayName("Throw an exception when the class's instance is attempted creating") + void createNewInstanceShouldThrowException() throws NoSuchMethodException { + var constructor = StringUtility.class.getDeclaredConstructor(); + assertTrue(Modifier.isPrivate(constructor.getModifiers())); + assertThrows(InvocationTargetException.class, () -> { + constructor.setAccessible(true); + constructor.newInstance(); + }); + } + + @Test + @DisplayName("It should return expected joined string") + void itShouldReturnExpectedJoinedString() { + var string = StringUtility.strgen("this", "is", "the", 9, "th", "test"); + assertEquals("thisisthe9thtest", string); + } + + @Test + @DisplayName("It should return random values") + void itShouldReturnRandomValues() { + var expectedUuid = UUID.randomUUID(); + var mockUuid = Mockito.mockStatic(UUID.class); + mockUuid.when(UUID::randomUUID).thenReturn(expectedUuid); + assertEquals(expectedUuid.toString(), StringUtility.getRandomUuid()); + + var expectedRandom = 0; + var ALPHA_NUMERIC_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvxyz"; + var mockRandom = Mockito.mockStatic(MathUtility.class); + mockRandom.when(() -> MathUtility.randInt(0, ALPHA_NUMERIC_STRING.length())) + .thenReturn(expectedRandom); + assertEquals("AAAAA", StringUtility.getRandomTextByLength(5)); + } +} diff --git a/src/test/java/com/tenio/common/utility/TimeUtilityTest.java b/src/test/java/com/tenio/common/utility/TimeUtilityTest.java new file mode 100644 index 0000000..63e4cea --- /dev/null +++ b/src/test/java/com/tenio/common/utility/TimeUtilityTest.java @@ -0,0 +1,48 @@ +/* +The MIT License + +Copyright (c) 2016-2022 kong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +package com.tenio.common.utility; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("Unit Test Cases For Time Utility") +class TimeUtilityTest { + + @Test + @DisplayName("Throw an exception when the class's instance is attempted creating") + void createNewInstanceShouldThrowException() throws NoSuchMethodException { + var constructor = TimeUtility.class.getDeclaredConstructor(); + assertTrue(Modifier.isPrivate(constructor.getModifiers())); + assertThrows(InvocationTargetException.class, () -> { + constructor.setAccessible(true); + constructor.newInstance(); + }); + } +} diff --git a/src/test/java/com/tenio/common/utility/XmlUtilityTest.java b/src/test/java/com/tenio/common/utility/XmlUtilityTest.java index 088be94..48e8cd2 100644 --- a/src/test/java/com/tenio/common/utility/XmlUtilityTest.java +++ b/src/test/java/com/tenio/common/utility/XmlUtilityTest.java @@ -25,17 +25,34 @@ of this software and associated documentation files (the "Software"), to deal package com.tenio.common.utility; 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 static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; import javax.imageio.metadata.IIOMetadataNode; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.w3c.dom.DOMException; import org.w3c.dom.Node; +@DisplayName("Unit Test Cases For XML Utility") class XmlUtilityTest { + @Test + @DisplayName("Throw an exception when the class's instance is attempted creating") + void createNewInstanceShouldThrowException() throws NoSuchMethodException { + var constructor = XmlUtility.class.getDeclaredConstructor(); + assertTrue(Modifier.isPrivate(constructor.getModifiers())); + assertThrows(InvocationTargetException.class, () -> { + constructor.setAccessible(true); + constructor.newInstance(); + }); + } + @Test void testGetNodeValue() throws DOMException { Node node = mock(Node.class); diff --git a/src/test/java/com/tenio/common/worker/WorkerPoolRunnableTest.java b/src/test/java/com/tenio/common/worker/WorkerPoolRunnableTest.java index 62902d3..a2e9c4a 100644 --- a/src/test/java/com/tenio/common/worker/WorkerPoolRunnableTest.java +++ b/src/test/java/com/tenio/common/worker/WorkerPoolRunnableTest.java @@ -27,15 +27,17 @@ of this software and associated documentation files (the "Software"), to deal import static org.junit.jupiter.api.Assertions.assertFalse; import java.util.concurrent.ArrayBlockingQueue; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +@DisplayName("Unit Test Cases For Worker Pool Runnable Utility") class WorkerPoolRunnableTest { + @Test void testConstructor() { assertFalse( - (new WorkerPoolRunnable("Name", 1, new ArrayBlockingQueue(3))).isStopped()); + (new WorkerPoolRunnable("Name", 1, new ArrayBlockingQueue<>(3))).isStopped()); assertFalse( - (new WorkerPoolRunnable("Name", 1, new ArrayBlockingQueue(3))).isStopped()); + (new WorkerPoolRunnable("Name", 1, new ArrayBlockingQueue<>(3))).isStopped()); } } - diff --git a/src/test/java/com/tenio/common/worker/WorkerPoolTest.java b/src/test/java/com/tenio/common/worker/WorkerPoolTest.java index 20940e3..ddad03c 100644 --- a/src/test/java/com/tenio/common/worker/WorkerPoolTest.java +++ b/src/test/java/com/tenio/common/worker/WorkerPoolTest.java @@ -26,159 +26,32 @@ of this software and associated documentation files (the "Software"), to deal import static org.mockito.Mockito.mock; -import com.tenio.common.custom.DisabledTestFindingSolution; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +@DisplayName("Unit Test Cases For Worker Pool Runnable Utility") class WorkerPoolTest { + @Test + @DisplayName("Creating a new instance should work") void testConstructor() { - // TODO: This test is incomplete. - // Reason: R002 Missing observers. - // Diffblue Cover was unable to create an assertion. - // Add getters for the following fields or make them package-private: - // WorkerPool.taskQueue - // WorkerPool.runnableWorkerPools - // WorkerPool.name - // WorkerPool.isStopped - // AbstractLogger.logger - new WorkerPool("Name", 1, 3); - - } - - @Test - void testConstructor2() { - // TODO: This test is incomplete. - // Reason: R002 Missing observers. - // Diffblue Cover was unable to create an assertion. - // Add getters for the following fields or make them package-private: - // WorkerPool.taskQueue - // WorkerPool.runnableWorkerPools - // WorkerPool.name - // WorkerPool.isStopped - // AbstractLogger.logger - - new WorkerPool("CREATED NEW WORKERS", 1, 3); - - } - - @Test - void testConstructor3() { - // TODO: This test is incomplete. - // Reason: R002 Missing observers. - // Diffblue Cover was unable to create an assertion. - // Add getters for the following fields or make them package-private: - // WorkerPool.taskQueue - // WorkerPool.runnableWorkerPools - // WorkerPool.name - // WorkerPool.isStopped - // AbstractLogger.logger - - new WorkerPool("Name", Double.SIZE, 3); - } @Test + @DisplayName("Executing a runnable worker delivers expected results") void testExecute() throws IllegalStateException { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by execute(Runnable, String) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - (new WorkerPool("Name", 1, 3)).execute(mock(Runnable.class), "Debug Text"); + var workerPool = new WorkerPool("Name", 1, 3); + workerPool.execute(mock(Runnable.class), "Test Runnable Worker"); + workerPool.stop(); + Assertions.assertThrows(IllegalStateException.class, + () -> workerPool.execute(mock(Runnable.class), "Test Runnable Worker")); } - @Test - void testExecute2() throws IllegalStateException { - // TODO: This test is incomplete. - // Reason: R004 No meaningful assertions found. - // Diffblue Cover was unable to create an assertion. - // Make sure that fields modified by execute(Runnable, String) - // have package-private, protected, or public getters. - // See https://diff.blue/R004 to resolve this issue. - - (new WorkerPool("com.tenio.common.worker.WorkerPoolRunnable", 1, 3)).execute( - mock(Runnable.class), - "EXECUTED A TASK"); - } - - @Test - @DisabledTestFindingSolution - void testStop() { - // TODO: This test is incomplete. - // Reason: R002 Missing observers. - // Diffblue Cover was unable to create an assertion. - // Add getters for the following fields or make them package-private: - // AbstractLogger.logger - // WorkerPool.isStopped - // WorkerPool.name - // WorkerPool.runnableWorkerPools - // WorkerPool.taskQueue - - (new WorkerPool("Name", 3, 1)).stop(); - } @Test void testWaitUntilAllTasksFinished() { - // TODO: This test is incomplete. - // Reason: R002 Missing observers. - // Diffblue Cover was unable to create an assertion. - // Add getters for the following fields or make them package-private: - // AbstractLogger.logger - // WorkerPool.isStopped - // WorkerPool.name - // WorkerPool.runnableWorkerPools - // WorkerPool.taskQueue - (new WorkerPool("Name", 1, 3)).waitUntilAllTasksFinished(); } - - @Test - void testWaitUntilAllTasksFinished2() { - // TODO: This test is incomplete. - // Reason: R002 Missing observers. - // Diffblue Cover was unable to create an assertion. - // Add getters for the following fields or make them package-private: - // AbstractLogger.logger - // WorkerPool.isStopped - // WorkerPool.name - // WorkerPool.runnableWorkerPools - // WorkerPool.taskQueue - - (new WorkerPool("com.tenio.common.worker.WorkerPoolRunnable", 1, - 3)).waitUntilAllTasksFinished(); - } - - @Test - void testWaitUntilAllTasksFinished3() { - // TODO: This test is incomplete. - // Reason: R002 Missing observers. - // Diffblue Cover was unable to create an assertion. - // Add getters for the following fields or make them package-private: - // AbstractLogger.logger - // WorkerPool.isStopped - // WorkerPool.name - // WorkerPool.runnableWorkerPools - // WorkerPool.taskQueue - - (new WorkerPool("Name", 1, 1)).waitUntilAllTasksFinished(); - } - - @Test - void testWaitUntilAllTasksFinished4() { - // TODO: This test is incomplete. - // Reason: R002 Missing observers. - // Diffblue Cover was unable to create an assertion. - // Add getters for the following fields or make them package-private: - // AbstractLogger.logger - // WorkerPool.isStopped - // WorkerPool.name - // WorkerPool.runnableWorkerPools - // WorkerPool.taskQueue - - (new WorkerPool("Name", 2, 1)).waitUntilAllTasksFinished(); - } } - diff --git a/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 0000000..ca6ee9c --- /dev/null +++ b/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file