Skip to content

Commit

Permalink
add tests for cruds
Browse files Browse the repository at this point in the history
  • Loading branch information
InsanusMokrassar committed Aug 9, 2024
1 parent 8d86f29 commit b0569f8
Show file tree
Hide file tree
Showing 21 changed files with 585 additions and 9 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ publishing.sh

local.*
local/
**/*.local.*

.kotlin/
7 changes: 6 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ jb-compose = "1.7.0-alpha02"
jb-exposed = "0.53.0"
jb-dokka = "1.9.20"

sqlite = "3.46.0.1"

korlibs = "5.4.0"
uuid = "0.8.4"

Expand All @@ -21,7 +23,7 @@ koin = "3.5.6"

okio = "3.9.0"

ksp = "2.0.0-1.0.23"
ksp = "2.0.10-1.0.24"
kotlin-poet = "1.18.0"

versions = "0.51.0"
Expand Down Expand Up @@ -52,6 +54,7 @@ kt-serialization-cbor = { module = "org.jetbrains.kotlinx:kotlinx-serialization-
kt-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kt-coroutines" }
kt-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kt-coroutines" }
kt-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kt-coroutines" }
kt-coroutines-debug = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-debug", version.ref = "kt-coroutines" }


ktor-io = { module = "io.ktor:ktor-io", version.ref = "ktor" }
Expand Down Expand Up @@ -79,6 +82,8 @@ koin = { module = "io.insert-koin:koin-core", version.ref = "koin" }


jb-exposed = { module = "org.jetbrains.exposed:exposed-core", version.ref = "jb-exposed" }
jb-exposed-jdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "jb-exposed" }
sqlite = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite" }


android-coreKtx = { module = "androidx.core:core-ktx", version.ref = "android-coreKtx" }
Expand Down
69 changes: 69 additions & 0 deletions repos/common/tests/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
plugins {
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
id "com.android.library"
}

project.version = "$version"
project.group = "$group"

kotlin {
jvm {
compilations.main {
kotlinOptions {
jvmTarget = "17"
}
}
}
js (IR) {
browser()
nodejs()
}
androidTarget {
compilations.all {
kotlinOptions {
jvmTarget = "17"
}
}
}
linuxX64()
mingwX64()
linuxArm64()

sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib')
api libs.kt.serialization
api kotlin('test')
api kotlin('test-annotations-common')
api libs.kt.coroutines.test
api project(":micro_utils.repos.common")
}
}

jvmMain {
dependencies {
implementation kotlin('test-junit')
}
}
jsMain {
dependencies {
implementation kotlin('test-js')
}
}
nativeMain.dependsOn commonMain
linuxX64Main.dependsOn nativeMain
mingwX64Main.dependsOn nativeMain
linuxArm64Main.dependsOn nativeMain

androidMain.dependsOn jvmMain
}
}

apply from: "$defaultAndroidSettingsPresetPath"

java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
76 changes: 76 additions & 0 deletions repos/common/tests/src/commonMain/kotlin/CommonCRUDRepoTests.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
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 korlibs.time.seconds
import kotlinx.coroutines.test.runTest
import kotlin.test.*

abstract class CommonCRUDRepoTests : CommonRepoTests<CRUDRepo<CommonCRUDRepoTests.Registered, String, CommonCRUDRepoTests.New>>() {
data class New(
val data: String
)
data class Registered(
val id: String,
val data: String
)

open fun creatingWorksProperly() = runTest(timeout = 120.seconds) {
val crudRepo = repoCreator()
val testData = (0 until testSequencesSize).map {
("$it-" + uuid4().toString())
}
val updatedTestData = (0 until 1000).map {
("$it-" + uuid4().toString())
}

val registereds = testData.map {
val created = crudRepo.create(New(it)).first()
assertEquals(it, created.data)
assertEquals(crudRepo.getById(created.id), created)
created
}

crudRepo.getAll().forEach { (id, value) ->
assertTrue {
registereds.first {
it.id == id
} == value
}
}
val updatedRegistereds = registereds.mapIndexed { i, it ->
val updated = crudRepo.update(it.id, New(updatedTestData[i])) ?: error("Unable to update data for $it")
assertEquals(updatedTestData[i], updated.data)
assertEquals(crudRepo.getById(updated.id), updated)
updated
}
crudRepo.getAll().forEach { (id, value) ->
assertTrue {
updatedRegistereds.first {
it.id == id
} == value
}
}
}
@Test
open fun removingWorksProperly() = runTest {
val crudRepo = repoCreator()
val testData = (0 until testSequencesSize).map {
(it.toString() + uuid4().toString())
}
val registereds = crudRepo.create(testData.map { New(it) })

registereds.forEach {
val id = it.id
assertTrue {
crudRepo.getAll()[id] == it
}

crudRepo.deleteById(id)
assertFalse {
crudRepo.contains(id)
}
}
assertEquals(0, crudRepo.count())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import com.benasher44.uuid.uuid4
import dev.inmo.micro_utils.repos.*
import korlibs.time.seconds
import kotlinx.coroutines.test.runTest
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue

abstract class CommonKeyValueRepoTests : CommonRepoTests<KeyValueRepo<String, String>>() {
open fun creatingWorksProperly() = runTest(timeout = 120.seconds) {
val repo = repoCreator()
val testData = (0 until testSequencesSize).associate {
("$it-" + uuid4().toString()) to "$it-" + uuid4().toString()
}
val updatedTestData = testData.keys.associateWith {
"$it-" + uuid4().toString()
}

testData.forEach {
repo.set(it.key, it.value)
assertEquals(it.value, repo.get(it.key))
}

updatedTestData.forEach {
repo.set(it.key, it.value)
assertEquals(repo.get(it.key), it.value)
}
}
open fun unsettingWorksProperly() = runTest {
val repo = repoCreator()
val testData = (0 until testSequencesSize).associate {
(it.toString() + uuid4().toString()) to uuid4().toString()
}

repo.set(testData)

testData.forEach {
val id = it.key
assertTrue {
repo.getAll()[id] == it.value
}

repo.unset(id)
assertFalse {
repo.contains(id)
}
}
assertEquals(0, repo.count())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import com.benasher44.uuid.uuid4
import dev.inmo.micro_utils.repos.*
import korlibs.time.seconds
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runTest
import kotlin.test.*

abstract class CommonKeyValuesRepoTests : CommonRepoTests<KeyValuesRepo<String, String>>() {
open fun creatingWorksProperly() = runTest(timeout = 120.seconds) {
val repo = repoCreator()
val testData = (0 until testSequencesSize).associate {
("$it-" + uuid4().toString()) to (0 until 1000).map {
"$it-" + uuid4().toString()
}.sorted()
}
val updatedTestData = testData.keys.associateWith {
(0 until 1000).map {
"$it-" + uuid4().toString()
}.sorted()
}
val addedData = testData.keys.associateWith {
"$it-" + uuid4().toString()
}

updatedTestData.map {
launch {
repo.set(it.key, it.value)
assertContentEquals(it.value.sorted(), repo.getAll(it.key).sorted())
}
}.joinAll()

updatedTestData.map {
launch {
repo.set(it.key, it.value)
val all = repo.getAll(it.key)
assertContentEquals(it.value.sorted(), all.sorted())
}
}.joinAll()

addedData.forEach {
repo.add(it.key, it.value)
assertTrue(repo.contains(it.key, it.value))
}
}
}
6 changes: 6 additions & 0 deletions repos/common/tests/src/commonMain/kotlin/CommonRepoTests.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import dev.inmo.micro_utils.repos.CRUDRepo

abstract class CommonRepoTests<T> {
protected open val testSequencesSize = 1000
protected abstract val repoCreator: suspend () -> T
}
7 changes: 7 additions & 0 deletions repos/exposed/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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>)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>(
Expand All @@ -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) {
Expand All @@ -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 ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
Expand Down
Loading

0 comments on commit b0569f8

Please sign in to comment.