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