View Javadoc
1   package org.eclipse.aether.named.hazelcast;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.nio.file.Files;
24  import java.nio.file.Paths;
25  import java.util.Arrays;
26  import java.util.HashMap;
27  import java.util.concurrent.CountDownLatch;
28  import java.util.concurrent.TimeUnit;
29  
30  import org.eclipse.aether.RepositorySystemSession;
31  import org.eclipse.aether.SyncContext;
32  import org.eclipse.aether.artifact.DefaultArtifact;
33  import org.eclipse.aether.internal.impl.synccontext.named.DiscriminatingNameMapper;
34  import org.eclipse.aether.internal.impl.synccontext.named.GAVNameMapper;
35  import org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactoryAdapter;
36  import org.eclipse.aether.named.NamedLockFactory;
37  import org.eclipse.aether.repository.LocalRepository;
38  import org.eclipse.aether.spi.synccontext.SyncContextFactory;
39  import org.junit.AfterClass;
40  import org.junit.Assert;
41  import org.junit.Before;
42  import org.junit.Test;
43  
44  import static org.mockito.Mockito.mock;
45  import static org.mockito.Mockito.when;
46  
47  /**
48   * UT support for {@link SyncContextFactory}.
49   */
50  public abstract class NamedLockFactoryAdapterTestSupport
51  {
52      protected static final HazelcastClientUtils utils = new HazelcastClientUtils();
53  
54      private static final long ADAPTER_TIME = 100L;
55  
56      private static final TimeUnit ADAPTER_TIME_UNIT = TimeUnit.MILLISECONDS;
57  
58      /**
59       * Subclass should populate this field, using {@link #setNamedLockFactory(NamedLockFactory)}, but subclass
60       * must take care of proper cleanup as well, if needed!
61       */
62      private static NamedLockFactoryAdapter adapter;
63  
64      private RepositorySystemSession session;
65  
66      protected static void setNamedLockFactory( final NamedLockFactory namedLockFactory )
67      {
68          adapter = new NamedLockFactoryAdapter(
69                  new DiscriminatingNameMapper( GAVNameMapper.gav() ), namedLockFactory
70          );
71      }
72  
73      @AfterClass
74      public static void cleanup()
75      {
76          if ( adapter != null )
77          {
78              adapter.getNamedLockFactory().shutdown();
79          }
80  
81          utils.cleanup();
82      }
83  
84      @Before
85      public void before() throws IOException
86      {
87          Files.createDirectories( Paths.get( System.getProperty( "java.io.tmpdir" ) ) ); // hack for Surefire
88          LocalRepository localRepository = new LocalRepository( Files.createTempDirectory( "test" ).toFile() );
89          session = mock( RepositorySystemSession.class );
90          when( session.getLocalRepository() ).thenReturn( localRepository );
91          HashMap<String, Object> config = new HashMap<>();
92          config.put( NamedLockFactoryAdapter.TIME_KEY, String.valueOf( ADAPTER_TIME ) );
93          config.put( NamedLockFactoryAdapter.TIME_UNIT_KEY, ADAPTER_TIME_UNIT.name() );
94          when( session.getConfigProperties() ).thenReturn( config );
95      }
96  
97      @Test
98      public void justCreateAndClose()
99      {
100         adapter.newInstance( session, false ).close();
101     }
102 
103     @Test
104     public void justAcquire()
105     {
106         try ( SyncContext syncContext = adapter.newInstance( session, false ) )
107         {
108             syncContext.acquire(
109                     Arrays.asList( new DefaultArtifact( "groupId:artifactId:1.0" ),
110                             new DefaultArtifact( "groupId:artifactId:1.1" ) ),
111                     null
112             );
113         }
114     }
115 
116     @Test( timeout = 5000 )
117     public void sharedAccess() throws InterruptedException
118     {
119         CountDownLatch winners = new CountDownLatch( 2 ); // we expect 2 winners
120         CountDownLatch losers = new CountDownLatch( 0 ); // we expect 0 losers
121         Thread t1 = new Thread( new Access( true, winners, losers, adapter, session, null ) );
122         Thread t2 = new Thread( new Access( true, winners, losers, adapter, session, null ) );
123         t1.start();
124         t2.start();
125         t1.join();
126         t2.join();
127         winners.await();
128         losers.await();
129     }
130 
131     @Test( timeout = 5000 )
132     public void exclusiveAccess() throws InterruptedException
133     {
134         CountDownLatch winners = new CountDownLatch( 1 ); // we expect 1 winner
135         CountDownLatch losers = new CountDownLatch( 1 ); // we expect 1 loser
136         Thread t1 = new Thread( new Access( false, winners, losers, adapter, session, null ) );
137         Thread t2 = new Thread( new Access( false, winners, losers, adapter, session, null ) );
138         t1.start();
139         t2.start();
140         t1.join();
141         t2.join();
142         winners.await();
143         losers.await();
144     }
145 
146     @Test( timeout = 5000 )
147     public void mixedAccess() throws InterruptedException
148     {
149         CountDownLatch winners = new CountDownLatch( 1 ); // we expect 1 winner
150         CountDownLatch losers = new CountDownLatch( 1 ); // we expect 1 loser
151         Thread t1 = new Thread( new Access( true, winners, losers, adapter, session, null ) );
152         Thread t2 = new Thread( new Access( false, winners, losers, adapter, session, null ) );
153         t1.start();
154         t2.start();
155         t1.join();
156         t2.join();
157         winners.await();
158         losers.await();
159     }
160 
161     @Test( timeout = 5000 )
162     public void nestedSharedShared() throws InterruptedException
163     {
164         CountDownLatch winners = new CountDownLatch( 2 ); // we expect 2 winners
165         CountDownLatch losers = new CountDownLatch( 0 ); // we expect 0 losers
166         Thread t1 = new Thread(
167                 new Access( true, winners, losers, adapter, session,
168                         new Access( true, winners, losers, adapter, session, null )
169                 )
170         );
171         t1.start();
172         t1.join();
173         winners.await();
174         losers.await();
175     }
176 
177     @Test( timeout = 5000 )
178     public void nestedExclusiveShared() throws InterruptedException
179     {
180         CountDownLatch winners = new CountDownLatch( 2 ); // we expect 2 winners
181         CountDownLatch losers = new CountDownLatch( 0 ); // we expect 0 losers
182         Thread t1 = new Thread(
183                 new Access( false, winners, losers, adapter, session,
184                         new Access( true, winners, losers, adapter, session, null )
185                 )
186         );
187         t1.start();
188         t1.join();
189         winners.await();
190         losers.await();
191     }
192 
193     @Test( timeout = 5000 )
194     public void nestedExclusiveExclusive() throws InterruptedException
195     {
196         CountDownLatch winners = new CountDownLatch( 2 ); // we expect 2 winners
197         CountDownLatch losers = new CountDownLatch( 0 ); // we expect 0 losers
198         Thread t1 = new Thread(
199                 new Access( false, winners, losers, adapter, session,
200                         new Access( false, winners, losers, adapter, session, null )
201                 )
202         );
203         t1.start();
204         t1.join();
205         winners.await();
206         losers.await();
207     }
208 
209     @Test( timeout = 5000 )
210     public void nestedSharedExclusive() throws InterruptedException
211     {
212         CountDownLatch winners = new CountDownLatch( 1 ); // we expect 1 winner (outer)
213         CountDownLatch losers = new CountDownLatch( 1 ); // we expect 1 loser (inner)
214         Thread t1 = new Thread(
215                 new Access( true, winners, losers, adapter, session,
216                         new Access( false, winners, losers, adapter, session, null )
217                 )
218         );
219         t1.start();
220         t1.join();
221         winners.await();
222         losers.await();
223     }
224 
225     private static class Access implements Runnable
226     {
227         final boolean shared;
228         final CountDownLatch winner;
229         final CountDownLatch loser;
230         final NamedLockFactoryAdapter adapter;
231         final RepositorySystemSession session;
232         final Access chained;
233 
234         public Access( boolean shared,
235                        CountDownLatch winner,
236                        CountDownLatch loser,
237                        NamedLockFactoryAdapter adapter,
238                        RepositorySystemSession session,
239                        Access chained )
240         {
241             this.shared = shared;
242             this.winner = winner;
243             this.loser = loser;
244             this.adapter = adapter;
245             this.session = session;
246             this.chained = chained;
247         }
248 
249         @Override
250         public void run()
251         {
252             try
253             {
254                 try ( SyncContext syncContext = adapter.newInstance( session, shared ) )
255                 {
256                     syncContext.acquire(
257                             Arrays.asList( new DefaultArtifact( "groupId:artifactId:1.0" ),
258                                     new DefaultArtifact( "groupId:artifactId:1.1" ) ),
259                             null
260                     );
261                     winner.countDown();
262                     if ( chained != null )
263                     {
264                         chained.run();
265                     }
266                     loser.await();
267                 }
268                 catch ( IllegalStateException e )
269                 {
270                     loser.countDown();
271                     winner.await();
272                 }
273             }
274             catch ( InterruptedException e )
275             {
276                 Assert.fail( "interrupted" );
277             }
278         }
279     }
280 }