Skip to content

Commit 9b4d8b3

Browse files
authored
Merge pull request #226 from Open-MBEE/develop
0.2.1
2 parents 974daf6 + 6f9eee6 commit 9b4d8b3

44 files changed

Lines changed: 907 additions & 1435 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.circleci/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ jobs:
4242
shell: /bin/bash
4343
command: |
4444
docker-compose -f src/test/resources/docker-compose.yml up -d
45+
cp src/main/resources/application.conf.test ./src/main/resources/application.conf
4546
docker build -t flexo-mms-test:latest -f Dockerfile-Test .
4647
docker run --network=flexo-mms-test-network --name flexo-mms-test-container flexo-mms-test:latest
4748
SIG_INT=$?

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ dependencies {
7171
implementation("io.ktor:ktor-server-netty:$ktorVersion")
7272
implementation("io.ktor:ktor-server-status-pages:$ktorVersion")
7373
testImplementation("io.ktor:ktor-server-tests:$ktorVersion")
74+
testImplementation("io.kotest.extensions:kotest-assertions-ktor:2.0.0")
7475

7576
val logbackVersion = "1.5.18"
7677
implementation("ch.qos.logback:logback-classic:$logbackVersion")

src/main/kotlin/org/openmbee/flexo/mms/Conditions.kt

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -88,39 +88,19 @@ val BRANCH_COMMIT_CONDITIONS = REPO_CRUD_CONDITIONS.append {
8888
}
8989
}
9090

