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