001package org.eclipse.aether.named.hazelcast; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import org.eclipse.aether.RepositorySystemSession; 023import org.eclipse.aether.SyncContext; 024import org.eclipse.aether.artifact.DefaultArtifact; 025import org.eclipse.aether.internal.impl.synccontext.named.DiscriminatingNameMapper; 026import org.eclipse.aether.internal.impl.synccontext.named.GAVNameMapper; 027import org.eclipse.aether.internal.impl.synccontext.named.NamedLockFactoryAdapter; 028import org.eclipse.aether.named.NamedLockFactory; 029import org.eclipse.aether.repository.LocalRepository; 030import org.eclipse.aether.spi.synccontext.SyncContextFactory; 031import org.junit.AfterClass; 032import org.junit.Assert; 033import org.junit.Before; 034import org.junit.Test; 035 036import java.io.IOException; 037import java.nio.file.Files; 038import java.nio.file.Paths; 039import java.util.Arrays; 040import java.util.concurrent.CountDownLatch; 041import java.util.concurrent.TimeUnit; 042 043import static org.mockito.Mockito.mock; 044import static org.mockito.Mockito.when; 045 046/** 047 * UT support for {@link SyncContextFactory}. 048 */ 049public abstract class NamedLockFactoryAdapterTestSupport 050{ 051 private static final long ADAPTER_TIME = 100L; 052 053 private static final TimeUnit ADAPTER_TIME_UNIT = TimeUnit.MILLISECONDS; 054 055 /** 056 * Subclass should populate this field, using {@link #setNamedLockFactory(NamedLockFactory)}, but subclass 057 * must take care of proper cleanup as well, if needed! 058 */ 059 private static NamedLockFactoryAdapter adapter; 060 061 private RepositorySystemSession session; 062 063 protected static void setNamedLockFactory(final NamedLockFactory namedLockFactory) { 064 adapter = new NamedLockFactoryAdapter( 065 new DiscriminatingNameMapper(new GAVNameMapper()), namedLockFactory, ADAPTER_TIME, ADAPTER_TIME_UNIT 066 ); 067 } 068 069 @AfterClass 070 public static void cleanupAdapter() { 071 if (adapter != null) { 072 adapter.shutdown(); 073 } 074 } 075 076 @Before 077 public void before() throws IOException { 078 Files.createDirectories(Paths.get(System.getProperty("java.io.tmpdir"))); // hack for Surefire 079 LocalRepository localRepository = new LocalRepository(Files.createTempDirectory("test").toFile()); 080 session = mock(RepositorySystemSession.class); 081 when(session.getLocalRepository()).thenReturn(localRepository); 082 } 083 084 @Test 085 public void justCreateAndClose() { 086 adapter.newInstance(session, false).close(); 087 } 088 089 @Test 090 public void justAcquire() { 091 try (SyncContext syncContext = adapter.newInstance(session, false)) { 092 syncContext.acquire( 093 Arrays.asList(new DefaultArtifact("groupId:artifactId:1.0"), new DefaultArtifact("groupId:artifactId:1.1")), 094 null 095 ); 096 } 097 } 098 099 @Test(timeout = 5000) 100 public void sharedAccess() throws InterruptedException { 101 CountDownLatch winners = new CountDownLatch(2); // we expect 2 winners 102 CountDownLatch losers = new CountDownLatch(0); // we expect 0 losers 103 Thread t1 = new Thread(new Access(true, winners, losers, adapter, session, null)); 104 Thread t2 = new Thread(new Access(true, winners, losers, adapter, session, null)); 105 t1.start(); 106 t2.start(); 107 t1.join(); 108 t2.join(); 109 winners.await(); 110 losers.await(); 111 } 112 113 @Test(timeout = 5000) 114 public void exclusiveAccess() throws InterruptedException { 115 CountDownLatch winners = new CountDownLatch(1); // we expect 1 winner 116 CountDownLatch losers = new CountDownLatch(1); // we expect 1 loser 117 Thread t1 = new Thread(new Access(false, winners, losers, adapter, session, null)); 118 Thread t2 = new Thread(new Access(false, winners, losers, adapter, session, null)); 119 t1.start(); 120 t2.start(); 121 t1.join(); 122 t2.join(); 123 winners.await(); 124 losers.await(); 125 } 126 127 @Test(timeout = 5000) 128 public void mixedAccess() throws InterruptedException { 129 CountDownLatch winners = new CountDownLatch(1); // we expect 1 winner 130 CountDownLatch losers = new CountDownLatch(1); // we expect 1 loser 131 Thread t1 = new Thread(new Access(true, winners, losers, adapter, session, null)); 132 Thread t2 = new Thread(new Access(false, winners, losers, adapter, session, null)); 133 t1.start(); 134 t2.start(); 135 t1.join(); 136 t2.join(); 137 winners.await(); 138 losers.await(); 139 } 140 141 @Test(timeout = 5000) 142 public void nestedSharedShared() throws InterruptedException { 143 CountDownLatch winners = new CountDownLatch(2); // we expect 2 winners 144 CountDownLatch losers = new CountDownLatch(0); // we expect 0 losers 145 Thread t1 = new Thread( 146 new Access(true, winners, losers, adapter, session, 147 new Access(true, winners, losers, adapter, session, null) 148 ) 149 ); 150 t1.start(); 151 t1.join(); 152 winners.await(); 153 losers.await(); 154 } 155 156 @Test(timeout = 5000) 157 public void nestedExclusiveShared() throws InterruptedException { 158 CountDownLatch winners = new CountDownLatch(2); // we expect 2 winners 159 CountDownLatch losers = new CountDownLatch(0); // we expect 0 losers 160 Thread t1 = new Thread( 161 new Access(false, winners, losers, adapter, session, 162 new Access(true, winners, losers, adapter, session, null) 163 ) 164 ); 165 t1.start(); 166 t1.join(); 167 winners.await(); 168 losers.await(); 169 } 170 171 @Test(timeout = 5000) 172 public void nestedExclusiveExclusive() throws InterruptedException { 173 CountDownLatch winners = new CountDownLatch(2); // we expect 2 winners 174 CountDownLatch losers = new CountDownLatch(0); // we expect 0 losers 175 Thread t1 = new Thread( 176 new Access(false, winners, losers, adapter, session, 177 new Access(false, winners, losers, adapter, session, null) 178 ) 179 ); 180 t1.start(); 181 t1.join(); 182 winners.await(); 183 losers.await(); 184 } 185 186 @Test(timeout = 5000) 187 public void nestedSharedExclusive() throws InterruptedException { 188 CountDownLatch winners = new CountDownLatch(1); // we expect 1 winner (outer) 189 CountDownLatch losers = new CountDownLatch(1); // we expect 1 loser (inner) 190 Thread t1 = new Thread( 191 new Access(true, winners, losers, adapter, session, 192 new Access(false, winners, losers, adapter, session, null) 193 ) 194 ); 195 t1.start(); 196 t1.join(); 197 winners.await(); 198 losers.await(); 199 } 200 201 private static class Access implements Runnable { 202 final boolean shared; 203 final CountDownLatch winner; 204 final CountDownLatch loser; 205 final NamedLockFactoryAdapter adapter; 206 final RepositorySystemSession session; 207 final Access chained; 208 209 public Access(boolean shared, 210 CountDownLatch winner, 211 CountDownLatch loser, 212 NamedLockFactoryAdapter adapter, 213 RepositorySystemSession session, 214 Access chained) { 215 this.shared = shared; 216 this.winner = winner; 217 this.loser = loser; 218 this.adapter = adapter; 219 this.session = session; 220 this.chained = chained; 221 } 222 223 @Override 224 public void run() { 225 try { 226 try (SyncContext syncContext = adapter.newInstance(session, shared)) { 227 syncContext.acquire( 228 Arrays.asList(new DefaultArtifact("groupId:artifactId:1.0"), new DefaultArtifact("groupId:artifactId:1.1")), 229 null 230 ); 231 winner.countDown(); 232 if (chained != null) { 233 chained.run(); 234 } 235 loser.await(); 236 } catch (IllegalStateException e) { 237 loser.countDown(); 238 winner.await(); 239 } 240 } 241 catch (InterruptedException e) { 242 Assert.fail("interrupted"); 243 } 244 } 245 } 246}