From 815f50633993f306a4d42f09a67944c4fd8d4ac1 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Wed, 19 Mar 2025 12:25:33 -0400 Subject: [PATCH] Add custom ITs for Java/Scala/Groovy --- .../src/main/kotlin/extensions/Connection.kt | 1 + src/jvm/src/main/kotlin/jvm/Results.kt | 9 +-- .../integration/common/CustomFunctions.groovy | 72 +++++++++++++++++ .../jvm/integration/postgresql/CountIT.groovy | 14 ++-- .../integration/postgresql/CustomIT.groovy | 55 +++++++++++++ .../jvm/integration/sqlite/CustomIT.groovy | 55 +++++++++++++ .../groovy/support/JsonDocument.groovy | 2 +- .../groovy/support/SubDocument.groovy | 2 +- .../integration/common/CustomFunctions.java | 78 +++++++++++++++++++ .../jvm/integration/postgresql/CustomIT.java | 70 +++++++++++++++++ .../java/jvm/integration/sqlite/CustomIT.java | 70 +++++++++++++++++ .../documents/java/support/JsonDocument.java | 4 + .../jvm/integration/postgresql/CustomIT.kt | 2 +- .../kotlin/jvm/integration/sqlite/CustomIT.kt | 2 +- .../integration/common/CustomFunctions.scala | 75 ++++++++++++++++++ .../jvm/integration/postgresql/CustomIT.scala | 46 +++++++++++ .../jvm/integration/sqlite/CustomIT.scala | 46 +++++++++++ 17 files changed, 586 insertions(+), 17 deletions(-) create mode 100644 src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/common/CustomFunctions.groovy create mode 100644 src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/postgresql/CustomIT.groovy create mode 100644 src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/sqlite/CustomIT.groovy create mode 100644 src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/common/CustomFunctions.java create mode 100644 src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/postgresql/CustomIT.java create mode 100644 src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/sqlite/CustomIT.java create mode 100644 src/jvm/src/test/scala/solutions/bitbadger/documents/scala/jvm/integration/common/CustomFunctions.scala create mode 100644 src/jvm/src/test/scala/solutions/bitbadger/documents/scala/jvm/integration/postgresql/CustomIT.scala create mode 100644 src/jvm/src/test/scala/solutions/bitbadger/documents/scala/jvm/integration/sqlite/CustomIT.scala diff --git a/src/jvm/src/main/kotlin/extensions/Connection.kt b/src/jvm/src/main/kotlin/extensions/Connection.kt index 9bdf51e..e539c22 100644 --- a/src/jvm/src/main/kotlin/extensions/Connection.kt +++ b/src/jvm/src/main/kotlin/extensions/Connection.kt @@ -56,6 +56,7 @@ fun Connection.customSingle( * @throws DocumentException If parameters are invalid */ @Throws(DocumentException::class) +@JvmOverloads fun Connection.customNonQuery(query: String, parameters: Collection> = listOf()) = Custom.nonQuery(query, parameters, this) diff --git a/src/jvm/src/main/kotlin/jvm/Results.kt b/src/jvm/src/main/kotlin/jvm/Results.kt index f670a67..0bea109 100644 --- a/src/jvm/src/main/kotlin/jvm/Results.kt +++ b/src/jvm/src/main/kotlin/jvm/Results.kt @@ -40,9 +40,8 @@ object Results { * @param mapFunc The mapping function from data reader to domain class instance * @param clazz The class of the document to be returned * @return A list of items from the query's result - * @throws DocumentException If there is a problem executing the query + * @throws DocumentException If there is a problem executing the query (unchecked) */ - @Throws(DocumentException::class) @JvmStatic fun toCustomList( stmt: PreparedStatement, clazz: Class, mapFunc: (ResultSet, Class) -> TDoc @@ -65,9 +64,8 @@ object Results { * @param rs A `ResultSet` set to the row with the count to retrieve * @param clazz The type parameter (ignored; this always returns `Long`) * @return The count from the row - * @throws DocumentException If the dialect has not been set + * @throws DocumentException If the dialect has not been set (unchecked) */ - @Throws(DocumentException::class) @JvmStatic fun toCount(rs: ResultSet, clazz: Class<*>) = when (Configuration.dialect()) { @@ -81,9 +79,8 @@ object Results { * @param rs A `ResultSet` set to the row with the true/false value to retrieve * @param clazz The type parameter (ignored; this always returns `Boolean`) * @return The true/false value from the row - * @throws DocumentException If the dialect has not been set + * @throws DocumentException If the dialect has not been set (unchecked) */ - @Throws(DocumentException::class) @JvmStatic fun toExists(rs: ResultSet, clazz: Class<*>) = when (Configuration.dialect()) { diff --git a/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/common/CustomFunctions.groovy b/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/common/CustomFunctions.groovy new file mode 100644 index 0000000..7147a8c --- /dev/null +++ b/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/common/CustomFunctions.groovy @@ -0,0 +1,72 @@ +package solutions.bitbadger.documents.groovy.jvm.integration.common + +import solutions.bitbadger.documents.Configuration +import solutions.bitbadger.documents.Field +import solutions.bitbadger.documents.Parameter +import solutions.bitbadger.documents.ParameterType +import solutions.bitbadger.documents.groovy.support.JsonDocument +import solutions.bitbadger.documents.jvm.Results +import solutions.bitbadger.documents.query.CountQuery +import solutions.bitbadger.documents.query.DeleteQuery +import solutions.bitbadger.documents.query.FindQuery +import solutions.bitbadger.documents.support.ThrowawayDatabase + +import static org.junit.jupiter.api.Assertions.* +import static solutions.bitbadger.documents.extensions.ConnExt.* +import static solutions.bitbadger.documents.support.TypesKt.TEST_TABLE + +class CustomFunctions { + + static void listEmpty(ThrowawayDatabase db) { + JsonDocument.load(db) + deleteByFields(db.conn, TEST_TABLE, List.of(Field.exists(Configuration.idField))) + def result = customList(db.conn, FindQuery.all(TEST_TABLE), List.of(), JsonDocument.class, Results.&fromData) + assertEquals(0, result.size(), "There should have been no results") + } + + static void listAll(ThrowawayDatabase db) { + JsonDocument.load(db) + def result = customList(db.conn, FindQuery.all(TEST_TABLE), List.of(), JsonDocument.class, Results.&fromData) + assertEquals(5, result.size(), "There should have been 5 results") + } + + static void singleNone(ThrowawayDatabase db) { + assertNull(customSingle(db.conn, FindQuery.all(TEST_TABLE), List.of(), JsonDocument.class, Results.&fromData), + "There should not have been a document returned") + + } + + static void singleOne(ThrowawayDatabase db) { + JsonDocument.load(db) + assertNotNull( + customSingle(db.conn, FindQuery.all(TEST_TABLE), List.of(), JsonDocument.class, Results.&fromData), + "There should not have been a document returned") + } + + static void nonQueryChanges(ThrowawayDatabase db) { + JsonDocument.load(db) + assertEquals(5L, customScalar(db.conn, CountQuery.all(TEST_TABLE), List.of(), Long.class, Results.&toCount), + "There should have been 5 documents in the table") + customNonQuery(db.conn, "DELETE FROM $TEST_TABLE") + assertEquals(0L, customScalar(db.conn, CountQuery.all(TEST_TABLE), List.of(), Long.class, Results.&toCount), + "There should have been no documents in the table") + } + + static void nonQueryNoChanges(ThrowawayDatabase db) { + JsonDocument.load(db) + assertEquals(5L, customScalar(db.conn, CountQuery.all(TEST_TABLE), List.of(), Long.class, Results.&toCount), + "There should have been 5 documents in the table") + customNonQuery(db.conn, DeleteQuery.byId(TEST_TABLE, "eighty-two"), + List.of(new Parameter(":id", ParameterType.STRING, "eighty-two"))) + assertEquals(5L, customScalar(db.conn, CountQuery.all(TEST_TABLE), List.of(), Long.class, Results.&toCount), + "There should still have been 5 documents in the table") + } + + static void scalar(ThrowawayDatabase db) { + JsonDocument.load(db) + assertEquals(3L, + customScalar(db.conn, "SELECT 3 AS it FROM $TEST_TABLE LIMIT 1", List.of(), Long.class, + Results.&toCount), + "The number 3 should have been returned") + } +} diff --git a/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/postgresql/CountIT.groovy b/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/postgresql/CountIT.groovy index 49ad2fa..0763644 100644 --- a/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/postgresql/CountIT.groovy +++ b/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/postgresql/CountIT.groovy @@ -14,42 +14,42 @@ class CountIT { @Test @DisplayName("all counts all documents") void all() { - new PgDB().withCloseable { CountFunctions.all(it) } + new PgDB().withCloseable(CountFunctions.&all) } @Test @DisplayName("byFields counts documents by a numeric value") void byFieldsNumeric() { - new PgDB().withCloseable { CountFunctions.byFieldsNumeric(it) } + new PgDB().withCloseable(CountFunctions.&byFieldsNumeric) } @Test @DisplayName("byFields counts documents by a alphanumeric value") void byFieldsAlpha() { - new PgDB().withCloseable { CountFunctions.byFieldsAlpha(it) } + new PgDB().withCloseable(CountFunctions.&byFieldsAlpha) } @Test @DisplayName("byContains counts documents when matches are found") void byContainsMatch() { - new PgDB().withCloseable { CountFunctions.byContainsMatch(it) } + new PgDB().withCloseable(CountFunctions.&byContainsMatch) } @Test @DisplayName("byContains counts documents when no matches are found") void byContainsNoMatch() { - new PgDB().withCloseable { CountFunctions.byContainsNoMatch(it) } + new PgDB().withCloseable(CountFunctions.&byContainsNoMatch) } @Test @DisplayName("byJsonPath counts documents when matches are found") void byJsonPathMatch() { - new PgDB().withCloseable { CountFunctions.byJsonPathMatch(it) } + new PgDB().withCloseable(CountFunctions.&byJsonPathMatch) } @Test @DisplayName("byJsonPath counts documents when no matches are found") void byJsonPathNoMatch() { - new PgDB().withCloseable { CountFunctions.byJsonPathNoMatch(it) } + new PgDB().withCloseable(CountFunctions.&byJsonPathNoMatch) } } diff --git a/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/postgresql/CustomIT.groovy b/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/postgresql/CustomIT.groovy new file mode 100644 index 0000000..2250f01 --- /dev/null +++ b/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/postgresql/CustomIT.groovy @@ -0,0 +1,55 @@ +package solutions.bitbadger.documents.groovy.jvm.integration.postgresql + +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import solutions.bitbadger.documents.groovy.jvm.integration.common.CustomFunctions +import solutions.bitbadger.documents.jvm.integration.postgresql.PgDB + +/** + * PostgreSQL integration tests for the `Custom` object / `custom*` connection extension functions + */ +@DisplayName("JVM | Groovy | PostgreSQL: Custom") +class CustomIT { + + @Test + @DisplayName("list succeeds with empty list") + void listEmpty() { + new PgDB().withCloseable(CustomFunctions.&listEmpty) + } + + @Test + @DisplayName("list succeeds with a non-empty list") + void listAll() { + new PgDB().withCloseable(CustomFunctions.&listAll) + } + + @Test + @DisplayName("single succeeds when document not found") + void singleNone() { + new PgDB().withCloseable(CustomFunctions.&singleNone) + } + + @Test + @DisplayName("single succeeds when a document is found") + void singleOne() { + new PgDB().withCloseable(CustomFunctions.&singleOne) + } + + @Test + @DisplayName("nonQuery makes changes") + void nonQueryChanges() { + new PgDB().withCloseable(CustomFunctions.&nonQueryChanges) + } + + @Test + @DisplayName("nonQuery makes no changes when where clause matches nothing") + void nonQueryNoChanges() { + new PgDB().withCloseable(CustomFunctions.&nonQueryNoChanges) + } + + @Test + @DisplayName("scalar succeeds") + void scalar() { + new PgDB().withCloseable(CustomFunctions.&scalar) + } +} diff --git a/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/sqlite/CustomIT.groovy b/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/sqlite/CustomIT.groovy new file mode 100644 index 0000000..8c3d155 --- /dev/null +++ b/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/jvm/integration/sqlite/CustomIT.groovy @@ -0,0 +1,55 @@ +package solutions.bitbadger.documents.groovy.jvm.integration.sqlite + +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import solutions.bitbadger.documents.groovy.jvm.integration.common.CustomFunctions +import solutions.bitbadger.documents.jvm.integration.sqlite.SQLiteDB + +/** + * SQLite integration tests for the `Custom` object / `custom*` connection extension functions + */ +@DisplayName("JVM | Groovy | SQLite: Custom") +class CustomIT { + + @Test + @DisplayName("list succeeds with empty list") + void listEmpty() { + new SQLiteDB().withCloseable(CustomFunctions.&listEmpty) + } + + @Test + @DisplayName("list succeeds with a non-empty list") + void listAll() { + new SQLiteDB().withCloseable(CustomFunctions.&listAll) + } + + @Test + @DisplayName("single succeeds when document not found") + void singleNone() { + new SQLiteDB().withCloseable(CustomFunctions.&singleNone) + } + + @Test + @DisplayName("single succeeds when a document is found") + void singleOne() { + new SQLiteDB().withCloseable(CustomFunctions.&singleOne) + } + + @Test + @DisplayName("nonQuery makes changes") + void nonQueryChanges() { + new SQLiteDB().withCloseable(CustomFunctions.&nonQueryChanges) + } + + @Test + @DisplayName("nonQuery makes no changes when where clause matches nothing") + void nonQueryNoChanges() { + new SQLiteDB().withCloseable(CustomFunctions.&nonQueryNoChanges) + } + + @Test + @DisplayName("scalar succeeds") + void scalar() { + new SQLiteDB().withCloseable(CustomFunctions.&scalar) + } +} diff --git a/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/support/JsonDocument.groovy b/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/support/JsonDocument.groovy index 4d94e97..78ba92e 100644 --- a/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/support/JsonDocument.groovy +++ b/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/support/JsonDocument.groovy @@ -11,7 +11,7 @@ class JsonDocument { int numValue SubDocument sub - JsonDocument(String id, String value = "", int numValue = 0, SubDocument sub = null) { + JsonDocument(String id = null, String value = "", int numValue = 0, SubDocument sub = null) { this.id = id this.value = value this.numValue = numValue diff --git a/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/support/SubDocument.groovy b/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/support/SubDocument.groovy index c2efe4d..744e498 100644 --- a/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/support/SubDocument.groovy +++ b/src/jvm/src/test/groovy/solutions/bitbadger/documents/groovy/support/SubDocument.groovy @@ -4,7 +4,7 @@ class SubDocument { String foo String bar - SubDocument(String foo, String bar) { + SubDocument(String foo = "", String bar = "") { this.foo = foo this.bar = bar } diff --git a/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/common/CustomFunctions.java b/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/common/CustomFunctions.java new file mode 100644 index 0000000..a1bdfe9 --- /dev/null +++ b/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/common/CustomFunctions.java @@ -0,0 +1,78 @@ +package solutions.bitbadger.documents.java.jvm.integration.common; + +import solutions.bitbadger.documents.*; +import solutions.bitbadger.documents.java.support.JsonDocument; +import solutions.bitbadger.documents.jvm.Results; +import solutions.bitbadger.documents.query.CountQuery; +import solutions.bitbadger.documents.query.DeleteQuery; +import solutions.bitbadger.documents.query.FindQuery; +import solutions.bitbadger.documents.support.ThrowawayDatabase; + +import java.util.Collection; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static solutions.bitbadger.documents.extensions.ConnExt.*; +import static solutions.bitbadger.documents.support.TypesKt.TEST_TABLE; + +final public class CustomFunctions { + + public static void listEmpty(ThrowawayDatabase db) throws DocumentException { + JsonDocument.load(db); + deleteByFields(db.getConn(), TEST_TABLE, List.of(Field.exists(Configuration.idField))); + Collection result = + customList(db.getConn(), FindQuery.all(TEST_TABLE), List.of(), JsonDocument.class, Results::fromData); + assertEquals(0, result.size(), "There should have been no results"); + } + + public static void listAll(ThrowawayDatabase db) throws DocumentException { + JsonDocument.load(db); + Collection result = + customList(db.getConn(), FindQuery.all(TEST_TABLE), List.of(), JsonDocument.class, Results::fromData); + assertEquals(5, result.size(), "There should have been 5 results"); + } + + public static void singleNone(ThrowawayDatabase db) throws DocumentException { + assertNull( + customSingle(db.getConn(), FindQuery.all(TEST_TABLE), List.of(), JsonDocument.class, Results::fromData), + "There should not have been a document returned"); + } + + public static void singleOne(ThrowawayDatabase db) throws DocumentException { + JsonDocument.load(db); + assertNotNull( + customSingle(db.getConn(), FindQuery.all(TEST_TABLE), List.of(), JsonDocument.class, Results::fromData), + "There should not have been a document returned"); + } + + public static void nonQueryChanges(ThrowawayDatabase db) throws DocumentException { + JsonDocument.load(db); + assertEquals(5L, + customScalar(db.getConn(), CountQuery.all(TEST_TABLE), List.of(), Long.class, Results::toCount), + "There should have been 5 documents in the table"); + customNonQuery(db.getConn(), String.format("DELETE FROM %s", TEST_TABLE)); + assertEquals(0L, + customScalar(db.getConn(), CountQuery.all(TEST_TABLE), List.of(), Long.class, Results::toCount), + "There should have been no documents in the table"); + } + + public static void nonQueryNoChanges(ThrowawayDatabase db) throws DocumentException { + JsonDocument.load(db); + assertEquals(5L, + customScalar(db.getConn(), CountQuery.all(TEST_TABLE), List.of(), Long.class, Results::toCount), + "There should have been 5 documents in the table"); + customNonQuery(db.getConn(), DeleteQuery.byId(TEST_TABLE, "eighty-two"), + List.of(new Parameter<>(":id", ParameterType.STRING, "eighty-two"))); + assertEquals(5L, + customScalar(db.getConn(), CountQuery.all(TEST_TABLE), List.of(), Long.class, Results::toCount), + "There should still have been 5 documents in the table"); + } + + public static void scalar(ThrowawayDatabase db) throws DocumentException { + JsonDocument.load(db); + assertEquals(3L, + customScalar(db.getConn(), String.format("SELECT 3 AS it FROM %s LIMIT 1", TEST_TABLE), List.of(), + Long.class, Results::toCount), + "The number 3 should have been returned"); + } +} diff --git a/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/postgresql/CustomIT.java b/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/postgresql/CustomIT.java new file mode 100644 index 0000000..3396255 --- /dev/null +++ b/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/postgresql/CustomIT.java @@ -0,0 +1,70 @@ +package solutions.bitbadger.documents.java.jvm.integration.postgresql; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import solutions.bitbadger.documents.DocumentException; +import solutions.bitbadger.documents.jvm.integration.postgresql.PgDB; +import solutions.bitbadger.documents.java.jvm.integration.common.CustomFunctions; + +/** + * PostgreSQL integration tests for the `Custom` object / `custom*` connection extension functions + */ +@DisplayName("JVM | Java | PostgreSQL: Custom") +final public class CustomIT { + + @Test + @DisplayName("list succeeds with empty list") + public void listEmpty() throws DocumentException { + try (PgDB db = new PgDB()) { + CustomFunctions.listEmpty(db); + } + } + + @Test + @DisplayName("list succeeds with a non-empty list") + public void listAll() throws DocumentException { + try (PgDB db = new PgDB()) { + CustomFunctions.listAll(db); + } + } + + @Test + @DisplayName("single succeeds when document not found") + public void singleNone() throws DocumentException { + try (PgDB db = new PgDB()) { + CustomFunctions.singleNone(db); + } + } + + @Test + @DisplayName("single succeeds when a document is found") + public void singleOne() throws DocumentException { + try (PgDB db = new PgDB()) { + CustomFunctions.singleOne(db); + } + } + + @Test + @DisplayName("nonQuery makes changes") + public void nonQueryChanges() throws DocumentException { + try (PgDB db = new PgDB()) { + CustomFunctions.nonQueryChanges(db); + } + } + + @Test + @DisplayName("nonQuery makes no changes when where clause matches nothing") + public void nonQueryNoChanges() throws DocumentException { + try (PgDB db = new PgDB()) { + CustomFunctions.nonQueryNoChanges(db); + } + } + + @Test + @DisplayName("scalar succeeds") + public void scalar() throws DocumentException { + try (PgDB db = new PgDB()) { + CustomFunctions.scalar(db); + } + } +} diff --git a/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/sqlite/CustomIT.java b/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/sqlite/CustomIT.java new file mode 100644 index 0000000..76acab9 --- /dev/null +++ b/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/sqlite/CustomIT.java @@ -0,0 +1,70 @@ +package solutions.bitbadger.documents.java.jvm.integration.sqlite; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import solutions.bitbadger.documents.DocumentException; +import solutions.bitbadger.documents.java.jvm.integration.common.CustomFunctions; +import solutions.bitbadger.documents.jvm.integration.sqlite.SQLiteDB; + +/** + * SQLite integration tests for the `Custom` object / `custom*` connection extension functions + */ +@DisplayName("JVM | Java | SQLite: Custom") +final public class CustomIT { + + @Test + @DisplayName("list succeeds with empty list") + public void listEmpty() throws DocumentException { + try (SQLiteDB db = new SQLiteDB()) { + CustomFunctions.listEmpty(db); + } + } + + @Test + @DisplayName("list succeeds with a non-empty list") + public void listAll() throws DocumentException { + try (SQLiteDB db = new SQLiteDB()) { + CustomFunctions.listAll(db); + } + } + + @Test + @DisplayName("single succeeds when document not found") + public void singleNone() throws DocumentException { + try (SQLiteDB db = new SQLiteDB()) { + CustomFunctions.singleNone(db); + } + } + + @Test + @DisplayName("single succeeds when a document is found") + public void singleOne() throws DocumentException { + try (SQLiteDB db = new SQLiteDB()) { + CustomFunctions.singleOne(db); + } + } + + @Test + @DisplayName("nonQuery makes changes") + public void nonQueryChanges() throws DocumentException { + try (SQLiteDB db = new SQLiteDB()) { + CustomFunctions.nonQueryChanges(db); + } + } + + @Test + @DisplayName("nonQuery makes no changes when where clause matches nothing") + public void nonQueryNoChanges() throws DocumentException { + try (SQLiteDB db = new SQLiteDB()) { + CustomFunctions.nonQueryNoChanges(db); + } + } + + @Test + @DisplayName("scalar succeeds") + public void scalar() throws DocumentException { + try (SQLiteDB db = new SQLiteDB()) { + CustomFunctions.scalar(db); + } + } +} diff --git a/src/jvm/src/test/java/solutions/bitbadger/documents/java/support/JsonDocument.java b/src/jvm/src/test/java/solutions/bitbadger/documents/java/support/JsonDocument.java index 8b118cc..ec6e639 100644 --- a/src/jvm/src/test/java/solutions/bitbadger/documents/java/support/JsonDocument.java +++ b/src/jvm/src/test/java/solutions/bitbadger/documents/java/support/JsonDocument.java @@ -62,6 +62,10 @@ public class JsonDocument { public JsonDocument(String id) { this(id, "", 0, null); } + + public JsonDocument() { + this(null); + } private static final List testDocuments = List.of( new JsonDocument("one", "FIRST!", 0), diff --git a/src/jvm/src/test/kotlin/jvm/integration/postgresql/CustomIT.kt b/src/jvm/src/test/kotlin/jvm/integration/postgresql/CustomIT.kt index a8ea10e..25272f1 100644 --- a/src/jvm/src/test/kotlin/jvm/integration/postgresql/CustomIT.kt +++ b/src/jvm/src/test/kotlin/jvm/integration/postgresql/CustomIT.kt @@ -8,7 +8,7 @@ import kotlin.test.Test /** * PostgreSQL integration tests for the `Custom` object / `custom*` connection extension functions */ -@DisplayName("Java | Kotlin | PostgreSQL: Custom") +@DisplayName("JVM | Kotlin | PostgreSQL: Custom") class CustomIT { @Test diff --git a/src/jvm/src/test/kotlin/jvm/integration/sqlite/CustomIT.kt b/src/jvm/src/test/kotlin/jvm/integration/sqlite/CustomIT.kt index 5d9b3dc..03ef8ee 100644 --- a/src/jvm/src/test/kotlin/jvm/integration/sqlite/CustomIT.kt +++ b/src/jvm/src/test/kotlin/jvm/integration/sqlite/CustomIT.kt @@ -7,7 +7,7 @@ import kotlin.test.Test /** * SQLite integration tests for the `Custom` object / `custom*` connection extension functions */ -@DisplayName("Java | Kotlin | SQLite: Custom") +@DisplayName("JVM | Kotlin | SQLite: Custom") class CustomIT { @Test diff --git a/src/jvm/src/test/scala/solutions/bitbadger/documents/scala/jvm/integration/common/CustomFunctions.scala b/src/jvm/src/test/scala/solutions/bitbadger/documents/scala/jvm/integration/common/CustomFunctions.scala new file mode 100644 index 0000000..0d7e5a0 --- /dev/null +++ b/src/jvm/src/test/scala/solutions/bitbadger/documents/scala/jvm/integration/common/CustomFunctions.scala @@ -0,0 +1,75 @@ +package solutions.bitbadger.documents.scala.jvm.integration.common + +import org.junit.jupiter.api.Assertions.* +import solutions.bitbadger.documents.{Configuration, Field, Parameter, ParameterType} +import solutions.bitbadger.documents.extensions.ConnExt.* +import solutions.bitbadger.documents.jvm.Results +import solutions.bitbadger.documents.query.{CountQuery, DeleteQuery, FindQuery} +import solutions.bitbadger.documents.scala.support.JsonDocument +import solutions.bitbadger.documents.support.ThrowawayDatabase +import solutions.bitbadger.documents.support.TypesKt.TEST_TABLE + +import scala.annotation.nowarn +import scala.jdk.CollectionConverters.* + +object CustomFunctions { + + def listEmpty(db: ThrowawayDatabase): Unit = + JsonDocument.load(db) + deleteByFields(db.getConn, TEST_TABLE, (Field.exists(Configuration.idField) :: Nil).asJava) + @nowarn + val result = customList(db.getConn, FindQuery.all(TEST_TABLE), List().asJava, classOf[JsonDocument], + Results.fromData) + assertEquals(0, result.size, "There should have been no results") + + def listAll(db: ThrowawayDatabase): Unit = + JsonDocument.load(db) + @nowarn + val result = customList(db.getConn, FindQuery.all(TEST_TABLE), List().asJava, classOf[JsonDocument], + Results.fromData) + assertEquals(5, result.size, "There should have been 5 results") + + @nowarn + def singleNone(db: ThrowawayDatabase): Unit = + assertNull( + customSingle(db.getConn, FindQuery.all(TEST_TABLE), List().asJava, classOf[JsonDocument], Results.fromData), + "There should not have been a document returned") + + @nowarn + def singleOne(db: ThrowawayDatabase): Unit = + JsonDocument.load(db) + assertNotNull( + customSingle(db.getConn, FindQuery.all(TEST_TABLE), List().asJava, classOf[JsonDocument], Results.fromData), + "There should not have been a document returned") + + @nowarn + def nonQueryChanges(db: ThrowawayDatabase): Unit = + JsonDocument.load(db) + assertEquals(5L, + customScalar(db.getConn, CountQuery.all(TEST_TABLE), List().asJava, classOf[Long], Results.toCount), + "There should have been 5 documents in the table") + customNonQuery(db.getConn, s"DELETE FROM $TEST_TABLE") + assertEquals(0L, + customScalar(db.getConn, CountQuery.all(TEST_TABLE), List().asJava, classOf[Long], Results.toCount), + "There should have been no documents in the table") + + @nowarn + def nonQueryNoChanges(db: ThrowawayDatabase): Unit = + JsonDocument.load(db) + assertEquals(5L, + customScalar(db.getConn, CountQuery.all(TEST_TABLE), List().asJava, classOf[Long], Results.toCount), + "There should have been 5 documents in the table") + customNonQuery(db.getConn, DeleteQuery.byId(TEST_TABLE, "eighty-two"), + (Parameter(":id", ParameterType.STRING, "eighty-two") :: Nil).asJava) + assertEquals(5L, + customScalar(db.getConn, CountQuery.all(TEST_TABLE), List().asJava, classOf[Long], Results.toCount), + "There should still have been 5 documents in the table") + + @nowarn + def scalar(db: ThrowawayDatabase): Unit = + JsonDocument.load(db) + assertEquals(3L, + customScalar(db.getConn, s"SELECT 3 AS it FROM $TEST_TABLE LIMIT 1", List().asJava, classOf[Long], + Results.toCount), + "The number 3 should have been returned") +} diff --git a/src/jvm/src/test/scala/solutions/bitbadger/documents/scala/jvm/integration/postgresql/CustomIT.scala b/src/jvm/src/test/scala/solutions/bitbadger/documents/scala/jvm/integration/postgresql/CustomIT.scala new file mode 100644 index 0000000..4e74f7d --- /dev/null +++ b/src/jvm/src/test/scala/solutions/bitbadger/documents/scala/jvm/integration/postgresql/CustomIT.scala @@ -0,0 +1,46 @@ +package solutions.bitbadger.documents.scala.jvm.integration.postgresql + +import org.junit.jupiter.api.{DisplayName, Test} +import solutions.bitbadger.documents.jvm.integration.postgresql.PgDB +import solutions.bitbadger.documents.scala.jvm.integration.common.CustomFunctions + +import scala.util.Using + +@DisplayName("JVM | Scala | PostgreSQL: Custom") +class CustomIT { + + @Test + @DisplayName("list succeeds with empty list") + def listEmpty(): Unit = + Using(PgDB()) { db => CustomFunctions.listEmpty(db) } + + @Test + @DisplayName("list succeeds with a non-empty list") + def listAll(): Unit = + Using(PgDB()) { db => CustomFunctions.listAll(db) } + + @Test + @DisplayName("single succeeds when document not found") + def singleNone(): Unit = + Using(PgDB()) { db => CustomFunctions.singleNone(db) } + + @Test + @DisplayName("single succeeds when a document is found") + def singleOne(): Unit = + Using(PgDB()) { db => CustomFunctions.singleOne(db) } + + @Test + @DisplayName("nonQuery makes changes") + def nonQueryChanges(): Unit = + Using(PgDB()) { db => CustomFunctions.nonQueryChanges(db) } + + @Test + @DisplayName("nonQuery makes no changes when where clause matches nothing") + def nonQueryNoChanges(): Unit = + Using(PgDB()) { db => CustomFunctions.nonQueryNoChanges(db) } + + @Test + @DisplayName("scalar succeeds") + def scalar(): Unit = + Using(PgDB()) { db => CustomFunctions.scalar(db) } +} diff --git a/src/jvm/src/test/scala/solutions/bitbadger/documents/scala/jvm/integration/sqlite/CustomIT.scala b/src/jvm/src/test/scala/solutions/bitbadger/documents/scala/jvm/integration/sqlite/CustomIT.scala new file mode 100644 index 0000000..36c08ab --- /dev/null +++ b/src/jvm/src/test/scala/solutions/bitbadger/documents/scala/jvm/integration/sqlite/CustomIT.scala @@ -0,0 +1,46 @@ +package solutions.bitbadger.documents.scala.jvm.integration.sqlite + +import org.junit.jupiter.api.{DisplayName, Test} +import solutions.bitbadger.documents.jvm.integration.sqlite.SQLiteDB +import solutions.bitbadger.documents.scala.jvm.integration.common.CustomFunctions + +import scala.util.Using + +@DisplayName("JVM | Scala | SQLite: Custom") +class CustomIT { + + @Test + @DisplayName("list succeeds with empty list") + def listEmpty(): Unit = + Using(SQLiteDB()) { db => CustomFunctions.listEmpty(db) } + + @Test + @DisplayName("list succeeds with a non-empty list") + def listAll(): Unit = + Using(SQLiteDB()) { db => CustomFunctions.listAll(db) } + + @Test + @DisplayName("single succeeds when document not found") + def singleNone(): Unit = + Using(SQLiteDB()) { db => CustomFunctions.singleNone(db) } + + @Test + @DisplayName("single succeeds when a document is found") + def singleOne(): Unit = + Using(SQLiteDB()) { db => CustomFunctions.singleOne(db) } + + @Test + @DisplayName("nonQuery makes changes") + def nonQueryChanges(): Unit = + Using(SQLiteDB()) { db => CustomFunctions.nonQueryChanges(db) } + + @Test + @DisplayName("nonQuery makes no changes when where clause matches nothing") + def nonQueryNoChanges(): Unit = + Using(SQLiteDB()) { db => CustomFunctions.nonQueryNoChanges(db) } + + @Test + @DisplayName("scalar succeeds") + def scalar(): Unit = + Using(SQLiteDB()) { db => CustomFunctions.scalar(db) } +}