From 6815c40fe118f361a252f88055e9ad717907f9bf Mon Sep 17 00:00:00 2001 From: Brian Demers Date: Mon, 29 Jul 2024 17:36:56 -0400 Subject: [PATCH 1/2] Enables parallel testing for UTs and ITs A handfull of minor issues were found and fixed after enabling parallel tests: - In memory example test servers were not thread safe - Quarkus tests needed to use dynamic server port - Test servers needed to use a shared single instance (shared between tests) - Similarly, single instance of Weld --- pom.xml | 12 +++++ .../junit/MockServerClientTestRunner.java | 20 +++----- .../junit/EmbeddedServerExtension.java | 51 +++++++++++-------- .../jersey/service/InMemoryUserService.java | 29 ++++++----- .../memory/service/InMemoryGroupService.java | 4 +- .../memory/service/InMemoryUserService.java | 29 ++++++----- .../quarkus/service/InMemoryGroupService.java | 15 +++--- .../quarkus/service/InMemoryUserService.java | 25 +++++---- .../src/test/resources/application.properties | 19 +++++++ .../spring/service/InMemoryUserService.java | 29 +++++++---- .../it/testapp/InMemoryGroupService.java | 15 ++++-- .../it/testapp/InMemoryUserService.java | 16 +++--- .../spring/it/app/InMemoryGroupService.java | 10 ++-- .../spring/it/app/InMemoryUserService.java | 16 ++++-- 14 files changed, 183 insertions(+), 107 deletions(-) create mode 100644 scim-server-examples/scim-server-quarkus/src/test/resources/application.properties diff --git a/pom.xml b/pom.xml index 82f23a119..09c4f1ffc 100644 --- a/pom.xml +++ b/pom.xml @@ -580,6 +580,12 @@ **/*Tests.java **/*TestCase.java + + + junit.jupiter.execution.parallel.enabled = true + junit.jupiter.execution.parallel.mode.default = concurrent + + @@ -594,6 +600,12 @@ org.apache.directory.scimple:scim-compliance-tests + + + junit.jupiter.execution.parallel.enabled = true + junit.jupiter.execution.parallel.mode.default = concurrent + + diff --git a/scim-client/src/test/java/org/apache/directory/scim/client/rest/junit/MockServerClientTestRunner.java b/scim-client/src/test/java/org/apache/directory/scim/client/rest/junit/MockServerClientTestRunner.java index 2120ba8fc..c11bfd866 100644 --- a/scim-client/src/test/java/org/apache/directory/scim/client/rest/junit/MockServerClientTestRunner.java +++ b/scim-client/src/test/java/org/apache/directory/scim/client/rest/junit/MockServerClientTestRunner.java @@ -34,6 +34,13 @@ public class MockServerClientTestRunner implements ParameterResolver, BeforeEach private final List> supportedClasses = List.of(MockWebServer.class, ScimUserClient.class, Client.class); + private final static Weld WELD = new Weld(); + static { + // Use single instance of Weld for all tests using this runner + WELD.initialize(); + Runtime.getRuntime().addShutdownHook(new Thread(WELD::shutdown)); + } + @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return supportedClasses.contains(parameterContext.getParameter().getType()); @@ -59,9 +66,6 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte @Override public void beforeEach(ExtensionContext context) throws Exception { - Weld weld = new Weld(); - getStore(context).put(Weld.class, weld); - MockWebServer server = new MockWebServer(); getStore(context).put(MockWebServer.class, server); @@ -79,11 +83,6 @@ public void beforeTestExecution(ExtensionContext context) throws Exception { if (server != null) { server.start(); } - - Weld weld = fromStore(Weld.class, context); - if (weld != null) { - weld.initialize(); - } } @Override @@ -93,11 +92,6 @@ public void afterEach(ExtensionContext context) throws Exception { server.shutdown(); } - Weld weld = fromStore(Weld.class, context); - if (weld != null) { - weld.shutdown(); - } - Client client = fromStore(Client.class, context); if (client != null) { client.close(); diff --git a/scim-compliance-tests/src/main/java/org/apache/directory/scim/compliance/junit/EmbeddedServerExtension.java b/scim-compliance-tests/src/main/java/org/apache/directory/scim/compliance/junit/EmbeddedServerExtension.java index 34df7638b..e51f2d29d 100644 --- a/scim-compliance-tests/src/main/java/org/apache/directory/scim/compliance/junit/EmbeddedServerExtension.java +++ b/scim-compliance-tests/src/main/java/org/apache/directory/scim/compliance/junit/EmbeddedServerExtension.java @@ -20,10 +20,9 @@ package org.apache.directory.scim.compliance.junit; import org.apache.commons.lang3.reflect.FieldUtils; -import org.junit.jupiter.api.extension.AfterAllCallback; -import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.TestInstantiationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,22 +38,41 @@ import java.util.List; import java.util.ServiceLoader; -public class EmbeddedServerExtension implements BeforeAllCallback, BeforeEachCallback, AfterAllCallback { +public class EmbeddedServerExtension implements BeforeEachCallback { private static final Logger logger = LoggerFactory.getLogger(EmbeddedServerExtension.class); - private ScimTestServer server; - private URI uri; + private static ScimTestServer server; + private static URI uri; - @Override - public void beforeAll(ExtensionContext context) throws Exception { + static { + // Start a single instance of the ScimTestServer + // this instance is shared for all tests using this extension + setupServer(); + } + + private static void setupServer() { ServiceLoader serviceLoader = ServiceLoader.load(ScimTestServer.class); - if (serviceLoader.findFirst().isPresent()) { - server = serviceLoader.findFirst().get(); - uri = server.start(randomPort()); - } else { - logger.info("Could not find implementation of ScimTestServer via ServiceLoader, assuming server is started using different technique"); - } + serviceLoader.findFirst() + .ifPresentOrElse(testServer -> { + try { + server = testServer; + uri = server.start(randomPort()); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + if (server != null) { + try { + server.shutdown(); + } catch (Exception e) { + logger.warn("Failed to shutdown test server", e); + } + } + })); + + } catch (Exception e) { + throw new TestInstantiationException("Failed to start test server: "+ testServer, e); + } + }, () -> logger.info("Could not find implementation of ScimTestServer via ServiceLoader, assuming server is started using different technique")); } @Override @@ -76,13 +94,6 @@ public void beforeEach(ExtensionContext context) throws Exception { } } - @Override - public void afterAll(ExtensionContext context) throws Exception { - if (server != null) { - server.shutdown(); - } - } - private static int randomPort() { try (ServerSocket socket = new ServerSocket(0)) { return socket.getLocalPort(); diff --git a/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/service/InMemoryUserService.java b/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/service/InMemoryUserService.java index cbbe1b0bb..715bc1db1 100644 --- a/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/service/InMemoryUserService.java +++ b/scim-server-examples/scim-server-jersey/src/main/java/org/apache/directory/scim/example/jersey/service/InMemoryUserService.java @@ -19,35 +19,38 @@ package org.apache.directory.scim.example.jersey.service; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; - import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.inject.Named; - import jakarta.ws.rs.core.Response; import org.apache.directory.scim.core.repository.ETag; import org.apache.directory.scim.core.repository.PatchHandler; +import org.apache.directory.scim.core.repository.Repository; +import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.example.jersey.extensions.LuckyNumberExtension; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.spec.exception.ResourceException; import org.apache.directory.scim.spec.extension.EnterpriseExtension; +import org.apache.directory.scim.spec.filter.Filter; import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; -import org.apache.directory.scim.spec.filter.Filter; import org.apache.directory.scim.spec.filter.PageRequest; import org.apache.directory.scim.spec.filter.SortRequest; import org.apache.directory.scim.spec.filter.attribute.AttributeReference; import org.apache.directory.scim.spec.patch.PatchOperation; -import org.apache.directory.scim.spec.resources.*; -import org.apache.directory.scim.core.schema.SchemaRegistry; +import org.apache.directory.scim.spec.resources.Email; +import org.apache.directory.scim.spec.resources.Name; +import org.apache.directory.scim.spec.resources.ScimExtension; +import org.apache.directory.scim.spec.resources.ScimResource; +import org.apache.directory.scim.spec.resources.ScimUser; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; /** * Creates a singleton (effectively) Repository with a memory-based @@ -66,7 +69,7 @@ public class InMemoryUserService implements Repository { static final String DEFAULT_USER_EMAIL_TYPE = "work"; static final int DEFAULT_USER_LUCKY_NUMBER = 7; - private final Map users = new HashMap<>(); + private final Map users = new ConcurrentHashMap<>(); private SchemaRegistry schemaRegistry; diff --git a/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryGroupService.java b/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryGroupService.java index 2d9ad1e5e..6feb58e84 100644 --- a/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryGroupService.java +++ b/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryGroupService.java @@ -39,11 +39,11 @@ import org.apache.directory.scim.spec.resources.ScimGroup; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import jakarta.enterprise.context.ApplicationScoped; @@ -54,7 +54,7 @@ @ApplicationScoped public class InMemoryGroupService implements Repository { - private final Map groups = new HashMap<>(); + private final Map groups = new ConcurrentHashMap<>(); private SchemaRegistry schemaRegistry; diff --git a/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryUserService.java b/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryUserService.java index f465f0ade..6e3ba0006 100644 --- a/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryUserService.java +++ b/scim-server-examples/scim-server-memory/src/main/java/org/apache/directory/scim/example/memory/service/InMemoryUserService.java @@ -19,35 +19,38 @@ package org.apache.directory.scim.example.memory.service; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; - import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.inject.Named; - import jakarta.ws.rs.core.Response; import org.apache.directory.scim.core.repository.ETag; import org.apache.directory.scim.core.repository.PatchHandler; +import org.apache.directory.scim.core.repository.Repository; +import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.example.memory.extensions.LuckyNumberExtension; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.spec.exception.ResourceException; import org.apache.directory.scim.spec.extension.EnterpriseExtension; +import org.apache.directory.scim.spec.filter.Filter; import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; -import org.apache.directory.scim.spec.filter.Filter; import org.apache.directory.scim.spec.filter.PageRequest; import org.apache.directory.scim.spec.filter.SortRequest; import org.apache.directory.scim.spec.filter.attribute.AttributeReference; import org.apache.directory.scim.spec.patch.PatchOperation; -import org.apache.directory.scim.spec.resources.*; -import org.apache.directory.scim.core.schema.SchemaRegistry; +import org.apache.directory.scim.spec.resources.Email; +import org.apache.directory.scim.spec.resources.Name; +import org.apache.directory.scim.spec.resources.ScimExtension; +import org.apache.directory.scim.spec.resources.ScimResource; +import org.apache.directory.scim.spec.resources.ScimUser; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; /** * Creates a singleton (effectively) Repository with a memory-based @@ -66,7 +69,7 @@ public class InMemoryUserService implements Repository { static final String DEFAULT_USER_EMAIL_TYPE = "work"; static final int DEFAULT_USER_LUCKY_NUMBER = 7; - private final Map users = new HashMap<>(); + private final Map users = new ConcurrentHashMap<>(); private SchemaRegistry schemaRegistry; diff --git a/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryGroupService.java b/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryGroupService.java index f17bde14e..79b4c2d93 100644 --- a/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryGroupService.java +++ b/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryGroupService.java @@ -20,17 +20,20 @@ package org.apache.directory.scim.example.quarkus.service; import jakarta.annotation.PostConstruct; +import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import jakarta.inject.Named; import jakarta.ws.rs.core.Response; import org.apache.commons.lang3.StringUtils; import org.apache.directory.scim.core.repository.ETag; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.core.repository.Repository; +import org.apache.directory.scim.core.schema.SchemaRegistry; +import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.spec.exception.ResourceException; +import org.apache.directory.scim.spec.filter.Filter; import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; -import org.apache.directory.scim.spec.filter.Filter; import org.apache.directory.scim.spec.filter.PageRequest; import org.apache.directory.scim.spec.filter.SortRequest; import org.apache.directory.scim.spec.filter.attribute.AttributeReference; @@ -39,22 +42,18 @@ import org.apache.directory.scim.spec.resources.ScimGroup; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Named; -import org.apache.directory.scim.core.schema.SchemaRegistry; - @Named @ApplicationScoped public class InMemoryGroupService implements Repository { - private final Map groups = new HashMap<>(); + private final Map groups = new ConcurrentHashMap<>(); private SchemaRegistry schemaRegistry; diff --git a/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryUserService.java b/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryUserService.java index 8aa6784f5..42d626b9b 100644 --- a/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryUserService.java +++ b/scim-server-examples/scim-server-quarkus/src/main/java/org/apache/directory/scim/example/quarkus/service/InMemoryUserService.java @@ -19,31 +19,38 @@ package org.apache.directory.scim.example.quarkus.service; -import java.util.*; -import java.util.stream.Collectors; - import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.inject.Named; - import jakarta.ws.rs.core.Response; import org.apache.directory.scim.core.repository.ETag; import org.apache.directory.scim.core.repository.PatchHandler; +import org.apache.directory.scim.core.repository.Repository; +import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.example.quarkus.extensions.LuckyNumberExtension; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; -import org.apache.directory.scim.core.repository.Repository; import org.apache.directory.scim.spec.exception.ResourceException; import org.apache.directory.scim.spec.extension.EnterpriseExtension; +import org.apache.directory.scim.spec.filter.Filter; import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; -import org.apache.directory.scim.spec.filter.Filter; import org.apache.directory.scim.spec.filter.PageRequest; import org.apache.directory.scim.spec.filter.SortRequest; import org.apache.directory.scim.spec.filter.attribute.AttributeReference; import org.apache.directory.scim.spec.patch.PatchOperation; -import org.apache.directory.scim.spec.resources.*; -import org.apache.directory.scim.core.schema.SchemaRegistry; +import org.apache.directory.scim.spec.resources.Email; +import org.apache.directory.scim.spec.resources.Name; +import org.apache.directory.scim.spec.resources.ScimExtension; +import org.apache.directory.scim.spec.resources.ScimResource; +import org.apache.directory.scim.spec.resources.ScimUser; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; /** * Creates a singleton (effectively) Repository with a memory-based @@ -62,7 +69,7 @@ public class InMemoryUserService implements Repository { static final String DEFAULT_USER_EMAIL_TYPE = "work"; static final int DEFAULT_USER_LUCKY_NUMBER = 7; - private final Map users = new HashMap<>(); + private final Map users = new ConcurrentHashMap<>(); private SchemaRegistry schemaRegistry; diff --git a/scim-server-examples/scim-server-quarkus/src/test/resources/application.properties b/scim-server-examples/scim-server-quarkus/src/test/resources/application.properties new file mode 100644 index 000000000..daa6a3282 --- /dev/null +++ b/scim-server-examples/scim-server-quarkus/src/test/resources/application.properties @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +quarkus.http.test-port=0 diff --git a/scim-server-examples/scim-server-spring-boot/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryUserService.java b/scim-server-examples/scim-server-spring-boot/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryUserService.java index 39c2eeff5..77c9f581d 100644 --- a/scim-server-examples/scim-server-spring-boot/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryUserService.java +++ b/scim-server-examples/scim-server-spring-boot/src/main/java/org/apache/directory/scim/example/spring/service/InMemoryUserService.java @@ -19,15 +19,7 @@ package org.apache.directory.scim.example.spring.service; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; - import jakarta.annotation.PostConstruct; - import jakarta.ws.rs.core.Response; import org.apache.directory.scim.core.repository.ETag; import org.apache.directory.scim.core.repository.PatchHandler; @@ -37,12 +29,27 @@ import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.spec.exception.ResourceException; import org.apache.directory.scim.spec.extension.EnterpriseExtension; -import org.apache.directory.scim.spec.filter.*; +import org.apache.directory.scim.spec.filter.Filter; +import org.apache.directory.scim.spec.filter.FilterExpressions; +import org.apache.directory.scim.spec.filter.FilterResponse; +import org.apache.directory.scim.spec.filter.PageRequest; +import org.apache.directory.scim.spec.filter.SortRequest; import org.apache.directory.scim.spec.filter.attribute.AttributeReference; import org.apache.directory.scim.spec.patch.PatchOperation; -import org.apache.directory.scim.spec.resources.*; +import org.apache.directory.scim.spec.resources.Email; +import org.apache.directory.scim.spec.resources.Name; +import org.apache.directory.scim.spec.resources.ScimExtension; +import org.apache.directory.scim.spec.resources.ScimResource; +import org.apache.directory.scim.spec.resources.ScimUser; import org.springframework.stereotype.Service; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + /** * Creates a singleton (effectively) Provider with a memory-based * persistence layer. @@ -59,7 +66,7 @@ public class InMemoryUserService implements Repository { static final String DEFAULT_USER_EMAIL_TYPE = "work"; static final int DEFAULT_USER_LUCKY_NUMBER = 7; - private final Map users = new HashMap<>(); + private final Map users = new ConcurrentHashMap<>(); private final SchemaRegistry schemaRegistry; diff --git a/scim-server/src/test/java/org/apache/directory/scim/server/it/testapp/InMemoryGroupService.java b/scim-server/src/test/java/org/apache/directory/scim/server/it/testapp/InMemoryGroupService.java index 9af8eeb53..2d73deed9 100644 --- a/scim-server/src/test/java/org/apache/directory/scim/server/it/testapp/InMemoryGroupService.java +++ b/scim-server/src/test/java/org/apache/directory/scim/server/it/testapp/InMemoryGroupService.java @@ -27,28 +27,33 @@ import org.apache.commons.lang3.StringUtils; import org.apache.directory.scim.core.repository.ETag; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.core.repository.Repository; +import org.apache.directory.scim.core.schema.SchemaRegistry; +import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.spec.exception.ResourceException; +import org.apache.directory.scim.spec.filter.Filter; import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; -import org.apache.directory.scim.spec.filter.Filter; import org.apache.directory.scim.spec.filter.PageRequest; import org.apache.directory.scim.spec.filter.SortRequest; import org.apache.directory.scim.spec.filter.attribute.AttributeReference; import org.apache.directory.scim.spec.patch.PatchOperation; import org.apache.directory.scim.spec.resources.ScimExtension; import org.apache.directory.scim.spec.resources.ScimGroup; -import org.apache.directory.scim.core.schema.SchemaRegistry; -import java.util.*; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @Named @ApplicationScoped public class InMemoryGroupService implements Repository { - private final Map groups = new HashMap<>(); + private final Map groups = new ConcurrentHashMap<>(); private SchemaRegistry schemaRegistry; diff --git a/scim-server/src/test/java/org/apache/directory/scim/server/it/testapp/InMemoryUserService.java b/scim-server/src/test/java/org/apache/directory/scim/server/it/testapp/InMemoryUserService.java index a8706103f..f8ac2cc46 100644 --- a/scim-server/src/test/java/org/apache/directory/scim/server/it/testapp/InMemoryUserService.java +++ b/scim-server/src/test/java/org/apache/directory/scim/server/it/testapp/InMemoryUserService.java @@ -26,23 +26,27 @@ import jakarta.ws.rs.core.Response; import org.apache.directory.scim.core.repository.ETag; import org.apache.directory.scim.core.repository.PatchHandler; -import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.core.repository.Repository; +import org.apache.directory.scim.core.schema.SchemaRegistry; +import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.spec.exception.ResourceException; +import org.apache.directory.scim.spec.filter.Filter; import org.apache.directory.scim.spec.filter.FilterExpressions; import org.apache.directory.scim.spec.filter.FilterResponse; -import org.apache.directory.scim.spec.filter.Filter; import org.apache.directory.scim.spec.filter.PageRequest; import org.apache.directory.scim.spec.filter.SortRequest; import org.apache.directory.scim.spec.filter.attribute.AttributeReference; import org.apache.directory.scim.spec.patch.PatchOperation; -import org.apache.directory.scim.spec.resources.*; -import org.apache.directory.scim.core.schema.SchemaRegistry; +import org.apache.directory.scim.spec.resources.Email; +import org.apache.directory.scim.spec.resources.Name; +import org.apache.directory.scim.spec.resources.ScimExtension; +import org.apache.directory.scim.spec.resources.ScimResource; +import org.apache.directory.scim.spec.resources.ScimUser; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** @@ -62,7 +66,7 @@ public class InMemoryUserService implements Repository { static final String DEFAULT_USER_EMAIL_TYPE = "work"; static final int DEFAULT_USER_LUCKY_NUMBER = 7; - private final Map users = new HashMap<>(); + private final Map users = new ConcurrentHashMap<>(); private SchemaRegistry schemaRegistry; diff --git a/support/spring-boot/src/test/java/org/apache/directory/scim/spring/it/app/InMemoryGroupService.java b/support/spring-boot/src/test/java/org/apache/directory/scim/spring/it/app/InMemoryGroupService.java index d849b72cb..ff7676526 100644 --- a/support/spring-boot/src/test/java/org/apache/directory/scim/spring/it/app/InMemoryGroupService.java +++ b/support/spring-boot/src/test/java/org/apache/directory/scim/spring/it/app/InMemoryGroupService.java @@ -28,7 +28,11 @@ import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.spec.exception.ResourceException; -import org.apache.directory.scim.spec.filter.*; +import org.apache.directory.scim.spec.filter.Filter; +import org.apache.directory.scim.spec.filter.FilterExpressions; +import org.apache.directory.scim.spec.filter.FilterResponse; +import org.apache.directory.scim.spec.filter.PageRequest; +import org.apache.directory.scim.spec.filter.SortRequest; import org.apache.directory.scim.spec.filter.attribute.AttributeReference; import org.apache.directory.scim.spec.patch.PatchOperation; import org.apache.directory.scim.spec.resources.ScimExtension; @@ -36,17 +40,17 @@ import org.springframework.stereotype.Service; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @Service public class InMemoryGroupService implements Repository { - private final Map groups = new HashMap<>(); + private final Map groups = new ConcurrentHashMap<>(); private final SchemaRegistry schemaRegistry; diff --git a/support/spring-boot/src/test/java/org/apache/directory/scim/spring/it/app/InMemoryUserService.java b/support/spring-boot/src/test/java/org/apache/directory/scim/spring/it/app/InMemoryUserService.java index 9ec72a87d..69a2aea2d 100644 --- a/support/spring-boot/src/test/java/org/apache/directory/scim/spring/it/app/InMemoryUserService.java +++ b/support/spring-boot/src/test/java/org/apache/directory/scim/spring/it/app/InMemoryUserService.java @@ -27,17 +27,25 @@ import org.apache.directory.scim.core.schema.SchemaRegistry; import org.apache.directory.scim.server.exception.UnableToCreateResourceException; import org.apache.directory.scim.spec.exception.ResourceException; -import org.apache.directory.scim.spec.filter.*; +import org.apache.directory.scim.spec.filter.Filter; +import org.apache.directory.scim.spec.filter.FilterExpressions; +import org.apache.directory.scim.spec.filter.FilterResponse; +import org.apache.directory.scim.spec.filter.PageRequest; +import org.apache.directory.scim.spec.filter.SortRequest; import org.apache.directory.scim.spec.filter.attribute.AttributeReference; import org.apache.directory.scim.spec.patch.PatchOperation; -import org.apache.directory.scim.spec.resources.*; +import org.apache.directory.scim.spec.resources.Email; +import org.apache.directory.scim.spec.resources.Name; +import org.apache.directory.scim.spec.resources.ScimExtension; +import org.apache.directory.scim.spec.resources.ScimResource; +import org.apache.directory.scim.spec.resources.ScimUser; import org.springframework.stereotype.Service; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** @@ -56,7 +64,7 @@ public class InMemoryUserService implements Repository { static final String DEFAULT_USER_EMAIL_TYPE = "work"; static final int DEFAULT_USER_LUCKY_NUMBER = 7; - private final Map users = new HashMap<>(); + private final Map users = new ConcurrentHashMap<>(); private final SchemaRegistry schemaRegistry; From cce2ce201b5d1fa57f2605449449b0a6433f37da Mon Sep 17 00:00:00 2001 From: Brian Demers Date: Tue, 30 Jul 2024 18:53:09 -0400 Subject: [PATCH 2/2] Working around Quarkus race condition in parallel tests I'm not 100% sure this will fix the issue, but the stack traces lead back to this callback, and it's not needed for these tests --- scim-server-examples/scim-server-quarkus/pom.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/scim-server-examples/scim-server-quarkus/pom.xml b/scim-server-examples/scim-server-quarkus/pom.xml index 31533aa2b..5df1bf3e0 100644 --- a/scim-server-examples/scim-server-quarkus/pom.xml +++ b/scim-server-examples/scim-server-quarkus/pom.xml @@ -119,6 +119,21 @@ + + org.apache.maven.plugins + maven-failsafe-plugin + + + + junit.jupiter.execution.parallel.enabled = true + junit.jupiter.execution.parallel.mode.default = concurrent + + # Looks like there is race condition, disable the logger callback + junit.quarkus.enable-basic-logging=false + + + + io.quarkus.platform quarkus-maven-plugin