package org.netbeans.gradle.project.view; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import javax.swing.event.ChangeListener; import org.jtrim.property.MutableProperty; import org.jtrim.property.PropertyFactory; import org.jtrim.property.PropertySource; import org.jtrim.property.swing.SwingPropertySource; import org.jtrim.utils.ExceptionHelper; import org.junit.Test; import org.netbeans.api.project.Project; import org.netbeans.gradle.project.api.nodes.SingleNodeFactory; import org.netbeans.gradle.project.properties.NbProperties; import org.netbeans.gradle.project.util.NbSupplier; import org.netbeans.gradle.project.util.SwingTest; import org.netbeans.gradle.project.util.SwingTestAware; import org.netbeans.spi.project.ui.support.NodeFactory; import org.netbeans.spi.project.ui.support.NodeList; import org.openide.filesystems.FileObject; import org.openide.nodes.Node; import org.openide.util.Lookup; import org.openide.util.lookup.Lookups; import static org.junit.Assert.*; import static org.mockito.Mockito.*; public class AnnotationChildNodesTest extends SwingTestAware { private static Project mockProject() { return new Project() { @Override public FileObject getProjectDirectory() { throw new UnsupportedOperationException("This is a mock project."); } @Override public Lookup getLookup() { return Lookup.EMPTY; } }; } private AnnotationChildNodes testNodes(Object... factories) { final Lookup lookup = Lookups.fixed(factories); Project project = mockProject(); return new AnnotationChildNodes(project, new NbSupplier<Lookup>() { @Override public Lookup get() { return lookup; } }); } private static NodeList<?> testNodeList(PropertySource<? extends TestNodeListSnapshot> nodeList) { return new TestNodeList(nodeList); } private static NodeFactory testNodeFactory(final PropertySource<? extends TestNodeListSnapshot> nodeList) { return new NodeFactory() { @Override public NodeList<?> createNodes(Project project) { ExceptionHelper.checkNotNullArgument(project, "project"); return testNodeList(nodeList); } }; } @Test @SwingTest public void testGetNodesAfterRecreate() { TestNodeListSnapshot initList = new TestNodeListSnapshot(0); TestNodeListSnapshot testList = new TestNodeListSnapshot(1); MutableProperty<TestNodeListSnapshot> nodeList = PropertyFactory.memProperty(initList); AnnotationChildNodes childNodes = testNodes(testNodeFactory(nodeList)); childNodes.addNotify(); childNodes.removeNotify(); PropertySource<Collection<SingleNodeFactory>> singleNodeFactoriesRef = childNodes.nodeFactories(); TestListener changeListener = new TestListener(); singleNodeFactoriesRef.addChangeListener(changeListener); assertEquals("node factory count", 0, singleNodeFactoriesRef.getValue().size()); childNodes.addNotify(); int preSetNotifyCount = changeListener.getCallCount(); nodeList.setValue(testList); changeListener.verifyCalledMore(preSetNotifyCount); testList.verifyNodes(singleNodeFactoriesRef.getValue()); childNodes.removeNotify(); assertEquals("node factory count", 0, singleNodeFactoriesRef.getValue().size()); } @Test @SwingTest public void testGetNodesAfterNotify() { TestNodeListSnapshot initList = new TestNodeListSnapshot(0); TestNodeListSnapshot testList = new TestNodeListSnapshot(1); MutableProperty<TestNodeListSnapshot> nodeList = PropertyFactory.memProperty(initList); AnnotationChildNodes childNodes = testNodes(testNodeFactory(nodeList)); PropertySource<Collection<SingleNodeFactory>> singleNodeFactoriesRef = childNodes.nodeFactories(); TestListener changeListener = new TestListener(); singleNodeFactoriesRef.addChangeListener(changeListener); assertEquals("node factory count", 0, singleNodeFactoriesRef.getValue().size()); childNodes.addNotify(); int preSetNotifyCount = changeListener.getCallCount(); nodeList.setValue(testList); changeListener.verifyCalledMore(preSetNotifyCount); testList.verifyNodes(singleNodeFactoriesRef.getValue()); childNodes.removeNotify(); assertEquals("node factory count", 0, singleNodeFactoriesRef.getValue().size()); } @Test @SwingTest public void testGetNodesBeforeNotify() { TestNodeListSnapshot initList = new TestNodeListSnapshot(0); TestNodeListSnapshot testList = new TestNodeListSnapshot(1); MutableProperty<TestNodeListSnapshot> nodeList = PropertyFactory.memProperty(initList); AnnotationChildNodes childNodes = testNodes(testNodeFactory(nodeList)); PropertySource<Collection<SingleNodeFactory>> singleNodeFactoriesRef = childNodes.nodeFactories(); TestListener changeListener = new TestListener(); singleNodeFactoriesRef.addChangeListener(changeListener); assertEquals("node factory count", 0, singleNodeFactoriesRef.getValue().size()); int preSetNotifyCount = changeListener.getCallCount(); nodeList.setValue(testList); childNodes.addNotify(); changeListener.verifyCalledMore(preSetNotifyCount); testList.verifyNodes(singleNodeFactoriesRef.getValue()); childNodes.removeNotify(); } private static final class TestNodeListSnapshot { private final TestNodeSnapshot[] nodes; public TestNodeListSnapshot(int count) { this.nodes = new TestNodeSnapshot[count]; for (int i = 0; i < nodes.length; i++) { nodes[i] = new TestNodeSnapshot("Node" + i); } } public void verifyNodes(Collection<? extends SingleNodeFactory> actualNodeFactories) { int i = 0; for (SingleNodeFactory nodeFactory: actualNodeFactories) { assertSame(nodeFactory.createNode(), nodes[i].getNode()); i++; } assertEquals("Node count must match", i, nodes.length); } public TestNodeListSnapshot(TestNodeSnapshot... nodes) { this.nodes = nodes.clone(); } public TestNodeSnapshot[] getNodes() { return nodes.clone(); } public TestNodeSnapshot tryGetByKey(String key) { for (TestNodeSnapshot node: nodes) { if (key.equals(node.getKey())) { return node; } } return null; } public Node tryGetNodeByKey(String key) { TestNodeSnapshot result = tryGetByKey(key); return result != null ? result.getNode() : null; } } private static final class TestNodeSnapshot { private final String key; private final Node node; public TestNodeSnapshot(String key) { this.key = key; this.node = mock(Node.class); doReturn(key) .when(node) .toString(); } public String getKey() { return key; } public Node getNode() { return node; } } private static final class TestNodeList implements NodeList<String> { private final SwingPropertySource<TestNodeListSnapshot, ChangeListener> nodeListRef; private final AtomicInteger notifyCount; public TestNodeList(PropertySource<? extends TestNodeListSnapshot> nodeList) { this(NbProperties.toOldProperty(nodeList, new Object())); } public TestNodeList(SwingPropertySource<TestNodeListSnapshot, ChangeListener> nodeList) { this.nodeListRef = nodeList; this.notifyCount = new AtomicInteger(); } public void verifyNotifyCount(int expected) { assertEquals("notify count", expected, notifyCount.get()); } @Override public List<String> keys() { TestNodeSnapshot[] nodeList = nodeListRef.getValue().getNodes(); List<String> result = new ArrayList<>(nodeList.length); for (TestNodeSnapshot node: nodeList) { result.add(node.getKey()); } return result; } @Override public void addChangeListener(ChangeListener l) { nodeListRef.addChangeListener(l); } @Override public void removeChangeListener(ChangeListener l) { nodeListRef.removeChangeListener(l); } @Override public Node node(String key) { return nodeListRef.getValue().tryGetNodeByKey(key); } @Override public void addNotify() { notifyCount.incrementAndGet(); } @Override public void removeNotify() { notifyCount.decrementAndGet(); } } private static final class TestListener implements Runnable { private final AtomicInteger callCount; public TestListener() { this.callCount = new AtomicInteger(0); } public int getCallCount() { return callCount.get(); } public void verifyCalledMore(int prevCallCount) { int currentCallCount = getCallCount(); if (prevCallCount >= currentCallCount) { fail("Expected to be called more than " + prevCallCount + " times but was called " + currentCallCount + " times."); } } @Override public void run() { callCount.incrementAndGet(); } } }