From a940e9c7f01972e59adf636df6fcb593c0b6bdad Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Mon, 10 Mar 2025 22:37:23 -0400 Subject: [PATCH] WIP on Java tests and Kotlin mods to support them --- documents.iml | 1 + pom.xml | 10 +- src/main/kotlin/AutoId.kt | 18 +- src/main/kotlin/Configuration.kt | 20 +- src/main/kotlin/Field.kt | 62 +- src/main/kotlin/Parameters.kt | 8 + .../bitbadger/documents/java/AutoIdTest.java | 217 ++++++ .../documents/java/ConfigurationTest.java | 56 ++ .../documents/java/DocumentIndexTest.java | 26 + .../documents/java/FieldMatchTest.java | 26 + .../bitbadger/documents/java/FieldTest.java | 629 ++++++++++++++++++ .../bitbadger/documents/java/OpTest.java | 80 +++ .../documents/java/ParameterNameTest.java | 32 + .../documents/java/ParameterTest.java | 40 ++ .../documents/java/ParametersTest.java | 121 ++++ .../documents/java/testDocs/ByteIdClass.java | 18 + .../documents/java/testDocs/IntIdClass.java | 18 + .../documents/java/testDocs/LongIdClass.java | 18 + .../documents/java/testDocs/ShortIdClass.java | 18 + .../java/testDocs/StringIdClass.java | 18 + src/test/kotlin/AutoIdTest.kt | 43 +- src/test/kotlin/ConfigurationTest.kt | 2 +- src/test/kotlin/DocumentIndexTest.kt | 2 +- src/test/kotlin/FieldMatchTest.kt | 2 +- src/test/kotlin/FieldTest.kt | 2 +- src/test/kotlin/OpTest.kt | 2 +- src/test/kotlin/ParameterNameTest.kt | 2 +- src/test/kotlin/ParameterTest.kt | 2 +- src/test/kotlin/ParametersTest.kt | 2 +- 29 files changed, 1455 insertions(+), 40 deletions(-) create mode 100644 src/test/java/solutions/bitbadger/documents/java/AutoIdTest.java create mode 100644 src/test/java/solutions/bitbadger/documents/java/ConfigurationTest.java create mode 100644 src/test/java/solutions/bitbadger/documents/java/DocumentIndexTest.java create mode 100644 src/test/java/solutions/bitbadger/documents/java/FieldMatchTest.java create mode 100644 src/test/java/solutions/bitbadger/documents/java/FieldTest.java create mode 100644 src/test/java/solutions/bitbadger/documents/java/OpTest.java create mode 100644 src/test/java/solutions/bitbadger/documents/java/ParameterNameTest.java create mode 100644 src/test/java/solutions/bitbadger/documents/java/ParameterTest.java create mode 100644 src/test/java/solutions/bitbadger/documents/java/ParametersTest.java create mode 100644 src/test/java/solutions/bitbadger/documents/java/testDocs/ByteIdClass.java create mode 100644 src/test/java/solutions/bitbadger/documents/java/testDocs/IntIdClass.java create mode 100644 src/test/java/solutions/bitbadger/documents/java/testDocs/LongIdClass.java create mode 100644 src/test/java/solutions/bitbadger/documents/java/testDocs/ShortIdClass.java create mode 100644 src/test/java/solutions/bitbadger/documents/java/testDocs/StringIdClass.java diff --git a/documents.iml b/documents.iml index ce12650..7b09b3a 100644 --- a/documents.iml +++ b/documents.iml @@ -3,6 +3,7 @@ + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 83150c0..19963a3 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ UTF-8 official - 1.8 + 11 2.1.0 1.8.0 @@ -111,6 +111,14 @@ MainKt + + org.apache.maven.plugins + maven-compiler-plugin + + 9 + 9 + + diff --git a/src/main/kotlin/AutoId.kt b/src/main/kotlin/AutoId.kt index a5bfa54..3e4c4c8 100644 --- a/src/main/kotlin/AutoId.kt +++ b/src/main/kotlin/AutoId.kt @@ -1,6 +1,8 @@ package solutions.bitbadger.documents +import kotlin.jvm.Throws import kotlin.reflect.full.* +import kotlin.reflect.jvm.isAccessible /** * Strategies for automatic document IDs @@ -22,7 +24,7 @@ enum class AutoId { * * @return A `UUID` string */ - fun generateUUID(): String = + @JvmStatic fun generateUUID(): String = java.util.UUID.randomUUID().toString().replace("-", "") /** @@ -31,7 +33,7 @@ enum class AutoId { * @param length The length of the string (optional; defaults to configured length) * @return A string of random hex characters of the requested length */ - fun generateRandomString(length: Int? = null): String = + @JvmStatic fun generateRandomString(length: Int? = null): String = (length ?: Configuration.idStringLength).let { len -> kotlin.random.Random.nextBytes((len + 2) / 2) .joinToString("") { String.format("%02x", it) } @@ -47,12 +49,13 @@ enum class AutoId { * @return `true` if the document needs an automatic ID, `false` if not * @throws DocumentException If bad input prevents the determination */ - fun needsAutoId(strategy: AutoId, document: T, idProp: String): Boolean { + @Throws(DocumentException::class) + @JvmStatic fun needsAutoId(strategy: AutoId, document: T, idProp: String): Boolean { if (document == null) throw DocumentException("document cannot be null") - if (strategy == DISABLED) return false; + if (strategy == DISABLED) return false - val id = document!!::class.memberProperties.find { it.name == idProp } + val id = document!!::class.memberProperties.find { it.name == idProp }?.apply { isAccessible = true } if (id == null) throw DocumentException("$idProp not found in document") if (strategy == NUMBER) { @@ -65,11 +68,12 @@ enum class AutoId { } } - if (id.returnType == String::class.createType()) { + val typ = id.returnType.toString() + if (typ.endsWith("String") || typ.endsWith("String!")) { return id.call(document) == "" } - throw DocumentException("$idProp was not a string; cannot auto-generate UUID or random string") + throw DocumentException("$idProp was not a string ($typ); cannot auto-generate UUID or random string") } } } diff --git a/src/main/kotlin/Configuration.kt b/src/main/kotlin/Configuration.kt index 8c2b484..7313eea 100644 --- a/src/main/kotlin/Configuration.kt +++ b/src/main/kotlin/Configuration.kt @@ -3,6 +3,7 @@ package solutions.bitbadger.documents import kotlinx.serialization.json.Json import java.sql.Connection import java.sql.DriverManager +import kotlin.jvm.Throws object Configuration { @@ -12,25 +13,33 @@ object Configuration { * The default sets `encodeDefaults` to `true` and `explicitNulls` to `false`; see * https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/json.md for all configuration options */ + @JvmField var json = Json { - encodeDefaults = true - explicitNulls = false + encodeDefaults = true + explicitNulls = false coerceInputValues = true } /** The field in which a document's ID is stored */ + @JvmField var idField = "id" /** The automatic ID strategy to use */ + @JvmField var autoIdStrategy = AutoId.DISABLED /** The length of automatic random hex character string */ + @JvmField var idStringLength = 16 + /** The JSON serializer to use for documents */ + var serializer: DocumentSerializer = DocumentSerializerKotlin() + /** The derived dialect value from the connection string */ internal var dialectValue: Dialect? = null /** The connection string for the JDBC connection */ + @JvmStatic var connectionString: String? = null set(value) { field = value @@ -43,6 +52,7 @@ object Configuration { * @return A new connection to the configured database * @throws IllegalArgumentException If the connection string is not set before calling this */ + @JvmStatic fun dbConn(): Connection { if (connectionString == null) { throw IllegalArgumentException("Please provide a connection string before attempting data access") @@ -57,7 +67,11 @@ object Configuration { * @return The dialect for the current connection * @throws DocumentException If the dialect has not been set */ + @Throws(DocumentException::class) + @JvmStatic + @JvmOverloads fun dialect(process: String? = null): Dialect = dialectValue ?: throw DocumentException( - "Database mode not set" + if (process == null) "" else "; cannot $process") + "Database mode not set" + if (process == null) "" else "; cannot $process" + ) } diff --git a/src/main/kotlin/Field.kt b/src/main/kotlin/Field.kt index 4a3d8e8..d15a838 100644 --- a/src/main/kotlin/Field.kt +++ b/src/main/kotlin/Field.kt @@ -69,18 +69,18 @@ class Field private constructor( if (parameterName == null && !listOf(Op.EXISTS, Op.NOT_EXISTS).contains(comparison.op)) throw DocumentException("Parameter for $name must be specified") - val dialect = Configuration.dialect("make field WHERE clause") + val dialect = Configuration.dialect("make field WHERE clause") val fieldName = path(dialect, if (comparison.op == Op.IN_ARRAY) FieldFormat.JSON else FieldFormat.SQL) val fieldPath = when (dialect) { Dialect.POSTGRESQL -> if (comparison.isNumeric) "($fieldName)::numeric" else fieldName - Dialect.SQLITE -> fieldName + Dialect.SQLITE -> fieldName } val criteria = when (comparison.op) { in listOf(Op.EXISTS, Op.NOT_EXISTS) -> "" - Op.BETWEEN -> " ${parameterName}min AND ${parameterName}max" - Op.IN -> " ($inParameterNames)" + Op.BETWEEN -> " ${parameterName}min AND ${parameterName}max" + Op.IN -> " ($inParameterNames)" Op.IN_ARRAY -> if (dialect == Dialect.POSTGRESQL) " ARRAY[$inParameterNames]" else "" - else -> " $parameterName" + else -> " $parameterName" } @Suppress("UNCHECKED_CAST") @@ -134,7 +134,7 @@ class Field private constructor( } override fun toString() = - "Field ${parameterName ?: ""} $comparison${qualifier?.let { " (qualifier $it)"} ?: ""}" + "Field ${parameterName ?: ""} $comparison${qualifier?.let { " (qualifier $it)" } ?: ""}" companion object { @@ -146,6 +146,8 @@ class Field private constructor( * @param paramName The parameter name for the field (optional, defaults to auto-generated) * @return A `Field` with the given comparison */ + @JvmStatic + @JvmOverloads fun equal(name: String, value: T, paramName: String? = null) = Field(name, ComparisonSingle(Op.EQUAL, value), paramName) @@ -157,6 +159,8 @@ class Field private constructor( * @param paramName The parameter name for the field (optional, defaults to auto-generated) * @return A `Field` with the given comparison */ + @JvmStatic + @JvmOverloads fun greater(name: String, value: T, paramName: String? = null) = Field(name, ComparisonSingle(Op.GREATER, value), paramName) @@ -168,6 +172,8 @@ class Field private constructor( * @param paramName The parameter name for the field (optional, defaults to auto-generated) * @return A `Field` with the given comparison */ + @JvmStatic + @JvmOverloads fun greaterOrEqual(name: String, value: T, paramName: String? = null) = Field(name, ComparisonSingle(Op.GREATER_OR_EQUAL, value), paramName) @@ -179,6 +185,8 @@ class Field private constructor( * @param paramName The parameter name for the field (optional, defaults to auto-generated) * @return A `Field` with the given comparison */ + @JvmStatic + @JvmOverloads fun less(name: String, value: T, paramName: String? = null) = Field(name, ComparisonSingle(Op.LESS, value), paramName) @@ -190,6 +198,8 @@ class Field private constructor( * @param paramName The parameter name for the field (optional, defaults to auto-generated) * @return A `Field` with the given comparison */ + @JvmStatic + @JvmOverloads fun lessOrEqual(name: String, value: T, paramName: String? = null) = Field(name, ComparisonSingle(Op.LESS_OR_EQUAL, value), paramName) @@ -201,6 +211,8 @@ class Field private constructor( * @param paramName The parameter name for the field (optional, defaults to auto-generated) * @return A `Field` with the given comparison */ + @JvmStatic + @JvmOverloads fun notEqual(name: String, value: T, paramName: String? = null) = Field(name, ComparisonSingle(Op.NOT_EQUAL, value), paramName) @@ -213,6 +225,8 @@ class Field private constructor( * @param paramName The parameter name for the field (optional, defaults to auto-generated) * @return A `Field` with the given comparison */ + @JvmStatic + @JvmOverloads fun between(name: String, minValue: T, maxValue: T, paramName: String? = null) = Field(name, ComparisonBetween(Pair(minValue, maxValue)), paramName) @@ -224,6 +238,8 @@ class Field private constructor( * @param paramName The parameter name for the field (optional, defaults to auto-generated) * @return A `Field` with the given comparison */ + @JvmStatic + @JvmOverloads fun any(name: String, values: Collection, paramName: String? = null) = Field(name, ComparisonIn(values), paramName) @@ -236,18 +252,50 @@ class Field private constructor( * @param paramName The parameter name for the field (optional, defaults to auto-generated) * @return A `Field` with the given comparison */ + @JvmStatic + @JvmOverloads fun inArray(name: String, tableName: String, values: Collection, paramName: String? = null) = Field(name, ComparisonInArray(Pair(tableName, values)), paramName) + /** + * Create a field where a document field should exist + * + * @param name The name of the field whose existence should be checked + * @return A `Field` with the given comparison + */ + @JvmStatic fun exists(name: String) = Field(name, ComparisonSingle(Op.EXISTS, "")) + /** + * Create a field where a document field should not exist + * + * @param name The name of the field whose existence should be checked + * @return A `Field` with the given comparison + */ + @JvmStatic fun notExists(name: String) = Field(name, ComparisonSingle(Op.NOT_EXISTS, "")) + /** + * Create a field with a given named comparison (useful for ordering fields) + * + * @param name The name of the field + * @return A `Field` with the given name (comparison equal to an empty string) + */ + @JvmStatic fun named(name: String) = Field(name, ComparisonSingle(Op.EQUAL, "")) + /** + * Convert a name to the SQL path for the given dialect + * + * @param name The field name to be translated + * @param dialect The database for which the path should be created + * @param format Whether the field should be retrieved as a JSON value or a SQL value + * @return The path to the JSON field + */ + @JvmStatic fun nameToPath(name: String, dialect: Dialect, format: FieldFormat): String { val path = StringBuilder("data") val extra = if (format == FieldFormat.SQL) ">" else "" @@ -266,4 +314,4 @@ class Field private constructor( return path.toString() } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/Parameters.kt b/src/main/kotlin/Parameters.kt index 4da353b..3bf15b2 100644 --- a/src/main/kotlin/Parameters.kt +++ b/src/main/kotlin/Parameters.kt @@ -3,6 +3,7 @@ package solutions.bitbadger.documents import java.sql.Connection import java.sql.PreparedStatement import java.sql.SQLException +import kotlin.jvm.Throws /** * Functions to assist with the creation and implementation of parameters for SQL queries @@ -17,6 +18,7 @@ object Parameters { * @param fields The collection of fields to be named * @return The collection of fields with parameter names assigned */ + @JvmStatic fun nameFields(fields: Collection>): Collection> { val name = ParameterName() return fields.map { @@ -45,6 +47,7 @@ object Parameters { * @param existing Any existing parameters for the query (optional, defaults to empty collection) * @return A collection of parameters for the query */ + @JvmStatic fun addFields(fields: Collection>, existing: MutableCollection> = mutableListOf()) = fields.fold(existing) { acc, field -> field.appendParameter(acc) } @@ -55,6 +58,7 @@ object Parameters { * @param parameters The parameters for the query * @return The query, with name parameters changed to `?`s */ + @JvmStatic fun replaceNamesInQuery(query: String, parameters: Collection>) = parameters.sortedByDescending { it.name.length }.fold(query) { acc, param -> acc.replace(param.name, "?") } @@ -67,6 +71,8 @@ object Parameters { * @return A `PreparedStatement` with the parameter names replaced with `?` and parameter values bound * @throws DocumentException If parameter names are invalid or number value types are invalid */ + @Throws(DocumentException::class) + @JvmStatic fun apply(conn: Connection, query: String, parameters: Collection>): PreparedStatement { if (parameters.isEmpty()) return try { @@ -105,6 +111,8 @@ object Parameters { * @param parameterName The parameter name to use for the query * @return A list of parameters to use for building the query */ + @JvmStatic + @JvmOverloads fun fieldNames(names: Collection, parameterName: String = ":name"): MutableCollection> = when (Configuration.dialect("generate field name parameters")) { Dialect.POSTGRESQL -> mutableListOf( diff --git a/src/test/java/solutions/bitbadger/documents/java/AutoIdTest.java b/src/test/java/solutions/bitbadger/documents/java/AutoIdTest.java new file mode 100644 index 0000000..6375b24 --- /dev/null +++ b/src/test/java/solutions/bitbadger/documents/java/AutoIdTest.java @@ -0,0 +1,217 @@ +package solutions.bitbadger.documents.java; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import solutions.bitbadger.documents.AutoId; +import solutions.bitbadger.documents.DocumentException; +import solutions.bitbadger.documents.java.testDocs.*; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for the `AutoId` enum + */ +@DisplayName("Java | AutoId") +final public class AutoIdTest { + + @Test + @DisplayName("Generates a UUID string") + public void generateUUID() { + assertEquals(32, AutoId.generateUUID().length(), "The UUID should have been a 32-character string"); + } + + @Test + @DisplayName("Generates a random hex character string of an even length") + public void generateRandomStringEven() { + final String result = AutoId.generateRandomString(8); + assertEquals(8, result.length(), "There should have been 8 characters in " + result); + } + + @Test + @DisplayName("Generates a random hex character string of an odd length") + public void generateRandomStringOdd() { + final String result = AutoId.generateRandomString(11); + assertEquals(11, result.length(), "There should have been 11 characters in " + result); + } + + @Test + @DisplayName("Generates different random hex character strings") + public void generateRandomStringIsRandom() { + final String result1 = AutoId.generateRandomString(16); + final String result2 = AutoId.generateRandomString(16); + assertNotEquals(result1, result2, "There should have been 2 different strings generated"); + } + + @Test + @DisplayName("needsAutoId fails for null document") + public void needsAutoIdFailsForNullDocument() { + assertThrows(DocumentException.class, () -> AutoId.needsAutoId(AutoId.DISABLED, null, "id")); + } + + @Test + @DisplayName("needsAutoId fails for missing ID property") + public void needsAutoIdFailsForMissingId() { + assertThrows(DocumentException.class, () -> AutoId.needsAutoId(AutoId.UUID, new IntIdClass(0), "Id")); + } + + @Test + @DisplayName("needsAutoId returns false if disabled") + public void needsAutoIdFalseIfDisabled() { + try { + assertFalse(AutoId.needsAutoId(AutoId.DISABLED, "", ""), "Disabled Auto ID should always return false"); + } catch (DocumentException ex) { + fail(ex); + } + } + + @Test + @DisplayName("needsAutoId returns true for Number strategy and byte ID of 0") + public void needsAutoIdTrueForByteWithZero() { + try { + assertTrue(AutoId.needsAutoId(AutoId.NUMBER, new ByteIdClass((byte) 0), "id"), + "Number Auto ID with 0 should return true"); + } catch (DocumentException ex) { + fail(ex); + } + } + + @Test + @DisplayName("needsAutoId returns false for Number strategy and byte ID of non-0") + public void needsAutoIdFalseForByteWithNonZero() { + try { + assertFalse(AutoId.needsAutoId(AutoId.NUMBER, new ByteIdClass((byte) 77), "id"), + "Number Auto ID with 77 should return false"); + } catch (DocumentException ex) { + fail(ex); + } + } + + @Test + @DisplayName("needsAutoId returns true for Number strategy and short ID of 0") + public void needsAutoIdTrueForShortWithZero() { + try { + assertTrue(AutoId.needsAutoId(AutoId.NUMBER, new ShortIdClass((short) 0), "id"), + "Number Auto ID with 0 should return true"); + } catch (DocumentException ex) { + fail(ex); + } + } + + @Test + @DisplayName("needsAutoId returns false for Number strategy and short ID of non-0") + public void needsAutoIdFalseForShortWithNonZero() { + try { + assertFalse(AutoId.needsAutoId(AutoId.NUMBER, new ShortIdClass((short) 31), "id"), + "Number Auto ID with 31 should return false"); + } catch (DocumentException ex) { + fail(ex); + } + } + + @Test + @DisplayName("needsAutoId returns true for Number strategy and int ID of 0") + public void needsAutoIdTrueForIntWithZero() { + try { + assertTrue(AutoId.needsAutoId(AutoId.NUMBER, new IntIdClass(0), "id"), + "Number Auto ID with 0 should return true"); + } catch (DocumentException ex) { + fail(ex); + } + } + + @Test + @DisplayName("needsAutoId returns false for Number strategy and int ID of non-0") + public void needsAutoIdFalseForIntWithNonZero() { + try { + assertFalse(AutoId.needsAutoId(AutoId.NUMBER, new IntIdClass(6), "id"), + "Number Auto ID with 6 should return false"); + } catch (DocumentException ex) { + fail(ex); + } + } + + @Test + @DisplayName("needsAutoId returns true for Number strategy and long ID of 0") + public void needsAutoIdTrueForLongWithZero() { + try { + assertTrue(AutoId.needsAutoId(AutoId.NUMBER, new LongIdClass(0L), "id"), + "Number Auto ID with 0 should return true"); + } catch (DocumentException ex) { + fail(ex); + } + } + + @Test + @DisplayName("needsAutoId returns false for Number strategy and long ID of non-0") + public void needsAutoIdFalseForLongWithNonZero() { + try { + assertFalse(AutoId.needsAutoId(AutoId.NUMBER, new LongIdClass(2L), "id"), + "Number Auto ID with 2 should return false"); + } catch (DocumentException ex) { + fail(ex); + } + } + + @Test + @DisplayName("needsAutoId fails for Number strategy and non-number ID") + public void needsAutoIdFailsForNumberWithStringId() { + assertThrows(DocumentException.class, () -> AutoId.needsAutoId(AutoId.NUMBER, new StringIdClass(""), "id")); + } + + @Test + @DisplayName("needsAutoId returns true for UUID strategy and blank ID") + public void needsAutoIdTrueForUUIDWithBlank() { + try { + assertTrue(AutoId.needsAutoId(AutoId.UUID, new StringIdClass(""), "id"), + "UUID Auto ID with blank should return true"); + } catch (DocumentException ex) { + fail(ex); + } + } + + @Test + @DisplayName("needsAutoId returns false for UUID strategy and non-blank ID") + public void needsAutoIdFalseForUUIDNotBlank() { + try { + assertFalse(AutoId.needsAutoId(AutoId.UUID, new StringIdClass("howdy"), "id"), + "UUID Auto ID with non-blank should return false"); + } catch (DocumentException ex) { + fail(ex); + } + } + + @Test + @DisplayName("needsAutoId fails for UUID strategy and non-string ID") + public void needsAutoIdFailsForUUIDNonString() { + assertThrows(DocumentException.class, () -> AutoId.needsAutoId(AutoId.UUID, new IntIdClass(5), "id")); + } + + @Test + @DisplayName("needsAutoId returns true for Random String strategy and blank ID") + public void needsAutoIdTrueForRandomWithBlank() { + try { + assertTrue(AutoId.needsAutoId(AutoId.RANDOM_STRING, new StringIdClass(""), "id"), + "Random String Auto ID with blank should return true"); + } catch (DocumentException ex) { + fail(ex); + } + } + + @Test + @DisplayName("needsAutoId returns false for Random String strategy and non-blank ID") + public void needsAutoIdFalseForRandomNotBlank() { + try { + assertFalse(AutoId.needsAutoId(AutoId.RANDOM_STRING, new StringIdClass("full"), "id"), + "Random String Auto ID with non-blank should return false"); + } catch (DocumentException ex) { + fail(ex); + } + } + + @Test + @DisplayName("needsAutoId fails for Random String strategy and non-string ID") + public void needsAutoIdFailsForRandomNonString() { + assertThrows(DocumentException.class, + () -> AutoId.needsAutoId(AutoId.RANDOM_STRING, new ShortIdClass((short) 55), "id")); + } +} diff --git a/src/test/java/solutions/bitbadger/documents/java/ConfigurationTest.java b/src/test/java/solutions/bitbadger/documents/java/ConfigurationTest.java new file mode 100644 index 0000000..ed6a71a --- /dev/null +++ b/src/test/java/solutions/bitbadger/documents/java/ConfigurationTest.java @@ -0,0 +1,56 @@ +package solutions.bitbadger.documents.java; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import solutions.bitbadger.documents.*; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for the `Configuration` object + */ +@DisplayName("Java | Configuration") +final public class ConfigurationTest { + + @Test + @DisplayName("Default JSON options are as expected") + public void defaultJsonOptions() { + assertTrue(Configuration.json.getConfiguration().getEncodeDefaults(), "Encode Defaults should have been set"); + assertFalse(Configuration.json.getConfiguration().getExplicitNulls(), + "Explicit Nulls should not have been set"); + assertTrue(Configuration.json.getConfiguration().getCoerceInputValues(), + "Coerce Input Values should have been set"); + } + + @Test + @DisplayName("Default ID field is `id`") + public void defaultIdField() { + assertEquals("id", Configuration.idField, "Default ID field incorrect"); + } + + @Test + @DisplayName("Default Auto ID strategy is `DISABLED`") + public void defaultAutoId() { + assertEquals(AutoId.DISABLED, Configuration.autoIdStrategy, "Default Auto ID strategy should be `disabled`"); + } + + @Test + @DisplayName("Default ID string length should be 16") + public void defaultIdStringLength() { + assertEquals(16, Configuration.idStringLength, "Default ID string length should be 16"); + } + + @Test + @DisplayName("Dialect is derived from connection string") + public void dialectIsDerived() { + try { + assertThrows(DocumentException.class, Configuration::dialect); + Configuration.setConnectionString("jdbc:postgresql:db"); + assertEquals(Dialect.POSTGRESQL, Configuration.dialect()); + } catch (DocumentException ex) { + fail(ex); + } finally { + Configuration.setConnectionString(null); + } + } +} diff --git a/src/test/java/solutions/bitbadger/documents/java/DocumentIndexTest.java b/src/test/java/solutions/bitbadger/documents/java/DocumentIndexTest.java new file mode 100644 index 0000000..c54f9cb --- /dev/null +++ b/src/test/java/solutions/bitbadger/documents/java/DocumentIndexTest.java @@ -0,0 +1,26 @@ +package solutions.bitbadger.documents.java; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import solutions.bitbadger.documents.DocumentIndex; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Unit tests for the `DocumentIndex` enum + */ +@DisplayName("Java | DocumentIndex") +final public class DocumentIndexTest { + + @Test + @DisplayName("FULL uses proper SQL") + public void fullSQL() { + assertEquals("", DocumentIndex.FULL.getSql(), "The SQL for Full is incorrect"); + } + + @Test + @DisplayName("OPTIMIZED uses proper SQL") + public void optimizedSQL() { + assertEquals(" jsonb_path_ops", DocumentIndex.OPTIMIZED.getSql(), "The SQL for Optimized is incorrect"); + } +} diff --git a/src/test/java/solutions/bitbadger/documents/java/FieldMatchTest.java b/src/test/java/solutions/bitbadger/documents/java/FieldMatchTest.java new file mode 100644 index 0000000..c974534 --- /dev/null +++ b/src/test/java/solutions/bitbadger/documents/java/FieldMatchTest.java @@ -0,0 +1,26 @@ +package solutions.bitbadger.documents.java; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import solutions.bitbadger.documents.FieldMatch; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Unit tests for the `FieldMatch` enum + */ +@DisplayName("Java | FieldMatch") +final public class FieldMatchTest { + + @Test + @DisplayName("ANY uses proper SQL") + public void any() { + assertEquals("OR", FieldMatch.ANY.getSql(), "ANY should use OR"); + } + + @Test + @DisplayName("ALL uses proper SQL") + public void all() { + assertEquals("AND", FieldMatch.ALL.getSql(), "ALL should use AND"); + } +} diff --git a/src/test/java/solutions/bitbadger/documents/java/FieldTest.java b/src/test/java/solutions/bitbadger/documents/java/FieldTest.java new file mode 100644 index 0000000..287b1ef --- /dev/null +++ b/src/test/java/solutions/bitbadger/documents/java/FieldTest.java @@ -0,0 +1,629 @@ +package solutions.bitbadger.documents.java; + +import kotlin.Pair; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import solutions.bitbadger.documents.*; + +import java.util.Collection; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for the `Field` class + */ +@DisplayName("Java | Field") +final public class FieldTest { + + /** + * Clear the connection string (resets Dialect) + */ + @AfterEach + public void cleanUp() { + Configuration.setConnectionString(null); + } + + // ~~~ INSTANCE METHODS ~~~ + + @Test + @DisplayName("withParameterName fails for invalid name") + public void withParamNameFails() { + assertThrows(DocumentException.class, () -> Field.equal("it", "").withParameterName("2424")); + } + + @Test + @DisplayName("withParameterName works with colon prefix") + public void withParamNameColon() { + Field field = Field.equal("abc", "22").withQualifier("me"); + Field withParam = field.withParameterName(":test"); + assertNotSame(field, withParam, "A new Field instance should have been created"); + assertEquals(field.getName(), withParam.getName(), "Name should have been preserved"); + assertEquals(field.getComparison(), withParam.getComparison(), "Comparison should have been preserved"); + assertEquals(":test", withParam.getParameterName(), "Parameter name not set correctly"); + assertEquals(field.getQualifier(), withParam.getQualifier(), "Qualifier should have been preserved"); + } + + @Test + @DisplayName("withParameterName works with at-sign prefix") + public void withParamNameAtSign() { + Field field = Field.equal("def", "44"); + Field withParam = field.withParameterName("@unit"); + assertNotSame(field, withParam, "A new Field instance should have been created"); + assertEquals(field.getName(), withParam.getName(), "Name should have been preserved"); + assertEquals(field.getComparison(), withParam.getComparison(), "Comparison should have been preserved"); + assertEquals("@unit", withParam.getParameterName(), "Parameter name not set correctly"); + assertEquals(field.getQualifier(), withParam.getQualifier(), "Qualifier should have been preserved"); + } + + @Test + @DisplayName("withQualifier sets qualifier correctly") + public void withQualifier() { + Field field = Field.equal("j", "k"); + Field withQual = field.withQualifier("test"); + assertNotSame(field, withQual, "A new Field instance should have been created"); + assertEquals(field.getName(), withQual.getName(), "Name should have been preserved"); + assertEquals(field.getComparison(), withQual.getComparison(), "Comparison should have been preserved"); + assertEquals(field.getParameterName(), withQual.getParameterName(), + "Parameter Name should have been preserved"); + assertEquals("test", withQual.getQualifier(), "Qualifier not set correctly"); + } + + @Test + @DisplayName("path generates for simple unqualified PostgreSQL field") + public void pathPostgresSimpleUnqualified() { + assertEquals("data->>'SomethingCool'", + Field.greaterOrEqual("SomethingCool", 18).path(Dialect.POSTGRESQL, FieldFormat.SQL), + "Path not correct"); + } + + @Test + @DisplayName("path generates for simple qualified PostgreSQL field") + public void pathPostgresSimpleQualified() { + assertEquals("this.data->>'SomethingElse'", + Field.less("SomethingElse", 9).withQualifier("this").path(Dialect.POSTGRESQL, FieldFormat.SQL), + "Path not correct"); + } + + @Test + @DisplayName("path generates for nested unqualified PostgreSQL field") + public void pathPostgresNestedUnqualified() { + assertEquals("data#>>'{My,Nested,Field}'", + Field.equal("My.Nested.Field", "howdy").path(Dialect.POSTGRESQL, FieldFormat.SQL), "Path not correct"); + } + + @Test + @DisplayName("path generates for nested qualified PostgreSQL field") + public void pathPostgresNestedQualified() { + assertEquals("bird.data#>>'{Nest,Away}'", + Field.equal("Nest.Away", "doc").withQualifier("bird").path(Dialect.POSTGRESQL, FieldFormat.SQL), + "Path not correct"); + } + + @Test + @DisplayName("path generates for simple unqualified SQLite field") + public void pathSQLiteSimpleUnqualified() { + assertEquals("data->>'SomethingCool'", + Field.greaterOrEqual("SomethingCool", 18).path(Dialect.SQLITE, FieldFormat.SQL), "Path not correct"); + } + + @Test + @DisplayName("path generates for simple qualified SQLite field") + public void pathSQLiteSimpleQualified() { + assertEquals("this.data->>'SomethingElse'", + Field.less("SomethingElse", 9).withQualifier("this").path(Dialect.SQLITE, FieldFormat.SQL), + "Path not correct"); + } + + @Test + @DisplayName("path generates for nested unqualified SQLite field") + public void pathSQLiteNestedUnqualified() { + assertEquals("data->'My'->'Nested'->>'Field'", + Field.equal("My.Nested.Field", "howdy").path(Dialect.SQLITE, FieldFormat.SQL), "Path not correct"); + } + + @Test + @DisplayName("path generates for nested qualified SQLite field") + public void pathSQLiteNestedQualified() { + assertEquals("bird.data->'Nest'->>'Away'", + Field.equal("Nest.Away", "doc").withQualifier("bird").path(Dialect.SQLITE, FieldFormat.SQL), + "Path not correct"); + } + + @Test + @DisplayName("toWhere generates for exists w/o qualifier (PostgreSQL)") + public void toWhereExistsNoQualPostgres() { + Configuration.setConnectionString(":postgresql:"); + assertEquals("data->>'that_field' IS NOT NULL", Field.exists("that_field").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for exists w/o qualifier (SQLite)") + public void toWhereExistsNoQualSQLite() { + Configuration.setConnectionString(":sqlite:"); + assertEquals("data->>'that_field' IS NOT NULL", Field.exists("that_field").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for not-exists w/o qualifier (PostgreSQL)") + public void toWhereNotExistsNoQualPostgres() { + Configuration.setConnectionString(":postgresql:"); + assertEquals("data->>'a_field' IS NULL", Field.notExists("a_field").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for not-exists w/o qualifier (SQLite)") + public void toWhereNotExistsNoQualSQLite() { + Configuration.setConnectionString(":sqlite:"); + assertEquals("data->>'a_field' IS NULL", Field.notExists("a_field").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for BETWEEN w/o qualifier, numeric range (PostgreSQL)") + public void toWhereBetweenNoQualNumericPostgres() { + Configuration.setConnectionString(":postgresql:"); + assertEquals("(data->>'age')::numeric BETWEEN @agemin AND @agemax", + Field.between("age", 13, 17, "@age").toWhere(), "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for BETWEEN w/o qualifier, alphanumeric range (PostgreSQL)") + public void toWhereBetweenNoQualAlphaPostgres() { + Configuration.setConnectionString(":postgresql:"); + assertEquals("data->>'city' BETWEEN :citymin AND :citymax", + Field.between("city", "Atlanta", "Chicago", ":city").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for BETWEEN w/o qualifier (SQLite)") + public void toWhereBetweenNoQualSQLite() { + Configuration.setConnectionString(":sqlite:"); + assertEquals("data->>'age' BETWEEN @agemin AND @agemax", Field.between("age", 13, 17, "@age").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for BETWEEN w/ qualifier, numeric range (PostgreSQL)") + public void toWhereBetweenQualNumericPostgres() { + Configuration.setConnectionString(":postgresql:"); + assertEquals("(test.data->>'age')::numeric BETWEEN @agemin AND @agemax", + Field.between("age", 13, 17, "@age").withQualifier("test").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for BETWEEN w/ qualifier, alphanumeric range (PostgreSQL)") + public void toWhereBetweenQualAlphaPostgres() { + Configuration.setConnectionString(":postgresql:"); + assertEquals("unit.data->>'city' BETWEEN :citymin AND :citymax", + Field.between("city", "Atlanta", "Chicago", ":city").withQualifier("unit").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for BETWEEN w/ qualifier (SQLite)") + public void toWhereBetweenQualSQLite() { + Configuration.setConnectionString(":sqlite:"); + assertEquals("my.data->>'age' BETWEEN @agemin AND @agemax", + Field.between("age", 13, 17, "@age").withQualifier("my").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for IN/any, numeric values (PostgreSQL)") + public void toWhereAnyNumericPostgres() { + Configuration.setConnectionString(":postgresql:"); + assertEquals("(data->>'even')::numeric IN (:nbr_0, :nbr_1, :nbr_2)", + Field.any("even", List.of(2, 4, 6), ":nbr").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for IN/any, alphanumeric values (PostgreSQL)") + public void toWhereAnyAlphaPostgres() { + Configuration.setConnectionString(":postgresql:"); + assertEquals("data->>'test' IN (:city_0, :city_1)", + Field.any("test", List.of("Atlanta", "Chicago"), ":city").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for IN/any (SQLite)") + public void toWhereAnySQLite() { + Configuration.setConnectionString(":sqlite:"); + assertEquals("data->>'test' IN (:city_0, :city_1)", + Field.any("test", List.of("Atlanta", "Chicago"), ":city").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for inArray (PostgreSQL)") + public void toWhereInArrayPostgres() { + Configuration.setConnectionString(":postgresql:"); + assertEquals("data->'even' ??| ARRAY[:it_0, :it_1, :it_2, :it_3]", + Field.inArray("even", "tbl", List.of(2, 4, 6, 8), ":it").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for inArray (SQLite)") + public void toWhereInArraySQLite() { + Configuration.setConnectionString(":sqlite:"); + assertEquals("EXISTS (SELECT 1 FROM json_each(tbl.data, '$.test') WHERE value IN (:city_0, :city_1))", + Field.inArray("test", "tbl", List.of("Atlanta", "Chicago"), ":city").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for others w/o qualifier (PostgreSQL)") + public void toWhereOtherNoQualPostgres() { + Configuration.setConnectionString(":postgresql:"); + assertEquals("data->>'some_field' = :value", Field.equal("some_field", "", ":value").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates for others w/o qualifier (SQLite)") + public void toWhereOtherNoQualSQLite() { + Configuration.setConnectionString(":sqlite:"); + assertEquals("data->>'some_field' = :value", Field.equal("some_field", "", ":value").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates no-parameter w/ qualifier (PostgreSQL)") + public void toWhereNoParamWithQualPostgres() { + Configuration.setConnectionString(":postgresql:"); + assertEquals("test.data->>'no_field' IS NOT NULL", Field.exists("no_field").withQualifier("test").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates no-parameter w/ qualifier (SQLite)") + public void toWhereNoParamWithQualSQLite() { + Configuration.setConnectionString(":sqlite:"); + assertEquals("test.data->>'no_field' IS NOT NULL", Field.exists("no_field").withQualifier("test").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates parameter w/ qualifier (PostgreSQL)") + public void toWhereParamWithQualPostgres() { + Configuration.setConnectionString(":postgresql:"); + assertEquals("(q.data->>'le_field')::numeric <= :it", + Field.lessOrEqual("le_field", 18, ":it").withQualifier("q").toWhere(), + "Field WHERE clause not generated correctly"); + } + + @Test + @DisplayName("toWhere generates parameter w/ qualifier (SQLite)") + public void toWhereParamWithQualSQLite() { + Configuration.setConnectionString(":sqlite:"); + assertEquals("q.data->>'le_field' <= :it", + Field.lessOrEqual("le_field", 18, ":it").withQualifier("q").toWhere(), + "Field WHERE clause not generated correctly"); + } + + // ~~~ STATIC TESTS ~~~ + + @Test + @DisplayName("equal constructs a field w/o parameter name") + public void equalCtor() { + Field field = Field.equal("Test", 14); + assertEquals("Test", field.getName(), "Field name not filled correctly"); + assertEquals(Op.EQUAL, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals(14, field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertNull(field.getParameterName(), "The parameter name should have been null"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("equal constructs a field w/ parameter name") + public void equalParameterCtor() { + Field field = Field.equal("Test", 14, ":w"); + assertEquals("Test", field.getName(), "Field name not filled correctly"); + assertEquals(Op.EQUAL, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals(14, field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertEquals(":w", field.getParameterName(), "Field parameter name not filled correctly"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("greater constructs a field w/o parameter name") + public void greaterCtor() { + Field field = Field.greater("Great", "night"); + assertEquals("Great", field.getName(), "Field name not filled correctly"); + assertEquals(Op.GREATER, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals("night", field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertNull(field.getParameterName(), "The parameter name should have been null"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("greater constructs a field w/ parameter name") + public void greaterParameterCtor() { + Field field = Field.greater("Great", "night", ":yeah"); + assertEquals("Great", field.getName(), "Field name not filled correctly"); + assertEquals(Op.GREATER, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals("night", field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertEquals(":yeah", field.getParameterName(), "Field parameter name not filled correctly"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("greaterOrEqual constructs a field w/o parameter name") + public void greaterOrEqualCtor() { + Field field = Field.greaterOrEqual("Nice", 88L); + assertEquals("Nice", field.getName(), "Field name not filled correctly"); + assertEquals(Op.GREATER_OR_EQUAL, field.getComparison().getOp(), + "Field comparison operation not filled correctly"); + assertEquals(88L, field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertNull(field.getParameterName(), "The parameter name should have been null"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("greaterOrEqual constructs a field w/ parameter name") + public void greaterOrEqualParameterCtor() { + Field field = Field.greaterOrEqual("Nice", 88L, ":nice"); + assertEquals("Nice", field.getName(), "Field name not filled correctly"); + assertEquals(Op.GREATER_OR_EQUAL, field.getComparison().getOp(), + "Field comparison operation not filled correctly"); + assertEquals(88L, field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertEquals(":nice", field.getParameterName(), "Field parameter name not filled correctly"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("less constructs a field w/o parameter name") + public void lessCtor() { + Field field = Field.less("Lesser", "seven"); + assertEquals("Lesser", field.getName(), "Field name not filled correctly"); + assertEquals(Op.LESS, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals("seven", field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertNull(field.getParameterName(), "The parameter name should have been null"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("less constructs a field w/ parameter name") + public void lessParameterCtor() { + Field field = Field.less("Lesser", "seven", ":max"); + assertEquals("Lesser", field.getName(), "Field name not filled correctly"); + assertEquals(Op.LESS, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals("seven", field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertEquals(":max", field.getParameterName(), "Field parameter name not filled correctly"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("lessOrEqual constructs a field w/o parameter name") + public void lessOrEqualCtor() { + Field field = Field.lessOrEqual("Nobody", "KNOWS"); + assertEquals("Nobody", field.getName(), "Field name not filled correctly"); + assertEquals(Op.LESS_OR_EQUAL, field.getComparison().getOp(), + "Field comparison operation not filled correctly"); + assertEquals("KNOWS", field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertNull(field.getParameterName(), "The parameter name should have been null"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("lessOrEqual constructs a field w/ parameter name") + public void lessOrEqualParameterCtor() { + Field field = Field.lessOrEqual("Nobody", "KNOWS", ":nope"); + assertEquals("Nobody", field.getName(), "Field name not filled correctly"); + assertEquals(Op.LESS_OR_EQUAL, field.getComparison().getOp(), + "Field comparison operation not filled correctly"); + assertEquals("KNOWS", field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertEquals(":nope", field.getParameterName(), "Field parameter name not filled correctly"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("notEqual constructs a field w/o parameter name") + public void notEqualCtor() { + Field field = Field.notEqual("Park", "here"); + assertEquals("Park", field.getName(), "Field name not filled correctly"); + assertEquals(Op.NOT_EQUAL, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals("here", field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertNull(field.getParameterName(), "The parameter name should have been null"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("notEqual constructs a field w/ parameter name") + public void notEqualParameterCtor() { + Field field = Field.notEqual("Park", "here", ":now"); + assertEquals("Park", field.getName(), "Field name not filled correctly"); + assertEquals(Op.NOT_EQUAL, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals("here", field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertEquals(":now", field.getParameterName(), "Field parameter name not filled correctly"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("between constructs a field w/o parameter name") + public void betweenCtor() { + Field> field = Field.between("Age", 18, 49); + assertEquals("Age", field.getName(), "Field name not filled correctly"); + assertEquals(Op.BETWEEN, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals(18, field.getComparison().getValue().getFirst(), + "Field comparison min value not filled correctly"); + assertEquals(49, field.getComparison().getValue().getSecond(), + "Field comparison max value not filled correctly"); + assertNull(field.getParameterName(), "The parameter name should have been null"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("between constructs a field w/ parameter name") + public void betweenParameterCtor() { + Field> field = Field.between("Age", 18, 49, ":limit"); + assertEquals("Age", field.getName(), "Field name not filled correctly"); + assertEquals(Op.BETWEEN, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals(18, field.getComparison().getValue().getFirst(), + "Field comparison min value not filled correctly"); + assertEquals(49, field.getComparison().getValue().getSecond(), + "Field comparison max value not filled correctly"); + assertEquals(":limit", field.getParameterName(), "The parameter name should have been null"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("any constructs a field w/o parameter name") + public void anyCtor() { + Field> field = Field.any("Here", List.of(8, 16, 32)); + assertEquals("Here", field.getName(), "Field name not filled correctly"); + assertEquals(Op.IN, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals(List.of(8, 16, 32), field.getComparison().getValue(), + "Field comparison value not filled correctly"); + assertNull(field.getParameterName(), "The parameter name should have been null"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("any constructs a field w/ parameter name") + public void anyParameterCtor() { + Field> field = Field.any("Here", List.of(8, 16, 32), ":list"); + assertEquals("Here", field.getName(), "Field name not filled correctly"); + assertEquals(Op.IN, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals(List.of(8, 16, 32), field.getComparison().getValue(), + "Field comparison value not filled correctly"); + assertEquals(":list", field.getParameterName(), "Field parameter name not filled correctly"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("inArray constructs a field w/o parameter name") + public void inArrayCtor() { + Field>> field = Field.inArray("ArrayField", "table", List.of("z")); + assertEquals("ArrayField", field.getName(), "Field name not filled correctly"); + assertEquals(Op.IN_ARRAY, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals("table", field.getComparison().getValue().getFirst(), + "Field comparison table not filled correctly"); + assertEquals(List.of("z"), field.getComparison().getValue().getSecond(), + "Field comparison values not filled correctly"); + assertNull(field.getParameterName(), "The parameter name should have been null"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("inArray constructs a field w/ parameter name") + public void inArrayParameterCtor() { + Field>> field = Field.inArray("ArrayField", "table", List.of("z"), ":a"); + assertEquals("ArrayField", field.getName(), "Field name not filled correctly"); + assertEquals(Op.IN_ARRAY, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals("table", field.getComparison().getValue().getFirst(), + "Field comparison table not filled correctly"); + assertEquals(List.of("z"), field.getComparison().getValue().getSecond(), + "Field comparison values not filled correctly"); + assertEquals(":a", field.getParameterName(), "Field parameter name not filled correctly"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("exists constructs a field") + public void existsCtor() { + Field field = Field.exists("Groovy"); + assertEquals("Groovy", field.getName(), "Field name not filled correctly"); + assertEquals(Op.EXISTS, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals("", field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertNull(field.getParameterName(), "The parameter name should have been null"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("notExists constructs a field") + public void notExistsCtor() { + Field field = Field.notExists("Groovy"); + assertEquals("Groovy", field.getName(), "Field name not filled correctly"); + assertEquals(Op.NOT_EXISTS, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals("", field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertNull(field.getParameterName(), "The parameter name should have been null"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("named constructs a field") + public void namedCtor() { + Field field = Field.named("Tacos"); + assertEquals("Tacos", field.getName(), "Field name not filled correctly"); + assertEquals(Op.EQUAL, field.getComparison().getOp(), "Field comparison operation not filled correctly"); + assertEquals("", field.getComparison().getValue(), "Field comparison value not filled correctly"); + assertNull(field.getParameterName(), "The parameter name should have been null"); + assertNull(field.getQualifier(), "The qualifier should have been null"); + } + + @Test + @DisplayName("static constructors fail for invalid parameter name") + public void staticCtorsFailOnParamName() { + assertThrows(DocumentException.class, () -> Field.equal("a", "b", "that ain't it, Jack...")); + } + + @Test + @DisplayName("nameToPath creates a simple PostgreSQL SQL name") + public void nameToPathPostgresSimpleSQL() { + assertEquals("data->>'Simple'", Field.nameToPath("Simple", Dialect.POSTGRESQL, FieldFormat.SQL), + "Path not constructed correctly"); + } + + @Test + @DisplayName("nameToPath creates a simple SQLite SQL name") + public void nameToPathSQLiteSimpleSQL() { + assertEquals("data->>'Simple'", Field.nameToPath("Simple", Dialect.SQLITE, FieldFormat.SQL), + "Path not constructed correctly"); + } + + @Test + @DisplayName("nameToPath creates a nested PostgreSQL SQL name") + public void nameToPathPostgresNestedSQL() { + assertEquals("data#>>'{A,Long,Path,to,the,Property}'", + Field.nameToPath("A.Long.Path.to.the.Property", Dialect.POSTGRESQL, FieldFormat.SQL), + "Path not constructed correctly"); + } + + @Test + @DisplayName("nameToPath creates a nested SQLite SQL name") + public void nameToPathSQLiteNestedSQL() { + assertEquals("data->'A'->'Long'->'Path'->'to'->'the'->>'Property'", + Field.nameToPath("A.Long.Path.to.the.Property", Dialect.SQLITE, FieldFormat.SQL), + "Path not constructed correctly"); + } + + @Test + @DisplayName("nameToPath creates a simple PostgreSQL JSON name") + public void nameToPathPostgresSimpleJSON() { + assertEquals("data->'Simple'", Field.nameToPath("Simple", Dialect.POSTGRESQL, FieldFormat.JSON), + "Path not constructed correctly"); + } + + @Test + @DisplayName("nameToPath creates a simple SQLite JSON name") + public void nameToPathSQLiteSimpleJSON() { + assertEquals("data->'Simple'", Field.nameToPath("Simple", Dialect.SQLITE, FieldFormat.JSON), + "Path not constructed correctly"); + } + + @Test + @DisplayName("nameToPath creates a nested PostgreSQL JSON name") + public void nameToPathPostgresNestedJSON() { + assertEquals("data#>'{A,Long,Path,to,the,Property}'", + Field.nameToPath("A.Long.Path.to.the.Property", Dialect.POSTGRESQL, FieldFormat.JSON), + "Path not constructed correctly"); + } + + @Test + @DisplayName("nameToPath creates a nested SQLite JSON name") + public void nameToPathSQLiteNestedJSON() { + assertEquals("data->'A'->'Long'->'Path'->'to'->'the'->'Property'", + Field.nameToPath("A.Long.Path.to.the.Property", Dialect.SQLITE, FieldFormat.JSON), + "Path not constructed correctly"); + } +} diff --git a/src/test/java/solutions/bitbadger/documents/java/OpTest.java b/src/test/java/solutions/bitbadger/documents/java/OpTest.java new file mode 100644 index 0000000..3a319cf --- /dev/null +++ b/src/test/java/solutions/bitbadger/documents/java/OpTest.java @@ -0,0 +1,80 @@ +package solutions.bitbadger.documents.java; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import solutions.bitbadger.documents.Op; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Unit tests for the `Op` enum + */ +@DisplayName("Java | Op") +final public class OpTest { + + @Test + @DisplayName("EQUAL uses proper SQL") + public void equalSQL() { + assertEquals("=", Op.EQUAL.getSql(), "The SQL for equal is incorrect"); + } + + @Test + @DisplayName("GREATER uses proper SQL") + public void greaterSQL() { + assertEquals(">", Op.GREATER.getSql(), "The SQL for greater is incorrect"); + } + + @Test + @DisplayName("GREATER_OR_EQUAL uses proper SQL") + public void greaterOrEqualSQL() { + assertEquals(">=", Op.GREATER_OR_EQUAL.getSql(), "The SQL for greater-or-equal is incorrect"); + } + + @Test + @DisplayName("LESS uses proper SQL") + public void lessSQL() { + assertEquals("<", Op.LESS.getSql(), "The SQL for less is incorrect"); + } + + @Test + @DisplayName("LESS_OR_EQUAL uses proper SQL") + public void lessOrEqualSQL() { + assertEquals("<=", Op.LESS_OR_EQUAL.getSql(), "The SQL for less-or-equal is incorrect"); + } + + @Test + @DisplayName("NOT_EQUAL uses proper SQL") + public void notEqualSQL() { + assertEquals("<>", Op.NOT_EQUAL.getSql(), "The SQL for not-equal is incorrect"); + } + + @Test + @DisplayName("BETWEEN uses proper SQL") + public void betweenSQL() { + assertEquals("BETWEEN", Op.BETWEEN.getSql(), "The SQL for between is incorrect"); + } + + @Test + @DisplayName("IN uses proper SQL") + public void inSQL() { + assertEquals("IN", Op.IN.getSql(), "The SQL for in is incorrect"); + } + + @Test + @DisplayName("IN_ARRAY uses proper SQL") + public void inArraySQL() { + assertEquals("??|", Op.IN_ARRAY.getSql(), "The SQL for in-array is incorrect"); + } + + @Test + @DisplayName("EXISTS uses proper SQL") + public void existsSQL() { + assertEquals("IS NOT NULL", Op.EXISTS.getSql(), "The SQL for exists is incorrect"); + } + + @Test + @DisplayName("NOT_EXISTS uses proper SQL") + public void notExistsSQL() { + assertEquals("IS NULL", Op.NOT_EXISTS.getSql(), "The SQL for not-exists is incorrect"); + } +} diff --git a/src/test/java/solutions/bitbadger/documents/java/ParameterNameTest.java b/src/test/java/solutions/bitbadger/documents/java/ParameterNameTest.java new file mode 100644 index 0000000..15d5498 --- /dev/null +++ b/src/test/java/solutions/bitbadger/documents/java/ParameterNameTest.java @@ -0,0 +1,32 @@ +package solutions.bitbadger.documents.java; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import solutions.bitbadger.documents.ParameterName; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Unit tests for the `ParameterName` class + */ +@DisplayName("Java | ParameterName") +final public class ParameterNameTest { + + @Test + @DisplayName("derive works when given existing names") + public void withExisting() { + ParameterName names = new ParameterName(); + assertEquals(":taco", names.derive(":taco"), "Name should have been :taco"); + assertEquals(":field0", names.derive(null), "Counter should not have advanced for named field"); + } + + @Test + @DisplayName("derive works when given all anonymous fields") + public void allAnonymous() { + ParameterName names = new ParameterName(); + assertEquals(":field0", names.derive(null), "Anonymous field name should have been returned"); + assertEquals(":field1", names.derive(null), "Counter should have advanced from previous call"); + assertEquals(":field2", names.derive(null), "Counter should have advanced from previous call"); + assertEquals(":field3", names.derive(null), "Counter should have advanced from previous call"); + } +} diff --git a/src/test/java/solutions/bitbadger/documents/java/ParameterTest.java b/src/test/java/solutions/bitbadger/documents/java/ParameterTest.java new file mode 100644 index 0000000..2e6556b --- /dev/null +++ b/src/test/java/solutions/bitbadger/documents/java/ParameterTest.java @@ -0,0 +1,40 @@ +package solutions.bitbadger.documents.java; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import solutions.bitbadger.documents.DocumentException; +import solutions.bitbadger.documents.Parameter; +import solutions.bitbadger.documents.ParameterType; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for the `Parameter` class + */ +@DisplayName("Java | Parameter") +final public class ParameterTest { + + @Test + @DisplayName("Construction with colon-prefixed name") + public void ctorWithColon() { + Parameter p = new Parameter<>(":test", ParameterType.STRING, "ABC"); + assertEquals(":test", p.getName(), "Parameter name was incorrect"); + assertEquals(ParameterType.STRING, p.getType(), "Parameter type was incorrect"); + assertEquals("ABC", p.getValue(), "Parameter value was incorrect"); + } + + @Test + @DisplayName("Construction with at-sign-prefixed name") + public void ctorWithAtSign() { + Parameter p = new Parameter<>("@yo", ParameterType.NUMBER, null); + assertEquals("@yo", p.getName(), "Parameter name was incorrect"); + assertEquals(ParameterType.NUMBER, p.getType(), "Parameter type was incorrect"); + assertNull(p.getValue(), "Parameter value was incorrect"); + } + + @Test + @DisplayName("Construction fails with incorrect prefix") + public void ctorFailsForPrefix() { + assertThrows(DocumentException.class, () -> new Parameter<>("it", ParameterType.JSON, "")); + } +} diff --git a/src/test/java/solutions/bitbadger/documents/java/ParametersTest.java b/src/test/java/solutions/bitbadger/documents/java/ParametersTest.java new file mode 100644 index 0000000..6c011d1 --- /dev/null +++ b/src/test/java/solutions/bitbadger/documents/java/ParametersTest.java @@ -0,0 +1,121 @@ +package solutions.bitbadger.documents.java; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import solutions.bitbadger.documents.*; + +import java.util.Collection; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for the `Parameters` object + */ +@DisplayName("Java | Parameters") +final public class ParametersTest { + + /** + * Reset the dialect + */ + @AfterEach + public void cleanUp() { + Configuration.setConnectionString(null); + } + + @Test + @DisplayName("nameFields works with no changes") + public void nameFieldsNoChange() { + List> fields = List.of(Field.equal("a", "", ":test"), Field.exists("q"), Field.equal("b", "", ":me")); + Field[] named = Parameters.nameFields(fields).toArray(new Field[] { }); + assertEquals(fields.size(), named.length, "There should have been 3 fields in the list"); + assertSame(fields.get(0), named[0], "The first field should be the same"); + assertSame(fields.get(1), named[1], "The second field should be the same"); + assertSame(fields.get(2), named[2], "The third field should be the same"); + } + + @Test + @DisplayName("nameFields works when changing fields") + public void nameFieldsChange() { + List> fields = List.of( + Field.equal("a", ""), Field.equal("e", "", ":hi"), Field.equal("b", ""), Field.notExists("z")); + Field[] named = Parameters.nameFields(fields).toArray(new Field[] { }); + assertEquals(fields.size(), named.length, "There should have been 4 fields in the list"); + assertNotSame(fields.get(0), named[0], "The first field should not be the same"); + assertEquals(":field0", named[0].getParameterName(), "First parameter name incorrect"); + assertSame(fields.get(1), named[1], "The second field should be the same"); + assertNotSame(fields.get(2), named[2], "The third field should not be the same"); + assertEquals(":field1", named[2].getParameterName(), "Third parameter name incorrect"); + assertSame(fields.get(3), named[3], "The fourth field should be the same"); + } + + @Test + @DisplayName("replaceNamesInQuery replaces successfully") + public void replaceNamesInQuery() { + List> parameters = List.of(new Parameter<>(":data", ParameterType.JSON, "{}"), + new Parameter<>(":data_ext", ParameterType.STRING, "")); + String query = + "SELECT data, data_ext FROM tbl WHERE data = :data AND data_ext = :data_ext AND more_data = :data"; + assertEquals("SELECT data, data_ext FROM tbl WHERE data = ? AND data_ext = ? AND more_data = ?", + Parameters.replaceNamesInQuery(query, parameters), "Parameters not replaced correctly"); + } + + @Test + @DisplayName("fieldNames generates a single parameter (PostgreSQL)") + public void fieldNamesSinglePostgres() { + Configuration.setConnectionString(":postgresql:"); + Parameter[] nameParams = Parameters.fieldNames(List.of("test")).toArray(new Parameter[] { }); + assertEquals(1, nameParams.length, "There should be one name parameter"); + assertEquals(":name", nameParams[0].getName(), "The parameter name is incorrect"); + assertEquals(ParameterType.STRING, nameParams[0].getType(), "The parameter type is incorrect"); + assertEquals("{test}", nameParams[0].getValue(), "The parameter value is incorrect"); + } + + @Test + @DisplayName("fieldNames generates multiple parameters (PostgreSQL)") + public void fieldNamesMultiplePostgres() { + Configuration.setConnectionString(":postgresql:"); + Parameter[] nameParams = Parameters.fieldNames(List.of("test", "this", "today")) + .toArray(new Parameter[] { }); + assertEquals(1, nameParams.length, "There should be one name parameter"); + assertEquals(":name", nameParams[0].getName(), "The parameter name is incorrect"); + assertEquals(ParameterType.STRING, nameParams[0].getType(), "The parameter type is incorrect"); + assertEquals("{test,this,today}", nameParams[0].getValue(), "The parameter value is incorrect"); + } + + @Test + @DisplayName("fieldNames generates a single parameter (SQLite)") + public void fieldNamesSingleSQLite() { + Configuration.setConnectionString(":sqlite:"); + Parameter[] nameParams = Parameters.fieldNames(List.of("test")).toArray(new Parameter[] { }); + assertEquals(1, nameParams.length, "There should be one name parameter"); + assertEquals(":name0", nameParams[0].getName(), "The parameter name is incorrect"); + assertEquals(ParameterType.STRING, nameParams[0].getType(), "The parameter type is incorrect"); + assertEquals("test", nameParams[0].getValue(), "The parameter value is incorrect"); + } + + @Test + @DisplayName("fieldNames generates multiple parameters (SQLite)") + public void fieldNamesMultipleSQLite() { + Configuration.setConnectionString(":sqlite:"); + Parameter[] nameParams = Parameters.fieldNames(List.of("test", "this", "today")) + .toArray(new Parameter[] { }); + assertEquals(3, nameParams.length, "There should be one name parameter"); + assertEquals(":name0", nameParams[0].getName(), "The first parameter name is incorrect"); + assertEquals(ParameterType.STRING, nameParams[0].getType(), "The first parameter type is incorrect"); + assertEquals("test", nameParams[0].getValue(), "The first parameter value is incorrect"); + assertEquals(":name1", nameParams[1].getName(), "The second parameter name is incorrect"); + assertEquals(ParameterType.STRING, nameParams[1].getType(), "The second parameter type is incorrect"); + assertEquals("this", nameParams[1].getValue(), "The second parameter value is incorrect"); + assertEquals(":name2", nameParams[2].getName(), "The third parameter name is incorrect"); + assertEquals(ParameterType.STRING, nameParams[2].getType(), "The third parameter type is incorrect"); + assertEquals("today", nameParams[2].getValue(), "The third parameter value is incorrect"); + } + + @Test + @DisplayName("fieldNames fails if dialect not set") + public void fieldNamesFails() { + assertThrows(DocumentException.class, () -> Parameters.fieldNames(List.of())); + } +} diff --git a/src/test/java/solutions/bitbadger/documents/java/testDocs/ByteIdClass.java b/src/test/java/solutions/bitbadger/documents/java/testDocs/ByteIdClass.java new file mode 100644 index 0000000..c0d41e7 --- /dev/null +++ b/src/test/java/solutions/bitbadger/documents/java/testDocs/ByteIdClass.java @@ -0,0 +1,18 @@ +package solutions.bitbadger.documents.java.testDocs; + +public class ByteIdClass { + + private byte id; + + public byte getId() { + return id; + } + + public void setId(byte id) { + this.id = id; + } + + public ByteIdClass(byte id) { + this.id = id; + } +} diff --git a/src/test/java/solutions/bitbadger/documents/java/testDocs/IntIdClass.java b/src/test/java/solutions/bitbadger/documents/java/testDocs/IntIdClass.java new file mode 100644 index 0000000..1d7a0cc --- /dev/null +++ b/src/test/java/solutions/bitbadger/documents/java/testDocs/IntIdClass.java @@ -0,0 +1,18 @@ +package solutions.bitbadger.documents.java.testDocs; + +public class IntIdClass { + + private int id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public IntIdClass(int id) { + this.id = id; + } +} diff --git a/src/test/java/solutions/bitbadger/documents/java/testDocs/LongIdClass.java b/src/test/java/solutions/bitbadger/documents/java/testDocs/LongIdClass.java new file mode 100644 index 0000000..1ee8bc0 --- /dev/null +++ b/src/test/java/solutions/bitbadger/documents/java/testDocs/LongIdClass.java @@ -0,0 +1,18 @@ +package solutions.bitbadger.documents.java.testDocs; + +public class LongIdClass { + + private long id; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public LongIdClass(long id) { + this.id = id; + } +} diff --git a/src/test/java/solutions/bitbadger/documents/java/testDocs/ShortIdClass.java b/src/test/java/solutions/bitbadger/documents/java/testDocs/ShortIdClass.java new file mode 100644 index 0000000..83a2f3c --- /dev/null +++ b/src/test/java/solutions/bitbadger/documents/java/testDocs/ShortIdClass.java @@ -0,0 +1,18 @@ +package solutions.bitbadger.documents.java.testDocs; + +public class ShortIdClass { + + private short id; + + public short getId() { + return id; + } + + public void setId(short id) { + this.id = id; + } + + public ShortIdClass(short id) { + this.id = id; + } +} diff --git a/src/test/java/solutions/bitbadger/documents/java/testDocs/StringIdClass.java b/src/test/java/solutions/bitbadger/documents/java/testDocs/StringIdClass.java new file mode 100644 index 0000000..3013885 --- /dev/null +++ b/src/test/java/solutions/bitbadger/documents/java/testDocs/StringIdClass.java @@ -0,0 +1,18 @@ +package solutions.bitbadger.documents.java.testDocs; + +public class StringIdClass { + + private String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public StringIdClass(String id) { + this.id = id; + } +} diff --git a/src/test/kotlin/AutoIdTest.kt b/src/test/kotlin/AutoIdTest.kt index e67df54..58cc9aa 100644 --- a/src/test/kotlin/AutoIdTest.kt +++ b/src/test/kotlin/AutoIdTest.kt @@ -11,7 +11,7 @@ import kotlin.test.assertTrue /** * Unit tests for the `AutoId` enum */ -@DisplayName("AutoId") +@DisplayName("Kotlin | AutoId") class AutoIdTest { @Test @@ -66,8 +66,10 @@ class AutoIdTest { @Test @DisplayName("needsAutoId returns false for Number strategy and byte ID of non-0") fun needsAutoIdFalseForByteWithNonZero() = - assertFalse(AutoId.needsAutoId(AutoId.NUMBER, ByteIdClass(77), "id"), - "Number Auto ID with 77 should return false") + assertFalse( + AutoId.needsAutoId(AutoId.NUMBER, ByteIdClass(77), "id"), + "Number Auto ID with 77 should return false" + ) @Test @DisplayName("needsAutoId returns true for Number strategy and short ID of 0") @@ -77,8 +79,10 @@ class AutoIdTest { @Test @DisplayName("needsAutoId returns false for Number strategy and short ID of non-0") fun needsAutoIdFalseForShortWithNonZero() = - assertFalse(AutoId.needsAutoId(AutoId.NUMBER, ShortIdClass(31), "id"), - "Number Auto ID with 31 should return false") + assertFalse( + AutoId.needsAutoId(AutoId.NUMBER, ShortIdClass(31), "id"), + "Number Auto ID with 31 should return false" + ) @Test @DisplayName("needsAutoId returns true for Number strategy and int ID of 0") @@ -98,7 +102,10 @@ class AutoIdTest { @Test @DisplayName("needsAutoId returns false for Number strategy and long ID of non-0") fun needsAutoIdFalseForLongWithNonZero() = - assertFalse(AutoId.needsAutoId(AutoId.NUMBER, IntIdClass(2), "id"), "Number Auto ID with 2 should return false") + assertFalse( + AutoId.needsAutoId(AutoId.NUMBER, LongIdClass(2), "id"), + "Number Auto ID with 2 should return false" + ) @Test @DisplayName("needsAutoId fails for Number strategy and non-number ID") @@ -109,14 +116,18 @@ class AutoIdTest { @Test @DisplayName("needsAutoId returns true for UUID strategy and blank ID") fun needsAutoIdTrueForUUIDWithBlank() = - assertTrue(AutoId.needsAutoId(AutoId.UUID, StringIdClass(""), "id"), - "UUID Auto ID with blank should return true") + assertTrue( + AutoId.needsAutoId(AutoId.UUID, StringIdClass(""), "id"), + "UUID Auto ID with blank should return true" + ) @Test @DisplayName("needsAutoId returns false for UUID strategy and non-blank ID") fun needsAutoIdFalseForUUIDNotBlank() = - assertFalse(AutoId.needsAutoId(AutoId.UUID, StringIdClass("howdy"), "id"), - "UUID Auto ID with non-blank should return false") + assertFalse( + AutoId.needsAutoId(AutoId.UUID, StringIdClass("howdy"), "id"), + "UUID Auto ID with non-blank should return false" + ) @Test @DisplayName("needsAutoId fails for UUID strategy and non-string ID") @@ -127,14 +138,18 @@ class AutoIdTest { @Test @DisplayName("needsAutoId returns true for Random String strategy and blank ID") fun needsAutoIdTrueForRandomWithBlank() = - assertTrue(AutoId.needsAutoId(AutoId.RANDOM_STRING, StringIdClass(""), "id"), - "Random String Auto ID with blank should return true") + assertTrue( + AutoId.needsAutoId(AutoId.RANDOM_STRING, StringIdClass(""), "id"), + "Random String Auto ID with blank should return true" + ) @Test @DisplayName("needsAutoId returns false for Random String strategy and non-blank ID") fun needsAutoIdFalseForRandomNotBlank() = - assertFalse(AutoId.needsAutoId(AutoId.RANDOM_STRING, StringIdClass("full"), "id"), - "Random String Auto ID with non-blank should return false") + assertFalse( + AutoId.needsAutoId(AutoId.RANDOM_STRING, StringIdClass("full"), "id"), + "Random String Auto ID with non-blank should return false" + ) @Test @DisplayName("needsAutoId fails for Random String strategy and non-string ID") diff --git a/src/test/kotlin/ConfigurationTest.kt b/src/test/kotlin/ConfigurationTest.kt index 9e83235..22754a5 100644 --- a/src/test/kotlin/ConfigurationTest.kt +++ b/src/test/kotlin/ConfigurationTest.kt @@ -10,7 +10,7 @@ import kotlin.test.assertTrue /** * Unit tests for the `Configuration` object */ -@DisplayName("Configuration") +@DisplayName("Kotlin | Configuration") class ConfigurationTest { @Test diff --git a/src/test/kotlin/DocumentIndexTest.kt b/src/test/kotlin/DocumentIndexTest.kt index 0947752..9747cde 100644 --- a/src/test/kotlin/DocumentIndexTest.kt +++ b/src/test/kotlin/DocumentIndexTest.kt @@ -7,7 +7,7 @@ import kotlin.test.assertEquals /** * Unit tests for the `DocumentIndex` enum */ -@DisplayName("Op") +@DisplayName("Kotlin | DocumentIndex") class DocumentIndexTest { @Test diff --git a/src/test/kotlin/FieldMatchTest.kt b/src/test/kotlin/FieldMatchTest.kt index 00ba366..ceb1725 100644 --- a/src/test/kotlin/FieldMatchTest.kt +++ b/src/test/kotlin/FieldMatchTest.kt @@ -7,7 +7,7 @@ import kotlin.test.assertEquals /** * Unit tests for the `FieldMatch` enum */ -@DisplayName("FieldMatch") +@DisplayName("Kotlin | FieldMatch") class FieldMatchTest { @Test diff --git a/src/test/kotlin/FieldTest.kt b/src/test/kotlin/FieldTest.kt index 5356893..783979b 100644 --- a/src/test/kotlin/FieldTest.kt +++ b/src/test/kotlin/FieldTest.kt @@ -11,7 +11,7 @@ import kotlin.test.assertNull /** * Unit tests for the `Field` class */ -@DisplayName("Field") +@DisplayName("Kotlin | Field") class FieldTest { /** diff --git a/src/test/kotlin/OpTest.kt b/src/test/kotlin/OpTest.kt index f30797a..5e6d6cd 100644 --- a/src/test/kotlin/OpTest.kt +++ b/src/test/kotlin/OpTest.kt @@ -7,7 +7,7 @@ import kotlin.test.assertEquals /** * Unit tests for the `Op` enum */ -@DisplayName("Op") +@DisplayName("Kotlin | Op") class OpTest { @Test diff --git a/src/test/kotlin/ParameterNameTest.kt b/src/test/kotlin/ParameterNameTest.kt index 44ed76b..b08f6bb 100644 --- a/src/test/kotlin/ParameterNameTest.kt +++ b/src/test/kotlin/ParameterNameTest.kt @@ -7,7 +7,7 @@ import kotlin.test.assertEquals /** * Unit tests for the `ParameterName` class */ -@DisplayName("ParameterName") +@DisplayName("Kotlin | ParameterName") class ParameterNameTest { @Test diff --git a/src/test/kotlin/ParameterTest.kt b/src/test/kotlin/ParameterTest.kt index 9f08515..959ad25 100644 --- a/src/test/kotlin/ParameterTest.kt +++ b/src/test/kotlin/ParameterTest.kt @@ -9,7 +9,7 @@ import kotlin.test.assertNull /** * Unit tests for the `Parameter` class */ -@DisplayName("Parameter") +@DisplayName("Kotlin | Parameter") class ParameterTest { @Test diff --git a/src/test/kotlin/ParametersTest.kt b/src/test/kotlin/ParametersTest.kt index e3d64a2..686ed67 100644 --- a/src/test/kotlin/ParametersTest.kt +++ b/src/test/kotlin/ParametersTest.kt @@ -11,7 +11,7 @@ import kotlin.test.assertSame /** * Unit tests for the `Parameters` object */ -@DisplayName("Parameters") +@DisplayName("Kotlin | Parameters") class ParametersTest { /**