View Javadoc

1   /*
2    * Grapht, an open source dependency injector.
3    * Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt)
4    * Copyright 2010-2014 Regents of the University of Minnesota
5    *
6    * This program is free software; you can redistribute it and/or modify
7    * it under the terms of the GNU Lesser General Public License as
8    * published by the Free Software Foundation; either version 2.1 of the
9    * License, or (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14   * details.
15   *
16   * You should have received a copy of the GNU General Public License along with
17   * this program; if not, write to the Free Software Foundation, Inc., 51
18   * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19   */
20  package org.grouplens.grapht.graph;
21  
22  import com.google.common.collect.Lists;
23  import org.hamcrest.Matcher;
24  import org.junit.Before;
25  import org.junit.Test;
26  
27  import java.util.List;
28  
29  import static org.hamcrest.Matchers.*;
30  import static org.junit.Assert.assertThat;
31  
32  public class MergePoolTest {
33      MergePool<String,String> pool;
34  
35      @Before
36      public void createPool() {
37          pool = MergePool.create();
38      }
39  
40      @Test
41      public void testSingletonNode() {
42          DAGNode<String,String> node = DAGNode.singleton("foo");
43          DAGNode<String,String> merged = pool.merge(node);
44          // merging a singleton node should just return the node
45          assertThat(merged, sameInstance(node));
46      }
47  
48      @Test
49      public void testReuseSingleton() {
50          DAGNode<String,String> node = DAGNode.singleton("foo");
51          DAGNode<String,String> node2 = DAGNode.singleton("foo");
52          // simplify first so it's in the pool
53          pool.merge(node);
54          // and merge the second
55          DAGNode<String,String> merged = pool.merge(node2);
56          // the first node should have been reused
57          assertThat(merged, sameInstance(node));
58      }
59  
60      @Test
61      public void testMergeDescendants() {
62          DAGNode<String,String> node = DAGNode.singleton("foo");
63          DAGNode<String,String> node2 = DAGNode.singleton("foo");
64          DAGNode<String,String> root =
65                  DAGNode.<String,String>newBuilder("root")
66                         .addEdge(node, "hello")
67                         .addEdge(node2, "goodbye")
68                         .build();
69  
70          DAGNode<String,String> merged = pool.merge(root);
71  
72          // now, node and node2 should be merged
73          // new graph (since they're merged)
74          assertThat(merged, not(sameInstance(root)));
75          // only 2 nodes (root has 2 edges to same node)
76          assertThat(merged.getReachableNodes(), hasSize(2));
77          // two edges have same target
78          List<DAGEdge<String,String>> nbrs =
79                  Lists.newArrayList(merged.getOutgoingEdges());
80          // both edges have the same instance
81          assertThat(nbrs.get(1).getTail(),
82                     sameInstance(nbrs.get(0).getTail()));
83          // it's one of the nodes we gave it
84          assertThat(nbrs.get(0).getTail(),
85                     anyOf(sameInstance(node),
86                           sameInstance(node2)));
87  
88          // and a new singleton should be merged
89          assertThat(pool.merge(DAGNode.<String, String>singleton("foo")),
90                     anyOf(sameInstance(node),
91                           sameInstance(node2)));
92  
93          // re-merging our old root should give us the same node
94          assertThat(pool.merge(root), sameInstance(merged));
95      }
96  
97      @Test
98      public void testMergeWithChildren() {
99          DAGNode<String,String> node = DAGNode.singleton("foo");
100         DAGNode<String,String> p1 =
101                 DAGNode.<String,String>newBuilder("child")
102                        .addEdge(node, "k1")
103                        .build();
104         DAGNode<String,String> node2 = DAGNode.singleton("foo");
105         // second parent node. it will have different label to test that labels are ignored
106         DAGNode<String,String> p2 =
107                 DAGNode.<String,String>newBuilder("child")
108                        .addEdge(node, "k2")
109                        .build();
110         DAGNode<String,String> root =
111                 DAGNode.<String,String>newBuilder("root")
112                        .addEdge(p1, "hello")
113                        .addEdge(p2, "fish")
114                        .build();
115 
116         DAGNode<String,String> merged = pool.merge(root);
117 
118         // now, p1 and p2 should be merged
119         // new graph (since they're merged)
120         assertThat(merged, not(sameInstance(root)));
121         // only 3 nodes (root has 2 edges to now-merged nodes)
122         assertThat(merged.getReachableNodes(), hasSize(3));
123         // it has one of the leaves
124         assertThat(merged.getReachableNodes(),
125                    (Matcher) anyOf(hasItem(sameInstance(node)),
126                                    hasItem(sameInstance(node2))));
127         // two edges have same target
128         List<DAGEdge<String,String>> nbrs =
129                 Lists.newArrayList(merged.getOutgoingEdges());
130         // both edges have the same instance
131         assertThat(nbrs.get(1).getTail(),
132                    sameInstance(nbrs.get(0).getTail()));
133 
134         // and a new singleton should be merged
135         assertThat(pool.merge(DAGNode.<String, String>singleton("foo")),
136                    anyOf(sameInstance(node),
137                          sameInstance(node2)));
138 
139         // re-merging a child should give us a previously-merged node
140         assertThat(pool.merge(p2), isIn(merged.getReachableNodes()));
141         assertThat(pool.merge(p1), isIn(merged.getReachableNodes()));
142     }
143 }