1 /*
2  * Copyright (C) 2014 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.graph;
18 
19 import static com.google.common.graph.TestUtil.EdgeType.DIRECTED;
20 import static com.google.common.graph.TestUtil.EdgeType.UNDIRECTED;
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import com.google.common.graph.TestUtil.EdgeType;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import org.junit.Test;
27 import org.junit.runner.RunWith;
28 import org.junit.runners.Parameterized;
29 import org.junit.runners.Parameterized.Parameters;
30 
31 @AndroidIncompatible
32 // TODO(cpovirk): Figure out Android JUnit 4 support. Does it work with Gingerbread? @RunWith?
33 @RunWith(Parameterized.class)
34 public final class NetworkEquivalenceTest {
35   private static final Integer N1 = 1;
36   private static final Integer N2 = 2;
37   private static final Integer N3 = 3;
38 
39   private static final String E11 = "1-1";
40   private static final String E12 = "1-2";
41   private static final String E12_A = "1-2a";
42   private static final String E13 = "1-3";
43 
44   private final EdgeType edgeType;
45   private final MutableNetwork<Integer, String> network;
46 
47   // add parameters: directed/undirected
48   @Parameters
parameters()49   public static Collection<Object[]> parameters() {
50     return Arrays.asList(new Object[][] {{EdgeType.UNDIRECTED}, {EdgeType.DIRECTED}});
51   }
52 
NetworkEquivalenceTest(EdgeType edgeType)53   public NetworkEquivalenceTest(EdgeType edgeType) {
54     this.edgeType = edgeType;
55     this.network = createNetwork(edgeType);
56   }
57 
createNetwork(EdgeType edgeType)58   private static MutableNetwork<Integer, String> createNetwork(EdgeType edgeType) {
59     switch (edgeType) {
60       case UNDIRECTED:
61         return NetworkBuilder.undirected().allowsSelfLoops(true).build();
62       case DIRECTED:
63         return NetworkBuilder.directed().allowsSelfLoops(true).build();
64       default:
65         throw new IllegalStateException("Unexpected edge type: " + edgeType);
66     }
67   }
68 
oppositeType(EdgeType edgeType)69   private static EdgeType oppositeType(EdgeType edgeType) {
70     switch (edgeType) {
71       case UNDIRECTED:
72         return EdgeType.DIRECTED;
73       case DIRECTED:
74         return EdgeType.UNDIRECTED;
75       default:
76         throw new IllegalStateException("Unexpected edge type: " + edgeType);
77     }
78   }
79 
80   @Test
equivalent_nodeSetsDiffer()81   public void equivalent_nodeSetsDiffer() {
82     network.addNode(N1);
83 
84     MutableNetwork<Integer, String> g2 = createNetwork(edgeType);
85     g2.addNode(N2);
86 
87     assertThat(network).isNotEqualTo(g2);
88   }
89 
90   // Node sets are the same, but edge sets differ.
91   @Test
equivalent_edgeSetsDiffer()92   public void equivalent_edgeSetsDiffer() {
93     network.addEdge(N1, N2, E12);
94 
95     MutableNetwork<Integer, String> g2 = createNetwork(edgeType);
96     g2.addEdge(N1, N2, E13);
97 
98     assertThat(network).isNotEqualTo(g2);
99   }
100 
101   // Node/edge sets are the same, but node/edge connections differ due to edge type.
102   @Test
equivalent_directedVsUndirected()103   public void equivalent_directedVsUndirected() {
104     network.addEdge(N1, N2, E12);
105 
106     MutableNetwork<Integer, String> g2 = createNetwork(oppositeType(edgeType));
107     g2.addEdge(N1, N2, E12);
108 
109     assertThat(network).isNotEqualTo(g2);
110   }
111 
112   // Node/edge sets and node/edge connections are the same, but directedness differs.
113   @Test
equivalent_selfLoop_directedVsUndirected()114   public void equivalent_selfLoop_directedVsUndirected() {
115     network.addEdge(N1, N1, E11);
116 
117     MutableNetwork<Integer, String> g2 = createNetwork(oppositeType(edgeType));
118     g2.addEdge(N1, N1, E11);
119 
120     assertThat(network).isNotEqualTo(g2);
121   }
122 
123   // Node/edge sets are the same, but node/edge connections differ.
124   @Test
equivalent_connectionsDiffer()125   public void equivalent_connectionsDiffer() {
126     network.addEdge(N1, N2, E12);
127     network.addEdge(N1, N3, E13);
128 
129     MutableNetwork<Integer, String> g2 = createNetwork(edgeType);
130     // connect E13 to N1 and N2, and E12 to N1 and N3 => not equivalent
131     g2.addEdge(N1, N2, E13);
132     g2.addEdge(N1, N3, E12);
133 
134     assertThat(network).isNotEqualTo(g2);
135   }
136 
137   // Node/edge sets and node/edge connections are the same, but network properties differ.
138   // (In this case the networks are considered equivalent; the property differences are irrelevant.)
139   @Test
equivalent_propertiesDiffer()140   public void equivalent_propertiesDiffer() {
141     network.addEdge(N1, N2, E12);
142 
143     MutableNetwork<Integer, String> g2 =
144         NetworkBuilder.from(network)
145             .allowsParallelEdges(!network.allowsParallelEdges())
146             .allowsSelfLoops(!network.allowsSelfLoops())
147             .build();
148     g2.addEdge(N1, N2, E12);
149 
150     assertThat(network).isEqualTo(g2);
151   }
152 
153   // Node/edge sets and node/edge connections are the same, but edge order differs.
154   // (In this case the networks are considered equivalent; the edge add orderings are irrelevant.)
155   @Test
equivalent_edgeAddOrdersDiffer()156   public void equivalent_edgeAddOrdersDiffer() {
157     NetworkBuilder<Integer, String> builder =
158         NetworkBuilder.from(network).allowsParallelEdges(true);
159     MutableNetwork<Integer, String> g1 = builder.build();
160     MutableNetwork<Integer, String> g2 = builder.build();
161 
162     // for ug1, add e12 first, then e12_a
163     g1.addEdge(N1, N2, E12);
164     g1.addEdge(N1, N2, E12_A);
165 
166     // for ug2, add e12_a first, then e12
167     g2.addEdge(N1, N2, E12_A);
168     g2.addEdge(N1, N2, E12);
169 
170     assertThat(g1).isEqualTo(g2);
171   }
172 
173   @Test
equivalent_edgeDirectionsDiffer()174   public void equivalent_edgeDirectionsDiffer() {
175     network.addEdge(N1, N2, E12);
176 
177     MutableNetwork<Integer, String> g2 = createNetwork(edgeType);
178     g2.addEdge(N2, N1, E12);
179 
180     switch (edgeType) {
181       case UNDIRECTED:
182         assertThat(network).isEqualTo(g2);
183         break;
184       case DIRECTED:
185         assertThat(network).isNotEqualTo(g2);
186         break;
187       default:
188         throw new IllegalStateException("Unexpected edge type: " + edgeType);
189     }
190   }
191 }
192