Skip to content

KAFKA-8240: Fix NPE in Source.equals()#6589

Merged
bbejeck merged 8 commits intoapache:trunkfrom
mjsax:kafka-8240-npe-topology-describe
May 3, 2019
Merged

KAFKA-8240: Fix NPE in Source.equals()#6589
bbejeck merged 8 commits intoapache:trunkfrom
mjsax:kafka-8240-npe-topology-describe

Conversation

@mjsax
Copy link
Copy Markdown
Member

@mjsax mjsax commented Apr 17, 2019

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)

  • Verify design and implementation
  • Verify test coverage and CI build status
  • Verify documentation (including upgrade notes)

@mjsax mjsax added the streams label Apr 17, 2019
@mjsax
Copy link
Copy Markdown
Member Author

mjsax commented Apr 17, 2019

Call for review @guozhangwang @bbejeck @vvcephei @ableegoldman @cadonna

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While debugging the issue, I figure that the use comparators don't do deep comparison. This is the corresponding fix. (Similar below)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a basic test for null pattern.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could you rename this test so that it reflects the focus on the null pattern?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack. Renamed this one and added a new test for Pattern case.

Note, we know that either one of both is null.

Copy link
Copy Markdown
Contributor

@vvcephei vvcephei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@mjsax
Copy link
Copy Markdown
Member Author

mjsax commented Apr 17, 2019

Java8 failed with know flaky test. Java11 passed.

Retest this please.

@bbejeck
Copy link
Copy Markdown
Member

bbejeck commented Apr 18, 2019

Java 8 passed, Java 11 failed; test results already cleaned up

retest this please

@bbejeck
Copy link
Copy Markdown
Member

bbejeck commented Apr 18, 2019

Failed with Execution failed for task ':core:compileTestScala'. but a PR (#6603) has been merged for this.

retest this please

@mjsax mjsax force-pushed the kafka-8240-npe-topology-describe branch from 113950d to 1e44568 Compare April 19, 2019 02:08
@mjsax
Copy link
Copy Markdown
Member Author

mjsax commented Apr 19, 2019

Rebased.

@mjsax
Copy link
Copy Markdown
Member Author

mjsax commented Apr 20, 2019

Updated this.

@mjsax
Copy link
Copy Markdown
Member Author

mjsax commented Apr 22, 2019

@bbejeck @vvcephei @cadonna Build finally passed. I change couple of things. Would like to get another review to make sure it's still ok.


@Test(expected = NullPointerException.class)
public void shouldThrowIfNameIsNull() {
new InternalTopologyBuilder.Source(null, Collections.emptySet(), null);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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());

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, makes sense. Didn't know about policy of internal checks. Would be good to have it written down somewhere.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 :)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack.

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"));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.");
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should happen if the topic or the pattern is empty?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@mjsax
Copy link
Copy Markdown
Member Author

mjsax commented Apr 23, 2019

Updated this.


@Test(expected = NullPointerException.class)
public void shouldThrowIfNameIsNull() {
new InternalTopologyBuilder.Source(null, Collections.emptySet(), null);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@daiweisong
Copy link
Copy Markdown

niubi

@mjsax
Copy link
Copy Markdown
Member Author

mjsax commented Apr 27, 2019

Updated this.

@cadonna
Copy link
Copy Markdown
Member

cadonna commented May 3, 2019

LGTM

@bbejeck bbejeck merged commit 6d3ff13 into apache:trunk May 3, 2019
@bbejeck
Copy link
Copy Markdown
Member

bbejeck commented May 3, 2019

Merged #6589 to trunk

@mjsax mjsax deleted the kafka-8240-npe-topology-describe branch May 6, 2019 13:06
mjsax added a commit to mjsax/kafka that referenced this pull request May 6, 2019
 - backport of PR apache#6589 to 2.2 branch
mjsax added a commit that referenced this pull request May 9, 2019
- backport of PR #6589 to 2.2 branch

Reviewers: Bruno Cadonna <bruno@confluent.io>, Bill Bejeck <bill@confluent.io>
mjsax added a commit that referenced this pull request May 9, 2019
- backport of PR #6589 to 2.2 branch

Reviewers: Bruno Cadonna <bruno@confluent.io>, Bill Bejeck <bill@confluent.io>
pengxiaolong pushed a commit to pengxiaolong/kafka that referenced this pull request Jun 14, 2019
Reviewers: John Roesler <john@confluent.io>, Bruno Cadonna <bruno@confluent.io>, Bill Bejeck <bbejeck@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants