From 67f5c5dc274837efbe5dbc57dca0ce26e4e32349 Mon Sep 17 00:00:00 2001
From: buczekp <buczekp>
Date: Fri, 20 May 2011 11:27:05 +0000
Subject: [PATCH] [LMS-2104] minor changes to virtual content & basic tests

SVN: 21416
---
 .../common/io/VirtualHierarchicalContent.java |  26 ++-
 .../io/VirtualHierarchicalContentTest.java    | 216 ++++++++++++++++++
 2 files changed, 231 insertions(+), 11 deletions(-)
 create mode 100644 common/sourceTest/java/ch/systemsx/cisd/common/io/VirtualHierarchicalContentTest.java

diff --git a/common/source/java/ch/systemsx/cisd/common/io/VirtualHierarchicalContent.java b/common/source/java/ch/systemsx/cisd/common/io/VirtualHierarchicalContent.java
index dbc9794e942..d36d8ba98a2 100644
--- a/common/source/java/ch/systemsx/cisd/common/io/VirtualHierarchicalContent.java
+++ b/common/source/java/ch/systemsx/cisd/common/io/VirtualHierarchicalContent.java
@@ -33,7 +33,7 @@ import ch.systemsx.cisd.base.io.IRandomAccessFile;
  * 
  * @author Piotr Buczek
  */
-public class VirtualHierarchicalContent implements IHierarchicalContent
+class VirtualHierarchicalContent implements IHierarchicalContent
 {
 
     private final List<IHierarchicalContent> components;
@@ -42,6 +42,10 @@ public class VirtualHierarchicalContent implements IHierarchicalContent
 
     public VirtualHierarchicalContent(List<IHierarchicalContent> components)
     {
+        if (components == null || components.isEmpty())
+        {
+            throw new IllegalArgumentException("Undefined contents");
+        }
         this.components = components;
     }
 
@@ -72,7 +76,7 @@ public class VirtualHierarchicalContent implements IHierarchicalContent
                         return content.getNode(relativePath);
                     } catch (IllegalArgumentException ex)
                     {
-                        return null;
+                        return null; // ignore (not all components need to contain the node)
                     }
                 }
             });
@@ -111,7 +115,7 @@ public class VirtualHierarchicalContent implements IHierarchicalContent
 
     private IHierarchicalContentNode mergeNodes(INodeProvider provider)
     {
-        IVirtualNodesMerger merger = createNodesMerger();
+        IVirtualNodeMerger merger = createNodeMerger();
         for (IHierarchicalContent component : components)
         {
             IHierarchicalContentNode componentNode = provider.tryGetNode(component);
@@ -134,9 +138,9 @@ public class VirtualHierarchicalContent implements IHierarchicalContent
         return listMerger.createMergedNodeList();
     }
 
-    private static IVirtualNodesMerger createNodesMerger()
+    private static IVirtualNodeMerger createNodeMerger()
     {
-        return new VirtualNodesMerger();
+        return new VirtualNodeMerger();
     }
 
     private static IVirtualNodeListMerger createNodeListMerger()
@@ -154,7 +158,7 @@ public class VirtualHierarchicalContent implements IHierarchicalContent
         List<IHierarchicalContentNode> getNodeList(IHierarchicalContent content);
     }
 
