package com.maxifier.mxcache.util;

import org.testng.Assert;
import org.testng.annotations.Test;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by IntelliJ IDEA.
 * User: dalex
 * Date: 08.11.2010
 * Time: 14:03:07
 */
@Test
public class MultiLockUTest {

    public void testNestedLock() {
        MultiLock lock = new MultiLock();
        MultiLock.Sublock part = new MultiLock.Sublock(lock);

        part.lock();
        try {
            part.lock();
            part.unlock();
        } finally {
            part.unlock();
        }
    }

    public void testLockWithParent() {
        MultiLock lock = new MultiLock();
        MultiLock.Sublock part = new MultiLock.Sublock(lock);

        lock.lock();
        try {
            part.lock();
            part.unlock();
        } finally {
            lock.unlock();
        }
    }

    public void testSimulateDeadlock() throws InterruptedException, BrokenBarrierException {
        final MultiLock lock = new MultiLock();
        final MultiLock.Sublock part = new MultiLock.Sublock(lock);
        final CyclicBarrier barrier = new CyclicBarrier(2);
        final AtomicBoolean notification = new AtomicBoolean();

        Thread thread = new Thread() {
            @Override
            public void run() {
                part.lock();
                barrier(barrier);
                barrier(barrier);
                try {
                    lock.lock();
                    try {
                        notification.set(true);
                    } finally {
                        lock.unlock();
                    }
                } finally {
                    part.unlock();
                }
            }
        };

        thread.start();

        barrier(barrier);

        lock.lock();

        barrier(barrier);

        try {
            //      
            part.lock();
            try {
                // ,  
                Assert.assertTrue(notification.get());
            } finally {
                part.lock();
            }
            thread.join();
        } finally {
            lock.unlock();
        }
    }

    public void testSimulateDeadlock2() throws InterruptedException, BrokenBarrierException {
        final MultiLock lock = new MultiLock();
        final MultiLock.Sublock part = new MultiLock.Sublock(lock);
        final CyclicBarrier barrier = new CyclicBarrier(2);
        final AtomicBoolean notification = new AtomicBoolean();

        Thread thread = new Thread() {
            @Override
            public void run() {
                part.lock();
                barrier(barrier);
                barrier(barrier);
                try {
                    lock.lock();
                    try {
                        notification.set(true);
                    } finally {
                        lock.unlock();
                    }
                } finally {
                    part.unlock();
                }
            }
        };

        thread.start();

        barrier(barrier);

        lock.lock();
        try {
            lock.lock();
            try {
                barrier(barrier);
                //      
                part.lock();
                try {
                    // ,  
                    Assert.assertTrue(notification.get());
                } finally {
                    part.lock();
                }
                thread.join();
            } finally {
                lock.unlock();
            }
        } finally {
            lock.unlock();
        }
    }

    private void barrier(CyclicBarrier barrier) {
        try {
            barrier.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (BrokenBarrierException e) {
            throw new RuntimeException(e);
        }
    }
}

@@ -247,16 +247,54 @@
 ean;%0D%0A%0D%0A
+import static org.testng.Assert.*;%0D%0A%0D%0A
 /**%0D%0A * 
@@ -610,38 +610,290 @@
             
-part.lock();%0D%0A
+assertTrue(part.isHeldByCurrentThread());%0D%0A            assertTrue(part.isLocked());%0D%0A%0D%0A            part.lock();%0D%0A            try %7B%0D%0A                assertTrue(part.isHeldByCurrentThread());%0D%0A                assertTrue(part.isLocked());%0D%0A            %7D finally %7B%0D%0A    
             
@@ -900,32 +900,47 @@
 part.unlock();%0D%0A
+            %7D%0D%0A
         %7D finall
@@ -984,32 +984,278 @@
     %7D%0D%0A    %7D%0D%0A%0D%0A
+    @Test(expectedExceptions = IllegalMonitorStateException.class)%0D%0A    public void testInvalidUnlock() %7B%0D%0A        MultiLock lock = new MultiLock();%0D%0A        MultiLock.Sublock part = new MultiLock.Sublock(lock);%0D%0A        part.unlock();%0D%0A    %7D%0D%0A%0D%0A
     public void 
@@ -1457,38 +1457,206 @@
             
-part.unlock();
+try %7B%0D%0A                assertTrue(part.isHeldByCurrentThread());%0D%0A                assertTrue(part.isLocked());%0D%0A            %7D finally %7B%0D%0A                part.unlock();%0D%0A            %7D
 %0D%0A        %7D 
@@ -2172,32 +2172,59 @@
   part.lock();%0D%0A
+                try %7B%0D%0A    
                 
@@ -2234,32 +2234,36 @@
 rier(barrier);%0D%0A
+    
                 
@@ -2273,32 +2273,34 @@
 rier(barrier);%0D%0A
+%0D%0A
                 
@@ -2291,37 +2291,129 @@
                 
-try %7B
+    assertTrue(part.isHeldByCurrentThread());%0D%0A                    assertTrue(part.isLocked());%0D%0A
 %0D%0A              
@@ -2940,39 +2940,32 @@
                 
-Assert.
 assertTrue(notif
@@ -4327,23 +4327,16 @@
         
-Assert.
 assertTr

improve test