diff options
Diffstat (limited to 'opendc-web/opendc-web-server/src/test')
16 files changed, 1432 insertions, 1567 deletions
diff --git a/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/SchedulerResourceTest.kt b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/SchedulerResourceTest.java index c1460db9..feeac4d3 100644 --- a/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/SchedulerResourceTest.kt +++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/SchedulerResourceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 AtLarge Research + * Copyright (c) 2023 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 @@ -20,29 +20,26 @@ * SOFTWARE. */ -package org.opendc.web.server.rest +package org.opendc.web.server.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 +import static io.restassured.RestAssured.when; + +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.http.ContentType; +import org.junit.jupiter.api.Test; /** - * Test suite for [SchedulerResource] + * Test suite for {@link SchedulerResource}. */ @QuarkusTest -class SchedulerResourceTest { +@TestHTTPEndpoint(SchedulerResource.class) +public final class SchedulerResourceTest { /** * Test to verify whether we can obtain all schedulers. */ @Test - fun testGetSchedulers() { - When { - get("/schedulers") - } Then { - statusCode(200) - contentType(ContentType.JSON) - } + public void testGetSchedulers() { + when().get().then().statusCode(200).contentType(ContentType.JSON); } } diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/TraceResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/TraceResourceTest.java new file mode 100644 index 00000000..ebef3945 --- /dev/null +++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/TraceResourceTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2023 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.server.rest; + +import static io.restassured.RestAssured.when; +import static org.hamcrest.Matchers.equalTo; + +import io.quarkus.panache.mock.PanacheMock; +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.http.ContentType; +import java.util.stream.Stream; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.opendc.web.server.model.Trace; + +/** + * Test suite for {@link TraceResource}. + */ +@QuarkusTest +@TestHTTPEndpoint(TraceResource.class) +public final class TraceResourceTest { + /** + * Set up the test environment. + */ + @BeforeEach + public void setUp() { + PanacheMock.mock(Trace.class); + } + + /** + * Test that tries to obtain all traces (empty response). + */ + @Test + public void testGetAllEmpty() { + Mockito.when(Trace.streamAll()).thenReturn(Stream.of()); + + when().get().then().statusCode(200).contentType(ContentType.JSON).body("", Matchers.empty()); + } + + /** + * Test that tries to obtain a non-existent trace. + */ + @Test + public void testGetNonExisting() { + Mockito.when(Trace.findById("bitbrains")).thenReturn(null); + + when().get("/bitbrains").then().statusCode(404).contentType(ContentType.JSON); + } + + /** + * Test that tries to obtain an existing trace. + */ + @Test + public void testGetExisting() { + Mockito.when(Trace.findById("bitbrains")).thenReturn(new Trace("bitbrains", "Bitbrains", "VM")); + + when().get("/bitbrains") + .then() + .statusCode(200) + .contentType(ContentType.JSON) + .body("name", equalTo("Bitbrains")); + } +} diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/runner/JobResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/runner/JobResourceTest.java new file mode 100644 index 00000000..a163cd29 --- /dev/null +++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/runner/JobResourceTest.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2023 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.server.rest.runner; + +import static io.restassured.RestAssured.given; +import static io.restassured.RestAssured.when; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; + +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.mockito.InjectMock; +import io.quarkus.test.security.TestSecurity; +import io.restassured.http.ContentType; +import java.time.Instant; +import java.util.List; +import java.util.Set; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.opendc.web.proto.JobState; +import org.opendc.web.proto.OperationalPhenomena; +import org.opendc.web.proto.Targets; +import org.opendc.web.proto.Trace; +import org.opendc.web.proto.Workload; +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 org.opendc.web.server.service.JobService; + +/** + * Test suite for {@link JobResource}. + */ +@QuarkusTest +@TestHTTPEndpoint(JobResource.class) +public final class JobResourceTest { + @InjectMock + private JobService jobService; + + /** + * Dummy values + */ + private final Portfolio dummyPortfolio = new Portfolio(1, 1, "test", new Targets(Set.of(), 1)); + + private final Topology dummyTopology = new Topology(1, 1, "test", List.of(), Instant.now(), Instant.now()); + private final Trace dummyTrace = new Trace("bitbrains", "Bitbrains", "vm"); + private final Scenario dummyScenario = new Scenario( + 1, + 1, + dummyPortfolio, + "test", + new Workload(dummyTrace, 1.0), + dummyTopology, + new OperationalPhenomena(false, false), + "test"); + private final Job dummyJob = new Job(1, dummyScenario, JobState.PENDING, Instant.now(), Instant.now(), 0, null); + + /** + * Test that tries to query the pending jobs without token. + */ + @Test + public void testQueryWithoutToken() { + when().get().then().statusCode(401); + } + + /** + * Test that tries to query the pending jobs for a user. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void testQueryInvalidScope() { + when().get().then().statusCode(403); + } + + /** + * Test that tries to query the pending jobs for a runner. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"runner"}) + public void testQuery() { + Mockito.when(jobService.listPending()).thenReturn(List.of(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"}) + public void testGetNonExisting() { + Mockito.when(jobService.findById(1)).thenReturn(null); + + when().get("/1").then().statusCode(404).contentType(ContentType.JSON); + } + + /** + * Test that tries to obtain a job. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"runner"}) + public void testGetExisting() { + Mockito.when(jobService.findById(1)).thenReturn(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"}) + public void testUpdateNonExistent() { + Mockito.when(jobService.updateState(eq(1L), any(), anyInt(), any())).thenReturn(null); + + given().body(new Job.Update(JobState.PENDING, 0, null)) + .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"}) + public void testUpdateState() { + Mockito.when(jobService.updateState(eq(1L), any(), anyInt(), any())) + .thenReturn(new Job(1, dummyScenario, JobState.CLAIMED, Instant.now(), Instant.now(), 0, null)); + + given().body(new Job.Update(JobState.CLAIMED, 0, null)) + .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"}) + public void testUpdateInvalidInput() { + given().body("{ \"test\": \"test\" }") + .contentType(ContentType.JSON) + .when() + .post("/1") + .then() + .statusCode(400) + .contentType(ContentType.JSON); + } +} diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioResourceTest.java new file mode 100644 index 00000000..cc3ac978 --- /dev/null +++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioResourceTest.java @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2023 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.server.rest.user; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; + +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.mockito.InjectMock; +import io.quarkus.test.security.TestSecurity; +import io.restassured.http.ContentType; +import java.time.Instant; +import java.util.List; +import java.util.Set; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +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 org.opendc.web.server.service.PortfolioService; + +/** + * Test suite for {@link PortfolioResource}. + */ +@QuarkusTest +@TestHTTPEndpoint(PortfolioResource.class) +public final class PortfolioResourceTest { + @InjectMock + private PortfolioService portfolioService; + + /** + * Dummy project and portfolio + */ + private final Project dummyProject = new Project(1, "test", Instant.now(), Instant.now(), ProjectRole.OWNER); + + private final Portfolio dummyPortfolio = + new Portfolio(1, 1, dummyProject, "test", new Targets(Set.of(), 1), List.of()); + + /** + * Test that tries to obtain the list of portfolios belonging to a project. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void testGetForProject() { + Mockito.when(portfolioService.findByUser("testUser", 1)).thenReturn(List.of()); + + 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"}) + public void testCreateNonExistent() { + Mockito.when(portfolioService.create(eq("testUser"), eq(1), any())).thenReturn(null); + + given().pathParam("project", "1") + .body(new Portfolio.Create("test", new Targets(Set.of(), 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"}) + public void testCreate() { + Mockito.when(portfolioService.create(eq("testUser"), eq(1L), any())).thenReturn(dummyPortfolio); + + given().pathParam("project", "1") + .body(new Portfolio.Create("test", new Targets(Set.of(), 1))) + .contentType(ContentType.JSON) + .when() + .post() + .then() + .statusCode(200) + .contentType(ContentType.JSON) + .body("id", equalTo(1)) + .body("name", equalTo("test")); + } + + /** + * Test to create a portfolio with an empty body. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void 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"}) + public void testCreateBlankName() { + given().pathParam("project", "1") + .body(new Portfolio.Create("", new Targets(Set.of(), 1))) + .contentType(ContentType.JSON) + .when() + .post() + .then() + .statusCode(400) + .contentType(ContentType.JSON); + } + + /** + * Test that tries to obtain a portfolio without token. + */ + @Test + public void 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"}) + public void 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"}) + public void testGetNonExisting() { + Mockito.when(portfolioService.findByUser("testUser", 1, 1)).thenReturn(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"}) + public void testGetExisting() { + Mockito.when(portfolioService.findByUser("testUser", 1, 1)).thenReturn(dummyPortfolio); + + given().pathParam("project", "1") + .when() + .get("/1") + .then() + .statusCode(200) + .contentType(ContentType.JSON) + .body("id", equalTo(1)); + } + + /** + * Test to delete a non-existent portfolio. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void testDeleteNonExistent() { + Mockito.when(portfolioService.delete("testUser", 1, 1)).thenReturn(null); + + given().pathParam("project", "1").when().delete("/1").then().statusCode(404); + } + + /** + * Test to delete a portfolio. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void testDelete() { + Mockito.when(portfolioService.delete("testUser", 1, 1)).thenReturn(dummyPortfolio); + + given().pathParam("project", "1") + .when() + .delete("/1") + .then() + .statusCode(200) + .contentType(ContentType.JSON); + } +} diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioScenarioResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioScenarioResourceTest.java new file mode 100644 index 00000000..8cb95a98 --- /dev/null +++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioScenarioResourceTest.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2023 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.server.rest.user; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; + +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.mockito.InjectMock; +import io.quarkus.test.security.TestSecurity; +import io.restassured.http.ContentType; +import java.time.Instant; +import java.util.List; +import java.util.Set; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.opendc.web.proto.JobState; +import org.opendc.web.proto.OperationalPhenomena; +import org.opendc.web.proto.Targets; +import org.opendc.web.proto.Trace; +import org.opendc.web.proto.Workload; +import org.opendc.web.proto.user.Job; +import org.opendc.web.proto.user.Portfolio; +import org.opendc.web.proto.user.Project; +import org.opendc.web.proto.user.ProjectRole; +import org.opendc.web.proto.user.Scenario; +import org.opendc.web.proto.user.Topology; +import org.opendc.web.server.service.ScenarioService; + +/** + * Test suite for {@link PortfolioScenarioResource}. + */ +@QuarkusTest +@TestHTTPEndpoint(PortfolioScenarioResource.class) +public final class PortfolioScenarioResourceTest { + @InjectMock + private ScenarioService scenarioService; + + /** + * Dummy values + */ + private final Project dummyProject = new Project(0, "test", Instant.now(), Instant.now(), ProjectRole.OWNER); + + private final Portfolio.Summary dummyPortfolio = new Portfolio.Summary(1, 1, "test", new Targets(Set.of(), 1)); + private final Job dummyJob = new Job(1, JobState.PENDING, Instant.now(), Instant.now(), null); + private final Trace dummyTrace = new Trace("bitbrains", "Bitbrains", "vm"); + private final Topology.Summary dummyTopology = new Topology.Summary(1, 1, "test", Instant.now(), Instant.now()); + private final Scenario dummyScenario = new Scenario( + 1, + 1, + dummyProject, + dummyPortfolio, + "test", + new Workload(dummyTrace, 1.0), + dummyTopology, + new OperationalPhenomena(false, false), + "test", + dummyJob); + + /** + * Test that tries to obtain a portfolio without token. + */ + @Test + public void 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"}) + public void 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"}) + public void testGet() { + Mockito.when(scenarioService.findAll("testUser", 1, 1)).thenReturn(List.of()); + + 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"}) + public void testCreateNonExistent() { + Mockito.when(scenarioService.create(eq("testUser"), eq(1L), anyInt(), any())) + .thenReturn(null); + + given().pathParam("project", "1") + .pathParam("portfolio", "1") + .body(new Scenario.Create( + "test", new Workload.Spec("test", 1.0), 1, new 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"}) + public void testCreate() { + Mockito.when(scenarioService.create(eq("testUser"), eq(1L), eq(1), any())) + .thenReturn(dummyScenario); + + given().pathParam("project", "1") + .pathParam("portfolio", "1") + .body(new Scenario.Create( + "test", new Workload.Spec("test", 1.0), 1, new OperationalPhenomena(false, false), "test")) + .contentType(ContentType.JSON) + .when() + .post() + .then() + .statusCode(200) + .contentType(ContentType.JSON) + .body("id", equalTo(1)) + .body("name", equalTo("test")); + } + + /** + * Test to create a project with an empty body. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void 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"}) + public void testCreateBlankName() { + given().pathParam("project", "1") + .pathParam("portfolio", "1") + .body(new Scenario.Create( + "", new Workload.Spec("test", 1.0), 1, new OperationalPhenomena(false, false), "test")) + .contentType(ContentType.JSON) + .when() + .post() + .then() + .statusCode(400) + .contentType(ContentType.JSON); + } +} diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ProjectResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ProjectResourceTest.java new file mode 100644 index 00000000..7ca314a6 --- /dev/null +++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ProjectResourceTest.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2023 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.server.rest.user; + +import static io.restassured.RestAssured.given; +import static io.restassured.RestAssured.when; +import static org.hamcrest.Matchers.equalTo; + +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.mockito.InjectMock; +import io.quarkus.test.security.TestSecurity; +import io.restassured.http.ContentType; +import java.time.Instant; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.opendc.web.proto.user.Project; +import org.opendc.web.proto.user.ProjectRole; +import org.opendc.web.server.service.ProjectService; + +/** + * Test suite for [ProjectResource]. + */ +@QuarkusTest +@TestHTTPEndpoint(ProjectResource.class) +public final class ProjectResourceTest { + @InjectMock + private ProjectService projectService; + + /** + * Dummy values. + */ + private final Project dummyProject = new Project(0, "test", Instant.now(), Instant.now(), ProjectRole.OWNER); + + /** + * Test that tries to obtain all projects without token. + */ + @Test + public void testGetAllWithoutToken() { + when().get().then().statusCode(401); + } + + /** + * Test that tries to obtain all projects with an invalid scope. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"runner"}) + public void testGetAllWithInvalidScope() { + when().get().then().statusCode(403); + } + + /** + * Test that tries to obtain all project for a user. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void testGetAll() { + Mockito.when(projectService.findByUser("testUser")).thenReturn(List.of(dummyProject)); + + 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"}) + public void testGetNonExisting() { + Mockito.when(projectService.findByUser("testUser", 1)).thenReturn(null); + + when().get("/1").then().statusCode(404).contentType(ContentType.JSON); + } + + /** + * Test that tries to obtain a job. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void testGetExisting() { + Mockito.when(projectService.findByUser("testUser", 1)).thenReturn(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"}) + public void testCreate() { + Mockito.when(projectService.create("testUser", "test")).thenReturn(dummyProject); + + given().body(new 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"}) + public void 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"}) + public void testCreateBlankName() { + given().body(new 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"}) + public void testDeleteNonExistent() { + Mockito.when(projectService.delete("testUser", 1)).thenReturn(null); + + when().delete("/1").then().statusCode(404).contentType(ContentType.JSON); + } + + /** + * Test to delete a project. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void testDelete() { + Mockito.when(projectService.delete("testUser", 1)).thenReturn(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"}) + public void testDeleteNonOwner() { + Mockito.when(projectService.delete("testUser", 1)) + .thenThrow(new IllegalArgumentException("User does not own project")); + + when().delete("/1").then().statusCode(403).contentType(ContentType.JSON); + } +} diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ScenarioResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ScenarioResourceTest.java new file mode 100644 index 00000000..850236d6 --- /dev/null +++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ScenarioResourceTest.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2023 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.server.rest.user; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.equalTo; + +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.mockito.InjectMock; +import io.quarkus.test.security.TestSecurity; +import io.restassured.http.ContentType; +import java.time.Instant; +import java.util.Set; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.opendc.web.proto.JobState; +import org.opendc.web.proto.OperationalPhenomena; +import org.opendc.web.proto.Targets; +import org.opendc.web.proto.Trace; +import org.opendc.web.proto.Workload; +import org.opendc.web.proto.user.Job; +import org.opendc.web.proto.user.Portfolio; +import org.opendc.web.proto.user.Project; +import org.opendc.web.proto.user.ProjectRole; +import org.opendc.web.proto.user.Scenario; +import org.opendc.web.proto.user.Topology; +import org.opendc.web.server.service.ScenarioService; + +/** + * Test suite for [ScenarioResource]. + */ +@QuarkusTest +@TestHTTPEndpoint(ScenarioResource.class) +public final class ScenarioResourceTest { + @InjectMock + private ScenarioService scenarioService; + + /** + * Dummy values + */ + private final Project dummyProject = new Project(0, "test", Instant.now(), Instant.now(), ProjectRole.OWNER); + + private final Portfolio.Summary dummyPortfolio = new Portfolio.Summary(1, 1, "test", new Targets(Set.of(), 1)); + private final Job dummyJob = new Job(1, JobState.PENDING, Instant.now(), Instant.now(), null); + private final Trace dummyTrace = new Trace("bitbrains", "Bitbrains", "vm"); + private final Topology.Summary dummyTopology = new Topology.Summary(1, 1, "test", Instant.now(), Instant.now()); + private final Scenario dummyScenario = new Scenario( + 1, + 1, + dummyProject, + dummyPortfolio, + "test", + new Workload(dummyTrace, 1.0), + dummyTopology, + new OperationalPhenomena(false, false), + "test", + dummyJob); + + /** + * Test that tries to obtain a scenario without token. + */ + @Test + public void 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"}) + public void 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"}) + public void testGetNonExisting() { + Mockito.when(scenarioService.findOne("testUser", 1, 1)).thenReturn(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"}) + public void testGetExisting() { + Mockito.when(scenarioService.findOne("testUser", 1, 1)).thenReturn(dummyScenario); + + given().pathParam("project", "1") + .when() + .get("/1") + .then() + .statusCode(200) + .contentType(ContentType.JSON) + .body("id", equalTo(1)); + } + + /** + * Test to delete a non-existent scenario. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void testDeleteNonExistent() { + Mockito.when(scenarioService.delete("testUser", 1, 1)).thenReturn(null); + + given().pathParam("project", "1").when().delete("/1").then().statusCode(404); + } + + /** + * Test to delete a scenario. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void testDelete() { + Mockito.when(scenarioService.delete("testUser", 1, 1)).thenReturn(dummyScenario); + + given().pathParam("project", "1") + .when() + .delete("/1") + .then() + .statusCode(200) + .contentType(ContentType.JSON); + } +} diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/TopologyResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/TopologyResourceTest.java new file mode 100644 index 00000000..2cc6ea4b --- /dev/null +++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/TopologyResourceTest.java @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2023 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.server.rest.user; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; + +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.mockito.InjectMock; +import io.quarkus.test.security.TestSecurity; +import io.restassured.http.ContentType; +import java.time.Instant; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.opendc.web.proto.user.Project; +import org.opendc.web.proto.user.ProjectRole; +import org.opendc.web.proto.user.Topology; +import org.opendc.web.server.service.TopologyService; + +/** + * Test suite for {@link TopologyResource}. + */ +@QuarkusTest +@TestHTTPEndpoint(TopologyResource.class) +public final class TopologyResourceTest { + @InjectMock + private TopologyService topologyService; + + /** + * Dummy project and topology. + */ + private final Project dummyProject = new Project(1, "test", Instant.now(), Instant.now(), ProjectRole.OWNER); + + private final Topology dummyTopology = + new Topology(1, 1, dummyProject, "test", List.of(), Instant.now(), Instant.now()); + + /** + * Test that tries to obtain the list of topologies belonging to a project. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void testGetForProject() { + Mockito.when(topologyService.findAll("testUser", 1)).thenReturn(List.of()); + + 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"}) + public void testCreateNonExistent() { + Mockito.when(topologyService.create(eq("testUser"), eq(1L), any())).thenReturn(null); + + given().pathParam("project", "1") + .body(new Topology.Create("test", List.of())) + .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"}) + public void testCreate() { + Mockito.when(topologyService.create(eq("testUser"), eq(1L), any())).thenReturn(dummyTopology); + + given().pathParam("project", "1") + .body(new Topology.Create("test", List.of())) + .contentType(ContentType.JSON) + .when() + .post() + .then() + .statusCode(200) + .contentType(ContentType.JSON) + .body("id", equalTo(1)) + .body("name", equalTo("test")); + } + + /** + * Test to create a topology with an empty body. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void 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"}) + public void testCreateBlankName() { + given().pathParam("project", "1") + .body(new Topology.Create("", List.of())) + .contentType(ContentType.JSON) + .when() + .post() + .then() + .statusCode(400) + .contentType(ContentType.JSON); + } + + /** + * Test that tries to obtain a topology without token. + */ + @Test + public void 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"}) + public void 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"}) + public void testGetNonExisting() { + Mockito.when(topologyService.findOne("testUser", 1, 1)).thenReturn(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"}) + public void testGetExisting() { + Mockito.when(topologyService.findOne("testUser", 1, 1)).thenReturn(dummyTopology); + + given().pathParam("project", "1") + .when() + .get("/1") + .then() + .statusCode(200) + .contentType(ContentType.JSON) + .body("id", equalTo(1)); + } + + /** + * Test to delete a non-existent topology. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void testUpdateNonExistent() { + Mockito.when(topologyService.update(eq("testUser"), anyLong(), anyInt(), any())) + .thenReturn(null); + + given().pathParam("project", "1") + .body(new Topology.Update(List.of())) + .contentType(ContentType.JSON) + .when() + .put("/1") + .then() + .statusCode(404); + } + + /** + * Test to update a topology. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void testUpdate() { + Mockito.when(topologyService.update(eq("testUser"), anyLong(), anyInt(), any())) + .thenReturn(dummyTopology); + + given().pathParam("project", "1") + .body(new Topology.Update(List.of())) + .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"}) + public void testDeleteNonExistent() { + Mockito.when(topologyService.delete("testUser", 1, 1)).thenReturn(null); + + given().pathParam("project", "1").when().delete("/1").then().statusCode(404); + } + + /** + * Test to delete a topology. + */ + @Test + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void testDelete() { + Mockito.when(topologyService.delete("testUser", 1, 1)).thenReturn(dummyTopology); + + given().pathParam("project", "1") + .when() + .delete("/1") + .then() + .statusCode(200) + .contentType(ContentType.JSON); + } +} diff --git a/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/user/UserResourceTest.kt b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/UserResourceTest.java index 36af20f4..6dcb3b4d 100644 --- a/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/user/UserResourceTest.kt +++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/UserResourceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 AtLarge Research + * Copyright (c) 2023 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 @@ -20,50 +20,46 @@ * SOFTWARE. */ -package org.opendc.web.server.rest.user +package org.opendc.web.server.rest.user; -import io.quarkus.test.common.http.TestHTTPEndpoint -import io.quarkus.test.junit.QuarkusTest -import io.quarkus.test.security.TestSecurity -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.junit.jupiter.api.Test +import static io.restassured.RestAssured.when; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; + +import io.quarkus.test.common.http.TestHTTPEndpoint; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.security.TestSecurity; +import io.restassured.http.ContentType; +import org.junit.jupiter.api.Test; /** * Test suite for [UserResource]. */ @QuarkusTest -@TestHTTPEndpoint(UserResource::class) -class UserResourceTest { +@TestHTTPEndpoint(UserResource.class) +public final class UserResourceTest { /** * Test that tries to obtain the profile of the active user. */ @Test - @TestSecurity(user = "testUser", roles = ["openid"]) - fun testMe() { - When { - get("me") - } Then { - statusCode(200) - contentType(ContentType.JSON) - - body("userId", Matchers.equalTo("testUser")) - body("accounting.simulationTime", Matchers.equalTo(0)) - body("accounting.simulationTimeBudget", Matchers.greaterThan(0)) - } + @TestSecurity( + user = "testUser", + roles = {"openid"}) + public void testMe() { + when().get("me") + .then() + .statusCode(200) + .contentType(ContentType.JSON) + .body("userId", equalTo("testUser")) + .body("accounting.simulationTime", equalTo(0)) + .body("accounting.simulationTimeBudget", greaterThan(0)); } /** * Test that tries to obtain the profile of the active user without authorization. */ @Test - fun testMeUnauthorized() { - When { - get("me") - } Then { - statusCode(401) - } + public void testMeUnauthorized() { + when().get("me").then().statusCode(401); } } diff --git a/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/TraceResourceTest.kt b/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/TraceResourceTest.kt deleted file mode 100644 index 2490cf46..00000000 --- a/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/TraceResourceTest.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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.server.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.proto.Trace -import org.opendc.web.server.service.TraceService - -/** - * 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-server/src/test/kotlin/org/opendc/web/server/rest/runner/JobResourceTest.kt b/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/runner/JobResourceTest.kt deleted file mode 100644 index 753b9ac4..00000000 --- a/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/runner/JobResourceTest.kt +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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.server.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.proto.JobState -import org.opendc.web.proto.OperationalPhenomena -import org.opendc.web.proto.Targets -import org.opendc.web.proto.Trace -import org.opendc.web.proto.Workload -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 org.opendc.web.server.service.JobService -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(), 0) - - @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.listPending() } 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(), any()) } returns null - - Given { - body(Job.Update(JobState.PENDING, 0)) - 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(), any()) } returns dummyJob.copy(state = JobState.CLAIMED) - - Given { - body(Job.Update(JobState.CLAIMED, 0)) - 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-server/src/test/kotlin/org/opendc/web/server/rest/user/PortfolioResourceTest.kt b/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/user/PortfolioResourceTest.kt deleted file mode 100644 index 3ef63a51..00000000 --- a/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/user/PortfolioResourceTest.kt +++ /dev/null @@ -1,265 +0,0 @@ -/* - * 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.server.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.proto.Targets -import org.opendc.web.proto.user.Portfolio -import org.opendc.web.proto.user.Project -import org.opendc.web.proto.user.ProjectRole -import org.opendc.web.server.service.PortfolioService -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.findByUser("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.findByUser("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.findByUser("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-server/src/test/kotlin/org/opendc/web/server/rest/user/PortfolioScenarioResourceTest.kt b/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/user/PortfolioScenarioResourceTest.kt deleted file mode 100644 index 676a43dc..00000000 --- a/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/user/PortfolioScenarioResourceTest.kt +++ /dev/null @@ -1,222 +0,0 @@ -/* - * 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.server.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.proto.JobState -import org.opendc.web.proto.OperationalPhenomena -import org.opendc.web.proto.Targets -import org.opendc.web.proto.Trace -import org.opendc.web.proto.Workload -import org.opendc.web.proto.user.Job -import org.opendc.web.proto.user.Portfolio -import org.opendc.web.proto.user.Project -import org.opendc.web.proto.user.ProjectRole -import org.opendc.web.proto.user.Scenario -import org.opendc.web.proto.user.Topology -import org.opendc.web.server.service.ScenarioService -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-server/src/test/kotlin/org/opendc/web/server/rest/user/ProjectResourceTest.kt b/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/user/ProjectResourceTest.kt deleted file mode 100644 index 0be56c56..00000000 --- a/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/user/ProjectResourceTest.kt +++ /dev/null @@ -1,240 +0,0 @@ -/* - * 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.server.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.proto.user.Project -import org.opendc.web.proto.user.ProjectRole -import org.opendc.web.server.service.ProjectService -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.findByUser("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.findByUser("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.findByUser("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.create("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.delete("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.delete("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.delete("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-server/src/test/kotlin/org/opendc/web/server/rest/user/ScenarioResourceTest.kt b/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/user/ScenarioResourceTest.kt deleted file mode 100644 index 2e080971..00000000 --- a/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/user/ScenarioResourceTest.kt +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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.server.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.proto.JobState -import org.opendc.web.proto.OperationalPhenomena -import org.opendc.web.proto.Targets -import org.opendc.web.proto.Trace -import org.opendc.web.proto.Workload -import org.opendc.web.proto.user.Job -import org.opendc.web.proto.user.Portfolio -import org.opendc.web.proto.user.Project -import org.opendc.web.proto.user.ProjectRole -import org.opendc.web.proto.user.Scenario -import org.opendc.web.proto.user.Topology -import org.opendc.web.server.service.ScenarioService -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-server/src/test/kotlin/org/opendc/web/server/rest/user/TopologyResourceTest.kt b/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/user/TopologyResourceTest.kt deleted file mode 100644 index 8a542d33..00000000 --- a/opendc-web/opendc-web-server/src/test/kotlin/org/opendc/web/server/rest/user/TopologyResourceTest.kt +++ /dev/null @@ -1,304 +0,0 @@ -/* - * 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.server.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.proto.user.Project -import org.opendc.web.proto.user.ProjectRole -import org.opendc.web.proto.user.Topology -import org.opendc.web.server.service.TopologyService -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) - } - } -} |