91-
val SNAPSHOT_QUERY_CONDITIONS = REPO_CRUD_CONDITIONS.append {
92-
require("queryableSnapshotExists") {
93-
handler = { layer1 -> "The target model is corrupt. No queryable snapshots found." to HttpStatusCode.InternalServerError }
94-
95-
"""
96-
graph mor-graph:Metadata {
97-
?__mms_ref
98-
# select the latest commit from the current named ref
99-
mms:commit ?__mms_baseCommit ;
100-
101-
# and its etag value
102-
mms:etag ?__mms_etag ;
103-
104-
# and a queryable snapshot
105-
mms:snapshot/mms:graph ?__mms_queryGraph .
106-
}
107-
"""
108-
}
109-
}
110-
111-
val REPO_QUERY_CONDITIONS = SNAPSHOT_QUERY_CONDITIONS.append {
91+
val REPO_QUERY_CONDITIONS = REPO_CRUD_CONDITIONS.append {
11292
permit(Permission.READ_REPO, Scope.REPO)
11393
}
11494

115-
val BRANCH_QUERY_CONDITIONS = SNAPSHOT_QUERY_CONDITIONS.append {
95+
val BRANCH_QUERY_CONDITIONS = REPO_CRUD_CONDITIONS.append {
11696
permit(Permission.READ_BRANCH, Scope.BRANCH)
11797
}
11898

119-
val LOCK_QUERY_CONDITIONS = SNAPSHOT_QUERY_CONDITIONS.append {
99+
val LOCK_QUERY_CONDITIONS = REPO_CRUD_CONDITIONS.append {
120100
permit(Permission.READ_LOCK, Scope.LOCK)
121101
}
122102

123-
val ARTIFACT_QUERY_CONDITIONS = SNAPSHOT_QUERY_CONDITIONS.append {
103+
val ARTIFACT_QUERY_CONDITIONS = REPO_CRUD_CONDITIONS.append {
124104
permit(Permission.READ_ARTIFACT, Scope.ARTIFACT)
125105
}
126106

@@ -134,7 +114,7 @@ val SCRATCH_UPDATE_CONDITIONS = REPO_CRUD_CONDITIONS.append {
134114
permit(Permission.UPDATE_SCRATCH, Scope.SCRATCH)
135115
}
136116

137-
val DIFF_QUERY_CONDITIONS = SNAPSHOT_QUERY_CONDITIONS.append {
117+
val DIFF_QUERY_CONDITIONS = REPO_CRUD_CONDITIONS.append {
138118
permit(Permission.READ_DIFF, Scope.DIFF)
139119
}
140120

src/test/kotlin/org/openmbee/flexo/mms/ArtifactAny.kt

Lines changed: 68 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
package org.openmbee.flexo.mms
22

3+
import io.kotest.assertions.ktor.client.shouldHaveStatus
34
import io.kotest.matchers.equals.shouldBeEqual
4-
import io.kotest.matchers.nulls.shouldBeNull
55
import io.kotest.matchers.shouldBe
6+
import io.kotest.matchers.string.shouldBeEmpty
7+
import io.kotest.matchers.string.shouldContain
68
import io.kotest.matchers.string.shouldStartWith
9+
import io.ktor.client.request.*
10+
import io.ktor.client.statement.*
711
import io.ktor.http.*
812
import io.ktor.server.testing.*
13+
import io.ktor.util.*
914
import org.openmbee.flexo.mms.util.*
1015
import org.slf4j.LoggerFactory
1116
import java.io.ByteArrayInputStream
1217
import java.util.zip.ZipEntry
1318
import java.util.zip.ZipInputStream
1419

1520

21+
@OptIn(InternalAPI::class)
1622
open class ArtifactAny : RefAny() {
1723
override val logger = LoggerFactory.getLogger(LockAny::class.java)
1824

@@ -21,61 +27,61 @@ open class ArtifactAny : RefAny() {
2127

2228
init {
2329
"post artifact text/plain" {
24-
withTest {
30+
testApplication {
2531
httpPost(artifactsPath) {
26-
addHeader("Content-Type", "text/plain")
32+
header("Content-Type", "text/plain")
2733
setBody("foo")
2834
}.apply {
29-
response shouldHaveStatus HttpStatusCode.Created
30-
response.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath)
31-
response.contentType() shouldBe ContentType.Text.Plain
35+
this shouldHaveStatus HttpStatusCode.Created
36+
this.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath)
37+
this.contentType() shouldBe ContentType.Text.Plain
3238
}
3339
}
3440
}
3541

3642
// Set a content-type with parameters (like utf-8 on text/plain) and assert that parameters have
3743
// been removed on returned content type
3844
"post artifact text/plain with parameter" {
39-
withTest{
45+
testApplication {
4046
httpPost(artifactsPath) {
41-
addHeader("Content-Type", "text/plain; charset=utf-8")
47+
header("Content-Type", "text/plain; charset=utf-8")
4248
setBody("foo")
4349
}.apply {
44-
response shouldHaveStatus HttpStatusCode.Created
45-
response.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath)
46-
response.contentType() shouldBe ContentType.Text.Plain
50+
this shouldHaveStatus HttpStatusCode.Created
51+
this.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath)
52+
this.contentType() shouldBe ContentType.Text.Plain
4753
}
4854
}
4955
}
5056

5157
"get all artifacts empty" {
52-
withTest{
58+
testApplication {
5359
httpGet("$artifactsPath?download") {
5460
}.apply {
55-
response shouldHaveStatus HttpStatusCode.NoContent
56-
response.content.shouldBeNull()
61+
this shouldHaveStatus HttpStatusCode.NoContent
62+
this.bodyAsText().shouldBeEmpty()
5763
}
5864
}
5965
}
6066

6167

6268
"get all artifacts two artifacts" {
63-
withTest{
69+
testApplication {
6470
httpPost(artifactsPath) {
65-
addHeader("Content-Type", "text/plain")
71+
header("Content-Type", "text/plain")
6672
setBody("foo")
6773
}.apply {
68-
val locationFile1 = getURI(response.headers[HttpHeaders.Location].toString())
74+
val locationFile1 = getURI(this.headers[HttpHeaders.Location].toString())
6975
httpPost(artifactsPath) {
70-
addHeader("Content-Type", "application/octet-stream")
76+
header("Content-Type", "application/octet-stream")
7177
setBody("bar".toByteArray())
7278
}.apply {
73-
val locationFile2 = getURI(response.headers[HttpHeaders.Location].toString())
79+
val locationFile2 = getURI(this.headers[HttpHeaders.Location].toString())
7480
httpGet("$artifactsPath?download") {}.apply {
75-
response shouldHaveStatus HttpStatusCode.OK
76-
response.contentType() shouldBe ContentType.Application.Zip
81+
this shouldHaveStatus HttpStatusCode.OK
82+
this.contentType() shouldBe ContentType.Application.Zip
7783

78-
val zipBytes = response.byteContent ?: throw IllegalStateException("Response byteContent is null")
84+
val zipBytes = this.content.toByteArray()
7985
val contents = readZipContents(zipBytes)
8086
contents.size shouldBe 2
8187
contents["$locationFile1.txt"] shouldBe "foo"
@@ -88,7 +94,7 @@ open class ArtifactAny : RefAny() {
8894

8995
// Not used http methods that should fail
9096
"artifact rejects other methods" {
91-
withTest {
97+
testApplication {
9298
onlyAllowsMethods(artifactsPath, setOf(
9399
HttpMethod.Head,
94100
HttpMethod.Get,
@@ -102,95 +108,94 @@ open class ArtifactAny : RefAny() {
102108
*********************************************/
103109

104110
"get an artifact by id - turtle" {
105-
withTest{
111+
testApplication {
106112
httpPost(artifactsPath) {
107-
addHeader("Content-Type", "text/plain")
113+
header("Content-Type", "text/plain")
108114
setBody("foo".toByteArray())
109115
}.apply {
110-
response shouldHaveStatus HttpStatusCode.Created
111-
response.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath)
112-
113-
val uri = getLocation(response.headers[HttpHeaders.Location].toString())
114-
httpGet(uri) {
115-
}.apply {
116-
response shouldHaveStatus HttpStatusCode.OK
117-
response.contentType() shouldBe ContentType.Text.Plain
118-
response shouldHaveContent "foo"
116+
this shouldHaveStatus HttpStatusCode.Created
117+
this.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath)
118+
119+
val uri = getLocation(this.headers[HttpHeaders.Location].toString())
120+
httpGet(uri) {}.apply {
121+
this shouldHaveStatus HttpStatusCode.OK
122+
this.contentType() shouldBe ContentType.Text.Plain
123+
this.bodyAsText() shouldContain "foo"
119124
}
120125
}
121126
}
122127
}
123128

124129
"download an artifact by id - text" {
125-
withTest{
130+
testApplication {
126131
httpPost(artifactsPath) {
127-
addHeader("Content-Type", "text/plain")
132+
header("Content-Type", "text/plain")
128133
setBody("foo")
129134
}.apply {
130-
response shouldHaveStatus HttpStatusCode.Created
131-
response.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath)
135+
this shouldHaveStatus HttpStatusCode.Created
136+
this.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath)
132137

133-
val uri = getLocation(response.headers[HttpHeaders.Location].toString())
138+
val uri = getLocation(this.headers[HttpHeaders.Location].toString())
134139
httpGet("$uri?download") {
135140
}.apply {
136-
response shouldHaveStatus HttpStatusCode.OK
137-
response.contentType() shouldBe ContentType.Text.Plain
138-
response shouldHaveContent "foo"
141+
this shouldHaveStatus HttpStatusCode.OK
142+
this.contentType() shouldBe ContentType.Text.Plain
143+
this.bodyAsText() shouldContain "foo"
139144
}
140145
}
141146
}
142147
}
143148

144149
"download an artifact by id - binary" {
145-
withTest{
150+
testApplication {
146151
httpPost(artifactsPath) {
147-
addHeader("Content-Type", "application/octet-stream")
152+
header("Content-Type", "application/octet-stream")
148153
setBody("foo".toByteArray())
149154
}.apply {
150-
response shouldHaveStatus HttpStatusCode.Created
151-
response.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath)
155+
this shouldHaveStatus HttpStatusCode.Created
156+
this.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath)
152157

153-
val uri = getLocation(response.headers[HttpHeaders.Location].toString())
158+
val uri = getLocation(this.headers[HttpHeaders.Location].toString())
154159
httpGet("$uri?download") {
155160
}.apply {
156-
response shouldHaveStatus HttpStatusCode.OK
157-
response.contentType() shouldBe ContentType.Application.OctetStream
158-
response shouldHaveContent "foo"
161+
this shouldHaveStatus HttpStatusCode.OK
162+
this.contentType() shouldBe ContentType.Application.OctetStream
163+
this.bodyAsText() shouldContain "foo"
159164
}
160165
}
161166
}
162167
}
163168

164169
"get an artifact by id - URI" {
165-
withTest{
170+
testApplication {
166171
httpPost(artifactsPath) {
167-
addHeader("Content-Type", "text/turtle")
172+
header("Content-Type", "text/turtle")
168173
setBody("<http://openmbee.org> <http://openmbee.org> <http://openmbee.org> .")
169174
}.apply {
170-
response shouldHaveStatus HttpStatusCode.Created
171-
response.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath)
175+
this shouldHaveStatus HttpStatusCode.Created
176+
this.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath)
172177

173-
val uri = getLocation(response.headers[HttpHeaders.Location].toString())
178+
val uri = getLocation(this.headers[HttpHeaders.Location].toString())
174179
httpGet("$uri?download") {}.apply {
175-
response shouldHaveStatus HttpStatusCode.OK
176-
response.contentType().toString() shouldBeEqual "text/turtle"
177-
response shouldHaveContent "<http://openmbee.org> <http://openmbee.org> <http://openmbee.org> ."
180+
this shouldHaveStatus HttpStatusCode.OK
181+
this.contentType().toString() shouldBeEqual "text/turtle"
182+
this.bodyAsText() shouldBeEqual "<http://openmbee.org> <http://openmbee.org> <http://openmbee.org> ."
178183
}
179184
}
180185
}
181186
}
182187

183188
// Not used http methods that should fail
184189
"artifact/{id} rejects other methods" {
185-
withTest {
190+
testApplication {
186191
httpPost(artifactsPath) {
187-
addHeader("Content-Type", "text/plain")
192+
header("Content-Type", "text/plain")
188193
setBody("foo")
189194
}.apply {
190-
response shouldHaveStatus HttpStatusCode.Created
191-
response.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath)
195+
this shouldHaveStatus HttpStatusCode.Created
196+
this.headers[HttpHeaders.Location] shouldStartWith localIri(artifactsPath)
192197

193-
val uri = getLocation(response.headers[HttpHeaders.Location].toString())
198+
val uri = getLocation(this.headers[HttpHeaders.Location].toString())
194199
onlyAllowsMethods(
195200
uri, setOf(
196201
HttpMethod.Head,

0 commit comments

Comments
 (0)