Skip to content

KAFKA-20677: Enhance test coverage of testCannotSendToInternalTopic#22575

Open
aravind-kvs wants to merge 1 commit into
apache:trunkfrom
aravind-kvs:KAFKA-20677-enhance-testCannotSendToInternalTopic
Open

KAFKA-20677: Enhance test coverage of testCannotSendToInternalTopic#22575
aravind-kvs wants to merge 1 commit into
apache:trunkfrom
aravind-kvs:KAFKA-20677-enhance-testCannotSendToInternalTopic

Conversation

@aravind-kvs

@aravind-kvs aravind-kvs commented Jun 15, 2026

Copy link
Copy Markdown

JIRA: https://issues.apache.org/jira/browse/KAFKA-20677

Problem

The existing testCannotSendToInternalTopic test was broken. It attempted
to cover case 2 (auto.create.topics.enable=false, topic exists) but
incorrectly created and then deleted the internal topic before sending,
accidentally testing the wrong scenario.

Changes

Replaced the broken test with four separate test cases covering all scenarios
when sending to an internal topic:

  1. auto.create.topics.enable=true, topic exists → InvalidTopicException
  2. auto.create.topics.enable=false, topic exists → InvalidTopicException
  3. auto.create.topics.enable=true, topic not exists → InvalidTopicException and topic gets auto-created
  4. auto.create.topics.enable=false, topic not exists → TimeoutException and topic is NOT created

Note on Case 4

The JIRA describes case 4 as throwing UnknownTopicOrPartitionException.
However, the actual broker behavior is to return UNKNOWN_TOPIC_OR_PARTITION
as a recoverable error, causing the producer to retry until TimeoutException.
The test reflects actual broker behavior.

Test

Ran the new test cases locally and all 4 passed:

./gradlew :clients:clients-integration-tests:test --tests "org.apache.kafka.clients.producer.ProducerFailureHandlingTest.testCannotSendToInternalTopic*"

Results: 4 tests completed, 0 failed
Reviewers: Chia-Ping Tsai chia7712@gmail.com, Ming-Yen Chung mingyen066@gmail.com

@github-actions github-actions Bot added triage PRs from the community tests Test fixes (including flaky tests) clients labels Jun 15, 2026
Replace broken testCannotSendToInternalTopic with four separate test cases
covering all scenarios when sending to an internal topic. The original test
incorrectly deleted the internal topic before sending, accidentally testing
the wrong scenario.
@aravind-kvs aravind-kvs force-pushed the KAFKA-20677-enhance-testCannotSendToInternalTopic branch from 9c96b0e to 490309c Compare June 15, 2026 07:38
@chia7712

Copy link
Copy Markdown
Member

@aravind-kvs thanks for this patch. However, this ticket is already assigned to someone else, so it would be good to ask before opening a PR. Otherwise, it is a bit of a waste to have two talented people working on the same thing

@aravind-kvs

Copy link
Copy Markdown
Author

@aravind-kvs thanks for this patch. However, this ticket is already assigned to someone else, so it would be good to ask before opening a PR. Otherwise, it is a bit of a waste to have two talented people working on the same thing

Thanks for the feedback!
I'll make sure to comment on the issue first before opening a PR next time. Happy to close this if the assignee is already working on it.

@mingyen066

Copy link
Copy Markdown
Collaborator

@aravind-kvs This was assigned to me, but since you've already opened a PR, you can take it — I've reassigned it to you. Please check with the assignee before opening a PR next time. I'll review the PR later.

@github-actions

Copy link
Copy Markdown

A label of 'needs-attention' was automatically added to this PR in order to raise the
attention of the committers. Once this issue has been triaged, the triage label
should be removed to prevent this automation from happening again.

@ClusterConfigProperty(key = OFFSETS_TOPIC_REPLICATION_FACTOR_CONFIG, value = "1")
})
public void testCannotSendToInternalTopicWhenAutoCreateTrueAndTopicNotExists(ClusterInstance clusterInstance) throws Exception {
clusterInstance.deleteTopic(Topic.GROUP_METADATA_TOPIC_NAME);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

clusterInstance.deleteTopic(Topic.GROUP_METADATA_TOPIC_NAME) is a no-op here — __consumer_offsets doesn't exist yet at this point, and deleteTopic discards the result without awaiting it. Looks like leftover from the old test; safe to drop.

@ClusterConfigProperty(key = OFFSETS_TOPIC_REPLICATION_FACTOR_CONFIG, value = "1")
})
public void testCannotSendToInternalTopicWhenAutoCreateFalseAndTopicNotExists(ClusterInstance clusterInstance) throws Exception {
clusterInstance.deleteTopic(Topic.GROUP_METADATA_TOPIC_NAME);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

ditto

@ClusterConfigProperty(key = AUTO_CREATE_TOPICS_ENABLE_CONFIG, value = "true")
})
public void testCannotSendToInternalTopicWhenAutoCreateTrueAndTopicExists(ClusterInstance clusterInstance) throws Exception {
// explicitly create __consumer_offsets to satisfy the "topic exists" precondition

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The four new tests repeat a lot of boilerplate — ...TrueAndTopicExists/...FalseAndTopicExists share nearly identical topic-creation code, and all four repeat the same send+assert block with only the expected exception differing. Worth extracting two helpers:

private void createInternalTopic(ClusterInstance clusterInstance) throws Exception {
    try (Admin admin = clusterInstance.admin()) {
        Map<String, String> topicConfig = clusterInstance.brokers().get(0)
                .groupCoordinator()
                .groupMetadataTopicConfigs();
        admin.createTopics(List.of(new NewTopic(Topic.GROUP_METADATA_TOPIC_NAME, 1, (short) 1).configs(topicConfig)));
        clusterInstance.waitTopicCreation(Topic.GROUP_METADATA_TOPIC_NAME, 1);
    }
}

private void assertSendToInternalTopicFails(ClusterInstance clusterInstance, Class<? extends Throwable> expectedCause) {
    try (Producer<byte[], byte[]> producer = clusterInstance.producer(producerConfig(1))) {
        Exception thrown = assertThrows(ExecutionException.class,
                () -> producer.send(new ProducerRecord<>(
                        Topic.GROUP_METADATA_TOPIC_NAME, "test".getBytes(), "test".getBytes())).get());
        assertInstanceOf(expectedCause, thrown.getCause(),
                () -> "Expected " + expectedCause.getSimpleName() + " but got " + thrown.getCause());
    }
}

Then each test shrinks to:

@ClusterTest(serverProperties = {@ClusterConfigProperty(key = AUTO_CREATE_TOPICS_ENABLE_CONFIG, value = "true")})
public void testCannotSendToInternalTopicWhenAutoCreateTrueAndTopicExists(ClusterInstance clusterInstance) throws Exception {
    createInternalTopic(clusterInstance);
    assertSendToInternalTopicFails(clusterInstance, InvalidTopicException.class);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-approved clients needs-attention tests Test fixes (including flaky tests) triage PRs from the community

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants