summaryrefslogtreecommitdiff
path: root/opendc-web/opendc-web-api/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'opendc-web/opendc-web-api/src/test')
-rw-r--r--opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/SchedulerResourceTest.kt48
-rw-r--r--opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/TraceResourceTest.kt100
-rw-r--r--opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/runner/JobResourceTest.kt200
-rw-r--r--opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/PortfolioResourceTest.kt265
-rw-r--r--opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/PortfolioScenarioResourceTest.kt213
-rw-r--r--opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/ProjectResourceTest.kt240
-rw-r--r--opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/ScenarioResourceTest.kt178
-rw-r--r--opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/TopologyResourceTest.kt304
8 files changed, 1548 insertions, 0 deletions
diff --git a/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/SchedulerResourceTest.kt b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/SchedulerResourceTest.kt
new file mode 100644
index 00000000..e88e1c1c
--- /dev/null
+++ b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/SchedulerResourceTest.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.api.rest
+
+import io.quarkus.test.junit.QuarkusTest
+import io.restassured.http.ContentType
+import io.restassured.module.kotlin.extensions.Then
+import io.restassured.module.kotlin.extensions.When
+import org.junit.jupiter.api.Test
+
+/**
+ * Test suite for [SchedulerResource]
+ */
+@QuarkusTest
+class SchedulerResourceTest {
+ /**
+ * Test to verify whether we can obtain all schedulers.
+ */
+ @Test
+ fun testGetSchedulers() {
+ When {
+ get("/schedulers")
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ }
+ }
+}
diff --git a/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/TraceResourceTest.kt b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/TraceResourceTest.kt
new file mode 100644
index 00000000..6fab9953
--- /dev/null
+++ b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/TraceResourceTest.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.api.rest
+
+import io.mockk.every
+import io.quarkiverse.test.junit.mockk.InjectMock
+import io.quarkus.test.common.http.TestHTTPEndpoint
+import io.quarkus.test.junit.QuarkusMock
+import io.quarkus.test.junit.QuarkusTest
+import io.restassured.http.ContentType
+import io.restassured.module.kotlin.extensions.Then
+import io.restassured.module.kotlin.extensions.When
+import org.hamcrest.Matchers
+import org.hamcrest.Matchers.equalTo
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.opendc.web.api.service.TraceService
+import org.opendc.web.proto.Trace
+
+/**
+ * Test suite for [TraceResource].
+ */
+@QuarkusTest
+@TestHTTPEndpoint(TraceResource::class)
+class TraceResourceTest {
+ @InjectMock
+ private lateinit var traceService: TraceService
+
+ @BeforeEach
+ fun setUp() {
+ QuarkusMock.installMockForType(traceService, TraceService::class.java)
+ }
+
+ /**
+ * Test that tries to obtain all traces (empty response).
+ */
+ @Test
+ fun testGetAllEmpy() {
+ every { traceService.findAll() } returns emptyList()
+
+ When {
+ get()
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ body("", Matchers.empty<String>())
+ }
+ }
+
+ /**
+ * Test that tries to obtain a non-existent trace.
+ */
+ @Test
+ fun testGetNonExisting() {
+ every { traceService.findById("bitbrains") } returns null
+
+ When {
+ get("/bitbrains")
+ } Then {
+ statusCode(404)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to obtain an existing trace.
+ */
+ @Test
+ fun testGetExisting() {
+ every { traceService.findById("bitbrains") } returns Trace("bitbrains", "Bitbrains", "VM")
+
+ When {
+ get("/bitbrains")
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ body("name", equalTo("Bitbrains"))
+ }
+ }
+}
diff --git a/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/runner/JobResourceTest.kt b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/runner/JobResourceTest.kt
new file mode 100644
index 00000000..b82c60e8
--- /dev/null
+++ b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/runner/JobResourceTest.kt
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.api.rest.runner
+
+import io.mockk.every
+import io.quarkiverse.test.junit.mockk.InjectMock
+import io.quarkus.test.common.http.TestHTTPEndpoint
+import io.quarkus.test.junit.QuarkusMock
+import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.security.TestSecurity
+import io.restassured.http.ContentType
+import io.restassured.module.kotlin.extensions.Given
+import io.restassured.module.kotlin.extensions.Then
+import io.restassured.module.kotlin.extensions.When
+import org.hamcrest.Matchers.equalTo
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.opendc.web.api.service.JobService
+import org.opendc.web.proto.*
+import org.opendc.web.proto.Targets
+import org.opendc.web.proto.runner.Job
+import org.opendc.web.proto.runner.Portfolio
+import org.opendc.web.proto.runner.Scenario
+import org.opendc.web.proto.runner.Topology
+import java.time.Instant
+
+/**
+ * Test suite for [JobResource].
+ */
+@QuarkusTest
+@TestHTTPEndpoint(JobResource::class)
+class JobResourceTest {
+ @InjectMock
+ private lateinit var jobService: JobService
+
+ /**
+ * Dummy values
+ */
+ private val dummyPortfolio = Portfolio(1, 1, "test", Targets(emptySet()))
+ private val dummyTopology = Topology(1, 1, "test", emptyList(), Instant.now(), Instant.now())
+ private val dummyTrace = Trace("bitbrains", "Bitbrains", "vm")
+ private val dummyScenario = Scenario(1, 1, dummyPortfolio, "test", Workload(dummyTrace, 1.0), dummyTopology, OperationalPhenomena(false, false), "test",)
+ private val dummyJob = Job(1, dummyScenario, JobState.PENDING, Instant.now(), Instant.now())
+
+ @BeforeEach
+ fun setUp() {
+ QuarkusMock.installMockForType(jobService, JobService::class.java)
+ }
+
+ /**
+ * Test that tries to query the pending jobs without token.
+ */
+ @Test
+ fun testQueryWithoutToken() {
+ When {
+ get()
+ } Then {
+ statusCode(401)
+ }
+ }
+
+ /**
+ * Test that tries to query the pending jobs for a user.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testQueryInvalidScope() {
+ When {
+ get()
+ } Then {
+ statusCode(403)
+ }
+ }
+
+ /**
+ * Test that tries to query the pending jobs for a runner.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["runner"])
+ fun testQuery() {
+ every { jobService.queryPending() } returns listOf(dummyJob)
+
+ When {
+ get()
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ body("get(0).id", equalTo(1))
+ }
+ }
+
+ /**
+ * Test that tries to obtain a non-existent job.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["runner"])
+ fun testGetNonExisting() {
+ every { jobService.findById(1) } returns null
+
+ When {
+ get("/1")
+ } Then {
+ statusCode(404)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a job.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["runner"])
+ fun testGetExisting() {
+ every { jobService.findById(1) } returns dummyJob
+
+ When {
+ get("/1")
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ body("id", equalTo(1))
+ }
+ }
+
+ /**
+ * Test that tries to update a non-existent job.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["runner"])
+ fun testUpdateNonExistent() {
+ every { jobService.updateState(1, any(), any()) } returns null
+
+ Given {
+ body(Job.Update(JobState.PENDING))
+ contentType(ContentType.JSON)
+ } When {
+ post("/1")
+ } Then {
+ statusCode(404)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to update a job.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["runner"])
+ fun testUpdateState() {
+ every { jobService.updateState(1, any(), any()) } returns dummyJob.copy(state = JobState.CLAIMED)
+
+ Given {
+ body(Job.Update(JobState.CLAIMED))
+ contentType(ContentType.JSON)
+ } When {
+ post("/1")
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ body("state", equalTo(JobState.CLAIMED.toString()))
+ }
+ }
+
+ /**
+ * Test that tries to update a job with invalid input.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["runner"])
+ fun testUpdateInvalidInput() {
+ Given {
+ body("""{ "test": "test" }""")
+ contentType(ContentType.JSON)
+ } When {
+ post("/1")
+ } Then {
+ statusCode(400)
+ contentType(ContentType.JSON)
+ }
+ }
+}
diff --git a/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/PortfolioResourceTest.kt b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/PortfolioResourceTest.kt
new file mode 100644
index 00000000..f74efbca
--- /dev/null
+++ b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/PortfolioResourceTest.kt
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.api.rest.user
+
+import io.mockk.every
+import io.quarkiverse.test.junit.mockk.InjectMock
+import io.quarkus.test.common.http.TestHTTPEndpoint
+import io.quarkus.test.junit.QuarkusMock
+import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.security.TestSecurity
+import io.restassured.http.ContentType
+import io.restassured.module.kotlin.extensions.Given
+import io.restassured.module.kotlin.extensions.Then
+import io.restassured.module.kotlin.extensions.When
+import org.hamcrest.Matchers
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.opendc.web.api.service.PortfolioService
+import org.opendc.web.proto.Targets
+import org.opendc.web.proto.user.Portfolio
+import org.opendc.web.proto.user.Project
+import org.opendc.web.proto.user.ProjectRole
+import java.time.Instant
+
+/**
+ * Test suite for [PortfolioResource].
+ */
+@QuarkusTest
+@TestHTTPEndpoint(PortfolioResource::class)
+class PortfolioResourceTest {
+ @InjectMock
+ private lateinit var portfolioService: PortfolioService
+
+ /**
+ * Dummy project and portfolio
+ */
+ private val dummyProject = Project(1, "test", Instant.now(), Instant.now(), ProjectRole.OWNER)
+ private val dummyPortfolio = Portfolio(1, 1, dummyProject, "test", Targets(emptySet(), 1), emptyList())
+
+ @BeforeEach
+ fun setUp() {
+ QuarkusMock.installMockForType(portfolioService, PortfolioService::class.java)
+ }
+
+ /**
+ * Test that tries to obtain the list of portfolios belonging to a project.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testGetForProject() {
+ every { portfolioService.findAll("testUser", 1) } returns emptyList()
+
+ Given {
+ pathParam("project", "1")
+ } When {
+ get()
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to create a topology for a project.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreateNonExistent() {
+ every { portfolioService.create("testUser", 1, any()) } returns null
+
+ Given {
+ pathParam("project", "1")
+
+ body(Portfolio.Create("test", Targets(emptySet(), 1)))
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(404)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to create a portfolio for a scenario.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreate() {
+ every { portfolioService.create("testUser", 1, any()) } returns dummyPortfolio
+
+ Given {
+ pathParam("project", "1")
+
+ body(Portfolio.Create("test", Targets(emptySet(), 1)))
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ body("id", Matchers.equalTo(1))
+ body("name", Matchers.equalTo("test"))
+ }
+ }
+
+ /**
+ * Test to create a portfolio with an empty body.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreateEmpty() {
+ Given {
+ pathParam("project", "1")
+
+ body("{}")
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(400)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test to create a portfolio with a blank name.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreateBlankName() {
+ Given {
+ pathParam("project", "1")
+
+ body(Portfolio.Create("", Targets(emptySet(), 1)))
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(400)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a portfolio without token.
+ */
+ @Test
+ fun testGetWithoutToken() {
+ Given {
+ pathParam("project", "1")
+ } When {
+ get("/1")
+ } Then {
+ statusCode(401)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a portfolio with an invalid scope.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["runner"])
+ fun testGetInvalidToken() {
+ Given {
+ pathParam("project", "1")
+ } When {
+ get("/1")
+ } Then {
+ statusCode(403)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a non-existent portfolio.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testGetNonExisting() {
+ every { portfolioService.findOne("testUser", 1, 1) } returns null
+
+ Given {
+ pathParam("project", "1")
+ } When {
+ get("/1")
+ } Then {
+ statusCode(404)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a portfolio.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testGetExisting() {
+ every { portfolioService.findOne("testUser", 1, 1) } returns dummyPortfolio
+
+ Given {
+ pathParam("project", "1")
+ } When {
+ get("/1")
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ body("id", Matchers.equalTo(1))
+ }
+ }
+
+ /**
+ * Test to delete a non-existent portfolio.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testDeleteNonExistent() {
+ every { portfolioService.delete("testUser", 1, 1) } returns null
+
+ Given {
+ pathParam("project", "1")
+ } When {
+ delete("/1")
+ } Then {
+ statusCode(404)
+ }
+ }
+
+ /**
+ * Test to delete a portfolio.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testDelete() {
+ every { portfolioService.delete("testUser", 1, 1) } returns dummyPortfolio
+
+ Given {
+ pathParam("project", "1")
+ } When {
+ delete("/1")
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ }
+ }
+}
diff --git a/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/PortfolioScenarioResourceTest.kt b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/PortfolioScenarioResourceTest.kt
new file mode 100644
index 00000000..dbafa8c0
--- /dev/null
+++ b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/PortfolioScenarioResourceTest.kt
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.api.rest.user
+
+import io.mockk.every
+import io.quarkiverse.test.junit.mockk.InjectMock
+import io.quarkus.test.common.http.TestHTTPEndpoint
+import io.quarkus.test.junit.QuarkusMock
+import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.security.TestSecurity
+import io.restassured.http.ContentType
+import io.restassured.module.kotlin.extensions.Given
+import io.restassured.module.kotlin.extensions.Then
+import io.restassured.module.kotlin.extensions.When
+import org.hamcrest.Matchers
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.opendc.web.api.service.ScenarioService
+import org.opendc.web.proto.*
+import org.opendc.web.proto.user.*
+import java.time.Instant
+
+/**
+ * Test suite for [PortfolioScenarioResource].
+ */
+@QuarkusTest
+@TestHTTPEndpoint(PortfolioScenarioResource::class)
+class PortfolioScenarioResourceTest {
+ @InjectMock
+ private lateinit var scenarioService: ScenarioService
+
+ /**
+ * Dummy values
+ */
+ private val dummyProject = Project(0, "test", Instant.now(), Instant.now(), ProjectRole.OWNER)
+ private val dummyPortfolio = Portfolio.Summary(1, 1, "test", Targets(emptySet()))
+ private val dummyJob = Job(1, JobState.PENDING, Instant.now(), Instant.now(), null)
+ private val dummyTrace = Trace("bitbrains", "Bitbrains", "vm")
+ private val dummyTopology = Topology.Summary(1, 1, "test", Instant.now(), Instant.now())
+ private val dummyScenario = Scenario(
+ 1,
+ 1,
+ dummyProject,
+ dummyPortfolio,
+ "test",
+ Workload(dummyTrace, 1.0),
+ dummyTopology,
+ OperationalPhenomena(false, false),
+ "test",
+ dummyJob
+ )
+
+ @BeforeEach
+ fun setUp() {
+ QuarkusMock.installMockForType(scenarioService, ScenarioService::class.java)
+ }
+
+ /**
+ * Test that tries to obtain a portfolio without token.
+ */
+ @Test
+ fun testGetWithoutToken() {
+ Given {
+ pathParam("project", "1")
+ pathParam("portfolio", "1")
+ } When {
+ get()
+ } Then {
+ statusCode(401)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a portfolio with an invalid scope.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["runner"])
+ fun testGetInvalidToken() {
+ Given {
+ pathParam("project", "1")
+ pathParam("portfolio", "1")
+ } When {
+ get()
+ } Then {
+ statusCode(403)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a non-existent portfolio.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testGet() {
+ every { scenarioService.findAll("testUser", 1, 1) } returns emptyList()
+
+ Given {
+ pathParam("project", "1")
+ pathParam("portfolio", "1")
+ } When {
+ get()
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to create a scenario for a portfolio.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreateNonExistent() {
+ every { scenarioService.create("testUser", 1, any(), any()) } returns null
+
+ Given {
+ pathParam("project", "1")
+ pathParam("portfolio", "1")
+
+ body(Scenario.Create("test", Workload.Spec("test", 1.0), 1, OperationalPhenomena(false, false), "test"))
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(404)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to create a scenario for a portfolio.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreate() {
+ every { scenarioService.create("testUser", 1, 1, any()) } returns dummyScenario
+
+ Given {
+ pathParam("project", "1")
+ pathParam("portfolio", "1")
+
+ body(Scenario.Create("test", Workload.Spec("test", 1.0), 1, OperationalPhenomena(false, false), "test"))
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ body("id", Matchers.equalTo(1))
+ body("name", Matchers.equalTo("test"))
+ }
+ }
+
+ /**
+ * Test to create a project with an empty body.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreateEmpty() {
+ Given {
+ pathParam("project", "1")
+ pathParam("portfolio", "1")
+
+ body("{}")
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(400)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test to create a project with a blank name.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreateBlankName() {
+ Given {
+ pathParam("project", "1")
+ pathParam("portfolio", "1")
+
+ body(Scenario.Create("", Workload.Spec("test", 1.0), 1, OperationalPhenomena(false, false), "test"))
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(400)
+ contentType(ContentType.JSON)
+ }
+ }
+}
diff --git a/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/ProjectResourceTest.kt b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/ProjectResourceTest.kt
new file mode 100644
index 00000000..bcbcbab1
--- /dev/null
+++ b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/ProjectResourceTest.kt
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.api.rest.user
+
+import io.mockk.every
+import io.quarkiverse.test.junit.mockk.InjectMock
+import io.quarkus.test.common.http.TestHTTPEndpoint
+import io.quarkus.test.junit.QuarkusMock
+import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.security.TestSecurity
+import io.restassured.http.ContentType
+import io.restassured.module.kotlin.extensions.Given
+import io.restassured.module.kotlin.extensions.Then
+import io.restassured.module.kotlin.extensions.When
+import org.hamcrest.Matchers.equalTo
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.opendc.web.api.service.ProjectService
+import org.opendc.web.proto.user.Project
+import org.opendc.web.proto.user.ProjectRole
+import java.time.Instant
+
+/**
+ * Test suite for [ProjectResource].
+ */
+@QuarkusTest
+@TestHTTPEndpoint(ProjectResource::class)
+class ProjectResourceTest {
+ @InjectMock
+ private lateinit var projectService: ProjectService
+
+ /**
+ * Dummy values.
+ */
+ private val dummyProject = Project(0, "test", Instant.now(), Instant.now(), ProjectRole.OWNER)
+
+ @BeforeEach
+ fun setUp() {
+ QuarkusMock.installMockForType(projectService, ProjectService::class.java)
+ }
+
+ /**
+ * Test that tries to obtain all projects without token.
+ */
+ @Test
+ fun testGetAllWithoutToken() {
+ When {
+ get()
+ } Then {
+ statusCode(401)
+ }
+ }
+
+ /**
+ * Test that tries to obtain all projects with an invalid scope.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["runner"])
+ fun testGetAllWithInvalidScope() {
+ When {
+ get()
+ } Then {
+ statusCode(403)
+ }
+ }
+
+ /**
+ * Test that tries to obtain all project for a user.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testGetAll() {
+ val projects = listOf(dummyProject)
+ every { projectService.findWithUser("testUser") } returns projects
+
+ When {
+ get()
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ body("get(0).name", equalTo("test"))
+ }
+ }
+
+ /**
+ * Test that tries to obtain a non-existent project.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testGetNonExisting() {
+ every { projectService.findWithUser("testUser", 1) } returns null
+
+ When {
+ get("/1")
+ } Then {
+ statusCode(404)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a job.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testGetExisting() {
+ every { projectService.findWithUser("testUser", 1) } returns dummyProject
+
+ When {
+ get("/1")
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ body("id", equalTo(0))
+ }
+ }
+
+ /**
+ * Test that tries to create a project.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreate() {
+ every { projectService.createForUser("testUser", "test") } returns dummyProject
+
+ Given {
+ body(Project.Create("test"))
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ body("id", equalTo(0))
+ body("name", equalTo("test"))
+ }
+ }
+
+ /**
+ * Test to create a project with an empty body.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreateEmpty() {
+ Given {
+ body("{}")
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(400)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test to create a project with a blank name.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreateBlankName() {
+ Given {
+ body(Project.Create(""))
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(400)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test to delete a non-existent project.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testDeleteNonExistent() {
+ every { projectService.deleteWithUser("testUser", 1) } returns null
+
+ When {
+ delete("/1")
+ } Then {
+ statusCode(404)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test to delete a project.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testDelete() {
+ every { projectService.deleteWithUser("testUser", 1) } returns dummyProject
+
+ When {
+ delete("/1")
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test to delete a project which the user does not own.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testDeleteNonOwner() {
+ every { projectService.deleteWithUser("testUser", 1) } throws IllegalArgumentException("User does not own project")
+
+ When {
+ delete("/1")
+ } Then {
+ statusCode(403)
+ contentType(ContentType.JSON)
+ }
+ }
+}
diff --git a/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/ScenarioResourceTest.kt b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/ScenarioResourceTest.kt
new file mode 100644
index 00000000..65e6e9a1
--- /dev/null
+++ b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/ScenarioResourceTest.kt
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.api.rest.user
+
+import io.mockk.every
+import io.quarkiverse.test.junit.mockk.InjectMock
+import io.quarkus.test.common.http.TestHTTPEndpoint
+import io.quarkus.test.junit.QuarkusMock
+import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.security.TestSecurity
+import io.restassured.http.ContentType
+import io.restassured.module.kotlin.extensions.Given
+import io.restassured.module.kotlin.extensions.Then
+import io.restassured.module.kotlin.extensions.When
+import org.hamcrest.Matchers
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.opendc.web.api.service.ScenarioService
+import org.opendc.web.proto.*
+import org.opendc.web.proto.user.*
+import java.time.Instant
+
+/**
+ * Test suite for [ScenarioResource].
+ */
+@QuarkusTest
+@TestHTTPEndpoint(ScenarioResource::class)
+class ScenarioResourceTest {
+ @InjectMock
+ private lateinit var scenarioService: ScenarioService
+
+ /**
+ * Dummy values
+ */
+ private val dummyProject = Project(0, "test", Instant.now(), Instant.now(), ProjectRole.OWNER)
+ private val dummyPortfolio = Portfolio.Summary(1, 1, "test", Targets(emptySet()))
+ private val dummyJob = Job(1, JobState.PENDING, Instant.now(), Instant.now(), null)
+ private val dummyTrace = Trace("bitbrains", "Bitbrains", "vm")
+ private val dummyTopology = Topology.Summary(1, 1, "test", Instant.now(), Instant.now())
+ private val dummyScenario = Scenario(
+ 1,
+ 1,
+ dummyProject,
+ dummyPortfolio,
+ "test",
+ Workload(dummyTrace, 1.0),
+ dummyTopology,
+ OperationalPhenomena(false, false),
+ "test",
+ dummyJob
+ )
+
+ @BeforeEach
+ fun setUp() {
+ QuarkusMock.installMockForType(scenarioService, ScenarioService::class.java)
+ }
+
+ /**
+ * Test that tries to obtain a scenario without token.
+ */
+ @Test
+ fun testGetWithoutToken() {
+ Given {
+ pathParam("project", "1")
+ } When {
+ get("/1")
+ } Then {
+ statusCode(401)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a scenario with an invalid scope.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["runner"])
+ fun testGetInvalidToken() {
+ Given {
+ pathParam("project", "1")
+ } When {
+ get("/1")
+ } Then {
+ statusCode(403)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a non-existent scenario.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testGetNonExisting() {
+ every { scenarioService.findOne("testUser", 1, 1) } returns null
+
+ Given {
+ pathParam("project", "1")
+ } When {
+ get("/1")
+ } Then {
+ statusCode(404)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a scenario.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testGetExisting() {
+ every { scenarioService.findOne("testUser", 1, 1) } returns dummyScenario
+
+ Given {
+ pathParam("project", "1")
+ } When {
+ get("/1")
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ body("id", Matchers.equalTo(1))
+ }
+ }
+
+ /**
+ * Test to delete a non-existent scenario.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testDeleteNonExistent() {
+ every { scenarioService.delete("testUser", 1, 1) } returns null
+
+ Given {
+ pathParam("project", "1")
+ } When {
+ delete("/1")
+ } Then {
+ statusCode(404)
+ }
+ }
+
+ /**
+ * Test to delete a scenario.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testDelete() {
+ every { scenarioService.delete("testUser", 1, 1) } returns dummyScenario
+
+ Given {
+ pathParam("project", "1")
+ } When {
+ delete("/1")
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ }
+ }
+}
diff --git a/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/TopologyResourceTest.kt b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/TopologyResourceTest.kt
new file mode 100644
index 00000000..ececeaca
--- /dev/null
+++ b/opendc-web/opendc-web-api/src/test/kotlin/org/opendc/web/api/rest/user/TopologyResourceTest.kt
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2022 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.web.api.rest.user
+
+import io.mockk.every
+import io.quarkiverse.test.junit.mockk.InjectMock
+import io.quarkus.test.common.http.TestHTTPEndpoint
+import io.quarkus.test.junit.QuarkusMock
+import io.quarkus.test.junit.QuarkusTest
+import io.quarkus.test.security.TestSecurity
+import io.restassured.http.ContentType
+import io.restassured.module.kotlin.extensions.Given
+import io.restassured.module.kotlin.extensions.Then
+import io.restassured.module.kotlin.extensions.When
+import org.hamcrest.Matchers
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.opendc.web.api.service.TopologyService
+import org.opendc.web.proto.user.Project
+import org.opendc.web.proto.user.ProjectRole
+import org.opendc.web.proto.user.Topology
+import java.time.Instant
+
+/**
+ * Test suite for [TopologyResource].
+ */
+@QuarkusTest
+@TestHTTPEndpoint(TopologyResource::class)
+class TopologyResourceTest {
+ @InjectMock
+ private lateinit var topologyService: TopologyService
+
+ /**
+ * Dummy project and topology.
+ */
+ private val dummyProject = Project(1, "test", Instant.now(), Instant.now(), ProjectRole.OWNER)
+ private val dummyTopology = Topology(1, 1, dummyProject, "test", emptyList(), Instant.now(), Instant.now())
+
+ @BeforeEach
+ fun setUp() {
+ QuarkusMock.installMockForType(topologyService, TopologyService::class.java)
+ }
+
+ /**
+ * Test that tries to obtain the list of topologies belonging to a project.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testGetForProject() {
+ every { topologyService.findAll("testUser", 1) } returns emptyList()
+
+ Given {
+ pathParam("project", "1")
+ } When {
+ get()
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to create a topology for a project.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreateNonExistent() {
+ every { topologyService.create("testUser", 1, any()) } returns null
+
+ Given {
+ pathParam("project", "1")
+
+ body(Topology.Create("test", emptyList()))
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(404)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to create a topology for a project.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreate() {
+ every { topologyService.create("testUser", 1, any()) } returns dummyTopology
+
+ Given {
+ pathParam("project", "1")
+
+ body(Topology.Create("test", emptyList()))
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ body("id", Matchers.equalTo(1))
+ body("name", Matchers.equalTo("test"))
+ }
+ }
+
+ /**
+ * Test to create a topology with an empty body.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreateEmpty() {
+ Given {
+ pathParam("project", "1")
+
+ body("{}")
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(400)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test to create a topology with a blank name.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testCreateBlankName() {
+ Given {
+ pathParam("project", "1")
+
+ body(Topology.Create("", emptyList()))
+ contentType(ContentType.JSON)
+ } When {
+ post()
+ } Then {
+ statusCode(400)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a topology without token.
+ */
+ @Test
+ fun testGetWithoutToken() {
+ Given {
+ pathParam("project", "1")
+ } When {
+ get("/1")
+ } Then {
+ statusCode(401)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a topology with an invalid scope.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["runner"])
+ fun testGetInvalidToken() {
+ Given {
+ pathParam("project", "1")
+ } When {
+ get("/1")
+ } Then {
+ statusCode(403)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a non-existent topology.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testGetNonExisting() {
+ every { topologyService.findOne("testUser", 1, 1) } returns null
+
+ Given {
+ pathParam("project", "1")
+ } When {
+ get("/1")
+ } Then {
+ statusCode(404)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test that tries to obtain a topology.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testGetExisting() {
+ every { topologyService.findOne("testUser", 1, 1) } returns dummyTopology
+
+ Given {
+ pathParam("project", "1")
+ } When {
+ get("/1")
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ body("id", Matchers.equalTo(1))
+ println(extract().asPrettyString())
+ }
+ }
+
+ /**
+ * Test to delete a non-existent topology.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testUpdateNonExistent() {
+ every { topologyService.update("testUser", any(), any(), any()) } returns null
+
+ Given {
+ pathParam("project", "1")
+ body(Topology.Update(emptyList()))
+ contentType(ContentType.JSON)
+ } When {
+ put("/1")
+ } Then {
+ statusCode(404)
+ }
+ }
+
+ /**
+ * Test to update a topology.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testUpdate() {
+ every { topologyService.update("testUser", any(), any(), any()) } returns dummyTopology
+
+ Given {
+ pathParam("project", "1")
+ body(Topology.Update(emptyList()))
+ contentType(ContentType.JSON)
+ } When {
+ put("/1")
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ }
+ }
+
+ /**
+ * Test to delete a non-existent topology.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testDeleteNonExistent() {
+ every { topologyService.delete("testUser", 1, 1) } returns null
+
+ Given {
+ pathParam("project", "1")
+ } When {
+ delete("/1")
+ } Then {
+ statusCode(404)
+ }
+ }
+
+ /**
+ * Test to delete a topology.
+ */
+ @Test
+ @TestSecurity(user = "testUser", roles = ["openid"])
+ fun testDelete() {
+ every { topologyService.delete("testUser", 1, 1) } returns dummyTopology
+
+ Given {
+ pathParam("project", "1")
+ } When {
+ delete("/1")
+ } Then {
+ statusCode(200)
+ contentType(ContentType.JSON)
+ }
+ }
+}