-
Notifications
You must be signed in to change notification settings - Fork 14.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
KAFKA-17587 Refactor test infrastructure #18602
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mumrah thanks for this refactor. I run the command ./gradlew cleanTest test-common:test-common-runtime:test
and it results in some error below:
Gradle Test Run :test-common:test-common-runtime:test > Gradle Test Executor 109 > TestKitNodeTest > testSecurityProtocol(SecurityProtocol) > initializationError FAILED
java.lang.IllegalStateException: Please annotate test methods with @ClusterTemplate, @ClusterTest, or @ClusterTests when using the ClusterTestExtensions provider
at org.apache.kafka.common.test.junit.ClusterTestExtensions.provideTestTemplateInvocationContexts(ClusterTestExtensions.java:147)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:273)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
@@ -79,7 +79,7 @@ a JUnit extension called `ClusterTestExtensions` which knows how to process thes | |||
invocations. Test classes that wish to make use of these annotations need to explicitly register this extension: | |||
|
|||
```scala | |||
import org.apache.kafka.common.test.api.ClusterTestExtensions | |||
import org.apache.kafka.common.test.junit.ClusterTestExtensions | |||
|
|||
@ExtendWith(value = Array(classOf[ClusterTestExtensions])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't need it, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. I'll update these docs.
import org.apache.kafka.common.config.SaslConfigs | ||
import org.apache.kafka.common.config.internals.BrokerSecurityConfigs | ||
import org.apache.kafka.common.message.SaslHandshakeRequestData | ||
import org.apache.kafka.common.protocol.{ApiKeys, Errors} | ||
import org.apache.kafka.common.requests.{ApiVersionsRequest, ApiVersionsResponse, SaslHandshakeRequest, SaslHandshakeResponse} | ||
import org.apache.kafka.common.security.auth.SecurityProtocol | ||
import org.apache.kafka.common.test.ClusterInstance | ||
import org.apache.kafka.common.test.junit.ClusterTestExtensions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we remove @ExtendWith(value = Array(classOf[ClusterTestExtensions]))
from this class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, good catch 😄 I left this one here intentionally to make sure it still worked if people explicitly add the annotation in the future
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well this was a bad choice for a test since this one is disabled. I tried it locally on another test and verified keeping the annotation is harmless
@chia7712 I think this commit should fix the initialization issue. Since SPI is being used, it loads the extension for all tests. We need some additional filtering to not apply the ClusterTest logic to regular tests. |
Thanks for the PR. A couple of questions:
These questions will help validate the names we have chosen. |
I think that would make sense. There's quite a bit of utility test code that could be kept at Java 11. In this case we might consider
I was thinking |
Makes sense to use the The only open question for me is the |
Hm, yea.. I see what you mean. Here are some ideas for alternatives to test-common-api
|
Since you're calling one |
I like "internal-api" 👍 |
...common/test-common-internal-api/src/main/java/org/apache/kafka/common/test/api/Defaults.java
Outdated
Show resolved
Hide resolved
testImplementation project(':test-common:test-common-api') | ||
testImplementation project(':test-common:test-common-runtime') | ||
testImplementation project(':test-common:test-common-internal-api') | ||
testImplementation project(':test-common:test-common-util') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems clients
, core
, and connect:runtime
need this because they need to import Flaky
. Maybe we can move Flaky
to test-common:test-common-internal-api
? test-common:test-common-internal-api
can be under java 11 if we move server-common
out of test-common:test-common-internal-api
. test-common:test-common-internal-api
is using enum classes of server-common
so they can be replaced by string easily. With that change, we can move AutoQuarantinedTestFilter
and QuarantinedPostDiscoveryFilter
to test-common:test-common-runtime
to remove the test-common:test-common-util
also
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me see if I understand your proposal
- Refactor "test-common-internal-api" to not depend on ":server-common"
- Move "test-common-internal-api" to Java 11
- Move
@Flaky
to the "test-common-internal-api" - Remove "test-common-util"
I think this would make sense, except that Java 11 modules like ":clients" cannot bring a runtime dependency with a newer java version. I tried this and got:
* What went wrong:
Could not determine the dependencies of task ':clients:test'.
> Could not resolve all dependencies for configuration ':clients:testRuntimeClasspath'.
> Could not resolve project :test-common:test-common-runtime.
Required by:
project :clients
> Dependency resolution is looking for a library compatible with JVM runtime version 11, but 'project :test-common:test-common-runtime' is only compatible with JVM runtime version 17 or newer.
Do you know of a way around this?
Since test-common-internal-api is meant to be the abstraction for the test infrastructure offered by test-common-runtime, it doesn't make sense to include one without the other. It might be confusing for developers if @ClusterTest
was available to import, but was not actually usable.
If we want the client integration tests to be moved out of core, we should create a ":clients:integration-tests" module that is Java 17 and move the tests there (similar to what streams does).
I expect "test-common-util" will grow to include helper/common test methods. We can probably combine the most of the various TestUtils into a single Java 11 utils class under this module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since test-common-internal-api is meant to be the abstraction for the test infrastructure offered by test-common-runtime, it doesn't make sense to include one without the other. It might be confusing for developers if @clustertest was available to import, but was not actually usable.
Yes, you're right. Let's keep the current structure.
@mumrah could you please fix the conflicts? Additionally, should we backport it to 4.0? |
@chia7712 yea I can backport it. That will make it easier to backport test changes during the ongoing 4.0.0 release and down the road in 4.0.x |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This patch reorganizes our test infrastructure into three Gradle modules: ":test-common:test-common-internal-api" is now a minimal dependency which exposes interfaces and annotations only. It has one project dependency on server-common to expose commonly used data classes (MetadataVersion, Feature, etc). Since this pulls in server-common, this module is Java 17+. It cannot be used by ":clients" or other Java 11 modules. ":test-common:test-common-util" includes the auto-quarantined JUnit extension. The @flaky annotation has been moved here. Since this module has no project dependencies, we can add it to the Java 11 list so that ":clients" and others can utilize the @flaky annotation ":test-common:test-common-runtime" now includes all of the test infrastructure code (TestKitNodes, etc). This module carries heavy dependencies (core, etc) and so it should not normally be included as a compile-time dependency. In addition to this reorganization, this patch leverages JUnit SPI service discovery so that modules can utilize the integration test framework without depending on ":core". This will allow us to start moving integration tests out of core and into the appropriate sub-module. This is done by adding ":test-common:test-common-runtime" as a testRuntimeOnly dependency rather than as a testImplementation dependency. A trivial example was added to QuorumControllerTest to illustrate this. Reviewers: Ismael Juma <[email protected]>, Chia-Ping Tsai <[email protected]>
This patch reorganizes our test infrastructure into three Gradle modules:
":test-common:test-common-internal-api" is now a minimal dependency which exposes interfaces and annotations only. It has one project dependency on server-common to expose commonly used data classes (MetadataVersion, Feature, etc). Since this pulls in server-common, this module is Java 17+. It cannot be used by ":clients" or other Java 11 modules.
":test-common:test-common-util" includes the auto-quarantined JUnit extension. The
@Flaky
annotation has been moved here. Since this module has no project dependencies, we can add it to the Java 11 list so that ":clients" and others can utilize the@Flaky
annotation":test-common:test-common-runtime" now includes all of the test infrastructure code (TestKitNodes, etc). This module carries heavy dependencies (core, etc) and so it should not normally be included as a compile-time dependency.
In addition to this reorganization, this patch leverages JUnit SPI service discovery so that modules can utilize the integration test framework without depending on ":core". This will allow us to start moving integration tests out of core and into the appropriate sub-module. This is done by adding ":test-common:test-common-runtime" as a testRuntimeOnly dependency rather than as a testImplementation dependency. A trivial example was added to QuorumControllerTest to illustrate this.
This patch does not expose ClusterInstance through the SPI since it has many direct dependencies on core. A stripped-down version of ClusterInstance that can be used by non-core modules remains as future work.