Skip to content

Commit

Permalink
common.graph: adding new EndpointPair-accepting overloads.
Browse files Browse the repository at this point in the history
RELNOTES=common.graph: added overloads to methods accepting pairs of nodes to also accept EndpointPair; changed behavior of *Graph.edges().contains() to allow undirected graphs to accept ordered EndpointPairs.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=218724287
  • Loading branch information
jrtom authored and cgdecker committed Oct 26, 2018
1 parent 64276db commit af3ee1c
Show file tree
Hide file tree
Showing 53 changed files with 1,591 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

package com.google.common.graph;

import static com.google.common.graph.GraphConstants.ENDPOINTS_MISMATCH;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;

import org.junit.Test;

Expand Down Expand Up @@ -68,10 +70,29 @@ public void outDegree_oneEdge() {
assertThat(graph.outDegree(N2)).isEqualTo(0);
}

@Test
public void hasEdgeConnecting_correct() {
putEdge(N1, N2);
assertThat(graph.hasEdgeConnecting(EndpointPair.ordered(N1, N2))).isTrue();
}

@Test
public void hasEdgeConnecting_backwards() {
putEdge(N1, N2);
assertThat(graph.hasEdgeConnecting(EndpointPair.ordered(N2, N1))).isFalse();
}

@Test
public void hasEdgeConnecting_mismatch() {
putEdge(N1, N2);
assertThat(graph.hasEdgeConnecting(EndpointPair.unordered(N1, N2))).isFalse();
assertThat(graph.hasEdgeConnecting(EndpointPair.unordered(N2, N1))).isFalse();
}

// Element Mutation

