From 374109fb6409ac9282a4bff6ec3b8894d9b17034 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Fri, 11 Mar 2022 09:14:35 +0100 Subject: [PATCH] [MRESOLVER-245] Isolate and update tests (#157) Main intent is to properly isolate ITs, but did other cleanup as well like patch update of Hazelcast and documentation updated as well. High level changes: * POM update with new patch release of HZ * removed obsolete `destroySemaphore` parameter (always false), factored out semaphore provision * updated all 4 ITs to form random named clusters (hence to prevent outer HZ instance joining) * provided hazelcast and hazelcast-client XML fixed (used wrong schema) * Tests reformatted to maven codestyle (changes best viewed with `?w=1`) --- maven-resolver-named-locks-hazelcast/pom.xml | 2 +- .../DirectHazelcastSemaphoreProvider.java | 43 ++ .../HazelcastCPSemaphoreNamedLockFactory.java | 41 +- ...castClientCPSemaphoreNamedLockFactory.java | 42 +- .../HazelcastSemaphoreNamedLockFactory.java | 66 ++- .../hazelcast/HazelcastSemaphoreProvider.java | 44 ++ .../src/site/markdown/index.md.vm | 54 ++- .../src/site/site.xml | 2 +- .../HazelcastCPSemaphoreAdapterIT.java | 10 +- ...azelcastCPSemaphoreNamedLockFactoryIT.java | 17 +- .../HazelcastClientCPSemaphoreAdapterIT.java | 23 +- ...stClientCPSemaphoreNamedLockFactoryIT.java | 26 +- .../named/hazelcast/HazelcastClientUtils.java | 94 ++-- .../NamedLockFactoryAdapterTestSupport.java | 421 ++++++++++-------- .../NamedLockFactoryTestSupport.java | 164 ++++--- .../src/test/resources/hazelcast-client.xml | 2 +- .../src/test/resources/hazelcast.xml | 14 +- 17 files changed, 618 insertions(+), 447 deletions(-) create mode 100644 maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/DirectHazelcastSemaphoreProvider.java create mode 100644 maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastSemaphoreProvider.java diff --git a/maven-resolver-named-locks-hazelcast/pom.xml b/maven-resolver-named-locks-hazelcast/pom.xml index d1597e0a5..531eaa00d 100644 --- a/maven-resolver-named-locks-hazelcast/pom.xml +++ b/maven-resolver-named-locks-hazelcast/pom.xml @@ -52,7 +52,7 @@ com.hazelcast hazelcast - 5.0.1 + 5.0.2 javax.inject diff --git a/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/DirectHazelcastSemaphoreProvider.java b/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/DirectHazelcastSemaphoreProvider.java new file mode 100644 index 000000000..6901dafe5 --- /dev/null +++ b/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/DirectHazelcastSemaphoreProvider.java @@ -0,0 +1,43 @@ +package org.eclipse.aether.named.hazelcast; + +/* + * 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. + */ + +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.cp.ISemaphore; + +/** + * Direct provider of {@link ISemaphore} instances: it simply uses the passed in lock name to create semaphore name out + * of it. This implies, that as many lock names are requested from it, this class will create as many semaphores in + * Hazelcast. + */ +public class DirectHazelcastSemaphoreProvider extends HazelcastSemaphoreProvider +{ + @Override + public ISemaphore acquireSemaphore( HazelcastInstance hazelcastInstance, String name ) + { + return hazelcastInstance.getCPSubsystem().getSemaphore( NAME_PREFIX + name ); + } + + @Override + public void releaseSemaphore( HazelcastInstance hazelcastInstance, String name, ISemaphore semaphore ) + { + // nothing + } +} diff --git a/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastCPSemaphoreNamedLockFactory.java b/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastCPSemaphoreNamedLockFactory.java index 81e428e20..3f110eadb 100644 --- a/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastCPSemaphoreNamedLockFactory.java +++ b/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastCPSemaphoreNamedLockFactory.java @@ -19,32 +19,37 @@ * under the License. */ -import com.hazelcast.core.Hazelcast; - import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import com.hazelcast.core.Hazelcast; +import com.hazelcast.core.HazelcastInstance; + /** - * {@link HazelcastSemaphoreNamedLockFactory} using Hazelcast and {@link - * com.hazelcast.core.HazelcastInstance#getCPSubsystem()} method to get CP semaphore. For this to work, the Hazelcast - * cluster the client is connecting to must be CP enabled cluster. + * {@link HazelcastSemaphoreNamedLockFactory} using {@link DirectHazelcastSemaphoreProvider} full Hazelcast member. */ @Singleton @Named( HazelcastCPSemaphoreNamedLockFactory.NAME ) -public class HazelcastCPSemaphoreNamedLockFactory - extends HazelcastSemaphoreNamedLockFactory +public class HazelcastCPSemaphoreNamedLockFactory extends HazelcastSemaphoreNamedLockFactory { - public static final String NAME = "semaphore-hazelcast"; + public static final String NAME = "semaphore-hazelcast"; + + /** + * The default constructor: creates own instance of Hazelcast using standard Hazelcast configuration discovery. + */ + @Inject + public HazelcastCPSemaphoreNamedLockFactory() + { + this( Hazelcast.newHazelcastInstance(), true ); + } - @Inject - public HazelcastCPSemaphoreNamedLockFactory() - { - super( - Hazelcast.newHazelcastInstance(), - ( hazelcastInstance, name ) -> hazelcastInstance.getCPSubsystem().getSemaphore( NAME_PREFIX + name ), - false, - true - ); - } + /** + * Constructor for customization. + */ + public HazelcastCPSemaphoreNamedLockFactory( HazelcastInstance hazelcastInstance, + boolean manageHazelcast ) + { + super( hazelcastInstance, manageHazelcast, new DirectHazelcastSemaphoreProvider() ); + } } diff --git a/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastClientCPSemaphoreNamedLockFactory.java b/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastClientCPSemaphoreNamedLockFactory.java index 097d12025..138f7bb2d 100644 --- a/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastClientCPSemaphoreNamedLockFactory.java +++ b/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastClientCPSemaphoreNamedLockFactory.java @@ -19,32 +19,38 @@ * under the License. */ -import com.hazelcast.client.HazelcastClient; - import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import com.hazelcast.client.HazelcastClient; +import com.hazelcast.core.HazelcastInstance; + /** - * Provider of {@link HazelcastSemaphoreNamedLockFactory} using Hazelcast Client and {@link - * com.hazelcast.core.HazelcastInstance#getCPSubsystem()} method to get CP semaphore. For this to work, the Hazelcast - * cluster the client is connecting to must be CP enabled cluster. + * {@link HazelcastSemaphoreNamedLockFactory} using {@link DirectHazelcastSemaphoreProvider} and Hazelcast client. The + * client must be configured to connect to some existing cluster (w/ proper configuration applied). */ @Singleton @Named( HazelcastClientCPSemaphoreNamedLockFactory.NAME ) -public class HazelcastClientCPSemaphoreNamedLockFactory - extends HazelcastSemaphoreNamedLockFactory +public class HazelcastClientCPSemaphoreNamedLockFactory extends HazelcastSemaphoreNamedLockFactory { - public static final String NAME = "semaphore-hazelcast-client"; + public static final String NAME = "semaphore-hazelcast-client"; + + /** + * The default constructor: creates own instance of Hazelcast using standard Hazelcast configuration discovery. + */ + @Inject + public HazelcastClientCPSemaphoreNamedLockFactory() + { + this( HazelcastClient.newHazelcastClient(), true ); + } - @Inject - public HazelcastClientCPSemaphoreNamedLockFactory() - { - super( - HazelcastClient.newHazelcastClient(), - ( hazelcastInstance, name ) -> hazelcastInstance.getCPSubsystem().getSemaphore( NAME_PREFIX + name ), - false, - true - ); - } + /** + * Constructor for customization. + */ + public HazelcastClientCPSemaphoreNamedLockFactory( HazelcastInstance hazelcastInstance, + boolean manageHazelcast ) + { + super( hazelcastInstance, manageHazelcast, new DirectHazelcastSemaphoreProvider() ); + } } diff --git a/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastSemaphoreNamedLockFactory.java b/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastSemaphoreNamedLockFactory.java index 01450dbd7..18a30fa63 100644 --- a/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastSemaphoreNamedLockFactory.java +++ b/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastSemaphoreNamedLockFactory.java @@ -19,82 +19,66 @@ * under the License. */ +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; + import com.hazelcast.core.HazelcastInstance; import com.hazelcast.cp.ISemaphore; import org.eclipse.aether.named.support.AdaptedSemaphoreNamedLock; import org.eclipse.aether.named.support.AdaptedSemaphoreNamedLock.AdaptedSemaphore; import org.eclipse.aether.named.support.NamedLockFactorySupport; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; -import java.util.function.BiFunction; +import static java.util.Objects.requireNonNull; /** - * Factory of {@link AdaptedSemaphoreNamedLock} instances using adapted Hazelcast {@link ISemaphore}. This class may - * use {@link HazelcastInstance} backed by Hazelcast Server or Hazelcast Client. + * Factory of {@link AdaptedSemaphoreNamedLock} instances, using adapted Hazelcast {@link ISemaphore}. It delegates + * most the work to {@link HazelcastSemaphoreProvider} and this class just adapts the returned semaphore to named lock + * and caches {@link ISemaphore} instances, as recommended by Hazelcast. */ public class HazelcastSemaphoreNamedLockFactory - extends NamedLockFactorySupport + extends NamedLockFactorySupport { - protected static final String NAME_PREFIX = "maven:resolver:"; - - private final HazelcastInstance hazelcastInstance; + protected final HazelcastInstance hazelcastInstance; - private final BiFunction semaphoreFunction; + protected final boolean manageHazelcast; - private final boolean destroySemaphore; - - private final boolean manageHazelcast; + private final HazelcastSemaphoreProvider hazelcastSemaphoreProvider; private final ConcurrentMap semaphores; public HazelcastSemaphoreNamedLockFactory( - final HazelcastInstance hazelcastInstance, - final BiFunction semaphoreFunction, - final boolean destroySemaphore, - final boolean manageHazelcast + final HazelcastInstance hazelcastInstance, + final boolean manageHazelcast, + final HazelcastSemaphoreProvider hazelcastSemaphoreProvider ) { - this.hazelcastInstance = hazelcastInstance; - this.semaphoreFunction = semaphoreFunction; - this.destroySemaphore = destroySemaphore; + this.hazelcastInstance = requireNonNull( hazelcastInstance ); this.manageHazelcast = manageHazelcast; + this.hazelcastSemaphoreProvider = requireNonNull( hazelcastSemaphoreProvider ); this.semaphores = new ConcurrentHashMap<>(); } @Override protected AdaptedSemaphoreNamedLock createLock( final String name ) { - ISemaphore semaphore = semaphores.computeIfAbsent( name, k -> - { - ISemaphore result = semaphoreFunction.apply( hazelcastInstance, k ); - result.init( Integer.MAX_VALUE ); - return result; - } ); + ISemaphore semaphore = semaphores.computeIfAbsent( name, + k -> hazelcastSemaphoreProvider.acquireSemaphore( hazelcastInstance, name ) ); return new AdaptedSemaphoreNamedLock( name, this, new HazelcastSemaphore( semaphore ) ); } @Override - public void shutdown() + protected void destroyLock( final String name ) { - if ( manageHazelcast ) - { - hazelcastInstance.shutdown(); - } + hazelcastSemaphoreProvider.releaseSemaphore( hazelcastInstance, name, semaphores.remove( name ) ); } @Override - protected void destroyLock( final String name ) + public void shutdown() { - ISemaphore semaphore = semaphores.remove( name ); - if ( destroySemaphore ) + if ( manageHazelcast ) { - if ( semaphore == null ) - { - throw new IllegalStateException( "Semaphore expected but does not exist: " + name ); - } - semaphore.destroy(); + hazelcastInstance.shutdown(); } } @@ -109,7 +93,7 @@ private HazelcastSemaphore( final ISemaphore semaphore ) @Override public boolean tryAcquire( final int perms, final long time, final TimeUnit unit ) - throws InterruptedException + throws InterruptedException { return semaphore.tryAcquire( perms, time, unit ); } diff --git a/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastSemaphoreProvider.java b/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastSemaphoreProvider.java new file mode 100644 index 000000000..7ffc98072 --- /dev/null +++ b/maven-resolver-named-locks-hazelcast/src/main/java/org/eclipse/aether/named/hazelcast/HazelcastSemaphoreProvider.java @@ -0,0 +1,44 @@ +package org.eclipse.aether.named.hazelcast; + +/* + * 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. + */ + +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.cp.ISemaphore; + +/** + * Support class for providers of {@link ISemaphore} instances. + */ +public abstract class HazelcastSemaphoreProvider +{ + /** + * Name prefix recommended using for simpler configuration of Hazelcast. + */ + protected static final String NAME_PREFIX = "maven:resolver:"; + + /** + * Invoked when new instance of semaphore needed for given name. must not return {@code null}. + */ + public abstract ISemaphore acquireSemaphore( HazelcastInstance hazelcastInstance, String name ); + + /** + * Invoked when passed in semaphore associated with passed in name is not to be used anymore. + */ + public abstract void releaseSemaphore( HazelcastInstance hazelcastInstance, String name, ISemaphore semaphore ); +} diff --git a/maven-resolver-named-locks-hazelcast/src/site/markdown/index.md.vm b/maven-resolver-named-locks-hazelcast/src/site/markdown/index.md.vm index 40f629c26..9f9329b76 100644 --- a/maven-resolver-named-locks-hazelcast/src/site/markdown/index.md.vm +++ b/maven-resolver-named-locks-hazelcast/src/site/markdown/index.md.vm @@ -19,40 +19,60 @@ specific language governing permissions and limitations under the License. --> -This module implement named locks using Hazelcast. It provides two implementations, that are distributed and rely on -Hazelcast 4.x ISemaphores. +This module implement named locks using Hazelcast. It provides two implementations, using members or clients and +rely on Hazelcast ISemaphore instances. Out of the box "hazelcast" (distributed) named lock implementations are the following: -- `semaphore-hazelcast` implemented in `org.eclipse.aether.named.hazelcast.HazelcastCPSemaphoreNamedLockFactory` that uses - Hazelcast backed `com.hazelcast.cp.ISemaphore`. Full Hazelcast member is used here. +- `semaphore-hazelcast` implemented in `org.eclipse.aether.named.hazelcast.HazelcastCPSemaphoreNamedLockFactory`. + Full Hazelcast member is used here. - `semaphore-hazelcast-client` implemented in `org.eclipse.aether.named.hazelcast.HazelcastClientCPSemaphoreNamedLockFactory` - that uses Hazelcast Client backed `com.hazelcast.cp.ISemaphore`. This implementation uses Hazelcast Client, so - connection to some existing Hazelcast cluster, and its existence is a requirement. + This implementation uses Hazelcast Client, so existing Hazelcast cluster to connect to is a requirement. + +The semaphore name prefix is `maven:resolver:` and pre-configuring semaphores in Hazelcast is a must. The Hazelcast +configuration must have the following entry: + +- Name prefix: `maven:resolver:` (use pattern matching configuration) +- JDK compatible: true +- Permit count: `Integer.MAX_VALUE` (value `2147483647`) + +Example Hazelcast XML relevant snippet: + +```xml + + + + maven:resolver:* + true + 2147483647 + + + +``` + +Without this configuration present, this library will not work. ${esc.hash}${esc.hash} Open Issues/Notes -- Usage from plugins has not been tested yet. - The `furnace-maven-plugin` does not work this implementation because it uses `ServiceLocator` instead of dependency injection. ${esc.hash}${esc.hash} Open Issues/Notes for Maven Resolver integrators -To use this implementation within your project, depending on how you integrate, you have following options: -- If you use Sisu DI, then all you need is to provide this module (and its dependencies) on classpath and you are done. -- If you use Guice, you need to add this module (and its dependencies) upfront, and bind them explicitly. +To use this implementation within your project, depending on how you integrate, you have the following options: + +- If you use Sisu DI, then all you need is to provide this module (and Hazelcast JAR) on classpath, and you are done. +- If you use Guice, you need to add this module (and its dependencies) upfront to classpath, and bind them explicitly. - If you use ServiceLocator, be aware it is deprecated, and you should move away from it. In this case, simplest is to roll your own "bootstrap" class that does pretty much same thing as ServiceLocator was, and extend it to instantiate these components as well. ${esc.hash}${esc.hash} Installation/Testing -- Create the directory `${maven.home}/lib/ext/hazelcast/`. -- Modify `${maven.home}/bin/m2.conf` by adding `load ${maven.home}/lib/ext/hazelcast/*.jar` - right after the `${maven.conf}/logging` line. -- Copy the following dependency from Maven Central to `${maven.home}/lib/ext/hazelcast/`: +- Copy the following JARs from Maven Central to `${maven.home}/lib/ext/`:
-      └── hazelcast-4.1.1.jar
-- Optionally configure Hazelcast instance with `${maven.conf}/hazelcast.xml` or `${maven.conf}/hazelcast-client.xml` - (see Hazelcast documentation for possibilities, or, see test resources of this project as starter). + ├── ${project.artifactId}-${project.version}.jar + └── hazelcast-5.0.2.jar +- Configure Hazelcast instance with `${maven.conf}/hazelcast.xml` or `${maven.conf}/hazelcast-client.xml` (if client used). + See Hazelcast documentation, default Hazelcast configuration discovery is being used. - Now start a multithreaded Maven build on your project and make sure `NamedSyncContextFactory` is being used. diff --git a/maven-resolver-named-locks-hazelcast/src/site/site.xml b/maven-resolver-named-locks-hazelcast/src/site/site.xml index 0a3c42317..38d8d76ab 100644 --- a/maven-resolver-named-locks-hazelcast/src/site/site.xml +++ b/maven-resolver-named-locks-hazelcast/src/site/site.xml @@ -21,7 +21,7 @@ under the License. diff --git a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastCPSemaphoreAdapterIT.java b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastCPSemaphoreAdapterIT.java index d2faad8cb..8f69655ca 100644 --- a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastCPSemaphoreAdapterIT.java +++ b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastCPSemaphoreAdapterIT.java @@ -22,10 +22,14 @@ import org.junit.BeforeClass; public class HazelcastCPSemaphoreAdapterIT - extends NamedLockFactoryAdapterTestSupport { + extends NamedLockFactoryAdapterTestSupport +{ @BeforeClass - public static void createNamedLockFactory() { - setNamedLockFactory(new HazelcastCPSemaphoreNamedLockFactory()); + public static void createNamedLockFactory() + { + String clusterName = utils.clusterName( HazelcastCPSemaphoreAdapterIT.class ); + setNamedLockFactory( + new HazelcastCPSemaphoreNamedLockFactory( utils.createMember( clusterName ), true ) ); } } diff --git a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastCPSemaphoreNamedLockFactoryIT.java b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastCPSemaphoreNamedLockFactoryIT.java index c53f501b7..cd1a091e3 100644 --- a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastCPSemaphoreNamedLockFactoryIT.java +++ b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastCPSemaphoreNamedLockFactoryIT.java @@ -19,21 +19,16 @@ * under the License. */ -import org.junit.AfterClass; import org.junit.BeforeClass; public class HazelcastCPSemaphoreNamedLockFactoryIT - extends NamedLockFactoryTestSupport { + extends NamedLockFactoryTestSupport +{ @BeforeClass - public static void createNamedLockFactory() { - namedLockFactory = new HazelcastCPSemaphoreNamedLockFactory(); - } - - @AfterClass - public static void cleanup() { - if (namedLockFactory != null) { - namedLockFactory.shutdown(); - } + public static void createNamedLockFactory() + { + String clusterName = utils.clusterName( HazelcastCPSemaphoreNamedLockFactoryIT.class ); + namedLockFactory = new HazelcastCPSemaphoreNamedLockFactory( utils.createMember( clusterName ), true ); } } diff --git a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastClientCPSemaphoreAdapterIT.java b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastClientCPSemaphoreAdapterIT.java index b5d0256eb..c770b7a39 100644 --- a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastClientCPSemaphoreAdapterIT.java +++ b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastClientCPSemaphoreAdapterIT.java @@ -19,24 +19,17 @@ * under the License. */ -import org.junit.AfterClass; import org.junit.BeforeClass; public class HazelcastClientCPSemaphoreAdapterIT - extends NamedLockFactoryAdapterTestSupport { - - private static HazelcastClientUtils utils; - + extends NamedLockFactoryAdapterTestSupport +{ @BeforeClass - public static void createNamedLockFactory() { - utils = new HazelcastClientUtils().createCpCluster(); - setNamedLockFactory(new HazelcastClientCPSemaphoreNamedLockFactory()); - } - - @AfterClass - public static void cleanup() { - if (utils != null) { - utils.cleanup(); - } + public static void createNamedLockFactory() + { + String clusterName = utils.clusterName( HazelcastClientCPSemaphoreAdapterIT.class ); + utils.createMember( clusterName ); + setNamedLockFactory( + new HazelcastClientCPSemaphoreNamedLockFactory( utils.createClient( clusterName ), true ) ); } } diff --git a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastClientCPSemaphoreNamedLockFactoryIT.java b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastClientCPSemaphoreNamedLockFactoryIT.java index 2718bec47..be50ed5be 100644 --- a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastClientCPSemaphoreNamedLockFactoryIT.java +++ b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastClientCPSemaphoreNamedLockFactoryIT.java @@ -19,27 +19,17 @@ * under the License. */ -import org.junit.AfterClass; import org.junit.BeforeClass; public class HazelcastClientCPSemaphoreNamedLockFactoryIT - extends NamedLockFactoryTestSupport { - - private static HazelcastClientUtils utils; - + extends NamedLockFactoryTestSupport +{ @BeforeClass - public static void createNamedLockFactory() { - utils = new HazelcastClientUtils().createCpCluster(); - namedLockFactory = new HazelcastClientCPSemaphoreNamedLockFactory(); - } - - @AfterClass - public static void cleanup() { - if (namedLockFactory != null) { - namedLockFactory.shutdown(); - } - if (utils != null) { - utils.cleanup(); - } + public static void createNamedLockFactory() + { + String clusterName = utils.clusterName( HazelcastClientCPSemaphoreNamedLockFactoryIT.class ); + utils.createMember( clusterName ); + namedLockFactory = + new HazelcastClientCPSemaphoreNamedLockFactory( utils.createClient( clusterName ), true ); } } diff --git a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastClientUtils.java b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastClientUtils.java index 1d3ecc2dc..ec547069c 100644 --- a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastClientUtils.java +++ b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/HazelcastClientUtils.java @@ -19,70 +19,74 @@ * under the License. */ +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.stream.IntStream; + +import com.hazelcast.client.HazelcastClient; +import com.hazelcast.client.config.ClientConfig; import com.hazelcast.config.Config; -import com.hazelcast.config.cp.CPSubsystemConfig; import com.hazelcast.core.Hazelcast; import com.hazelcast.core.HazelcastInstance; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - /** - * Hazelcast Client connects to remote server (or servers, in case of cluster). This class is a helper to - * help create and validate remote Hazelcast environment, that Hazelcast Client will connect to. + * Hazelcast test utilities. */ -public final class HazelcastClientUtils { - - private static final int CP_CLUSTER_NODES = 3; - - private List servers; +public final class HazelcastClientUtils +{ + private final List servers = new ArrayList<>(); /** - * Creates a Hazelcast server instance, that client may connect to. + * Creates similar but still randomized name. */ - public HazelcastClientUtils createSingleServer() { - servers = Collections.singletonList(Hazelcast.newHazelcastInstance()); - return this; + public String clusterName( Class klazz ) + { + return String.format( "%s-%s", klazz.getSimpleName(), UUID.randomUUID() ); } /** - * Creates a Hazelcast CP cluster, that client may connect to. When this method returns, cluster is not only - * created but it is properly formed as well. + * Creates single Hazelcast client instance. */ - public HazelcastClientUtils createCpCluster() { - ArrayList instances = new ArrayList<>(CP_CLUSTER_NODES); - for (int i = 0; i < CP_CLUSTER_NODES; i++) { - HazelcastInstance instance = Hazelcast.newHazelcastInstance( - loadCPNodeConfig().setInstanceName("node" + i) - ); - instances.add(instance); - } - servers = instances; + public synchronized HazelcastInstance createClient( String clusterName ) + { + ClientConfig config = ClientConfig.load(); + config.setClusterName( clusterName ); + return HazelcastClient.newHazelcastClient( config ); + } - // make sure HZ CP Cluster is ready - for (HazelcastInstance instance : servers) { - // this call will block until CP cluster if formed - // important thing here is that this blocking does not happen during timeout surrounded test - // hence, once this method returns, the CP cluster is "ready for use" without any delay. - instance.getCPSubsystem().getAtomicLong(instance.getName()); - } - return this; + /** + * Creates single Hazelcast member instance. + */ + public synchronized HazelcastInstance createMember( String clusterName ) + { + return createMembers( 1, clusterName ).get( 0 ); } /** - * Shuts down the created server(s) + * Creates given count of Hazelcast member instances. */ - public void cleanup() { - if (servers != null) { - servers.forEach(HazelcastInstance::shutdown); - } + public synchronized List createMembers( int memberCount, String clusterName ) + { + Config config = Config.load(); + config.setClusterName( clusterName ); + ArrayList result = new ArrayList<>( memberCount ); + IntStream.range( 0, memberCount ).forEach( i -> { + config.setInstanceName( "node-" + i ); + HazelcastInstance instance = Hazelcast.newHazelcastInstance( config ); + result.add( instance ); + servers.add( instance ); + } + ); + return result; } - private Config loadCPNodeConfig() { - // "cluster" for CP needs some config tweak from the test/resources/hazelcast.xml - Config config = Config.load().setCPSubsystemConfig(new CPSubsystemConfig().setCPMemberCount(3)); - config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(true); - return config; + /** + * Shuts down the created instances. + */ + public synchronized void cleanup() + { + servers.forEach( HazelcastInstance::shutdown ); + servers.clear(); } } diff --git a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/NamedLockFactoryAdapterTestSupport.java b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/NamedLockFactoryAdapterTestSupport.java index fc85955c7..db5beb2c5 100644 --- a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/NamedLockFactoryAdapterTestSupport.java +++ b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/NamedLockFactoryAdapterTestSupport.java @@ -19,6 +19,14 @@ * under the License. */ +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.HashMap; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.SyncContext; import org.eclipse.aether.artifact.DefaultArtifact; @@ -33,14 +41,6 @@ import org.junit.Before; import org.junit.Test; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.HashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -49,203 +49,232 @@ */ public abstract class NamedLockFactoryAdapterTestSupport { - private static final long ADAPTER_TIME = 100L; + protected static final HazelcastClientUtils utils = new HazelcastClientUtils(); + + private static final long ADAPTER_TIME = 100L; + + private static final TimeUnit ADAPTER_TIME_UNIT = TimeUnit.MILLISECONDS; + + /** + * Subclass should populate this field, using {@link #setNamedLockFactory(NamedLockFactory)}, but subclass + * must take care of proper cleanup as well, if needed! + */ + private static NamedLockFactoryAdapter adapter; + + private RepositorySystemSession session; + + protected static void setNamedLockFactory( final NamedLockFactory namedLockFactory ) + { + adapter = new NamedLockFactoryAdapter( + new DiscriminatingNameMapper( new GAVNameMapper() ), namedLockFactory + ); + } - private static final TimeUnit ADAPTER_TIME_UNIT = TimeUnit.MILLISECONDS; + @AfterClass + public static void cleanup() + { + if ( adapter != null ) + { + adapter.shutdown(); + } - /** - * Subclass should populate this field, using {@link #setNamedLockFactory(NamedLockFactory)}, but subclass - * must take care of proper cleanup as well, if needed! - */ - private static NamedLockFactoryAdapter adapter; + utils.cleanup(); + } - private RepositorySystemSession session; + @Before + public void before() throws IOException + { + Files.createDirectories( Paths.get( System.getProperty( "java.io.tmpdir" ) ) ); // hack for Surefire + LocalRepository localRepository = new LocalRepository( Files.createTempDirectory( "test" ).toFile() ); + session = mock( RepositorySystemSession.class ); + when( session.getLocalRepository() ).thenReturn( localRepository ); + HashMap config = new HashMap<>(); + config.put( NamedLockFactoryAdapter.TIME_KEY, String.valueOf( ADAPTER_TIME ) ); + config.put( NamedLockFactoryAdapter.TIME_UNIT_KEY, ADAPTER_TIME_UNIT.name() ); + when( session.getConfigProperties() ).thenReturn( config ); + } - protected static void setNamedLockFactory(final NamedLockFactory namedLockFactory) { - adapter = new NamedLockFactoryAdapter( - new DiscriminatingNameMapper(new GAVNameMapper()), namedLockFactory - ); - } + @Test + public void justCreateAndClose() + { + adapter.newInstance( session, false ).close(); + } - @AfterClass - public static void cleanupAdapter() { - if (adapter != null) { - adapter.shutdown(); + @Test + public void justAcquire() + { + try ( SyncContext syncContext = adapter.newInstance( session, false ) ) + { + syncContext.acquire( + Arrays.asList( new DefaultArtifact( "groupId:artifactId:1.0" ), + new DefaultArtifact( "groupId:artifactId:1.1" ) ), + null + ); + } } - } - - @Before - public void before() throws IOException { - Files.createDirectories(Paths.get(System.getProperty("java.io.tmpdir"))); // hack for Surefire - LocalRepository localRepository = new LocalRepository(Files.createTempDirectory("test").toFile()); - session = mock(RepositorySystemSession.class); - when(session.getLocalRepository()).thenReturn(localRepository); - HashMap config = new HashMap<>(); - config.put(NamedLockFactoryAdapter.TIME_KEY, String.valueOf(ADAPTER_TIME)); - config.put(NamedLockFactoryAdapter.TIME_UNIT_KEY, ADAPTER_TIME_UNIT.name()); - when(session.getConfigProperties()).thenReturn(config); - } - - @Test - public void justCreateAndClose() { - adapter.newInstance(session, false).close(); - } - - @Test - public void justAcquire() { - try (SyncContext syncContext = adapter.newInstance(session, false)) { - syncContext.acquire( - Arrays.asList(new DefaultArtifact("groupId:artifactId:1.0"), new DefaultArtifact("groupId:artifactId:1.1")), - null - ); + + @Test( timeout = 5000 ) + public void sharedAccess() throws InterruptedException + { + CountDownLatch winners = new CountDownLatch( 2 ); // we expect 2 winners + CountDownLatch losers = new CountDownLatch( 0 ); // we expect 0 losers + Thread t1 = new Thread( new Access( true, winners, losers, adapter, session, null ) ); + Thread t2 = new Thread( new Access( true, winners, losers, adapter, session, null ) ); + t1.start(); + t2.start(); + t1.join(); + t2.join(); + winners.await(); + losers.await(); } - } - - @Test(timeout = 5000) - public void sharedAccess() throws InterruptedException { - CountDownLatch winners = new CountDownLatch(2); // we expect 2 winners - CountDownLatch losers = new CountDownLatch(0); // we expect 0 losers - Thread t1 = new Thread(new Access(true, winners, losers, adapter, session, null)); - Thread t2 = new Thread(new Access(true, winners, losers, adapter, session, null)); - t1.start(); - t2.start(); - t1.join(); - t2.join(); - winners.await(); - losers.await(); - } - - @Test(timeout = 5000) - public void exclusiveAccess() throws InterruptedException { - CountDownLatch winners = new CountDownLatch(1); // we expect 1 winner - CountDownLatch losers = new CountDownLatch(1); // we expect 1 loser - Thread t1 = new Thread(new Access(false, winners, losers, adapter, session, null)); - Thread t2 = new Thread(new Access(false, winners, losers, adapter, session, null)); - t1.start(); - t2.start(); - t1.join(); - t2.join(); - winners.await(); - losers.await(); - } - - @Test(timeout = 5000) - public void mixedAccess() throws InterruptedException { - CountDownLatch winners = new CountDownLatch(1); // we expect 1 winner - CountDownLatch losers = new CountDownLatch(1); // we expect 1 loser - Thread t1 = new Thread(new Access(true, winners, losers, adapter, session, null)); - Thread t2 = new Thread(new Access(false, winners, losers, adapter, session, null)); - t1.start(); - t2.start(); - t1.join(); - t2.join(); - winners.await(); - losers.await(); - } - - @Test(timeout = 5000) - public void nestedSharedShared() throws InterruptedException { - CountDownLatch winners = new CountDownLatch(2); // we expect 2 winners - CountDownLatch losers = new CountDownLatch(0); // we expect 0 losers - Thread t1 = new Thread( - new Access(true, winners, losers, adapter, session, - new Access(true, winners, losers, adapter, session, null) - ) - ); - t1.start(); - t1.join(); - winners.await(); - losers.await(); - } - - @Test(timeout = 5000) - public void nestedExclusiveShared() throws InterruptedException { - CountDownLatch winners = new CountDownLatch(2); // we expect 2 winners - CountDownLatch losers = new CountDownLatch(0); // we expect 0 losers - Thread t1 = new Thread( - new Access(false, winners, losers, adapter, session, - new Access(true, winners, losers, adapter, session, null) - ) - ); - t1.start(); - t1.join(); - winners.await(); - losers.await(); - } - - @Test(timeout = 5000) - public void nestedExclusiveExclusive() throws InterruptedException { - CountDownLatch winners = new CountDownLatch(2); // we expect 2 winners - CountDownLatch losers = new CountDownLatch(0); // we expect 0 losers - Thread t1 = new Thread( - new Access(false, winners, losers, adapter, session, - new Access(false, winners, losers, adapter, session, null) - ) - ); - t1.start(); - t1.join(); - winners.await(); - losers.await(); - } - - @Test(timeout = 5000) - public void nestedSharedExclusive() throws InterruptedException { - CountDownLatch winners = new CountDownLatch(1); // we expect 1 winner (outer) - CountDownLatch losers = new CountDownLatch(1); // we expect 1 loser (inner) - Thread t1 = new Thread( - new Access(true, winners, losers, adapter, session, - new Access(false, winners, losers, adapter, session, null) - ) - ); - t1.start(); - t1.join(); - winners.await(); - losers.await(); - } - - private static class Access implements Runnable { - final boolean shared; - final CountDownLatch winner; - final CountDownLatch loser; - final NamedLockFactoryAdapter adapter; - final RepositorySystemSession session; - final Access chained; - - public Access(boolean shared, - CountDownLatch winner, - CountDownLatch loser, - NamedLockFactoryAdapter adapter, - RepositorySystemSession session, - Access chained) { - this.shared = shared; - this.winner = winner; - this.loser = loser; - this.adapter = adapter; - this.session = session; - this.chained = chained; + + @Test( timeout = 5000 ) + public void exclusiveAccess() throws InterruptedException + { + CountDownLatch winners = new CountDownLatch( 1 ); // we expect 1 winner + CountDownLatch losers = new CountDownLatch( 1 ); // we expect 1 loser + Thread t1 = new Thread( new Access( false, winners, losers, adapter, session, null ) ); + Thread t2 = new Thread( new Access( false, winners, losers, adapter, session, null ) ); + t1.start(); + t2.start(); + t1.join(); + t2.join(); + winners.await(); + losers.await(); } - @Override - public void run() { - try { - try (SyncContext syncContext = adapter.newInstance(session, shared)) { - syncContext.acquire( - Arrays.asList(new DefaultArtifact("groupId:artifactId:1.0"), new DefaultArtifact("groupId:artifactId:1.1")), - null - ); - winner.countDown(); - if (chained != null) { - chained.run(); - } - loser.await(); - } catch (IllegalStateException e) { - loser.countDown(); - winner.await(); + @Test( timeout = 5000 ) + public void mixedAccess() throws InterruptedException + { + CountDownLatch winners = new CountDownLatch( 1 ); // we expect 1 winner + CountDownLatch losers = new CountDownLatch( 1 ); // we expect 1 loser + Thread t1 = new Thread( new Access( true, winners, losers, adapter, session, null ) ); + Thread t2 = new Thread( new Access( false, winners, losers, adapter, session, null ) ); + t1.start(); + t2.start(); + t1.join(); + t2.join(); + winners.await(); + losers.await(); + } + + @Test( timeout = 5000 ) + public void nestedSharedShared() throws InterruptedException + { + CountDownLatch winners = new CountDownLatch( 2 ); // we expect 2 winners + CountDownLatch losers = new CountDownLatch( 0 ); // we expect 0 losers + Thread t1 = new Thread( + new Access( true, winners, losers, adapter, session, + new Access( true, winners, losers, adapter, session, null ) + ) + ); + t1.start(); + t1.join(); + winners.await(); + losers.await(); + } + + @Test( timeout = 5000 ) + public void nestedExclusiveShared() throws InterruptedException + { + CountDownLatch winners = new CountDownLatch( 2 ); // we expect 2 winners + CountDownLatch losers = new CountDownLatch( 0 ); // we expect 0 losers + Thread t1 = new Thread( + new Access( false, winners, losers, adapter, session, + new Access( true, winners, losers, adapter, session, null ) + ) + ); + t1.start(); + t1.join(); + winners.await(); + losers.await(); + } + + @Test( timeout = 5000 ) + public void nestedExclusiveExclusive() throws InterruptedException + { + CountDownLatch winners = new CountDownLatch( 2 ); // we expect 2 winners + CountDownLatch losers = new CountDownLatch( 0 ); // we expect 0 losers + Thread t1 = new Thread( + new Access( false, winners, losers, adapter, session, + new Access( false, winners, losers, adapter, session, null ) + ) + ); + t1.start(); + t1.join(); + winners.await(); + losers.await(); + } + + @Test( timeout = 5000 ) + public void nestedSharedExclusive() throws InterruptedException + { + CountDownLatch winners = new CountDownLatch( 1 ); // we expect 1 winner (outer) + CountDownLatch losers = new CountDownLatch( 1 ); // we expect 1 loser (inner) + Thread t1 = new Thread( + new Access( true, winners, losers, adapter, session, + new Access( false, winners, losers, adapter, session, null ) + ) + ); + t1.start(); + t1.join(); + winners.await(); + losers.await(); + } + + private static class Access implements Runnable + { + final boolean shared; + final CountDownLatch winner; + final CountDownLatch loser; + final NamedLockFactoryAdapter adapter; + final RepositorySystemSession session; + final Access chained; + + public Access( boolean shared, + CountDownLatch winner, + CountDownLatch loser, + NamedLockFactoryAdapter adapter, + RepositorySystemSession session, + Access chained ) + { + this.shared = shared; + this.winner = winner; + this.loser = loser; + this.adapter = adapter; + this.session = session; + this.chained = chained; + } + + @Override + public void run() + { + try + { + try ( SyncContext syncContext = adapter.newInstance( session, shared ) ) + { + syncContext.acquire( + Arrays.asList( new DefaultArtifact( "groupId:artifactId:1.0" ), + new DefaultArtifact( "groupId:artifactId:1.1" ) ), + null + ); + winner.countDown(); + if ( chained != null ) + { + chained.run(); + } + loser.await(); + } + catch ( IllegalStateException e ) + { + loser.countDown(); + winner.await(); + } + } + catch ( InterruptedException e ) + { + Assert.fail( "interrupted" ); + } } - } - catch (InterruptedException e) { - Assert.fail("interrupted"); - } } - } } diff --git a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/NamedLockFactoryTestSupport.java b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/NamedLockFactoryTestSupport.java index c128e7f52..04b009c8a 100644 --- a/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/NamedLockFactoryTestSupport.java +++ b/maven-resolver-named-locks-hazelcast/src/test/java/org/eclipse/aether/named/hazelcast/NamedLockFactoryTestSupport.java @@ -19,16 +19,17 @@ * under the License. */ +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + import org.eclipse.aether.named.NamedLock; import org.eclipse.aether.named.NamedLockFactory; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; @@ -37,86 +38,112 @@ /** * UT support for {@link NamedLockFactory}. */ -public abstract class NamedLockFactoryTestSupport { +public abstract class NamedLockFactoryTestSupport +{ + protected static final HazelcastClientUtils utils = new HazelcastClientUtils(); protected static NamedLockFactory namedLockFactory; @Rule public TestName testName = new TestName(); + @AfterClass + public static void cleanup() + { + if ( namedLockFactory != null ) + { + namedLockFactory.shutdown(); + } + utils.cleanup(); + } + @Test - public void refCounting() { + public void refCounting() + { final String name = testName.getMethodName(); - try (NamedLock one = namedLockFactory.getLock(name); - NamedLock two = namedLockFactory.getLock(name)) { - assertThat(one, sameInstance(two)); + try ( NamedLock one = namedLockFactory.getLock( name ); + NamedLock two = namedLockFactory.getLock( name ) ) + { + assertThat( one, sameInstance( two ) ); one.close(); two.close(); - try (NamedLock three = namedLockFactory.getLock(name)) { - assertThat(three, not(sameInstance(two))); + try ( NamedLock three = namedLockFactory.getLock( name ) ) + { + assertThat( three, not( sameInstance( two ) ) ); } } } - @Test(expected = IllegalStateException.class) - public void unlockWoLock() { + @Test( expected = IllegalStateException.class ) + public void unlockWoLock() + { final String name = testName.getMethodName(); - try (NamedLock one = namedLockFactory.getLock(name)) { + try ( NamedLock one = namedLockFactory.getLock( name ) ) + { one.unlock(); } } @Test - public void wwBoxing() throws InterruptedException { + public void wwBoxing() throws InterruptedException + { final String name = testName.getMethodName(); - try (NamedLock one = namedLockFactory.getLock(name)) { - assertThat(one.lockExclusively(1L, TimeUnit.MILLISECONDS), is(true)); - assertThat(one.lockExclusively(1L, TimeUnit.MILLISECONDS), is(true)); + try ( NamedLock one = namedLockFactory.getLock( name ) ) + { + assertThat( one.lockExclusively( 1L, TimeUnit.MILLISECONDS ), is( true ) ); + assertThat( one.lockExclusively( 1L, TimeUnit.MILLISECONDS ), is( true ) ); one.unlock(); one.unlock(); } } @Test - public void rrBoxing() throws InterruptedException { + public void rrBoxing() throws InterruptedException + { final String name = testName.getMethodName(); - try (NamedLock one = namedLockFactory.getLock(name)) { - assertThat(one.lockShared(1L, TimeUnit.MILLISECONDS), is(true)); - assertThat(one.lockShared(1L, TimeUnit.MILLISECONDS), is(true)); + try ( NamedLock one = namedLockFactory.getLock( name ) ) + { + assertThat( one.lockShared( 1L, TimeUnit.MILLISECONDS ), is( true ) ); + assertThat( one.lockShared( 1L, TimeUnit.MILLISECONDS ), is( true ) ); one.unlock(); one.unlock(); } } @Test - public void wrBoxing() throws InterruptedException { + public void wrBoxing() throws InterruptedException + { final String name = testName.getMethodName(); - try (NamedLock one = namedLockFactory.getLock(name)) { - assertThat(one.lockExclusively(1L, TimeUnit.MILLISECONDS), is(true)); - assertThat(one.lockShared(1L, TimeUnit.MILLISECONDS), is(true)); + try ( NamedLock one = namedLockFactory.getLock( name ) ) + { + assertThat( one.lockExclusively( 1L, TimeUnit.MILLISECONDS ), is( true ) ); + assertThat( one.lockShared( 1L, TimeUnit.MILLISECONDS ), is( true ) ); one.unlock(); one.unlock(); } } @Test - public void rwBoxing() throws InterruptedException { + public void rwBoxing() throws InterruptedException + { final String name = testName.getMethodName(); - try (NamedLock one = namedLockFactory.getLock(name)) { - assertThat(one.lockShared(1L, TimeUnit.MILLISECONDS), is(true)); - assertThat(one.lockExclusively(1L, TimeUnit.MILLISECONDS), is(false)); + try ( NamedLock one = namedLockFactory.getLock( name ) ) + { + assertThat( one.lockShared( 1L, TimeUnit.MILLISECONDS ), is( true ) ); + assertThat( one.lockExclusively( 1L, TimeUnit.MILLISECONDS ), is( false ) ); one.unlock(); } } - @Test(timeout = 5000) - public void sharedAccess() throws InterruptedException { + @Test( timeout = 5000 ) + public void sharedAccess() throws InterruptedException + { final String name = testName.getMethodName(); - CountDownLatch winners = new CountDownLatch(2); // we expect 2 winner - CountDownLatch losers = new CountDownLatch(0); // we expect 0 loser - Thread t1 = new Thread(new Access(namedLockFactory, name, true, winners, losers)); - Thread t2 = new Thread(new Access(namedLockFactory, name, true, winners, losers)); + CountDownLatch winners = new CountDownLatch( 2 ); // we expect 2 winner + CountDownLatch losers = new CountDownLatch( 0 ); // we expect 0 loser + Thread t1 = new Thread( new Access( namedLockFactory, name, true, winners, losers ) ); + Thread t2 = new Thread( new Access( namedLockFactory, name, true, winners, losers ) ); t1.start(); t2.start(); t1.join(); @@ -125,13 +152,14 @@ public void sharedAccess() throws InterruptedException { losers.await(); } - @Test(timeout = 5000) - public void exclusiveAccess() throws InterruptedException { + @Test( timeout = 5000 ) + public void exclusiveAccess() throws InterruptedException + { final String name = testName.getMethodName(); - CountDownLatch winners = new CountDownLatch(1); // we expect 1 winner - CountDownLatch losers = new CountDownLatch(1); // we expect 1 loser - Thread t1 = new Thread(new Access(namedLockFactory, name, false, winners, losers)); - Thread t2 = new Thread(new Access(namedLockFactory, name, false, winners, losers)); + CountDownLatch winners = new CountDownLatch( 1 ); // we expect 1 winner + CountDownLatch losers = new CountDownLatch( 1 ); // we expect 1 loser + Thread t1 = new Thread( new Access( namedLockFactory, name, false, winners, losers ) ); + Thread t2 = new Thread( new Access( namedLockFactory, name, false, winners, losers ) ); t1.start(); t2.start(); t1.join(); @@ -140,13 +168,14 @@ public void exclusiveAccess() throws InterruptedException { losers.await(); } - @Test(timeout = 5000) - public void mixedAccess() throws InterruptedException { + @Test( timeout = 5000 ) + public void mixedAccess() throws InterruptedException + { final String name = testName.getMethodName(); - CountDownLatch winners = new CountDownLatch(1); // we expect 1 winner - CountDownLatch losers = new CountDownLatch(1); // we expect 1 loser - Thread t1 = new Thread(new Access(namedLockFactory, name, true, winners, losers)); - Thread t2 = new Thread(new Access(namedLockFactory, name, false, winners, losers)); + CountDownLatch winners = new CountDownLatch( 1 ); // we expect 1 winner + CountDownLatch losers = new CountDownLatch( 1 ); // we expect 1 loser + Thread t1 = new Thread( new Access( namedLockFactory, name, true, winners, losers ) ); + Thread t2 = new Thread( new Access( namedLockFactory, name, false, winners, losers ) ); t1.start(); t2.start(); t1.join(); @@ -155,18 +184,20 @@ public void mixedAccess() throws InterruptedException { losers.await(); } - private static class Access implements Runnable { + private static class Access implements Runnable + { final NamedLockFactory namedLockFactory; final String name; final boolean shared; final CountDownLatch winner; final CountDownLatch loser; - public Access(NamedLockFactory namedLockFactory, - String name, - boolean shared, - CountDownLatch winner, - CountDownLatch loser) { + public Access( NamedLockFactory namedLockFactory, + String name, + boolean shared, + CountDownLatch winner, + CountDownLatch loser ) + { this.namedLockFactory = namedLockFactory; this.name = name; this.shared = shared; @@ -175,21 +206,32 @@ public Access(NamedLockFactory namedLockFactory, } @Override - public void run() { - try (NamedLock lock = namedLockFactory.getLock(name)) { - if (shared ? lock.lockShared(100L, TimeUnit.MILLISECONDS) : lock.lockExclusively(100L, TimeUnit.MILLISECONDS)) { - try { + public void run() + { + try ( NamedLock lock = namedLockFactory.getLock( name ) ) + { + if ( shared ? lock.lockShared( 100L, TimeUnit.MILLISECONDS ) : + lock.lockExclusively( 100L, TimeUnit.MILLISECONDS ) ) + { + try + { winner.countDown(); loser.await(); - } finally { + } + finally + { lock.unlock(); } - } else { + } + else + { loser.countDown(); winner.await(); } - } catch (InterruptedException e) { - Assert.fail(e.getMessage()); + } + catch ( InterruptedException e ) + { + Assert.fail( e.getMessage() ); } } } diff --git a/maven-resolver-named-locks-hazelcast/src/test/resources/hazelcast-client.xml b/maven-resolver-named-locks-hazelcast/src/test/resources/hazelcast-client.xml index 19f1cc0f9..92a2fbfaa 100644 --- a/maven-resolver-named-locks-hazelcast/src/test/resources/hazelcast-client.xml +++ b/maven-resolver-named-locks-hazelcast/src/test/resources/hazelcast-client.xml @@ -22,7 +22,7 @@ + https://www.hazelcast.com/schema/client-config/hazelcast-client-config-5.0.xsd"> maven-resolver-named client diff --git a/maven-resolver-named-locks-hazelcast/src/test/resources/hazelcast.xml b/maven-resolver-named-locks-hazelcast/src/test/resources/hazelcast.xml index 0c204f771..8516b7ccc 100644 --- a/maven-resolver-named-locks-hazelcast/src/test/resources/hazelcast.xml +++ b/maven-resolver-named-locks-hazelcast/src/test/resources/hazelcast.xml @@ -22,7 +22,7 @@ + https://www.hazelcast.com/schema/config/hazelcast-config-5.0.xsd"> maven-resolver-named server @@ -31,10 +31,22 @@ + localhost + + + + + maven:resolver:* + true + + 2147483647 + + +