@@ -19,7 +19,9 @@ import io.ktor.client.HttpClient
19
19
import io.ktor.client.engine.cio.CIO
20
20
import io.ktor.client.plugins.HttpTimeout
21
21
import io.ktor.client.plugins.defaultRequest
22
+ import io.ktor.client.request.delete
22
23
import io.ktor.client.request.get
24
+ import io.ktor.client.statement.bodyAsText
23
25
import io.ktor.http.HttpHeaders
24
26
import io.ktor.http.HttpStatusCode
25
27
import io.ktor.http.appendPathSegments
@@ -51,39 +53,52 @@ import org.modelix.model.server.store.InMemoryStoreClient
51
53
import org.modelix.model.server.store.LocalModelClient
52
54
import org.modelix.modelql.core.assertNotEmpty
53
55
import kotlin.test.Test
56
+ import kotlin.test.assertContains
54
57
import kotlin.test.assertEquals
58
+ import kotlin.test.assertFalse
55
59
import kotlin.test.fail
56
60
import kotlin.time.Duration.Companion.seconds
57
61
58
62
class ModelReplicationServerTest {
59
63
60
- private fun getDefaultModelReplicationServer (): ModelReplicationServer {
64
+ private data class Fixture (
65
+ val storeClient : InMemoryStoreClient ,
66
+ val modelClient : LocalModelClient ,
67
+ val repositoriesManager : IRepositoriesManager ,
68
+ val modelReplicationServer : ModelReplicationServer ,
69
+ )
70
+
71
+ private fun getDefaultModelReplicationServerFixture (): Fixture {
61
72
val storeClient = InMemoryStoreClient ()
62
73
val modelClient = LocalModelClient (storeClient)
63
74
val repositoriesManager = RepositoriesManager (modelClient)
64
- return ModelReplicationServer (repositoriesManager, modelClient, InMemoryModels ())
75
+ return Fixture (
76
+ storeClient,
77
+ modelClient,
78
+ repositoriesManager,
79
+ ModelReplicationServer (repositoriesManager, modelClient, InMemoryModels ()),
80
+ )
65
81
}
66
82
67
83
private fun runWithTestModelServer (
68
- modelReplicationServer : ModelReplicationServer = getDefaultModelReplicationServer (),
69
- block : suspend ApplicationTestBuilder .(scope: CoroutineScope ) -> Unit ,
84
+ fixture : Fixture = getDefaultModelReplicationServerFixture (),
85
+ block : suspend ApplicationTestBuilder .(scope: CoroutineScope , fixture: Fixture ) -> Unit ,
70
86
) = testApplication {
71
87
application {
72
88
installAuthentication(unitTestMode = true )
73
89
installDefaultServerPlugins()
74
- modelReplicationServer.init (this )
90
+ fixture. modelReplicationServer.init (this )
75
91
}
76
92
77
93
coroutineScope {
78
- block(this )
94
+ block(this , fixture )
79
95
}
80
96
}
81
97
82
98
@Test
83
- fun `pulling delta does not return objects twice` () = runWithTestModelServer {
99
+ fun `pulling delta does not return objects twice` () = runWithTestModelServer { _, _ ->
84
100
// Arrange
85
- val url = " http://localhost/v2"
86
- val modelClient = ModelClientV2 .builder().url(url).client(client).build().also { it.init () }
101
+ val modelClient = ModelClientV2 .builder().url(" v2" ).client(client).build().also { it.init () }
87
102
val repositoryId = RepositoryId (" repo1" )
88
103
val branchId = repositoryId.getBranchReference(" my-branch" )
89
104
// By calling modelClient.runWrite twice, we create to versions.
@@ -98,8 +113,7 @@ class ModelReplicationServerTest {
98
113
// Act
99
114
val response = client.get {
100
115
url {
101
- takeFrom(url)
102
- appendPathSegments(" repositories" , repositoryId.id, " branches" , branchId.branchName)
116
+ appendPathSegments(" v2" , " repositories" , repositoryId.id, " branches" , branchId.branchName)
103
117
}
104
118
useVersionStreamFormat()
105
119
}
@@ -117,6 +131,75 @@ class ModelReplicationServerTest {
117
131
}
118
132
}
119
133
134
+ @Test
135
+ fun `responds with 404 when deleting a branch from a non-existent repository` () {
136
+ runWithTestModelServer { _, _ ->
137
+ val response = client.delete {
138
+ url {
139
+ appendPathSegments(" v2" , " repositories" , " doesnotexist" , " branches" , " does not exist" )
140
+ }
141
+ }
142
+
143
+ assertEquals(HttpStatusCode .NotFound , response.status)
144
+ assertContains(response.bodyAsText(), " does not exist in repository" )
145
+ }
146
+ }
147
+
148
+ @Test
149
+ fun `responds with 404 when deleting a non-existent branch` () {
150
+ val repositoryId = RepositoryId (" repo1" )
151
+
152
+ runWithTestModelServer { _, fixture ->
153
+ fixture.repositoriesManager.createRepository(repositoryId, null )
154
+
155
+ val response = client.delete {
156
+ url {
157
+ appendPathSegments(" v2" , " repositories" , repositoryId.id, " branches" , " does not exist" )
158
+ }
159
+ }
160
+
161
+ assertEquals(HttpStatusCode .NotFound , response.status)
162
+ assertContains(response.bodyAsText(), " does not exist in repository" )
163
+ }
164
+ }
165
+
166
+ @Test
167
+ fun `responds with 400 when deleting from an invalid repository ID` () {
168
+ runWithTestModelServer { _, fixture ->
169
+ val response = client.delete {
170
+ url {
171
+ appendPathSegments(" v2" , " repositories" , " invalid with spaces" , " branches" , " master" )
172
+ }
173
+ }
174
+ assertEquals(HttpStatusCode .BadRequest , response.status)
175
+ assertContains(response.bodyAsText(), " Invalid repository name" )
176
+ }
177
+ }
178
+
179
+ @Test
180
+ fun `successfully deletes existing branches` () {
181
+ val repositoryId = RepositoryId (" repo1" )
182
+ val branch = " testbranch"
183
+ val defaultBranchRef = repositoryId.getBranchReference(" master" )
184
+
185
+ runWithTestModelServer { _, fixture ->
186
+ fixture.repositoriesManager.createRepository(repositoryId, null )
187
+ fixture.repositoriesManager.mergeChanges(
188
+ repositoryId.getBranchReference(branch),
189
+ checkNotNull(fixture.repositoriesManager.getVersionHash(defaultBranchRef)) { " Default branch must exist" },
190
+ )
191
+
192
+ val response = client.delete {
193
+ url {
194
+ appendPathSegments(" v2" , " repositories" , repositoryId.id, " branches" , branch)
195
+ }
196
+ }
197
+
198
+ assertEquals(HttpStatusCode .NoContent , response.status)
199
+ assertFalse(fixture.repositoriesManager.getBranchNames(repositoryId).contains(branch))
200
+ }
201
+ }
202
+
120
203
@Test
121
204
fun `server responds with error when failing to compute delta before starting to respond` () {
122
205
// Arrange
@@ -130,18 +213,16 @@ class ModelReplicationServerTest {
130
213
}
131
214
}
132
215
val modelReplicationServer = ModelReplicationServer (faultyRepositoriesManager, modelClient, InMemoryModels ())
133
- val url = " http://localhost/v2"
134
216
val repositoryId = RepositoryId (" repo1" )
135
217
val branchRef = repositoryId.getBranchReference()
136
218
137
- runWithTestModelServer(modelReplicationServer) {
219
+ runWithTestModelServer(Fixture (storeClient, modelClient, faultyRepositoriesManager, modelReplicationServer)) { _, _ ->
138
220
repositoriesManager.createRepository(repositoryId, null )
139
221
140
222
// Act
141
223
val response = client.get {
142
224
url {
143
- takeFrom(url)
144
- appendPathSegments(" repositories" , repositoryId.id, " branches" , branchRef.branchName)
225
+ appendPathSegments(" v2" , " repositories" , repositoryId.id, " branches" , branchRef.branchName)
145
226
}
146
227
useVersionStreamFormat()
147
228
}
@@ -210,10 +291,10 @@ class ModelReplicationServerTest {
210
291
runWithNettyServer(setupBlock, testBlock)
211
292
}
212
293
213
- fun `client can pull versions in legacy version delta format` () = runWithTestModelServer {
294
+ @Test
295
+ fun `client can pull versions in legacy version delta format` () = runWithTestModelServer { _, _ ->
214
296
// Arrange
215
- val url = " http://localhost/v2"
216
- val modelClient = ModelClientV2 .builder().url(url).client(client).build().also { it.init () }
297
+ val modelClient = ModelClientV2 .builder().url(" v2" ).client(client).build().also { it.init () }
217
298
val repositoryId = RepositoryId (" repo1" )
218
299
val branchId = repositoryId.getBranchReference(" my-branch" )
219
300
modelClient.runWrite(branchId) { root ->
@@ -224,8 +305,7 @@ class ModelReplicationServerTest {
224
305
val response = client.get {
225
306
headers[HttpHeaders .Accept ] = VersionDeltaStream .CONTENT_TYPE .toString()
226
307
url {
227
- takeFrom(url)
228
- appendPathSegments(" repositories" , repositoryId.id, " branches" , branchId.branchName)
308
+ appendPathSegments(" v2" , " repositories" , repositoryId.id, " branches" , branchId.branchName)
229
309
}
230
310
}
231
311
val versionDelta = response.readVersionDelta()
0 commit comments