Skip to content

Commit 924485c

Browse files
committed
test(model-server): restructured repository removal tests
1 parent e6907b7 commit 924485c

File tree

7 files changed

+220
-108
lines changed

7 files changed

+220
-108
lines changed

gradle/libs.versions.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ cucumber-java = { group = "io.cucumber", name = "cucumber-java", version = "7.18
106106
junit = { group = "junit", name = "junit", version = "4.13.2" }
107107
xmlunit-core = { group = "org.xmlunit", name = "xmlunit-core", version = "2.10.0"}
108108
jsoup = { group = "org.jsoup", name = "jsoup", version = "1.17.2" }
109+
mockk = { group = "io.mockk", name = "mockk", version = "1.13.11"}
109110

110111
apache-cxf-sse = { group = "org.apache.cxf", name = "cxf-rt-rs-sse", version.ref = "apacheCxf" }
111112
apache-cxf-client = { group = "org.apache.cxf", name = "cxf-rt-rs-client", version.ref = "apacheCxf" }

model-server-test/build.gradle.kts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ plugins {
66
dependencies {
77
testImplementation(kotlin("test"))
88
testImplementation(project(":model-server"))
9-
testImplementation(project(":model-server").dependencyProject.sourceSets.test.get().runtimeClasspath)
109
}
1110

1211
tasks.test {
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright (c) 2024.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
import org.junit.jupiter.api.AfterAll
17+
import org.junit.jupiter.api.Test
18+
import org.junit.jupiter.api.assertDoesNotThrow
19+
import org.modelix.model.lazy.RepositoryId
20+
import org.modelix.model.server.store.IgniteStoreClient
21+
import org.modelix.model.server.store.ObjectInRepository
22+
import java.sql.Connection
23+
import java.sql.DriverManager
24+
import kotlin.test.AfterTest
25+
import kotlin.test.assertEquals
26+
import kotlin.test.assertFalse
27+
import kotlin.test.assertTrue
28+
29+
class IgnitePostgresRepositoryRemovalTest {
30+
private val store = IgniteStoreClient()
31+
32+
private val toDelete = RepositoryId("repository-removal-toDelete")
33+
private val existing = RepositoryId("repository-removal-existing")
34+
35+
@AfterTest
36+
fun cleanup() {
37+
dbConnection.prepareStatement("DELETE FROM modelix.model WHERE repository IN ( ? , ? )").use {
38+
it.setString(1, toDelete.id)
39+
it.setString(2, existing.id)
40+
}
41+
store.putAll(store.getAll().keys.associateWith { null })
42+
store.close()
43+
}
44+
45+
@Test
46+
fun `data is removed from the cache`() {
47+
val entries = mapOf(
48+
ObjectInRepository(toDelete.id, "key0") to "value0",
49+
ObjectInRepository(toDelete.id, "key1") to "value1",
50+
)
51+
store.putAll(entries)
52+
53+
store.removeRepositoryObjects(toDelete)
54+
55+
assertTrue { store.getAll(entries.keys).isEmpty() }
56+
}
57+
58+
@Test
59+
fun `data is removed from the database`() {
60+
dbConnection.prepareStatement("INSERT INTO modelix.model (repository, key, value) VALUES (?, 'myKey', 'myValue')")
61+
.use {
62+
it.setString(1, toDelete.id)
63+
it.execute()
64+
check(it.updateCount == 1)
65+
}
66+
67+
store.removeRepositoryObjects(toDelete)
68+
69+
dbConnection.prepareStatement("SELECT * FROM modelix.model WHERE repository = ?").use {
70+
it.setString(1, toDelete.id)
71+
val result = it.executeQuery()
72+
assertFalse("Database contained leftover repository data.") { result.isBeforeFirst }
73+
}
74+
}
75+
76+
@Test
77+
fun `removal does not affect other repository data in the database`() {
78+
dbConnection.prepareStatement("INSERT INTO modelix.model (repository, key, value) VALUES (?, 'myKey', 'myValue')")
79+
.use {
80+
it.setString(1, existing.id)
81+
it.execute()
82+
check(it.updateCount == 1)
83+
it.setString(1, toDelete.id)
84+
it.execute()
85+
check(it.updateCount == 1)
86+
}
87+
88+
store.removeRepositoryObjects(toDelete)
89+
90+
dbConnection.prepareStatement("SELECT * FROM modelix.model WHERE repository = ?").use {
91+
it.setString(1, existing.id)
92+
val result = it.executeQuery()
93+
assertTrue("Other repository data was removed from the database.") { result.isBeforeFirst }
94+
}
95+
}
96+
97+
@Test
98+
fun `removal does not affect other repository data in the cache`() {
99+
val existingEntries = mapOf(
100+
ObjectInRepository(existing.id, "key0") to "value0",
101+
ObjectInRepository(existing.id, "key1") to "value1",
102+
)
103+
store.putAll(existingEntries)
104+
105+
val toDeleteEntries = mapOf(
106+
ObjectInRepository(toDelete.id, "key0") to "value0",
107+
ObjectInRepository(toDelete.id, "key1") to "value1",
108+
)
109+
store.putAll(toDeleteEntries)
110+
store.removeRepositoryObjects(toDelete)
111+
112+
assertEquals(existingEntries, store.getAll())
113+
}
114+
115+
@Test
116+
fun `removing a non-existing repository does not throw`() {
117+
assertDoesNotThrow {
118+
store.removeRepositoryObjects(RepositoryId("invalid"))
119+
}
120+
}
121+
122+
companion object {
123+
val dbConnection: Connection = DriverManager.getConnection(System.getProperty("jdbc.url"), "modelix", "modelix")
124+
125+
@JvmStatic
126+
@AfterAll
127+
fun closeDbConnection() {
128+
dbConnection.close()
129+
}
130+
}
131+
}

model-server-test/src/test/kotlin/RepositoriesManagerWithDatabaseTest.kt

Lines changed: 0 additions & 93 deletions
This file was deleted.

model-server/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ dependencies {
7070
testImplementation(libs.ktor.server.test.host)
7171
testImplementation(libs.kotlin.coroutines.test)
7272
testImplementation(libs.jsoup)
73+
testImplementation(libs.mockk)
7374
testImplementation(kotlin("test"))
7475
testImplementation(project(":modelql-untyped"))
7576

model-server/src/test/kotlin/org/modelix/model/server/handlers/RepositoriesManagerTest.kt

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package org.modelix.model.server.handlers
22

3+
import io.mockk.spyk
4+
import io.mockk.verify
35
import kotlinx.coroutines.test.runTest
46
import org.modelix.model.lazy.RepositoryId
5-
import org.modelix.model.server.store.IgniteStoreClient
67
import org.modelix.model.server.store.InMemoryStoreClient
78
import org.modelix.model.server.store.IsolatingStore
89
import org.modelix.model.server.store.LocalModelClient
@@ -11,12 +12,12 @@ import kotlin.test.Test
1112
import kotlin.test.assertEquals
1213
import kotlin.test.assertTrue
1314

14-
class RepositoriesManagerWithInMemoryStoreClientTest : RepositoriesManagerTest(InMemoryStoreClient())
15-
class RepositoriesManagerWithIgniteStoreClientTest : RepositoriesManagerTest(IgniteStoreClient(inmemory = true))
15+
class RepositoriesManagerTest {
1616

17-
abstract class RepositoriesManagerTest(val store: IsolatingStore) {
18-
protected val repoManager = RepositoriesManager(LocalModelClient(store))
19-
protected suspend fun initRepository(repoId: RepositoryId) {
17+
val store = spyk<IsolatingStore>(InMemoryStoreClient())
18+
private val repoManager = RepositoriesManager(LocalModelClient(store))
19+
20+
private suspend fun initRepository(repoId: RepositoryId) {
2021
repoManager.createRepository(repoId, "testUser", useRoleIds = true, legacyGlobalStorage = false)
2122
}
2223

@@ -29,15 +30,8 @@ abstract class RepositoriesManagerTest(val store: IsolatingStore) {
2930
fun `repository data is removed when removing repository`() = runTest {
3031
val repoId = RepositoryId("abc")
3132
initRepository(repoId)
32-
33-
fun getRepositoryData() = store.getAll().filterKeys { it.getRepositoryId() == repoId.id }
34-
35-
val dataBeforeDeletion = getRepositoryData()
3633
repoManager.removeRepository(repoId)
37-
val dataAfterDeletion = getRepositoryData()
38-
39-
assertTrue(dataBeforeDeletion.isNotEmpty(), "Expected data to be present before deletion.")
40-
assertTrue(dataAfterDeletion.isEmpty(), "Leftover repository data was found after deletion. entries=${dataAfterDeletion.size}")
34+
verify(exactly = 1) { store.removeRepositoryObjects(repoId) }
4135
}
4236

4337
@Test
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright (c) 2024.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.modelix.model.server.store
18+
19+
import org.junit.jupiter.api.Nested
20+
import org.junit.jupiter.api.Test
21+
import org.junit.jupiter.api.assertDoesNotThrow
22+
import org.modelix.model.lazy.RepositoryId
23+
import kotlin.test.AfterTest
24+
import kotlin.test.assertEquals
25+
import kotlin.test.assertTrue
26+
27+
class InMemoryIsolatingStoreTest {
28+
29+
private val store = InMemoryStoreClient()
30+
31+
@Nested
32+
inner class RemoveRepositoryObjectsTest {
33+
@Test
34+
fun `repository data is removed successfully`() {
35+
val repoId = RepositoryId("abc")
36+
val entries = mapOf(
37+
ObjectInRepository(repoId.id, "key0") to "value0",
38+
ObjectInRepository(repoId.id, "key1") to "value1",
39+
)
40+
store.putAll(entries)
41+
42+
store.removeRepositoryObjects(repoId)
43+
44+
assertTrue { store.getAll().isEmpty() }
45+
}
46+
47+
@Test
48+
fun `data of other repositories stays intact`() {
49+
val existingId = RepositoryId("existing")
50+
val existingEntries = mapOf(
51+
ObjectInRepository(existingId.id, "key0") to "value0",
52+
ObjectInRepository(existingId.id, "key1") to "value1",
53+
)
54+
store.putAll(existingEntries)
55+
56+
val toDeleteId = RepositoryId("toDelete")
57+
val toDeleteEntries = mapOf(
58+
ObjectInRepository(toDeleteId.id, "key0") to "value0",
59+
ObjectInRepository(toDeleteId.id, "key1") to "value1",
60+
)
61+
store.putAll(toDeleteEntries)
62+
store.removeRepositoryObjects(toDeleteId)
63+
64+
assertEquals(existingEntries, store.getAll())
65+
}
66+
67+
@Test
68+
fun `removing a non-existing repository does not throw`() {
69+
assertDoesNotThrow {
70+
store.removeRepositoryObjects(RepositoryId("invalid"))
71+
}
72+
}
73+
}
74+
75+
@AfterTest
76+
fun cleanup() {
77+
store.close()
78+
}
79+
}

0 commit comments

Comments
 (0)