@Test
public void addEdge_existingNodes() {
public void putEdge_existingNodes() {
// Adding nodes initially for safety (insulating from possible future
// modifications to proxy methods)
addNode(N1);
Expand All @@ -80,11 +101,22 @@ public void addEdge_existingNodes() {
}

@Test
public void addEdge_existingEdgeBetweenSameNodes() {
putEdge(N1, N2);
public void putEdge_existingEdgeBetweenSameNodes() {
assertThat(putEdge(N1, N2)).isTrue();
assertThat(putEdge(N1, N2)).isFalse();
}

@Test
public void putEdge_orderMismatch() {
EndpointPair<Integer> endpoints = EndpointPair.unordered(N1, N2);
try {
putEdge(endpoints);
fail("Expected IllegalArgumentException: " + ENDPOINTS_MISMATCH);
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().contains(ENDPOINTS_MISMATCH);
}
}

public void removeEdge_antiparallelEdges() {
putEdge(N1, N2);
putEdge(N2, N1);
Expand All @@ -99,4 +131,16 @@ public void removeEdge_antiparallelEdges() {
assertThat(graph.predecessors(N1)).isEmpty();
assertThat(graph.edges()).isEmpty();
}

@Test
public void removeEdge_orderMismatch() {
putEdge(N1, N2);
EndpointPair<Integer> endpoints = EndpointPair.unordered(N1, N2);
try {
graph.removeEdge(endpoints);
fail("Expected IllegalArgumentException: " + ENDPOINTS_MISMATCH);
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().contains(ENDPOINTS_MISMATCH);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.google.common.graph;

import static com.google.common.graph.GraphConstants.ENDPOINTS_MISMATCH;
import static com.google.common.graph.TestUtil.assertEdgeNotInGraphErrorMessage;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
Expand Down Expand Up @@ -59,6 +60,37 @@ public void validateSourceAndTarget() {
}
}

@Test
public void edges_containsOrderMismatch() {
addEdge(N1, N2, E12);
EndpointPair<Integer> endpointsN1N2 = EndpointPair.unordered(N1, N2);
EndpointPair<Integer> endpointsN2N1 = EndpointPair.unordered(N2, N1);
assertThat(network.asGraph().edges()).doesNotContain(endpointsN1N2);
assertThat(network.asGraph().edges()).doesNotContain(endpointsN2N1);
}

@Test
public void edgesConnecting_orderMismatch() {
addEdge(N1, N2, E12);
try {
Set<String> unused = network.edgesConnecting(EndpointPair.unordered(N1, N2));
fail("Expected IllegalArgumentException: " + ENDPOINTS_MISMATCH);
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().contains(ENDPOINTS_MISMATCH);
}
}

@Test
public void edgeConnectingOrNull_orderMismatch() {
addEdge(N1, N2, E12);
try {
String unused = network.edgeConnectingOrNull(EndpointPair.unordered(N1, N2));
fail("Expected IllegalArgumentException: " + ENDPOINTS_MISMATCH);
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().contains(ENDPOINTS_MISMATCH);
}
}

@Override
@Test
public void incidentNodes_oneEdge() {
Expand Down Expand Up @@ -187,14 +219,14 @@ public void addEdge_existingEdgeBetweenDifferentNodes() {
addEdge(N4, N5, E12);
fail(ERROR_ADDED_EXISTING_EDGE);
} catch (IllegalArgumentException e) {
assertThat(e.getMessage()).contains(ERROR_REUSE_EDGE);
assertThat(e).hasMessageThat().contains(ERROR_REUSE_EDGE);
}
try {
// Edge between same nodes but in reverse direction
addEdge(N2, N1, E12);
fail(ERROR_ADDED_EXISTING_EDGE);
} catch (IllegalArgumentException e) {
assertThat(e.getMessage()).contains(ERROR_REUSE_EDGE);
assertThat(e).hasMessageThat().contains(ERROR_REUSE_EDGE);
}
}

Expand All @@ -205,7 +237,18 @@ public void addEdge_parallelEdge() {
addEdge(N1, N2, EDGE_NOT_IN_GRAPH);
fail(ERROR_ADDED_PARALLEL_EDGE);
} catch (IllegalArgumentException e) {
assertThat(e.getMessage()).contains(ERROR_PARALLEL_EDGE);
assertThat(e).hasMessageThat().contains(ERROR_PARALLEL_EDGE);
}
}

@Test
public void addEdge_orderMismatch() {
EndpointPair<Integer> endpoints = EndpointPair.unordered(N1, N2);
try {
addEdge(endpoints, E12);
fail("Expected IllegalArgumentException: " + ENDPOINTS_MISMATCH);
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().contains(ENDPOINTS_MISMATCH);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ protected boolean putEdge(Integer n1, Integer n2) {
return graph.putEdge(n1, n2);
}

@CanIgnoreReturnValue
protected boolean putEdge(EndpointPair<Integer> endpoints) {
graph.addNode(endpoints.nodeU());
graph.addNode(endpoints.nodeV());
return graph.putEdge(endpoints);
}

@Before
public void init() {
graph = createGraph();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ protected boolean addNode(Integer n) {
* add an edge whose end-points don't already exist in the graph), you should <b>not</b> use this
* method.
*
* TODO(user): remove the addNode() calls, that's now contractually guaranteed
*
* @return {@code true} iff the graph was modified as a result of this call
*/
@CanIgnoreReturnValue
Expand All @@ -129,6 +131,12 @@ protected boolean addEdge(Integer n1, Integer n2, String e) {
return network.addEdge(n1, n2, e);
}

protected boolean addEdge(EndpointPair<Integer> endpoints, String e) {
network.addNode(endpoints.nodeU());
network.addNode(endpoints.nodeV());
return network.addEdge(endpoints, e);
}

@Before
public void init() {
network = createGraph();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,20 @@ public void outDegree_oneEdge() {
assertThat(graph.outDegree(N2)).isEqualTo(1);
}

@Test
public void hasEdgeConnecting_correct() {
putEdge(N1, N2);
assertThat(graph.hasEdgeConnecting(EndpointPair.unordered(N1, N2))).isTrue();
assertThat(graph.hasEdgeConnecting(EndpointPair.unordered(N2, N1))).isTrue();
}

@Test
public void hasEdgeConnecting_mismatch() {
putEdge(N1, N2);
assertThat(graph.hasEdgeConnecting(EndpointPair.ordered(N1, N2))).isTrue();
assertThat(graph.hasEdgeConnecting(EndpointPair.ordered(N2, N1))).isTrue();
}

// Element Mutation

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
* Test cases that do not require the graph to be undirected are found in superclasses.
*/
public abstract class AbstractUndirectedNetworkTest extends AbstractNetworkTest {
private static final EndpointPair<Integer> ENDPOINTS_N1N2 = EndpointPair.ordered(N1, N2);
private static final EndpointPair<Integer> ENDPOINTS_N2N1 = EndpointPair.ordered(N2, N1);

@After
public void validateUndirectedEdges() {
Expand All @@ -52,6 +54,27 @@ public void validateUndirectedEdges() {
}
}

@Test
public void edges_containsOrderMismatch() {
addEdge(N1, N2, E12);
assertThat(network.asGraph().edges()).contains(ENDPOINTS_N2N1);
assertThat(network.asGraph().edges()).contains(ENDPOINTS_N1N2);
}

@Test
public void edgesConnecting_orderMismatch() {
addEdge(N1, N2, E12);
assertThat(network.edgesConnecting(ENDPOINTS_N2N1)).containsExactly(E12);
assertThat(network.edgesConnecting(ENDPOINTS_N1N2)).containsExactly(E12);
}

@Test
public void edgeConnectingOrNull_orderMismatch() {
addEdge(N1, N2, E12);
assertThat(network.edgeConnectingOrNull(ENDPOINTS_N2N1)).isEqualTo(E12);
assertThat(network.edgeConnectingOrNull(ENDPOINTS_N1N2)).isEqualTo(E12);
}

@Test
public void edgesConnecting_oneEdge() {
addEdge(N1, N2, E12);
Expand Down Expand Up @@ -117,7 +140,7 @@ public void addEdge_existingNodes() {

@Test
public void addEdge_existingEdgeBetweenSameNodes() {
addEdge(N1, N2, E12);
assertThat(addEdge(N1, N2, E12)).isTrue();
ImmutableSet<String> edges = ImmutableSet.copyOf(network.edges());
assertThat(addEdge(N1, N2, E12)).isFalse();
assertThat(network.edges()).containsExactlyElementsIn(edges);
Expand Down Expand Up @@ -153,4 +176,10 @@ public void addEdge_parallelEdge() {
assertThat(e.getMessage()).contains(ERROR_PARALLEL_EDGE);
}
}

@Test
public void addEdge_orderMismatch() {
EndpointPair<Integer> endpoints = EndpointPair.ordered(N1, N2);
assertThat(addEdge(endpoints, E12)).isTrue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ public void endpointPair_unmodifiableView() {
}

@Test
public void endpointPair_containment() {
public void endpointPair_undirected_contains() {
MutableGraph<Integer> undirectedGraph = GraphBuilder.undirected().allowsSelfLoops(true).build();
undirectedGraph.putEdge(N1, N1);
undirectedGraph.putEdge(N1, N2);
Expand All @@ -214,11 +214,32 @@ public void endpointPair_containment() {
assertThat(edges).contains(EndpointPair.unordered(N1, N2));
assertThat(edges).contains(EndpointPair.unordered(N2, N1)); // equal to unordered(N1, N2)

assertThat(edges).doesNotContain(EndpointPair.unordered(N2, N2));
assertThat(edges).doesNotContain(EndpointPair.ordered(N1, N2)); // graph not directed
// ordered endpoints OK for undirected graph (because ordering is irrelevant)
assertThat(edges).contains(EndpointPair.ordered(N1, N2));

assertThat(edges).doesNotContain(EndpointPair.unordered(N2, N2)); // edge not present
assertThat(edges).doesNotContain(EndpointPair.unordered(N3, N4)); // nodes not in graph
}

@Test
public void endpointPair_directed_contains() {
MutableGraph<Integer> directedGraph = GraphBuilder.directed().allowsSelfLoops(true).build();
directedGraph.putEdge(N1, N1);
directedGraph.putEdge(N1, N2);
Set<EndpointPair<Integer>> edges = directedGraph.edges();

assertThat(edges).hasSize(2);
assertThat(edges).contains(EndpointPair.ordered(N1, N1));
assertThat(edges).contains(EndpointPair.ordered(N1, N2));

// unordered endpoints not OK for directed graph (undefined behavior)
assertThat(edges).doesNotContain(EndpointPair.unordered(N1, N2));

assertThat(edges).doesNotContain(EndpointPair.ordered(N2, N1)); // wrong order
assertThat(edges).doesNotContain(EndpointPair.ordered(N2, N2)); // edge not present
assertThat(edges).doesNotContain(EndpointPair.ordered(N3, N4)); // nodes not in graph
}

private static void containsExactlySanityCheck(Collection<?> collection, Object... varargs) {
assertThat(collection).hasSize(varargs.length);
for (Object obj : varargs) {
Expand Down
Loading

0 comments on commit af3ee1c

Please sign in to comment.