question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Contract of Collection.contains violated in AbstractBaseGraph.edges

See original GitHub issue

Let p be an EndpointPair<Integer>. The method AbstractBaseGraph#edges can return a Set<EndpointPair<Integer>> edges for which edges.contains(p) is true, but e.equals(p) is false for each element e. This violates the contract of java.util.Collection#contains:

Returns true if this collection contains the specified element. More formally, returns true if and only if this collection contains at least one element e such that Objects.equals(o, e).

Note the failing assertion in the following test:

@Test
public void contains_contract_violated() {
    MutableGraph<Integer> undirectedGraph = GraphBuilder.undirected().build();
    undirectedGraph.putEdge(1, 2);
    Set<EndpointPair<Integer>> edges = undirectedGraph.edges();
    EndpointPair<Integer> ordered = EndpointPair.ordered(1, 2);
    Assertions.assertTrue(edges.contains(ordered));
    Assertions.assertTrue(edges.stream().anyMatch(ordered::equals)); // fails
}

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:1
  • Comments:13 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
jrtomcommented, Jan 21, 2022

Thanks, @jbduncan.

How much code do we have like graph.edges().contains(endpointPair) or graph.putEdge(endpointPair), where graph is an instance of Graph, ValueGraph or Network, and graph.isDirected() != endpointPair.isOrdered()?

As far as I can tell, neither of these cases exist in Google’s code base. However, that doesn’t tell us whether they exist in the rest of the world. 😃

Otherwise, my gut feeling is for directedGraph.edges().contains(undirectedEndpointPair) to always be false

I think we’ve settled on this change: that was the original subject of this issue, and I agree that we need to not violate the Set.contains() contract. Since we have an existing contract for hasEdgeConnecting() that requires that it be consistent with edges().contains(), that means that behavior needs to change as well.

and for directedGraph.putEdge(undirectedEndpointPair) to never “work”.

This is the remaining question, yes. 😃

1reaction
jrtomcommented, Jan 19, 2022

@h908714124 thanks for the catch. This is a bug. It arose from a bug fix, but @cpovirk is correct that the behavior of contains() didn’t specifically come up in the review (@cpovirk, the API review which led to this change included “endpoint ordering mismatches” in the title if you want to look it up).

@jbduncan thanks for the analysis; you are correct about the cause.

The original review was about fixing undefined behavior for mutations involving the case where someone added an unordered EndpointPair to a directed graph (the behavior is undefined, because the assignment of “nodeU” and “nodeV” to the endpoints is arbitrary).

Unfortunately, I think that I got a bit too cute with the solution (and I don’t think any of the reviewers noticed the problem). Technically adding an ordered edge <u, v> to an undirected graph is…not invalid, because the graph can simply ignore the directionality of the endpoints. Our mistake was that we should not have (implicitly) concluded that you can say that the resultant graph contains a directed edge <u, v> if there is an undirected edge connecting u and v.

As @h908714124 pointed out, we should not have defined contains() in such a way as to be inconsistent with equals() (that’s clearly a violation of the Set contract as well as being weird) and it is also clear that an unordered EndpointPair should never be equal to an ordered EndpointPair. Therefore we need to fix the contains() behavior.

@cpovirk, since you’ve apparently already identified the failing tests (which implies that you have a CL with this change), I’d be happy to review a fix for this. Otherwise I’ll try to get to it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Collections.sort() Comparison method violates its general ...
In your case you violate it when two Users have checkMatchConditions false , in which case compare(u1, u2) and compare(u2, u1) both return...
Read more >
OUTSOURCING COLLECTIONS CONTRACTS What you ...
(d) A defendant is not liable for the collection fees authorized under Subsection (b) if the court of original jurisdiction has determined the ......
Read more >
System.AddIn.Contract.Collections Namespace | Microsoft Docs
Contains interfaces that define collections of IContract and RemoteArgument objects.
Read more >
How to Break a Contract With a Collections Agency
Breach of Contract. If the collections agency has breached a material term of the agreement, you will also be free to break your...
Read more >
What Is a Breach of Contract in a Debt Collection Case
What is a breach of contract as it pertains to your business debt collection case? Get the details on what happens & what...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found