This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit a803f40081d78d56c8339d6669692fb40d2fdda4 Author: Benoit Tellier <[email protected]> AuthorDate: Thu May 21 15:26:01 2020 +0700 JAMES-3184 Expose RecomputeCurrentQuotasTask RunningOptions over webadmin --- .../james/webadmin/routes/UserQuotaRoutes.java | 20 ++- .../james/webadmin/routes/UserQuotaRoutesTest.java | 152 +++++++++++++++++++++ .../routes/WebAdminQuotaSearchTestSystem.java | 14 +- 3 files changed, 183 insertions(+), 3 deletions(-) diff --git a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java index 4201768..b34e12b 100644 --- a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java +++ b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/UserQuotaRoutes.java @@ -89,9 +89,27 @@ public class UserQuotaRoutes implements Routes { public static final String USER_QUOTAS_OPERATIONS_INJECTION_KEY = "userQuotasOperations"; public static class RecomputeCurrentQuotasRequestToTask extends TaskFromRequestRegistry.TaskRegistration { + private static final String USERS_PER_SECOND = "usersPerSecond"; + @Inject public RecomputeCurrentQuotasRequestToTask(RecomputeCurrentQuotasService service) { - super(RECOMPUTE_CURRENT_QUOTAS, request -> new RecomputeCurrentQuotasTask(service, RunningOptions.DEFAULT)); + super(RECOMPUTE_CURRENT_QUOTAS, request -> new RecomputeCurrentQuotasTask(service,parseRunningOptions(request))); + } + + private static RunningOptions parseRunningOptions(Request request) { + return intQueryParameter(request) + .map(RunningOptions::withUsersPerSecond) + .orElse(RunningOptions.DEFAULT); + } + + private static Optional<Integer> intQueryParameter(Request request) { + try { + return Optional.ofNullable(request.queryParams(USERS_PER_SECOND)) + .map(Integer::parseInt); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(String.format("Illegal value supplied for query parameter '%s', expecting a " + + "strictly positive optional integer", USERS_PER_SECOND), e); + } } } diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserQuotaRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserQuotaRoutesTest.java index d656dcc..e5e1825 100644 --- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserQuotaRoutesTest.java +++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserQuotaRoutesTest.java @@ -28,6 +28,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; @@ -51,6 +54,7 @@ import org.apache.james.mailbox.quota.MaxQuotaManager; import org.apache.james.mailbox.quota.UserQuotaRootResolver; import org.apache.james.quota.search.QuotaSearchTestSystem; import org.apache.james.user.api.UsersRepository; +import org.apache.james.webadmin.utils.ErrorResponder; import org.assertj.core.api.SoftAssertions; import org.eclipse.jetty.http.HttpStatus; import org.junit.jupiter.api.BeforeEach; @@ -1257,4 +1261,152 @@ class UserQuotaRoutesTest { } } + + @Nested + @ExtendWith(ScanningQuotaSearchExtension.class) + class PostRecomputeQuotas { + @Test + void actionRequestParameterShouldBeCompulsory() { + when() + .post("/quota/users") + .then() + .statusCode(HttpStatus.BAD_REQUEST_400) + .body("statusCode", is(400)) + .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType())) + .body("message", is("Invalid arguments supplied in the user request")) + .body("details", is("'task' query parameter is compulsory. Supported values are [RecomputeCurrentQuotas]")); + } + + @Test + void postShouldFailUponEmptyAction() { + given() + .queryParam("task", "") + .post("/quota/users") + .then() + .statusCode(HttpStatus.BAD_REQUEST_400) + .body("statusCode", is(400)) + .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType())) + .body("message", is("Invalid arguments supplied in the user request")) + .body("details", is("'task' query parameter cannot be empty or blank. Supported values are [RecomputeCurrentQuotas]")); + } + + @Test + void postShouldFailUponInvalidAction() { + given() + .queryParam("task", "invalid") + .post("/quota/users") + .then() + .statusCode(HttpStatus.BAD_REQUEST_400) + .body("statusCode", is(400)) + .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType())) + .body("message", is("Invalid arguments supplied in the user request")) + .body("details", is("Invalid value supplied for query parameter 'task': invalid. Supported values are [RecomputeCurrentQuotas]")); + } + + @Test + void postShouldFailWhenUsersPerSecondIsNotAnInt() { + given() + .queryParam("task", "RecomputeCurrentQuotas") + .queryParam("usersPerSecond", "abc") + .post("/quota/users") + .then() + .statusCode(HttpStatus.BAD_REQUEST_400) + .body("statusCode", is(400)) + .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType())) + .body("message", is("Invalid arguments supplied in the user request")) + .body("details", is("Illegal value supplied for query parameter 'usersPerSecond', expecting a strictly positive optional integer")); + } + + @Test + void postShouldFailWhenUsersPerSecondIsNegative() { + given() + .queryParam("task", "RecomputeCurrentQuotas") + .queryParam("usersPerSecond", "-1") + .post("/quota/users") + .then() + .statusCode(HttpStatus.BAD_REQUEST_400) + .body("statusCode", is(400)) + .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType())) + .body("message", is("Invalid arguments supplied in the user request")) + .body("details", is("'usersPerSecond' needs to be strictly positive")); + } + + @Test + void postShouldFailWhenUsersPerSecondIsZero() { + given() + .queryParam("task", "RecomputeCurrentQuotas") + .queryParam("usersPerSecond", "0") + .post("/quota/users") + .then() + .statusCode(HttpStatus.BAD_REQUEST_400) + .body("statusCode", is(400)) + .body("type", is(ErrorResponder.ErrorType.INVALID_ARGUMENT.getType())) + .body("message", is("Invalid arguments supplied in the user request")) + .body("details", is("'usersPerSecond' needs to be strictly positive")); + } + + @Test + void postShouldCreateANewTask() { + given() + .queryParam("task", "RecomputeCurrentQuotas") + .post("/quota/users") + .then() + .statusCode(HttpStatus.CREATED_201) + .body("taskId", notNullValue()); + } + + @Test + void postShouldCreateANewTaskWhenConcurrencyParametersAreSpecified() { + given() + .queryParam("task", "RecomputeCurrentQuotas") + .queryParam("usersPerSecond", "1") + .post("/quota/users") + .then() + .statusCode(HttpStatus.CREATED_201) + .body("taskId", notNullValue()); + } + + @Test + void recomputeAllShouldCompleteWhenNoUser() { + String taskId = with() + .queryParam("task", "RecomputeCurrentQuotas") + .post("/quota/users") + .jsonPath() + .get("taskId"); + + given() + .basePath(TasksRoutes.BASE) + .when() + .get(taskId + "/await") + .then() + .body("status", is("completed")) + .body("taskId", is(taskId)) + .body("type", is("recompute-current-quotas")) + .body("additionalInformation.processedQuotaRoots", is(0)) + .body("additionalInformation.failedQuotaRoots", hasSize(0)) + .body("additionalInformation.runningOptions.usersPerSecond", is(1)) + .body("startedDate", is(notNullValue())) + .body("submitDate", is(notNullValue())) + .body("completedDate", is(notNullValue())); + } + + @Test + void runningOptionsShouldBePartOfTaskDetails() { + String taskId = with() + .queryParam("task", "RecomputeCurrentQuotas") + .queryParam("usersPerSecond", "20") + .post("/quota/users") + .jsonPath() + .get("taskId"); + + given() + .basePath(TasksRoutes.BASE) + .when() + .get(taskId + "/await") + .then() + .body("taskId", is(taskId)) + .body("type", is("recompute-current-quotas")) + .body("additionalInformation.runningOptions.usersPerSecond", is(20)); + } + } } diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/WebAdminQuotaSearchTestSystem.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/WebAdminQuotaSearchTestSystem.java index 898d5d6..b315dbc 100644 --- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/WebAdminQuotaSearchTestSystem.java +++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/WebAdminQuotaSearchTestSystem.java @@ -19,9 +19,15 @@ package org.apache.james.webadmin.routes; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.james.mailbox.quota.task.RecomputeCurrentQuotasService; import org.apache.james.quota.search.QuotaSearchTestSystem; import org.apache.james.task.Hostname; import org.apache.james.task.MemoryTaskManager; +import org.apache.james.task.Task; import org.apache.james.task.TaskManager; import org.apache.james.webadmin.WebAdminServer; import org.apache.james.webadmin.WebAdminUtils; @@ -34,6 +40,7 @@ import org.apache.james.webadmin.utils.JsonTransformer; import com.google.common.collect.ImmutableSet; import io.restassured.specification.RequestSpecification; +import reactor.core.publisher.Mono; public class WebAdminQuotaSearchTestSystem { private final QuotaSearchTestSystem quotaSearchTestSystem; @@ -51,12 +58,15 @@ public class WebAdminQuotaSearchTestSystem { QuotaModule quotaModule = new QuotaModule(); JsonTransformer jsonTransformer = new JsonTransformer(quotaModule); TaskManager taskManager = new MemoryTaskManager(new Hostname("foo")); + RecomputeCurrentQuotasService mock = mock(RecomputeCurrentQuotasService.class); + when(mock.recomputeCurrentQuotas(any(), any())).thenReturn(Mono.just(Task.Result.COMPLETED)); + TasksRoutes tasksRoutes = new TasksRoutes(taskManager, new JsonTransformer()); UserQuotaRoutes userQuotaRoutes = new UserQuotaRoutes(quotaSearchTestSystem.getUsersRepository(), userQuotaService, jsonTransformer, ImmutableSet.of(quotaModule), taskManager, - ImmutableSet.of()); + ImmutableSet.of(new UserQuotaRoutes.RecomputeCurrentQuotasRequestToTask(mock))); DomainQuotaRoutes domainQuotaRoutes = new DomainQuotaRoutes( quotaSearchTestSystem.getDomainList(), new DomainQuotaService(quotaSearchTestSystem.getMaxQuotaManager()), @@ -67,7 +77,7 @@ public class WebAdminQuotaSearchTestSystem { new GlobalQuotaService(quotaSearchTestSystem.getMaxQuotaManager()), jsonTransformer); - this.webAdminServer = WebAdminUtils.createWebAdminServer(userQuotaRoutes, domainQuotaRoutes, globalQuotaRoutes) + this.webAdminServer = WebAdminUtils.createWebAdminServer(userQuotaRoutes, domainQuotaRoutes, globalQuotaRoutes, tasksRoutes) .start(); this.requestSpecBuilder = WebAdminUtils.buildRequestSpecification(webAdminServer) --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