-    interface IVirtualNodesMerger
+    interface IVirtualNodeMerger
     {
         void addNode(IHierarchicalContentNode node);
 
@@ -175,7 +179,7 @@ public class VirtualHierarchicalContent implements IHierarchicalContent
      * <li>For normal files uses the 'last' node's file.
      * </ul>
      */
-    static class VirtualNodesMerger implements IVirtualNodesMerger
+    static class VirtualNodeMerger implements IVirtualNodeMerger
     {
         // For convenience in iteration the order of these nodes is reversed.
         // It is the first node, not the last one, which is overriding all files of other nodes.
@@ -199,17 +203,17 @@ public class VirtualHierarchicalContent implements IHierarchicalContent
     static class VirtualNodeListMerger implements IVirtualNodeListMerger
     {
         // relative path -> merger (with preserved order)
-        Map<String, IVirtualNodesMerger> mergers = new LinkedHashMap<String, IVirtualNodesMerger>();
+        Map<String, IVirtualNodeMerger> mergers = new LinkedHashMap<String, IVirtualNodeMerger>();
 
         public void addNodes(List<IHierarchicalContentNode> nodes)
         {
             for (IHierarchicalContentNode node : nodes)
             {
                 String relativePath = node.getRelativePath();
-                IVirtualNodesMerger merger = mergers.get(relativePath);
+                IVirtualNodeMerger merger = mergers.get(relativePath);
                 if (merger == null)
                 {
-                    merger = createNodesMerger();
+                    merger = createNodeMerger();
                     mergers.put(relativePath, merger);
                 }
                 merger.addNode(node);
@@ -219,7 +223,7 @@ public class VirtualHierarchicalContent implements IHierarchicalContent
         public List<IHierarchicalContentNode> createMergedNodeList()
         {
             List<IHierarchicalContentNode> result = new ArrayList<IHierarchicalContentNode>();
-            for (IVirtualNodesMerger merger : mergers.values())
+            for (IVirtualNodeMerger merger : mergers.values())
             {
                 result.add(merger.createMergedNode());
             }
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/io/VirtualHierarchicalContentTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/io/VirtualHierarchicalContentTest.java
new file mode 100644
index 00000000000..023c7c44062
--- /dev/null
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/io/VirtualHierarchicalContentTest.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.common.io;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase;
+
+/**
+ * Unit tests for {@link VirtualHierarchicalContent}
+ * 
+ * @author Piotr Buczek
+ */
+public class VirtualHierarchicalContentTest extends AbstractFileSystemTestCase
+{
+
+    private IHierarchicalContent[] components;
+
+    // mocks
+
+    private Mockery context;
+
+    private IHierarchicalContent component1;
+
+    private IHierarchicalContent component2;
+
+    private IHierarchicalContent component3;
+
+    @BeforeMethod
+    public void beforeMethod() throws Exception
+    {
+        context = new Mockery();
+
+        component1 = context.mock(IHierarchicalContent.class, "component 1");
+        component2 = context.mock(IHierarchicalContent.class, "component 2");
+        component3 = context.mock(IHierarchicalContent.class, "component 3");
+
+        components = new IHierarchicalContent[]
+            { component1, component2, component3 };
+    }
+
+    @AfterMethod
+    public void tearDown()
+    {
+        // To following line of code should also be called at the end of each test method.
+        // Otherwise one do not known which test failed.
+        context.assertIsSatisfied();
+    }
+
+    private IHierarchicalContent createContent(IHierarchicalContent... contents)
+    {
+        return new VirtualHierarchicalContent(Arrays.asList(contents));
+    }
+
+    @Test
+    public void testFailWithNullOrEmptyComponents()
+    {
+        try
+        {
+            createContent();
+            fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException ex)
+        {
+            assertEquals("Undefined contents", ex.getMessage());
+        }
+
+        try
+        {
+            createContent(new IHierarchicalContent[0]);
+            fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException ex)
+        {
+            assertEquals("Undefined contents", ex.getMessage());
+        }
+
+        context.assertIsSatisfied();
+    }
+
+    // TODO public void testEqualsAndHashCode()
+
+    @Test
+    public void testClose()
+    {
+        final IHierarchicalContent virtualContent = createContent(components);
+
+        context.checking(new Expectations()
+            {
+                {
+                    for (IHierarchicalContent component : components)
+                    {
+                        one(component).close();
+                    }
+                }
+            });
+        virtualContent.close();
+
+        context.assertIsSatisfied();
+    }
+
+    @Test
+    public void testGetRootNode()
+    {
+        final IHierarchicalContent virtualContent = createContent(components);
+
+        context.checking(new Expectations()
+            {
+                {
+                    for (IHierarchicalContent component : components)
+                    {
+                        one(component).getRootNode();
+                    }
+                }
+            });
+
+        IHierarchicalContentNode root1 = virtualContent.getRootNode();
+        // 2nd call uses cache (doesn't invoke getRootNode() on components)
+        IHierarchicalContentNode root2 = virtualContent.getRootNode();
+        assertSame(root1, root2);
+        // TODO merging & handling exceptions not tested
+
+        context.assertIsSatisfied();
+    }
+
+    @Test
+    public void testGetNode()
+    {
+        final IHierarchicalContent virtualContent = createContent(components);
+        final String relativePath = "rel/path";
+
+        context.checking(new Expectations()
+            {
+                {
+                    one(component1).getNode(relativePath);
+                    one(component2).getNode(relativePath);
+                    one(component3).getNode(relativePath);
+                    will(throwException(new IllegalArgumentException("")));
+                }
+            });
+
+        IHierarchicalContentNode node = virtualContent.getNode(relativePath);
+        assertNotNull(node);
+        // TODO merging & handling exceptions not tested
+
+        context.assertIsSatisfied();
+    }
+
+    @Test
+    public void testListMatchingNodesWithRelativePathPattern()
+    {
+        final IHierarchicalContent virtualContent = createContent(components);
+        final String pattern = "rel.*path.?pattern";
+
+        context.checking(new Expectations()
+            {
+                {
+                    for (IHierarchicalContent component : components)
+                    {
+                        one(component).listMatchingNodes(pattern);
+                    }
+                }
+            });
+
+        List<IHierarchicalContentNode> nodeList = virtualContent.listMatchingNodes(pattern);
+        assertNotNull(nodeList);
+        // TODO merging & handling exceptions not tested
+
+        context.assertIsSatisfied();
+    }
+
+    @Test
+    public void testListMatchingNodesWithStartingPath()
+    {
+        final IHierarchicalContent virtualContent = createContent(components);
+        final String startingPath = "some/dir";
+        final String pattern = "file.*name.?pattern";
+
+        context.checking(new Expectations()
+            {
+                {
+                    for (IHierarchicalContent component : components)
+                    {
+                        one(component).listMatchingNodes(startingPath, pattern);
+                    }
+                }
+            });
+
+        List<IHierarchicalContentNode> nodeList =
+                virtualContent.listMatchingNodes(startingPath, pattern);
+        assertNotNull(nodeList);
+        // TODO merging & handling exceptions not tested
+
+        context.assertIsSatisfied();
+    }
+
+}
-- 
GitLab