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 java.util.concurrent.CountDownLatch;
023import java.util.concurrent.TimeUnit;
024
025import org.eclipse.aether.named.NamedLock;
026import org.eclipse.aether.named.NamedLockFactory;
027import org.junit.AfterClass;
028import org.junit.Assert;
029import org.junit.Rule;
030import org.junit.Test;
031import org.junit.rules.TestName;
032
033import static org.hamcrest.MatcherAssert.assertThat;
034import static org.hamcrest.Matchers.is;
035import static org.hamcrest.Matchers.not;
036import static org.hamcrest.Matchers.sameInstance;
037
038/**
039 * UT support for {@link NamedLockFactory}.
040 */
041public abstract class NamedLockFactoryTestSupport
042{
043    protected static final HazelcastClientUtils utils = new HazelcastClientUtils();
044
045    protected static NamedLockFactory namedLockFactory;
046
047    @Rule
048    public TestName testName = new TestName();
049
050    @AfterClass
051    public static void cleanup()
052    {
053        if ( namedLockFactory != null )
054        {
055            namedLockFactory.shutdown();
056        }
057        utils.cleanup();
058    }
059
060    @Test
061    public void refCounting()
062    {
063        final String name = testName.getMethodName();
064        try ( NamedLock one = namedLockFactory.getLock( name );
065              NamedLock two = namedLockFactory.getLock( name ) )
066        {
067            assertThat( one, sameInstance( two ) );
068            one.close();
069            two.close();
070
071            try ( NamedLock three = namedLockFactory.getLock( name ) )
072            {
073                assertThat( three, not( sameInstance( two ) ) );
074            }
075        }
076    }
077
078    @Test( expected = IllegalStateException.class )
079    public void unlockWoLock()
080    {
081        final String name = testName.getMethodName();
082        try ( NamedLock one = namedLockFactory.getLock( name ) )
083        {
084            one.unlock();
085        }
086    }
087
088    @Test
089    public void wwBoxing() throws InterruptedException
090    {
091        final String name = testName.getMethodName();
092        try ( NamedLock one = namedLockFactory.getLock( name ) )
093        {
094            assertThat( one.lockExclusively( 1L, TimeUnit.MILLISECONDS ), is( true ) );
095            assertThat( one.lockExclusively( 1L, TimeUnit.MILLISECONDS ), is( true ) );
096            one.unlock();
097            one.unlock();
098        }
099    }
100
101    @Test
102    public void rrBoxing() throws InterruptedException
103    {
104        final String name = testName.getMethodName();
105        try ( NamedLock one = namedLockFactory.getLock( name ) )
106        {
107            assertThat( one.lockShared( 1L, TimeUnit.MILLISECONDS ), is( true ) );
108            assertThat( one.lockShared( 1L, TimeUnit.MILLISECONDS ), is( true ) );
109            one.unlock();
110            one.unlock();
111        }
112    }
113
114    @Test
115    public void wrBoxing() throws InterruptedException
116    {
117        final String name = testName.getMethodName();
118        try ( NamedLock one = namedLockFactory.getLock( name ) )
119        {
120            assertThat( one.lockExclusively( 1L, TimeUnit.MILLISECONDS ), is( true ) );
121            assertThat( one.lockShared( 1L, TimeUnit.MILLISECONDS ), is( true ) );
122            one.unlock();
123            one.unlock();
124        }
125    }
126
127    @Test
128    public void rwBoxing() throws InterruptedException
129    {
130        final String name = testName.getMethodName();
131        try ( NamedLock one = namedLockFactory.getLock( name ) )
132        {
133            assertThat( one.lockShared( 1L, TimeUnit.MILLISECONDS ), is( true ) );
134            assertThat( one.lockExclusively( 1L, TimeUnit.MILLISECONDS ), is( false ) );
135            one.unlock();
136        }
137    }
138
139    @Test( timeout = 5000 )
140    public void sharedAccess() throws InterruptedException
141    {
142        final String name = testName.getMethodName();
143        CountDownLatch winners = new CountDownLatch( 2 ); // we expect 2 winner
144        CountDownLatch losers = new CountDownLatch( 0 ); // we expect 0 loser
145        Thread t1 = new Thread( new Access( namedLockFactory, name, true, winners, losers ) );
146        Thread t2 = new Thread( new Access( namedLockFactory, name, true, winners, losers ) );
147        t1.start();
148        t2.start();
149        t1.join();
150        t2.join();
151        winners.await();
152        losers.await();
153    }
154
155    @Test( timeout = 5000 )
156    public void exclusiveAccess() throws InterruptedException
157    {
158        final String name = testName.getMethodName();
159        CountDownLatch winners = new CountDownLatch( 1 ); // we expect 1 winner
160        CountDownLatch losers = new CountDownLatch( 1 ); // we expect 1 loser
161        Thread t1 = new Thread( new Access( namedLockFactory, name, false, winners, losers ) );
162        Thread t2 = new Thread( new Access( namedLockFactory, name, false, winners, losers ) );
163        t1.start();
164        t2.start();
165        t1.join();
166        t2.join();
167        winners.await();
168        losers.await();
169    }
170
171    @Test( timeout = 5000 )
172    public void mixedAccess() throws InterruptedException
173    {
174        final String name = testName.getMethodName();
175        CountDownLatch winners = new CountDownLatch( 1 ); // we expect 1 winner
176        CountDownLatch losers = new CountDownLatch( 1 ); // we expect 1 loser
177        Thread t1 = new Thread( new Access( namedLockFactory, name, true, winners, losers ) );
178        Thread t2 = new Thread( new Access( namedLockFactory, name, false, winners, losers ) );
179        t1.start();
180        t2.start();
181        t1.join();
182        t2.join();
183        winners.await();
184        losers.await();
185    }
186
187    private static class Access implements Runnable
188    {
189        final NamedLockFactory namedLockFactory;
190        final String name;
191        final boolean shared;
192        final CountDownLatch winner;
193        final CountDownLatch loser;
194
195        public Access( NamedLockFactory namedLockFactory,
196                       String name,
197                       boolean shared,
198                       CountDownLatch winner,
199                       CountDownLatch loser )
200        {
201            this.namedLockFactory = namedLockFactory;
202            this.name = name;
203            this.shared = shared;
204            this.winner = winner;
205            this.loser = loser;
206        }
207
208        @Override
209        public void run()
210        {
211            try ( NamedLock lock = namedLockFactory.getLock( name ) )
212            {
213                if ( shared ? lock.lockShared( 100L, TimeUnit.MILLISECONDS ) :
214                        lock.lockExclusively( 100L, TimeUnit.MILLISECONDS ) )
215                {
216                    try
217                    {
218                        winner.countDown();
219                        loser.await();
220                    }
221                    finally
222                    {
223                        lock.unlock();
224                    }
225                }
226                else
227                {
228                    loser.countDown();
229                    winner.await();
230                }
231            }
232            catch ( InterruptedException e )
233            {
234                Assert.fail( e.getMessage() );
235            }
236        }
237    }
238}