/* * Copyright (c) 2016 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; import com.emc.storageos.coordinator.client.service.CoordinatorTestBase; import com.emc.storageos.volumecontroller.impl.ControllerLockingServiceImpl; public class ControllerLockingServiceTest extends CoordinatorTestBase{ private static final Logger log = LoggerFactory.getLogger(ControllerLockingServiceTest.class); private static String LOCKNAME = "TESTLOCK"; private static String CLIENT_A = "CLIENTA"; private static String CLIENT_B = "CLIENTB"; private static int NUMCLIENTS = 5; private ControllerLockingServiceImpl impl; public ControllerLockingServiceTest() {} @Before public void setUp() throws Exception { impl = new ControllerLockingServiceImpl(); impl.setCoordinator(this.connectClient()); } @Test public void testAcquireReleaseLock() { String lockName = getLockName(); Assert.assertTrue(impl.acquireLock(lockName, 10)); impl.releaseLock(lockName); // Lock can be acquired again Assert.assertTrue(impl.acquireLock(lockName, 10)); Assert.assertTrue(impl.releaseLock(lockName)); // Lock are re-entrant Assert.assertTrue(impl.acquireLock(lockName, 10)); Assert.assertTrue(impl.acquireLock(lockName, 10)); Assert.assertTrue(impl.releaseLock(lockName)); Assert.assertTrue(impl.releaseLock(lockName)); } @Test public void testAcquireReleaseLockTimeout() throws InterruptedException { final String lockName = getLockName(); ExecutorService clients = Executors.newFixedThreadPool(2); // Thread 1 - hold the lock clients.submit(new Runnable() { @Override public void run() { try { boolean bLockActionResult = impl.acquireLock(lockName, 10); Assert.assertTrue(bLockActionResult); log.info("Thread 1 - acquire lock {}", bLockActionResult); Thread.sleep(30000); } catch (InterruptedException e) { // Ignore this. } catch (Exception e) { log.info(": {} transient error ...", e); } } }); // Thread 2 - acquire the lock - should fail clients.submit(new Runnable() { @Override public void run() { try { Thread.sleep(10000); // yield so that thread 1 acquired the lock boolean bLockActionResult = impl.acquireLock(lockName, 10); log.info("Thread 2 - acquire lock {}", bLockActionResult); Assert.assertFalse(bLockActionResult); Thread.sleep(30000); } catch (InterruptedException e) { // Ignore this. } catch (Exception e) { log.info(": {} transient error ...", e); } } }); clients.awaitTermination(30, TimeUnit.SECONDS); log.info("*** testAcquireReleaseLockTimeout end"); } @Test public void testAcquireReleaseLockMultiThread() throws InterruptedException { final String lockName = getLockName(); ExecutorService clients = Executors.newFixedThreadPool(NUMCLIENTS); for (int i = 0; i < NUMCLIENTS; i++) { clients.submit(new Runnable() { @Override public void run() { while (true) { try { log.info(": {} ------ client: starts loop ------"); log.info(": {} client trying to acquire lock"); String clientName = Thread.currentThread().getName(); boolean bLockActionResult = impl.acquireLock(lockName, 10); Assert.assertTrue(bLockActionResult); log.info(": request succeeded. doing work {}", clientName); Thread.sleep(2000); log.info(": work done. releasing lock"); bLockActionResult = impl.releaseLock(lockName); Assert.assertTrue(bLockActionResult); log.info(": lock release status: {};released lock", bLockActionResult); } catch (InterruptedException e) { // Ignore this. } catch (Exception e) { log.info(": {} transient error ...", e); } } } }); } clients.awaitTermination(60, TimeUnit.SECONDS); log.info("*** testAcquireReleaseLockMultiThread end"); } @Test public void testAcquireReleasePersistentLock() { final String lockName = getLockName(); Assert.assertTrue(impl.acquirePersistentLock(lockName, CLIENT_A, 10)); Assert.assertFalse(impl.releasePersistentLock(lockName, CLIENT_B)); Assert.assertTrue(impl.releasePersistentLock(lockName, CLIENT_A)); // Lock again Assert.assertTrue(impl.acquirePersistentLock(lockName, CLIENT_A, 10)); Assert.assertFalse(impl.acquirePersistentLock(lockName, CLIENT_B, 10)); Assert.assertTrue(impl.releasePersistentLock(lockName, CLIENT_A)); } private String getLockName() { return LOCKNAME + new Random(System.currentTimeMillis()).nextInt(); } }