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.truth.Truth.assertThat;
20 import static com.google.common.truth.Truth8.assertThat;
21 import static com.google.common.truth.TruthJUnit.assume;
22 import static org.junit.Assert.assertTrue;
23 import static org.junit.Assert.fail;
24 
25 import com.google.common.collect.ImmutableSet;
26 import com.google.common.testing.EqualsTester;
27 import java.util.Set;
28 import org.junit.After;
29 import org.junit.Test;
30 
31 /**
32  * Abstract base class for testing undirected {@link Network} implementations defined in this
33  * package.
34  */
35 public abstract class AbstractStandardUndirectedNetworkTest extends AbstractNetworkTest {
36   private static final EndpointPair<Integer> ENDPOINTS_N1N2 = EndpointPair.ordered(N1, N2);
37   private static final EndpointPair<Integer> ENDPOINTS_N2N1 = EndpointPair.ordered(N2, N1);
38 
39   @After
validateUndirectedEdges()40   public void validateUndirectedEdges() {
41     for (Integer node : network.nodes()) {
42       new EqualsTester()
43           .addEqualityGroup(
44               network.inEdges(node), network.outEdges(node), network.incidentEdges(node))
45           .testEquals();
46       new EqualsTester()
47           .addEqualityGroup(
48               network.predecessors(node), network.successors(node), network.adjacentNodes(node))
49           .testEquals();
50 
51       for (Integer adjacentNode : network.adjacentNodes(node)) {
52         assertThat(network.edgesConnecting(node, adjacentNode))
53             .containsExactlyElementsIn(network.edgesConnecting(adjacentNode, node));
54       }
55     }
56   }
57 
58   @Override
59   @Test
nodes_checkReturnedSetMutability()60   public void nodes_checkReturnedSetMutability() {
61     Set<Integer> nodes = network.nodes();
62     try {
63       nodes.add(N2);
64       fail(ERROR_MODIFIABLE_COLLECTION);
65     } catch (UnsupportedOperationException e) {
66       addNode(N1);
67       assertThat(network.nodes()).containsExactlyElementsIn(nodes);
68     }
69   }
70 
71   @Override
72   @Test
edges_checkReturnedSetMutability()73   public void edges_checkReturnedSetMutability() {
74     Set<String> edges = network.edges();
75     try {
76       edges.add(E12);
77       fail(ERROR_MODIFIABLE_COLLECTION);
78     } catch (UnsupportedOperationException e) {
79       addEdge(N1, N2, E12);
80       assertThat(network.edges()).containsExactlyElementsIn(edges);
81     }
82   }
83 
84   @Override
85   @Test
incidentEdges_checkReturnedSetMutability()86   public void incidentEdges_checkReturnedSetMutability() {
87     addNode(N1);
88     Set<String> incidentEdges = network.incidentEdges(N1);
89     try {
90       incidentEdges.add(E12);
91       fail(ERROR_MODIFIABLE_COLLECTION);
92     } catch (UnsupportedOperationException e) {
93       addEdge(N1, N2, E12);
94       assertThat(network.incidentEdges(N1)).containsExactlyElementsIn(incidentEdges);
95     }
96   }
97 
98   @Override
99   @Test
adjacentNodes_checkReturnedSetMutability()100   public void adjacentNodes_checkReturnedSetMutability() {
101     addNode(N1);
102     Set<Integer> adjacentNodes = network.adjacentNodes(N1);
103     try {
104       adjacentNodes.add(N2);
105       fail(ERROR_MODIFIABLE_COLLECTION);
106     } catch (UnsupportedOperationException e) {
107       addEdge(N1, N2, E12);
108       assertThat(network.adjacentNodes(N1)).containsExactlyElementsIn(adjacentNodes);
109     }
110   }
111 
112   @Override
adjacentEdges_checkReturnedSetMutability()113   public void adjacentEdges_checkReturnedSetMutability() {
114     addEdge(N1, N2, E12);
115     Set<String> adjacentEdges = network.adjacentEdges(E12);
116     try {
117       adjacentEdges.add(E23);
118       fail(ERROR_MODIFIABLE_COLLECTION);
119     } catch (UnsupportedOperationException e) {
120       addEdge(N2, N3, E23);
121       assertThat(network.adjacentEdges(E12)).containsExactlyElementsIn(adjacentEdges);
122     }
123   }
124 
125   @Override
126   @Test
edgesConnecting_checkReturnedSetMutability()127   public void edgesConnecting_checkReturnedSetMutability() {
128     addNode(N1);
129     addNode(N2);
130     Set<String> edgesConnecting = network.edgesConnecting(N1, N2);
131     try {
132       edgesConnecting.add(E23);
133       fail(ERROR_MODIFIABLE_COLLECTION);
134     } catch (UnsupportedOperationException e) {
135       addEdge(N1, N2, E12);
136       assertThat(network.edgesConnecting(N1, N2)).containsExactlyElementsIn(edgesConnecting);
137     }
138   }
139 
140   @Override
141   @Test
inEdges_checkReturnedSetMutability()142   public void inEdges_checkReturnedSetMutability() {
143     addNode(N2);
144     Set<String> inEdges = network.inEdges(N2);
145     try {
146       inEdges.add(E12);
147       fail(ERROR_MODIFIABLE_COLLECTION);
148     } catch (UnsupportedOperationException e) {
149       addEdge(N1, N2, E12);
150       assertThat(network.inEdges(N2)).containsExactlyElementsIn(inEdges);
151     }
152   }
153 
154   @Override
155   @Test
outEdges_checkReturnedSetMutability()156   public void outEdges_checkReturnedSetMutability() {
157     addNode(N1);
158     Set<String> outEdges = network.outEdges(N1);
159     try {
160       outEdges.add(E12);
161       fail(ERROR_MODIFIABLE_COLLECTION);
162     } catch (UnsupportedOperationException e) {
163       addEdge(N1, N2, E12);
164       assertThat(network.outEdges(N1)).containsExactlyElementsIn(outEdges);
165     }
166   }
167 
168   @Override
169   @Test
predecessors_checkReturnedSetMutability()170   public void predecessors_checkReturnedSetMutability() {
171     addNode(N2);
172     Set<Integer> predecessors = network.predecessors(N2);
173     try {
174       predecessors.add(N1);
175       fail(ERROR_MODIFIABLE_COLLECTION);
176     } catch (UnsupportedOperationException e) {
177       addEdge(N1, N2, E12);
178       assertThat(network.predecessors(N2)).containsExactlyElementsIn(predecessors);
179     }
180   }
181 
182   @Override
183   @Test
successors_checkReturnedSetMutability()184   public void successors_checkReturnedSetMutability() {
185     addNode(N1);
186     Set<Integer> successors = network.successors(N1);
187     try {
188       successors.add(N2);
189       fail(ERROR_MODIFIABLE_COLLECTION);
190     } catch (UnsupportedOperationException e) {
191       addEdge(N1, N2, E12);
192       assertThat(network.successors(N1)).containsExactlyElementsIn(successors);
193     }
194   }
195 
196   @Test
edges_containsOrderMismatch()197   public void edges_containsOrderMismatch() {
198     addEdge(N1, N2, E12);
199     assertThat(network.asGraph().edges()).contains(ENDPOINTS_N2N1);
200     assertThat(network.asGraph().edges()).contains(ENDPOINTS_N1N2);
201   }
202 
203   @Test
edgesConnecting_orderMismatch()204   public void edgesConnecting_orderMismatch() {
205     addEdge(N1, N2, E12);
206     assertThat(network.edgesConnecting(ENDPOINTS_N2N1)).containsExactly(E12);
207     assertThat(network.edgesConnecting(ENDPOINTS_N1N2)).containsExactly(E12);
208   }
209 
210   @Test
edgeConnecting_orderMismatch()211   public void edgeConnecting_orderMismatch() {
212     addEdge(N1, N2, E12);
213     assertThat(network.edgeConnecting(ENDPOINTS_N2N1)).hasValue(E12);
214     assertThat(network.edgeConnecting(ENDPOINTS_N1N2)).hasValue(E12);
215   }
216 
217   @Test
edgeConnectingOrNull_orderMismatch()218   public void edgeConnectingOrNull_orderMismatch() {
219     addEdge(N1, N2, E12);
220     assertThat(network.edgeConnectingOrNull(ENDPOINTS_N2N1)).isEqualTo(E12);
221     assertThat(network.edgeConnectingOrNull(ENDPOINTS_N1N2)).isEqualTo(E12);
222   }
223 
224   @Test
edgesConnecting_oneEdge()225   public void edgesConnecting_oneEdge() {
226     addEdge(N1, N2, E12);
227     assertThat(network.edgesConnecting(N1, N2)).containsExactly(E12);
228     assertThat(network.edgesConnecting(N2, N1)).containsExactly(E12);
229   }
230 
231   @Test
inEdges_oneEdge()232   public void inEdges_oneEdge() {
233     addEdge(N1, N2, E12);
234     assertThat(network.inEdges(N2)).containsExactly(E12);
235     assertThat(network.inEdges(N1)).containsExactly(E12);
236   }
237 
238   @Test
outEdges_oneEdge()239   public void outEdges_oneEdge() {
240     addEdge(N1, N2, E12);
241     assertThat(network.outEdges(N2)).containsExactly(E12);
242     assertThat(network.outEdges(N1)).containsExactly(E12);
243   }
244 
245   @Test
predecessors_oneEdge()246   public void predecessors_oneEdge() {
247     addEdge(N1, N2, E12);
248     assertThat(network.predecessors(N2)).containsExactly(N1);
249     assertThat(network.predecessors(N1)).containsExactly(N2);
250   }
251 
252   @Test
successors_oneEdge()253   public void successors_oneEdge() {
254     addEdge(N1, N2, E12);
255     assertThat(network.successors(N1)).containsExactly(N2);
256     assertThat(network.successors(N2)).containsExactly(N1);
257   }
258 
259   @Test
inDegree_oneEdge()260   public void inDegree_oneEdge() {
261     addEdge(N1, N2, E12);
262     assertThat(network.inDegree(N2)).isEqualTo(1);
263     assertThat(network.inDegree(N1)).isEqualTo(1);
264   }
265 
266   @Test
outDegree_oneEdge()267   public void outDegree_oneEdge() {
268     addEdge(N1, N2, E12);
269     assertThat(network.outDegree(N1)).isEqualTo(1);
270     assertThat(network.outDegree(N2)).isEqualTo(1);
271   }
272 
273   @Test
edges_selfLoop()274   public void edges_selfLoop() {
275     assume().that(network.allowsSelfLoops()).isTrue();
276 
277     addEdge(N1, N1, E11);
278     assertThat(network.edges()).containsExactly(E11);
279   }
280 
281   @Test
incidentEdges_selfLoop()282   public void incidentEdges_selfLoop() {
283     assume().that(network.allowsSelfLoops()).isTrue();
284 
285     addEdge(N1, N1, E11);
286     assertThat(network.incidentEdges(N1)).containsExactly(E11);
287   }
288 
289   @Test
incidentNodes_selfLoop()290   public void incidentNodes_selfLoop() {
291     assume().that(network.allowsSelfLoops()).isTrue();
292 
293     addEdge(N1, N1, E11);
294     assertThat(network.incidentNodes(E11).nodeU()).isEqualTo(N1);
295     assertThat(network.incidentNodes(E11).nodeV()).isEqualTo(N1);
296   }
297 
298   @Test
adjacentNodes_selfLoop()299   public void adjacentNodes_selfLoop() {
300     assume().that(network.allowsSelfLoops()).isTrue();
301 
302     addEdge(N1, N1, E11);
303     addEdge(N1, N2, E12);
304     assertThat(network.adjacentNodes(N1)).containsExactly(N1, N2);
305   }
306 
307   @Test
adjacentEdges_selfLoop()308   public void adjacentEdges_selfLoop() {
309     assume().that(network.allowsSelfLoops()).isTrue();
310 
311     addEdge(N1, N1, E11);
312     addEdge(N1, N2, E12);
313     assertThat(network.adjacentEdges(E11)).containsExactly(E12);
314   }
315 
316   @Test
edgesConnecting_selfLoop()317   public void edgesConnecting_selfLoop() {
318     assume().that(network.allowsSelfLoops()).isTrue();
319 
320     addEdge(N1, N1, E11);
321     assertThat(network.edgesConnecting(N1, N1)).containsExactly(E11);
322     addEdge(N1, N2, E12);
323     assertThat(network.edgesConnecting(N1, N2)).containsExactly(E12);
324     assertThat(network.edgesConnecting(N2, N1)).containsExactly(E12);
325     assertThat(network.edgesConnecting(N1, N1)).containsExactly(E11);
326   }
327 
328   @Test
inEdges_selfLoop()329   public void inEdges_selfLoop() {
330     assume().that(network.allowsSelfLoops()).isTrue();
331 
332     addEdge(N1, N1, E11);
333     assertThat(network.inEdges(N1)).containsExactly(E11);
334     addEdge(N1, N2, E12);
335     assertThat(network.inEdges(N1)).containsExactly(E11, E12);
336   }
337 
338   @Test
outEdges_selfLoop()339   public void outEdges_selfLoop() {
340     assume().that(network.allowsSelfLoops()).isTrue();
341 
342     addEdge(N1, N1, E11);
343     assertThat(network.outEdges(N1)).containsExactly(E11);
344     addEdge(N2, N1, E12);
345     assertThat(network.outEdges(N1)).containsExactly(E11, E12);
346   }
347 
348   @Test
predecessors_selfLoop()349   public void predecessors_selfLoop() {
350     assume().that(network.allowsSelfLoops()).isTrue();
351 
352     addEdge(N1, N1, E11);
353     assertThat(network.predecessors(N1)).containsExactly(N1);
354     addEdge(N1, N2, E12);
355     assertThat(network.predecessors(N1)).containsExactly(N1, N2);
356   }
357 
358   @Test
successors_selfLoop()359   public void successors_selfLoop() {
360     assume().that(network.allowsSelfLoops()).isTrue();
361 
362     addEdge(N1, N1, E11);
363     assertThat(network.successors(N1)).containsExactly(N1);
364     addEdge(N2, N1, E12);
365     assertThat(network.successors(N1)).containsExactly(N1, N2);
366   }
367 
368   @Test
degree_selfLoop()369   public void degree_selfLoop() {
370     assume().that(network.allowsSelfLoops()).isTrue();
371 
372     addEdge(N1, N1, E11);
373     assertThat(network.degree(N1)).isEqualTo(2);
374     addEdge(N1, N2, E12);
375     assertThat(network.degree(N1)).isEqualTo(3);
376   }
377 
378   @Test
inDegree_selfLoop()379   public void inDegree_selfLoop() {
380     assume().that(network.allowsSelfLoops()).isTrue();
381 
382     addEdge(N1, N1, E11);
383     assertThat(network.inDegree(N1)).isEqualTo(2);
384     addEdge(N1, N2, E12);
385     assertThat(network.inDegree(N1)).isEqualTo(3);
386   }
387 
388   @Test
outDegree_selfLoop()389   public void outDegree_selfLoop() {
390     assume().that(network.allowsSelfLoops()).isTrue();
391 
392     addEdge(N1, N1, E11);
393     assertThat(network.outDegree(N1)).isEqualTo(2);
394     addEdge(N2, N1, E12);
395     assertThat(network.outDegree(N1)).isEqualTo(3);
396   }
397 
398   // Element Mutation
399 
400   @Test
addEdge_existingNodes()401   public void addEdge_existingNodes() {
402     assume().that(graphIsMutable()).isTrue();
403 
404     // Adding nodes initially for safety (insulating from possible future
405     // modifications to proxy methods)
406     addNode(N1);
407     addNode(N2);
408     assertThat(networkAsMutableNetwork.addEdge(N1, N2, E12)).isTrue();
409     assertThat(network.edges()).contains(E12);
410     assertThat(network.edgesConnecting(N1, N2)).containsExactly(E12);
411     assertThat(network.edgesConnecting(N2, N1)).containsExactly(E12);
412   }
413 
414   @Test
addEdge_existingEdgeBetweenSameNodes()415   public void addEdge_existingEdgeBetweenSameNodes() {
416     assume().that(graphIsMutable()).isTrue();
417 
418     assertThat(networkAsMutableNetwork.addEdge(N1, N2, E12)).isTrue();
419     ImmutableSet<String> edges = ImmutableSet.copyOf(network.edges());
420     assertThat(networkAsMutableNetwork.addEdge(N1, N2, E12)).isFalse();
421     assertThat(network.edges()).containsExactlyElementsIn(edges);
422     assertThat(networkAsMutableNetwork.addEdge(N2, N1, E12)).isFalse();
423     assertThat(network.edges()).containsExactlyElementsIn(edges);
424   }
425 
426   @Test
addEdge_existingEdgeBetweenDifferentNodes()427   public void addEdge_existingEdgeBetweenDifferentNodes() {
428     assume().that(graphIsMutable()).isTrue();
429 
430     addEdge(N1, N2, E12);
431     try {
432       // Edge between totally different nodes
433       networkAsMutableNetwork.addEdge(N4, N5, E12);
434       fail(ERROR_ADDED_EXISTING_EDGE);
435     } catch (IllegalArgumentException e) {
436       assertThat(e.getMessage()).contains(ERROR_REUSE_EDGE);
437     }
438   }
439 
440   @Test
addEdge_parallelEdge_notAllowed()441   public void addEdge_parallelEdge_notAllowed() {
442     assume().that(graphIsMutable()).isTrue();
443     assume().that(network.allowsParallelEdges()).isFalse();
444 
445     addEdge(N1, N2, E12);
446     try {
447       networkAsMutableNetwork.addEdge(N1, N2, EDGE_NOT_IN_GRAPH);
448       fail(ERROR_ADDED_PARALLEL_EDGE);
449     } catch (IllegalArgumentException e) {
450       assertThat(e.getMessage()).contains(ERROR_PARALLEL_EDGE);
451     }
452     try {
453       networkAsMutableNetwork.addEdge(N2, N1, EDGE_NOT_IN_GRAPH);
454       fail(ERROR_ADDED_PARALLEL_EDGE);
455     } catch (IllegalArgumentException e) {
456       assertThat(e.getMessage()).contains(ERROR_PARALLEL_EDGE);
457     }
458   }
459 
460   @Test
addEdge_parallelEdge_allowsParallelEdges()461   public void addEdge_parallelEdge_allowsParallelEdges() {
462     assume().that(graphIsMutable()).isTrue();
463     assume().that(network.allowsParallelEdges()).isTrue();
464 
465     assertTrue(networkAsMutableNetwork.addEdge(N1, N2, E12));
466     assertTrue(networkAsMutableNetwork.addEdge(N2, N1, E21));
467     assertTrue(networkAsMutableNetwork.addEdge(N1, N2, E12_A));
468     assertThat(network.edgesConnecting(N1, N2)).containsExactly(E12, E12_A, E21);
469   }
470 
471   @Test
addEdge_orderMismatch()472   public void addEdge_orderMismatch() {
473     assume().that(graphIsMutable()).isTrue();
474 
475     EndpointPair<Integer> endpoints = EndpointPair.ordered(N1, N2);
476     assertThat(networkAsMutableNetwork.addEdge(endpoints, E12)).isTrue();
477   }
478 
479   @Test
addEdge_selfLoop_notAllowed()480   public void addEdge_selfLoop_notAllowed() {
481     assume().that(graphIsMutable()).isTrue();
482     assume().that(network.allowsSelfLoops()).isFalse();
483 
484     try {
485       networkAsMutableNetwork.addEdge(N1, N1, E11);
486       fail(ERROR_ADDED_SELF_LOOP);
487     } catch (IllegalArgumentException e) {
488       assertThat(e).hasMessageThat().contains(ERROR_SELF_LOOP);
489     }
490   }
491 
492   /**
493    * This test checks an implementation dependent feature. It tests that the method {@code addEdge}
494    * will silently add the missing nodes to the graph, then add the edge connecting them. We are not
495    * using the proxy methods here as we want to test {@code addEdge} when the end-points are not
496    * elements of the graph.
497    */
498   @Test
addEdge_nodesNotInGraph()499   public void addEdge_nodesNotInGraph() {
500     assume().that(graphIsMutable()).isTrue();
501 
502     networkAsMutableNetwork.addNode(N1);
503     assertTrue(networkAsMutableNetwork.addEdge(N1, N5, E15));
504     assertTrue(networkAsMutableNetwork.addEdge(N4, N1, E41));
505     assertTrue(networkAsMutableNetwork.addEdge(N2, N3, E23));
506     assertThat(network.nodes()).containsExactly(N1, N5, N4, N2, N3);
507     assertThat(network.edges()).containsExactly(E15, E41, E23);
508     assertThat(network.edgesConnecting(N1, N5)).containsExactly(E15);
509     assertThat(network.edgesConnecting(N4, N1)).containsExactly(E41);
510     assertThat(network.edgesConnecting(N2, N3)).containsExactly(E23);
511     assertThat(network.edgesConnecting(N3, N2)).containsExactly(E23);
512   }
513 
514   @Test
addEdge_selfLoop()515   public void addEdge_selfLoop() {
516     assume().that(graphIsMutable()).isTrue();
517     assume().that(network.allowsSelfLoops()).isTrue();
518 
519     assertThat(networkAsMutableNetwork.addEdge(N1, N1, E11)).isTrue();
520     assertThat(network.edges()).contains(E11);
521     assertThat(network.edgesConnecting(N1, N1)).containsExactly(E11);
522   }
523 
524   @Test
addEdge_existingSelfLoopEdgeBetweenSameNodes()525   public void addEdge_existingSelfLoopEdgeBetweenSameNodes() {
526     assume().that(graphIsMutable()).isTrue();
527     assume().that(network.allowsSelfLoops()).isTrue();
528 
529     addEdge(N1, N1, E11);
530     ImmutableSet<String> edges = ImmutableSet.copyOf(network.edges());
531     assertThat(networkAsMutableNetwork.addEdge(N1, N1, E11)).isFalse();
532     assertThat(network.edges()).containsExactlyElementsIn(edges);
533   }
534 
535   @Test
addEdge_existingEdgeBetweenDifferentNodes_selfLoops()536   public void addEdge_existingEdgeBetweenDifferentNodes_selfLoops() {
537     assume().that(graphIsMutable()).isTrue();
538     assume().that(network.allowsSelfLoops()).isTrue();
539 
540     addEdge(N1, N1, E11);
541     try {
542       networkAsMutableNetwork.addEdge(N1, N2, E11);
543       fail("Reusing an existing self-loop edge to connect different nodes succeeded");
544     } catch (IllegalArgumentException e) {
545       assertThat(e.getMessage()).contains(ERROR_REUSE_EDGE);
546     }
547     try {
548       networkAsMutableNetwork.addEdge(N2, N2, E11);
549       fail("Reusing an existing self-loop edge to make a different self-loop edge succeeded");
550     } catch (IllegalArgumentException e) {
551       assertThat(e.getMessage()).contains(ERROR_REUSE_EDGE);
552     }
553     addEdge(N1, N2, E12);
554     try {
555       networkAsMutableNetwork.addEdge(N1, N1, E12);
556       fail("Reusing an existing edge to add a self-loop edge between different nodes succeeded");
557     } catch (IllegalArgumentException e) {
558       assertThat(e.getMessage()).contains(ERROR_REUSE_EDGE);
559     }
560   }
561 
562   @Test
addEdge_parallelSelfLoopEdge_notAllowed()563   public void addEdge_parallelSelfLoopEdge_notAllowed() {
564     assume().that(graphIsMutable()).isTrue();
565     assume().that(network.allowsSelfLoops()).isTrue();
566     assume().that(network.allowsParallelEdges()).isFalse();
567 
568     addEdge(N1, N1, E11);
569     try {
570       networkAsMutableNetwork.addEdge(N1, N1, EDGE_NOT_IN_GRAPH);
571       fail("Adding a parallel self-loop edge succeeded");
572     } catch (IllegalArgumentException e) {
573       assertThat(e.getMessage()).contains(ERROR_PARALLEL_EDGE);
574     }
575   }
576 
577   @Test
addEdge_parallelSelfLoopEdge_allowsParallelEdges()578   public void addEdge_parallelSelfLoopEdge_allowsParallelEdges() {
579     assume().that(graphIsMutable()).isTrue();
580     assume().that(network.allowsSelfLoops()).isTrue();
581     assume().that(network.allowsParallelEdges()).isTrue();
582 
583     assertTrue(networkAsMutableNetwork.addEdge(N1, N1, E11));
584     assertTrue(networkAsMutableNetwork.addEdge(N1, N1, E11_A));
585     assertThat(network.edgesConnecting(N1, N1)).containsExactly(E11, E11_A);
586   }
587 
588   @Test
removeNode_existingNodeWithSelfLoopEdge()589   public void removeNode_existingNodeWithSelfLoopEdge() {
590     assume().that(graphIsMutable()).isTrue();
591     assume().that(network.allowsSelfLoops()).isTrue();
592 
593     addNode(N1);
594     addEdge(N1, N1, E11);
595     assertThat(networkAsMutableNetwork.removeNode(N1)).isTrue();
596     assertThat(network.nodes()).isEmpty();
597     assertThat(network.edges()).doesNotContain(E11);
598   }
599 
600   @Test
removeEdge_existingSelfLoopEdge()601   public void removeEdge_existingSelfLoopEdge() {
602     assume().that(graphIsMutable()).isTrue();
603     assume().that(network.allowsSelfLoops()).isTrue();
604 
605     addEdge(N1, N1, E11);
606     assertThat(networkAsMutableNetwork.removeEdge(E11)).isTrue();
607     assertThat(network.edges()).doesNotContain(E11);
608     assertThat(network.edgesConnecting(N1, N1)).isEmpty();
609   }
610 }
611