package org.netbeans.gradle.project.util; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.jtrim.property.MutableProperty; import org.jtrim.property.PropertyFactory; import org.junit.Test; import static org.junit.Assert.*; public class CloseableActionContainerTest { @Test public void test1Action1Open() { CloseableActionContainer container = new CloseableActionContainer(); TestCloseableAction action0 = new TestCloseableAction(); MutableProperty<TestCloseableAction> actionRef = PropertyFactory.memProperty(action0); container.defineAction(actionRef); action0.assertOpenCount(0); container.open(); action0.assertAllClosedButLast(1); container.close(); action0.assertAllClosedOnce(1); } @Test public void test1Action2Open() { CloseableActionContainer container = new CloseableActionContainer(); TestCloseableAction action0 = new TestCloseableAction(); MutableProperty<TestCloseableAction> actionRef = PropertyFactory.memProperty(action0); container.defineAction(actionRef); container.open(); container.close(); container.open(); action0.assertAllClosedButLast(2); container.close(); action0.assertAllClosedOnce(2); } @Test public void test3Action1Open() { CloseableActionContainer container = new CloseableActionContainer(); TestCloseableAction action0 = new TestCloseableAction(); TestCloseableAction action1 = new TestCloseableAction(); MutableProperty<TestCloseableAction> actionRef = PropertyFactory.memProperty(action0); container.defineAction(actionRef); action0.assertOpenCount(0); container.open(); action0.assertAllClosedButLast(1); actionRef.setValue(action1); action0.assertAllClosedOnce(1); action1.assertAllClosedButLast(1); container.close(); action0.assertAllClosedOnce(1); action1.assertAllClosedOnce(1); TestCloseableAction action2 = new TestCloseableAction(); actionRef.setValue(action2); action0.assertAllClosedOnce(1); action1.assertAllClosedOnce(1); action2.assertOpenCount(0); } @Test public void testActionDefinedAfterOpen() { CloseableActionContainer container = new CloseableActionContainer(); container.open(); TestCloseableAction action0 = new TestCloseableAction(); MutableProperty<TestCloseableAction> actionRef = PropertyFactory.memProperty(action0); container.defineAction(actionRef); action0.assertAllClosedButLast(1); container.close(); action0.assertAllClosedOnce(1); } @Test public void testActionDefinedAfterClose() { CloseableActionContainer container = new CloseableActionContainer(); container.open(); container.close(); TestCloseableAction action0 = new TestCloseableAction(); MutableProperty<TestCloseableAction> actionRef = PropertyFactory.memProperty(action0); container.defineAction(actionRef); action0.assertOpenCount(0); } @Test public void test1Action1DuplicateOpen() { CloseableActionContainer container = new CloseableActionContainer(); TestCloseableAction action0 = new TestCloseableAction(); MutableProperty<TestCloseableAction> actionRef = PropertyFactory.memProperty(action0); container.defineAction(actionRef); action0.assertOpenCount(0); container.open(); container.open(); action0.assertAllClosedButLast(1); container.close(); action0.assertAllClosedOnce(1); } @Test public void test1Action1OpenDuplicateClose() { CloseableActionContainer container = new CloseableActionContainer(); TestCloseableAction action0 = new TestCloseableAction(); MutableProperty<TestCloseableAction> actionRef = PropertyFactory.memProperty(action0); container.defineAction(actionRef); action0.assertOpenCount(0); container.open(); action0.assertAllClosedButLast(1); container.close(); container.close(); action0.assertAllClosedOnce(1); } @Test public void test1ActionDuplicateCloseWithoutOpen() { CloseableActionContainer container = new CloseableActionContainer(); TestCloseableAction action0 = new TestCloseableAction(); MutableProperty<TestCloseableAction> actionRef = PropertyFactory.memProperty(action0); container.defineAction(actionRef); container.close(); action0.assertOpenCount(0); container.close(); action0.assertOpenCount(0); } private static final class TestCloseableAction implements CloseableAction { private final Lock mainLock; private final List<TestActionRef> openedRefs; public TestCloseableAction() { this.mainLock = new ReentrantLock(); this.openedRefs = new ArrayList<>(); } public TestActionRef getOpenedRef(int openIndex) { mainLock.lock(); try { return openedRefs.get(openIndex); } finally { mainLock.unlock(); } } public void assertAllClosedButLast(int expectedOpenCount) { assert expectedOpenCount > 0; mainLock.lock(); try { assertEquals("Open count", expectedOpenCount, openedRefs.size()); for (int i = 0; i < expectedOpenCount - 1; i++) { TestActionRef actionRef = openedRefs.get(i); actionRef.assertCloseCount(1); } openedRefs.get(expectedOpenCount - 1); } finally { mainLock.unlock(); } } public void assertAllClosedOnce(int numberOfExpectedOpens) { mainLock.lock(); try { assertEquals("Open count", numberOfExpectedOpens, openedRefs.size()); for (TestActionRef actionRef: openedRefs) { actionRef.assertCloseCount(1); } } finally { mainLock.unlock(); } } public void assertOpenCount(int expectedOpenCount) { mainLock.lock(); try { assertEquals("Open count", expectedOpenCount, openedRefs.size()); } finally { mainLock.unlock(); } } public TestActionRef[] getOpenedRefs() { mainLock.lock(); try { return openedRefs.toArray(new TestActionRef[openedRefs.size()]); } finally { mainLock.unlock(); } } @Override public TestActionRef open() { TestActionRef result = new TestActionRef(); mainLock.lock(); try { openedRefs.add(result); } finally { mainLock.unlock(); } return result; } } private static final class TestActionRef implements CloseableAction.Ref { private final AtomicInteger closeCount; public TestActionRef() { this.closeCount = new AtomicInteger(0); } public void assertCloseCount(int expectedCloseCount) { assertEquals("closeCount", expectedCloseCount, closeCount.get()); } public int getCloseCount() { return closeCount.get(); } @Override public void close() { closeCount.incrementAndGet(); } } }