diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2023-01-22 00:30:51 +0000 |
|---|---|---|
| committer | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2023-02-01 22:01:19 +0000 |
| commit | 6927c51885bb3073b310150c4f40c64eea44a919 (patch) | |
| tree | a3da33f2e1653be23008dba15e9b3ed7044ae921 /opendc-web/opendc-web-server/src/test/java/org/opendc/web | |
| parent | e64487cb57ca75d17fe5a8a664c1e8247c7b5168 (diff) | |
refactor(web/server): Convert resources to Java
This change converts the resource classes of the OpenDC web server to
use Java, The Quarkus integration for Java is more mature and the
programming quality of experience is not that much worse.
Diffstat (limited to 'opendc-web/opendc-web-server/src/test/java/org/opendc/web')
9 files changed, 1503 insertions, 0 deletions
diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/SchedulerResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/SchedulerResourceTest.java new file mode 100644 index 00000000..feeac4d3 --- /dev/null +++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/SchedulerResourceTest.java @@ -0,0 +1,45 @@ +/* + * 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 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 {@link SchedulerResource}. + */ +@QuarkusTest +@TestHTTPEndpoint(SchedulerResource.class) +public final class SchedulerResourceTest { + /** + * Test to verify whether we can obtain all schedulers. + */ + @Test + 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/java/org/opendc/web/server/rest/user/UserResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/UserResourceTest.java new file mode 100644 index 00000000..6dcb3b4d --- /dev/null +++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/UserResourceTest.java @@ -0,0 +1,65 @@ +/* + * 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.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) +public final class UserResourceTest { + /** + * Test that tries to obtain the profile of the active user. + */ + @Test + @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 + public void testMeUnauthorized() { + when().get("me").then().statusCode(401); + } +} |
