View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.named.hazelcast;
20  
21  import java.util.concurrent.CountDownLatch;
22  import java.util.concurrent.TimeUnit;
23  
24  import org.eclipse.aether.named.NamedLock;
25  import org.eclipse.aether.named.NamedLockFactory;
26  import org.eclipse.aether.named.support.LockUpgradeNotSupportedException;
27  import org.junit.jupiter.api.AfterAll;
28  import org.junit.jupiter.api.Test;
29  import org.junit.jupiter.api.TestInfo;
30  import org.junit.jupiter.api.Timeout;
31  
32  import static org.junit.jupiter.api.Assertions.*;
33  
34  /**
35   * UT support for {@link NamedLockFactory}.
36   */
37  public abstract class NamedLockFactoryTestSupport {
38      protected static final HazelcastClientUtils utils = new HazelcastClientUtils();
39  
40      protected static NamedLockFactory namedLockFactory;
41  
42      @AfterAll
43      static void cleanup() {
44          if (namedLockFactory != null) {
45              namedLockFactory.shutdown();
46          }
47          utils.cleanup();
48      }
49  
50      @Test
51      void refCounting(TestInfo testInfo) {
52          final String name = testInfo.getDisplayName();
53          try (NamedLock one = namedLockFactory.getLock(name);
54                  NamedLock two = namedLockFactory.getLock(name)) {
55              assertSame(one, two);
56              one.close();
57              two.close();
58  
59              try (NamedLock three = namedLockFactory.getLock(name)) {
60                  assertNotSame(three, two);
61              }
62          }
63      }
64  
65      @Test
66      void unlockWoLock(TestInfo testInfo) {
67          final String name = testInfo.getDisplayName();
68          try (NamedLock one = namedLockFactory.getLock(name)) {
69              assertThrows(IllegalStateException.class, one::unlock);
70          }
71      }
72  
73      @Test
74      void wwBoxing(TestInfo testInfo) throws InterruptedException {
75          final String name = testInfo.getDisplayName();
76          try (NamedLock one = namedLockFactory.getLock(name)) {
77              assertTrue(one.lockExclusively(1L, TimeUnit.MILLISECONDS));
78              assertTrue(one.lockExclusively(1L, TimeUnit.MILLISECONDS));
79              one.unlock();
80              one.unlock();
81          }
82      }
83  
84      @Test
85      void rrBoxing(TestInfo testInfo) throws InterruptedException {
86          final String name = testInfo.getDisplayName();
87          try (NamedLock one = namedLockFactory.getLock(name)) {
88              assertTrue(one.lockShared(1L, TimeUnit.MILLISECONDS));
89              assertTrue(one.lockShared(1L, TimeUnit.MILLISECONDS));
90              one.unlock();
91              one.unlock();
92          }
93      }
94  
95      @Test
96      void wrBoxing(TestInfo testInfo) throws InterruptedException {
97          final String name = testInfo.getDisplayName();
98          try (NamedLock one = namedLockFactory.getLock(name)) {
99              assertTrue(one.lockExclusively(1L, TimeUnit.MILLISECONDS));
100             assertTrue(one.lockShared(1L, TimeUnit.MILLISECONDS));
101             one.unlock();
102             one.unlock();
103         }
104     }
105 
106     @Test
107     void rwBoxing(TestInfo testInfo) throws InterruptedException {
108         final String name = testInfo.getDisplayName();
109         try (NamedLock one = namedLockFactory.getLock(name)) {
110             assertTrue(one.lockShared(1L, TimeUnit.MILLISECONDS));
111             try {
112                 one.lockExclusively(1L, TimeUnit.MILLISECONDS);
113                 fail("lock upgrade should be not supported");
114             } catch (LockUpgradeNotSupportedException e) {
115                 // good
116             }
117             one.unlock();
118         }
119     }
120 
121     @Test
122     @Timeout(5)
123     public void sharedAccess(TestInfo testInfo) throws InterruptedException {
124         final String name = testInfo.getDisplayName();
125         CountDownLatch winners = new CountDownLatch(2); // we expect 2 winner
126         CountDownLatch losers = new CountDownLatch(0); // we expect 0 loser
127         Thread t1 = new Thread(new Access(namedLockFactory, name, true, winners, losers));
128         Thread t2 = new Thread(new Access(namedLockFactory, name, true, winners, losers));
129         t1.start();
130         t2.start();
131         t1.join();
132         t2.join();
133         winners.await();
134         losers.await();
135     }
136 
137     @Test
138     @Timeout(5)
139     public void exclusiveAccess(TestInfo testInfo) throws InterruptedException {
140         final String name = testInfo.getDisplayName();
141         CountDownLatch winners = new CountDownLatch(1); // we expect 1 winner
142         CountDownLatch losers = new CountDownLatch(1); // we expect 1 loser
143         Thread t1 = new Thread(new Access(namedLockFactory, name, false, winners, losers));
144         Thread t2 = new Thread(new Access(namedLockFactory, name, false, winners, losers));
145         t1.start();
146         t2.start();
147         t1.join();
148         t2.join();
149         winners.await();
150         losers.await();
151     }
152 
153     @Test
154     @Timeout(5)
155     public void mixedAccess(TestInfo testInfo) throws InterruptedException {
156         final String name = testInfo.getDisplayName();
157         CountDownLatch winners = new CountDownLatch(1); // we expect 1 winner
158         CountDownLatch losers = new CountDownLatch(1); // we expect 1 loser
159         Thread t1 = new Thread(new Access(namedLockFactory, name, true, winners, losers));
160         Thread t2 = new Thread(new Access(namedLockFactory, name, false, winners, losers));
161         t1.start();
162         t2.start();
163         t1.join();
164         t2.join();
165         winners.await();
166         losers.await();
167     }
168 
169     private static class Access implements Runnable {
170         final NamedLockFactory namedLockFactory;
171         final String name;
172         final boolean shared;
173         final CountDownLatch winner;
174         final CountDownLatch loser;
175 
176         public Access(
177                 NamedLockFactory namedLockFactory,
178                 String name,
179                 boolean shared,
180                 CountDownLatch winner,
181                 CountDownLatch loser) {
182             this.namedLockFactory = namedLockFactory;
183             this.name = name;
184             this.shared = shared;
185             this.winner = winner;
186             this.loser = loser;
187         }
188 
189         @Override
190         public void run() {
191             try (NamedLock lock = namedLockFactory.getLock(name)) {
192                 if (shared
193                         ? lock.lockShared(100L, TimeUnit.MILLISECONDS)
194                         : lock.lockExclusively(100L, TimeUnit.MILLISECONDS)) {
195                     try {
196                         winner.countDown();
197                         loser.await();
198                     } finally {
199                         lock.unlock();
200                     }
201                 } else {
202                     loser.countDown();
203                     winner.await();
204                 }
205             } catch (InterruptedException e) {
206                 fail(e.getMessage());
207             }
208         }
209     }
210 }