add tests for cruds

This commit is contained in:
2024-08-09 19:22:32 +06:00
parent 8d86f29325
commit b0569f8421
21 changed files with 585 additions and 9 deletions

View File

@@ -14,5 +14,12 @@ kotlin {
api internalProject("micro_utils.pagination.exposed")
}
}
jvmTest {
dependencies {
api libs.sqlite
api libs.jb.exposed.jdbc
api project(":micro_utils.repos.common.tests")
}
}
}
}

View File

@@ -52,9 +52,9 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
*
* @return In case when id for the model has been created new [IdType] should be returned
*/
protected open fun createAndInsertId(value: InputValueType, it: InsertStatement<Number>): IdType? = null
protected open fun createAndInsertId(value: InputValueType, it: UpdateBuilder<Int>): IdType? = null
protected open fun insert(value: InputValueType, it: InsertStatement<Number>) {
protected open fun insert(value: InputValueType, it: UpdateBuilder<Int>) {
val id = createAndInsertId(value, it)
update(id, value, it as UpdateBuilder<Int>)
}

View File

@@ -23,11 +23,11 @@ abstract class AbstractExposedKeyValueRepo<Key, Value>(
override val onValueRemoved: Flow<Key> = _onValueRemoved.asSharedFlow()
protected abstract fun update(k: Key, v: Value, it: UpdateBuilder<Int>)
protected abstract fun insertKey(k: Key, v: Value, it: InsertStatement<Number>)
protected abstract fun insertKey(k: Key, v: Value, it: UpdateBuilder<Int>)
protected open fun insert(k: Key, v: Value, it: InsertStatement<Number>) {
protected open fun insert(k: Key, v: Value, it: UpdateBuilder<Int>) {
insertKey(k, v, it)
update(k, v, it as UpdateBuilder<Int>)
update(k, v, it)
}
override suspend fun set(toSet: Map<Key, Value>) {

View File

@@ -5,6 +5,7 @@ import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.*
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.statements.InsertStatement
import org.jetbrains.exposed.sql.statements.UpdateBuilder
import org.jetbrains.exposed.sql.transactions.transaction
abstract class AbstractExposedKeyValuesRepo<Key, Value>(
@@ -26,7 +27,7 @@ abstract class AbstractExposedKeyValuesRepo<Key, Value>(
override val onDataCleared: Flow<Key>
get() = _onDataCleared.asSharedFlow()
protected abstract fun insert(k: Key, v: Value, it: InsertStatement<Number>)
protected abstract fun insert(k: Key, v: Value, it: UpdateBuilder<Int>)
override suspend fun add(toAdd: Map<Key, List<Value>>) {
transaction(database) {
@@ -48,6 +49,28 @@ abstract class AbstractExposedKeyValuesRepo<Key, Value>(
}.forEach { _onNewValue.emit(it) }
}
override suspend fun set(toSet: Map<Key, List<Value>>) {
if (toSet.isEmpty()) return
val prepreparedData = toSet.flatMap { (k, vs) ->
vs.map { v ->
k to v
}
}
transaction(database) {
deleteWhere {
selectByIds(it, toSet.keys.toList())
}
batchInsert(
prepreparedData,
) { (k, v) ->
insert(k, v, this)
}.map {
it.asKey to it.asObject
}
}.forEach { _onNewValue.emit(it) }
}
override suspend fun remove(toRemove: Map<Key, List<Value>>) {
transaction(database) {
toRemove.keys.flatMap { k ->

View File

@@ -83,8 +83,8 @@ abstract class AbstractExposedReadKeyValuesRepo<Key, Value>(
}
}
override suspend fun getAll(k: Key, reverseLists: Boolean): List<Value> = transaction(database) {
val query = if (reverseLists) {
override suspend fun getAll(k: Key, reversed: Boolean): List<Value> = transaction(database) {
val query = if (reversed) {
selectAll().where { selectById(k) }.orderBy(keyColumn, SortOrder.DESC)
} else {
selectAll().where { selectById(k) }

View File

@@ -0,0 +1,21 @@
package full
import com.benasher44.uuid.uuid4
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.transactions.transactionManager
import org.sqlite.JDBC
import java.io.File
import java.sql.Connection
fun filename() = "${uuid4()}.local.sql".also {
val file = File(it)
file.createNewFile()
file.deleteOnExit()
}
fun createDatabase(filename: String) = Database.connect(
url = "jdbc:sqlite:$filename",
driver = JDBC::class.qualifiedName!!
).also {
it.transactionManager.defaultIsolationLevel = Connection.TRANSACTION_SERIALIZABLE
it.connector().close()
}

View File

@@ -0,0 +1,77 @@
package full
import CommonCRUDRepoTests
import com.benasher44.uuid.uuid4
import dev.inmo.micro_utils.repos.CRUDRepo
import dev.inmo.micro_utils.repos.create
import dev.inmo.micro_utils.repos.deleteById
import dev.inmo.micro_utils.repos.exposed.AbstractExposedCRUDRepo
import dev.inmo.micro_utils.repos.exposed.initTable
import korlibs.time.seconds
import kotlinx.coroutines.test.TestResult
import kotlinx.coroutines.test.runTest
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.ISqlExpressionBuilder
import org.jetbrains.exposed.sql.Op
import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.statements.InsertStatement
import org.jetbrains.exposed.sql.statements.UpdateBuilder
import java.io.File
import javax.xml.crypto.Data
import kotlin.test.*
class ExposedCRUDRepoTests : CommonCRUDRepoTests() {
class Repo(override val database: Database) : AbstractExposedCRUDRepo<CommonCRUDRepoTests.Registered, String, CommonCRUDRepoTests.New>() {
val idColumn = text("_id")
val dataColumn = text("data")
override val primaryKey: PrimaryKey = PrimaryKey(idColumn)
override val ResultRow.asId: String
get() = get(idColumn)
override val ResultRow.asObject: CommonCRUDRepoTests.Registered
get() = CommonCRUDRepoTests.Registered(
asId,
get(dataColumn)
)
override val selectById: ISqlExpressionBuilder.(String) -> Op<Boolean> = { idColumn.eq(it) }
init {
initTable()
}
override fun update(id: String?, value: CommonCRUDRepoTests.New, it: UpdateBuilder<Int>) {
it[idColumn] = id ?: uuid4().toString()
it[dataColumn] = value.data
}
override fun InsertStatement<Number>.asObject(value: CommonCRUDRepoTests.New): CommonCRUDRepoTests.Registered {
return CommonCRUDRepoTests.Registered(
get(idColumn),
get(dataColumn)
)
}
}
val filename = filename()
var database: Database? = null
override val repoCreator: suspend () -> CRUDRepo<Registered, String, New> = { Repo(database!!) }
@BeforeTest
fun beforeTest() {
database = createDatabase(filename)
}
@AfterTest
fun afterTest() {
database = null
File(filename).delete()
}
@Test
override fun creatingWorksProperly(): TestResult {
return super.creatingWorksProperly()
}
@Test
override fun removingWorksProperly(): TestResult {
return super.removingWorksProperly()
}
}

View File

@@ -0,0 +1,67 @@
package full
import CommonKeyValueRepoTests
import com.benasher44.uuid.uuid4
import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.exposed.initTable
import dev.inmo.micro_utils.repos.exposed.keyvalue.AbstractExposedKeyValueRepo
import korlibs.time.seconds
import kotlinx.coroutines.test.TestResult
import kotlinx.coroutines.test.runTest
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.statements.InsertStatement
import org.jetbrains.exposed.sql.statements.UpdateBuilder
import java.io.File
import kotlin.test.*
class ExposedKeyValueRepoTests : CommonKeyValueRepoTests() {
class Repo(override val database: Database) : AbstractExposedKeyValueRepo<String, String>(database) {
override val keyColumn = text("_id")
val dataColumn = text("data")
override val primaryKey: PrimaryKey = PrimaryKey(keyColumn)
override val ResultRow.asKey: String
get() = get(keyColumn)
override val selectByValue: ISqlExpressionBuilder.(String) -> Op<Boolean> = { dataColumn.eq(it) }
override val ResultRow.asObject: String
get() = get(dataColumn)
override val selectById: ISqlExpressionBuilder.(String) -> Op<Boolean> = { keyColumn.eq(it) }
init {
initTable()
}
override fun update(k: String, v: String, it: UpdateBuilder<Int>) {
it[keyColumn] = k
it[dataColumn] = v
}
override fun insertKey(k: String, v: String, it: UpdateBuilder<Int>) {
it[keyColumn] = k
}
}
val filename = filename()
var database: Database? = null
@BeforeTest
fun beforeTest() {
database = createDatabase(filename)
}
@AfterTest
fun afterTest() {
database = null
File(filename).delete()
}
override val repoCreator: suspend () -> KeyValueRepo<String, String> = { Repo(database!!) }
@Test
override fun creatingWorksProperly(): TestResult {
return super.creatingWorksProperly()
}
@Test
override fun unsettingWorksProperly(): TestResult {
return super.unsettingWorksProperly()
}
}

View File

@@ -0,0 +1,57 @@
package full
import CommonKeyValuesRepoTests
import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.exposed.initTable
import dev.inmo.micro_utils.repos.exposed.onetomany.AbstractExposedKeyValuesRepo
import kotlinx.coroutines.test.TestResult
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.ISqlExpressionBuilder
import org.jetbrains.exposed.sql.Op
import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.statements.UpdateBuilder
import java.io.File
import kotlin.test.*
class ExposedKeyValuesRepoTests : CommonKeyValuesRepoTests() {
override val testSequencesSize: Int = 100
class Repo(override val database: Database) : AbstractExposedKeyValuesRepo<String, String>(database) {
override val keyColumn = text("_id")
val dataColumn = text("data")
override val ResultRow.asKey: String
get() = get(keyColumn)
override val selectByValue: ISqlExpressionBuilder.(String) -> Op<Boolean> = { dataColumn.eq(it) }
override val ResultRow.asObject: String
get() = get(dataColumn)
override val selectById: ISqlExpressionBuilder.(String) -> Op<Boolean> = { keyColumn.eq(it) }
init {
initTable()
}
override fun insert(k: String, v: String, it: UpdateBuilder<Int>) {
it[keyColumn] = k
it[dataColumn] = v
}
}
val filename = filename()
var database: Database? = null
@BeforeTest
fun beforeTest() {
database = createDatabase(filename)
}
@AfterTest
fun afterTest() {
database = null
File(filename).delete()
}
override val repoCreator: suspend () -> KeyValuesRepo<String, String> = { Repo(database!!) }
@Test
override fun creatingWorksProperly(): TestResult {
super.creatingWorksProperly()
}
}