improve-tests #28

Merged
flecomte merged 28 commits from improve-tests into master 2021-07-20 02:24:22 +02:00
2 changed files with 104 additions and 5 deletions
Showing only changes of commit 6e9175d84f - Show all commits

View File

@@ -3,6 +3,8 @@ package fr.postgresjson.connexion
import com.fasterxml.jackson.core.type.TypeReference import com.fasterxml.jackson.core.type.TypeReference
import com.github.jasync.sql.db.Connection import com.github.jasync.sql.db.Connection
import com.github.jasync.sql.db.QueryResult import com.github.jasync.sql.db.QueryResult
import com.github.jasync.sql.db.ResultSet
import com.github.jasync.sql.db.general.ArrayRowData
import com.github.jasync.sql.db.pool.ConnectionPool import com.github.jasync.sql.db.pool.ConnectionPool
import com.github.jasync.sql.db.postgresql.PostgreSQLConnection import com.github.jasync.sql.db.postgresql.PostgreSQLConnection
import com.github.jasync.sql.db.postgresql.PostgreSQLConnectionBuilder import com.github.jasync.sql.db.postgresql.PostgreSQLConnectionBuilder
@@ -12,6 +14,7 @@ import fr.postgresjson.entity.Serializable
import fr.postgresjson.serializer.Serializer import fr.postgresjson.serializer.Serializer
import fr.postgresjson.utils.LoggerDelegate import fr.postgresjson.utils.LoggerDelegate
import org.slf4j.Logger import org.slf4j.Logger
import java.lang.ClassCastException
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
typealias SelectOneCallback<T> = QueryResult.(T?) -> Unit typealias SelectOneCallback<T> = QueryResult.(T?) -> Unit
@@ -142,8 +145,15 @@ class Connection(
} }
return line.run { return line.run {
val json = rows[0].getString(0) val firstLine = rows.firstOrNull() ?: queryError("The query has no return", sql, newValues)
val entities = if (json === null) { if (!(firstLine as ArrayRowData).mapping.keys.contains("total")) queryError("""The query not return the "total" column""", sql, newValues, rows)
val total = try {
firstLine.getInt("total") ?: queryError("The query return \"total\" must not be null", sql, newValues, rows)
} catch (e: ClassCastException) {
queryError("""Column "total" must be an integer""", sql, newValues, rows)
}
val json = firstLine.getString(0)
val entities = if (json == null) {
listOf<EntityI>() as List<R> listOf<EntityI>() as List<R>
} else { } else {
serializer.deserializeList(json, typeReference) serializer.deserializeList(json, typeReference)
@@ -152,7 +162,7 @@ class Connection(
entities, entities,
offset, offset,
limit, limit,
rows[0].getInt("total") ?: error("The query not return total") total
) )
}.also { }.also {
block(line, it) block(line, it)
@@ -201,7 +211,7 @@ class Connection(
val paramRegex = "(?<!:):([a-zA-Z0-9_-]+)".toRegex(RegexOption.IGNORE_CASE) val paramRegex = "(?<!:):([a-zA-Z0-9_-]+)".toRegex(RegexOption.IGNORE_CASE)
val newArgs = paramRegex.findAll(sql).map { match -> val newArgs = paramRegex.findAll(sql).map { match ->
val name = match.groups[1]!!.value val name = match.groups[1]!!.value
values[name] ?: values[name.trimStart('_')] ?: error("Parameter $name missing") values[name] ?: values[name.trimStart('_')] ?: queryError("Parameter $name missing", sql, values)
}.toList() }.toList()
var newSql = sql var newSql = sql
@@ -218,7 +228,7 @@ class Connection(
var i = 0 var i = 0
if (values.isNotEmpty()) { if (values.isNotEmpty()) {
val newSql = paramRegex.replace(sql) { val newSql = paramRegex.replace(sql) {
values[i] ?: error("Parameter $i missing") values[i] ?: queryError("Parameter $i missing", sql, values)
val valToReplace = values[i].toString() val valToReplace = values[i].toString()
++i ++i
"'$valToReplace'" "'$valToReplace'"
@@ -266,4 +276,40 @@ class Connection(
throw e throw e
} }
} }
class QueryError(msg: String) : Exception(msg)
private fun queryError(
msg: String,
sql: String,
parameters: List<Any?>,
result: ResultSet? = null
): Nothing = throw QueryError(
"""
|$msg
|
|${parameters.joinToString(", ") { it.toString() }.prependIndent(" > ")}
|${sql.prependIndent(" > ")}
|${result?.let { "-----" }?.prependIndent(" > ")}
|${result?.columnNames()?.joinToString(" | ")?.prependIndent(" > ")}
|${result?.map { it.joinToString(" | ") }?.joinToString("\n")?.prependIndent(" > ")}
""".trimMargin().trim(' ', '\n')
)
private fun queryError(
msg: String,
sql: String,
parameters: Map<String, Any?>,
result: ResultSet? = null
): Nothing = throw QueryError(
"""
|$msg
|
|${parameters.map { it.key + ": " + it.value }.joinToString(", ").prependIndent(" > ")}
|${sql.prependIndent(" > ")}
|${result?.let { "-----" }?.prependIndent(" > ")}
|${result?.columnNames()?.joinToString(" | ")?.prependIndent(" > ")}
|${result?.map { it.joinToString(" | ") }?.joinToString("\n")?.prependIndent(" > ")}
""".trimMargin().trim(' ')
)
} }

View File

@@ -1,6 +1,7 @@
package fr.postgresjson package fr.postgresjson
import com.fasterxml.jackson.core.type.TypeReference import com.fasterxml.jackson.core.type.TypeReference
import fr.postgresjson.connexion.Connection.QueryError
import fr.postgresjson.connexion.Paginated import fr.postgresjson.connexion.Paginated
import fr.postgresjson.connexion.select import fr.postgresjson.connexion.select
import fr.postgresjson.connexion.selectOne import fr.postgresjson.connexion.selectOne
@@ -14,6 +15,7 @@ import org.junit.Assert.assertTrue
import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.assertThrows
import java.util.UUID import java.util.UUID
import kotlin.test.assertNull import kotlin.test.assertNull
@@ -197,6 +199,57 @@ class ConnectionTest : TestAbstract() {
assertEquals(result.offset, 0) assertEquals(result.offset, 0)
} }
@Test
fun `test select paginated without result`() {
val result: Paginated<ObjTest> = connection.select(
"""
SELECT null,
10 as total
LIMIT :limit
OFFSET :offset
""".trimIndent(),
1,
2,
object : TypeReference<List<ObjTest>>() {}
)
assertNotNull(result)
assertTrue(result.result.isEmpty())
assertEquals(0, result.result.size)
assertEquals(result.total, 10)
assertEquals(result.offset, 0)
}
@Test
fun `test select paginated without total`() {
val exception = assertThrows<QueryError> {
val result: Paginated<ObjTest> = connection.select(
"""
SELECT null
LIMIT :limit
OFFSET :offset
""".trimIndent(),
1,
2,
object : TypeReference<List<ObjTest>>() {}
)
}
assertEquals(
"""
|The query not return the "total" column
|
| > offset: 0, limit: 2
| > SELECT null
| > LIMIT :limit
| > OFFSET :offset
| > -----
| > ?column?
| > null
""".trimMargin(),
exception.message
)
}
@Test @Test
fun `selectOne with extra parameters`() { fun `selectOne with extra parameters`() {
val params: Map<String, Any?> = mapOf( val params: Map<String, Any?> = mapOf(