KAFKA-8240: Fix NPE in Source.equals()#6589
Conversation
|
Call for review @guozhangwang @bbejeck @vvcephei @ableegoldman @cadonna |
There was a problem hiding this comment.
While debugging the issue, I figure that the use comparators don't do deep comparison. This is the corresponding fix. (Similar below)
There was a problem hiding this comment.
Just a basic test for null pattern.
There was a problem hiding this comment.
nit: Could you rename this test so that it reflects the focus on the null pattern?
There was a problem hiding this comment.
Ack. Renamed this one and added a new test for Pattern case.
Note, we know that either one of both is null.
|
Java8 failed with know flaky test. Java11 passed. Retest this please. |
|
Java 8 passed, Java 11 failed; test results already cleaned up retest this please |
|
Failed with retest this please |
113950d to
1e44568
Compare
|
Rebased. |
|
Updated this. |
|
|
||
| @Test(expected = NullPointerException.class) | ||
| public void shouldThrowIfNameIsNull() { | ||
| new InternalTopologyBuilder.Source(null, Collections.emptySet(), null); |
There was a problem hiding this comment.
Here and for the next two tests, it would be better to rewrite the tests to following:
final Exception e = assertThrows(NullPointerException.class, () -> new InternalTopologyBuilder.Source(null, Collections.emptySet(), null);
assertEquals(<expected message>, e.getMessage());
There was a problem hiding this comment.
We get an NPE with null message here. Not sure if this improves the test? Let me know you think. We cannot set a message because we use Objects.requireNonNull that trows the NPE.
There was a problem hiding this comment.
OK, I overlooked that the overload of requireNonNull without the message is used in the code under test. However, I think it would be better to use the overload with message, i.e.,
public static <T> T requireNonNull(T obj, String message)
There was a problem hiding this comment.
Well. We never specify a message for internal checks. It's not a user facing API but effectively an internal assertion. So not sure if we gain much adding a message and checking for it. It's a fatal error anyway if we hit the NPE.
If we think we should specify messages, we should change our pattern and do this consistently. Thoughts?
There was a problem hiding this comment.
OK, makes sense. Didn't know about policy of internal checks. Would be good to have it written down somewhere.
There was a problem hiding this comment.
Do you mean the assert keyword in Java? IIUC assertions need to explicitly turned on at execution time. So you need to rely on the user to turn them on.
There was a problem hiding this comment.
Yes, I mean assert keyword. If we turn it on in our tests, it might be sufficient (it's internal checks)? Not sure.
Other suggestions are more than welcome :)
There was a problem hiding this comment.
My preference would be requireNonNull and add the message. First IMHO it's always better to have some sort of description v.s just a NullPointerException and second, there is less chance for error since we need to explicitly enable assertions. Just my 2 cents.
There was a problem hiding this comment.
I am with @bbejeck on this. Alternatively, we could specify a separate exception that shows that a contract was violated internally and gives you information to quickly identify the bug. However, I am not sure whether this additional exception would introduce more complexity than benefits.
I would not use an assert and turn it on only in tests. If a contract is violated internally during production, it could prolong the search for the bug, because the error could pop up in places other than the actual origin of the violation.
| public void shouldCompareSourceNodeWithTopicPattern() { | ||
| final InternalTopologyBuilder.Source base = new InternalTopologyBuilder.Source("name", null, Pattern.compile("topic")); | ||
| final InternalTopologyBuilder.Source sameAsBase = new InternalTopologyBuilder.Source("name", null, Pattern.compile("topic")); | ||
| final InternalTopologyBuilder.Source differentName = new InternalTopologyBuilder.Source("name2", null, Pattern.compile("topic")); |
There was a problem hiding this comment.
You basically specified the differentName check twice, in this and in the previous method. I would specify the following tests into separate methods:
- same
- different names
- different topics
- different patterns
Makes the test better readable and avoids repetitions of checks.
| if (topics != null && pattern != null) { | ||
| throw new IllegalArgumentException("Either topics or pattern must be null, but both are not null."); | ||
| } | ||
|
|
There was a problem hiding this comment.
What should happen if the topic or the pattern is empty?
There was a problem hiding this comment.
I don't think those are special cases. For Pattern.compile(null) it throws NPE, so we would never hit this code but fail before.
Pattern.compile("") should be fine but just don't match any topic. Similar, to empty topic list. For both cases, the consumer should just be idle.
\cc @guozhangwang or @hachikuji to confirm.
|
Updated this. |
|
|
||
| @Test(expected = NullPointerException.class) | ||
| public void shouldThrowIfNameIsNull() { | ||
| new InternalTopologyBuilder.Source(null, Collections.emptySet(), null); |
There was a problem hiding this comment.
My preference would be requireNonNull and add the message. First IMHO it's always better to have some sort of description v.s just a NullPointerException and second, there is less chance for error since we need to explicitly enable assertions. Just my 2 cents.
|
niubi |
|
Updated this. |
|
LGTM |
|
Merged #6589 to trunk |
- backport of PR apache#6589 to 2.2 branch
- backport of PR #6589 to 2.2 branch Reviewers: Bruno Cadonna <bruno@confluent.io>, Bill Bejeck <bill@confluent.io>
- backport of PR #6589 to 2.2 branch Reviewers: Bruno Cadonna <bruno@confluent.io>, Bill Bejeck <bill@confluent.io>
Reviewers: John Roesler <john@confluent.io>, Bruno Cadonna <bruno@confluent.io>, Bill Bejeck <bbejeck@gmail.com>
More detailed description of your change,
if necessary. The PR title and PR message become
the squashed commit message, so use a separate
comment to ping reviewers.
Summary of testing strategy (including rationale)
for the feature or bug fix. Unit and/or integration
tests are expected for any behaviour change and
system tests should be considered for larger changes.
Committer Checklist (excluded from commit message)