-
Notifications
You must be signed in to change notification settings - Fork 161
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
Convert main integration tests into reusable blackbox tests #590
base: main
Are you sure you want to change the base?
Conversation
...n-tests/src/main/java/org/apache/polaris/service/it/ext/PolarisIntegrationTestExtension.java
Outdated
Show resolved
Hide resolved
this.realm = realm; | ||
this.server = server; | ||
|
||
ObjectMapper mapper = new ObjectMapper(); |
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.
Couldn't we create this client outside of the extension? In Quarkus, it would be better to inject the ObjectMapper
that's used server-side, but it won't be available for injection here.
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.
Oh sorry, this is for blackbox testing only. My bad.
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.
Unresolving this conversation because it turns out the Server
impl will need access to an ObjectMapper
. We can't access the one created by Quarkus because this is a black box test. But we may be able to share the object mapper created here with the server impl. This is minor though, for now my Quarkus server impl is simply creating another ObjectMapper
identical to this one.
|
||
@Override | ||
public URI baseUri() { | ||
return URI.create(String.format("http://localhost:%d", ext.getLocalPort())); |
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.
The old TestEnv
extension could modify this to hit a remote Polaris server afaict.
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.
My thinking was that remote cases would have their own Server Manager impl.
The old TestEnvironmentExtension
is too intertwined with existing whitebox DW extensions... I though we'd have a totally new interface and gradually migrate TestEnvironmentExtension
use cases to it.
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.
To clarify: if a remote server is available outside the JUnit5 lifecycle, one can simply make an Server Manager impl. that returned a pre-configured URI and Realm, and then use a JUnit5 "suite" to execute tests from the new test 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.
I like the proposal for remote tests to implement their own PolarisServerManager
. Otherwise, the concern for one use case ends up cluttering the code for the other use case.
|
||
@Override | ||
public ClientCredentials adminCredentials() { | ||
return new ClientCredentials("test-admin", "test-secret"); |
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.
The old TestEnv
extension used to append a "test ID" to the generated credentials afaict.
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.
I'm not sure that the purpose of that append was, TBH 😅 I believe having one admin user per realm (as in this case) is sufficient.
Currently, there's only one realm for Server Manager instance, so other implementations can chose to use unique admin user names, if they prefer.
|
||
AuthToken adminToken(); | ||
|
||
ClientCredentials adminCredentials(); |
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.
Where has the Snowman
user gone?
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.
Into the Nothing. The Server Manager provides "root" (admin) credentials. Tests create extra principals when they need to.
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.
I am fine with that, although my impression was that the snowman user was introduced precisely to avoid using the root user for all admin tasks. Let's wait and see what @andrew4699 says.
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.
I moved the work done by the SnowmanCredentialsExtension
into specific test classes... hopefully maintaining the same functionality as before (the "snowman" principals used to be created using "admin" tokens too). Those can be found by searching for "snowman" in Principal names in the new test code. I believe explicit principal manipulation by test code is easier to follow and maintain than if it is done by a test extension.
The principal and role manipulation logic moved to the methods in the new ManagementApi
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.
The intention of the SnowmanExtension
was simply to have a non-root user easily available so that all the tests didn't just run everything as root, thus missing issues that would be faced by non-root users. If snowman
is just as easy to access without the extension, that's fine with me.
8b7325e
to
90ee9d0
Compare
I noticed that 3 other tests use the Dropwizard extension and could be considered as "integration" tests:
We could create "black-box" versions of those while still keeping the "white-box" ones around, wdyt? |
.stream() | ||
.collect( | ||
Collectors.toMap(PolarisFeatureConfig::name, PolarisFeatureConfig::value)); | ||
return new Env(manager.realm(), manager.startServer(featureConfig)); |
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.
I'm struggling to adapt this to Quarkus. In a Quarkus test (integration or not), the application will be running already when the extension is executed, and it's not possible to change the feature configs at that moment. The only way to change the application config is through a QuarkusTestProfile
afaik. I don't think we can use a QuarkusTestResourceLifecycleManager
to launch the application itself on demand; that's intended for dependent resources like databases etc. I think the @PolarisFeatureConfig
annotation would eventually go away completely with Quarkus.
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 we this can be refactored to fit Quarkus better
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.
On a closer look at the test that use @PolarisFeatureConfig
I tend to think that those tests are an overkill to have at the integration test level. The test variations merely check how configuration keys are resolved between catalog properties, server config and default values. I believe that part can be done by a unit test.
I'll try and refactor the blackbox tests to rely only on default config settings.
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.
I think I'm going to make a separate refactoring PR for tests currently using @PolarisFeatureConfig
in order to push the config behaviour concerns to the unit test level, but keep blackbox test concentrating on user-visible functionality with default config.
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.
#607 converts the tests that relied on config overrides to proper unit tests (those will be outside the scope of this PR if 607 is merged)
|
|
Indeed I haven't thought about interference when the server is shared. In this case let's leave |
Another related unit test refactoring: #612 |
90ee9d0
to
854885d
Compare
@adutra : I've rebased and resolved conflicts. Application log is now checked in Config overrides are gone. I hope the backbox tests are reusable in Quarkus now. |
integration-tests/src/main/java/org/apache/polaris/service/it/ext/PolarisServerManager.java
Outdated
Show resolved
Hide resolved
...n-tests/src/main/java/org/apache/polaris/service/it/ext/PolarisIntegrationTestExtension.java
Outdated
Show resolved
Hide resolved
920a2fa
to
bb4b6fb
Compare
03d3890
to
3ed1873
Compare
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.
Making good progress! With the latest changes the test at least are executed with Quarkus. I'm seeing a few failures though.
...ests/src/main/java/org/apache/polaris/service/it/test/PolarisApplicationIntegrationTest.java
Outdated
Show resolved
Hide resolved
...ests/src/main/java/org/apache/polaris/service/it/test/PolarisApplicationIntegrationTest.java
Outdated
Show resolved
Hide resolved
...rc/main/java/org/apache/polaris/service/it/test/PolarisManagementServiceIntegrationTest.java
Outdated
Show resolved
Hide resolved
07b6a08
to
d3bc035
Compare
e50c564
to
f6d2a8c
Compare
f6d2a8c
to
354f4f3
Compare
...rc/main/java/org/apache/polaris/service/it/test/PolarisManagementServiceIntegrationTest.java
Show resolved
Hide resolved
ad84b95
to
09dcd88
Compare
@andrew4699 : I propose we merge this PR and address your points in follow-up PRs if you do not mind :) Would this be ok? |
09dcd88
to
198def0
Compare
It's great that we're refactoring this and I think it's going in a good direction, my main concern is that this is a breaking change. Today, you can provide your own HTTP client. If this change is merged as-is, you won't be able to. |
* Introduce new module: `integration-tests` to contain the test code for backbox integration tests * Refactors existing main integration tests to avoid relying on Dropwizard internals. * Add new test extension for managing the test environment with custom server managers discovered via `ServiceLoader` * Use Dropwizard test extentions for the reference implementation of `PolarisServerManager`. Custom server builds can provide their own environment-specific implementations. * Add helper classes for REST API (Management and Catalog) * Run reusable tests by extending them in the DW module. Using test suites is also possible, but it only uses one gradle test worker, so test parallelism is reduced. At the same time running tests in parallel withing the same JVM using JUnit5 threads currently leads to errors.
Use Awaitility to make sure the expected response code is received within a reasonable timeout (1 min).
198def0
to
7c44ea3
Compare
@andrew4699 : does the commit entitled |
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.
Please ignore outdated comments - there was refactoring after my initial review, which I forgot to publish :)
"grant_type", | ||
"client_credentials", | ||
"scope", | ||
"PRINCIPAL_ROLE:ALL", |
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.
Can we make scope an optional argument (default to PRINCIPAL_ROLE:ALL
) so tests can verify sub-scoped tokens?
|
||
AuthToken adminToken(); | ||
|
||
ClientCredentials adminCredentials(); |
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.
The intention of the SnowmanExtension
was simply to have a non-root user easily available so that all the tests didn't just run everything as root, thus missing issues that would be faced by non-root users. If snowman
is just as easy to access without the extension, that's fine with me.
|
||
import java.net.URI; | ||
|
||
public interface Server extends AutoCloseable { |
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.
Can we add javadocs to public classes an interfaces? It's really helpful to see, at a glance, what classes purpose some of these classes are intended to serve.
config.entrySet().stream() | ||
.map((e) -> ConfigOverride.config(e.getKey(), e.getValue())) | ||
.toList() | ||
.toArray(new ConfigOverride[0]); |
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.
nit: I tend to prefer Stream.toArray(ConfigOverride[]::new)
for this purpose
|
||
@Override | ||
public String realmId() { | ||
return TEST_REALM; |
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.
Most of the tests today create a distinct realm per test so that there's no overlap for roles or catalogs, etc. It also means that a test that fails to clean up doesn't leave clutter that effects other tests.
|
||
@Override | ||
public URI baseUri() { | ||
return URI.create(String.format("http://localhost:%d", ext.getLocalPort())); |
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.
I like the proposal for remote tests to implement their own PolarisServerManager
. Otherwise, the concern for one use case ends up cluttering the code for the other use case.
// Create a new CatalogRole that has CATALOG_MANAGE_CONTENT and CATALOG_MANAGE_ACCESS | ||
String catalogRoleName = "custom-admin"; | ||
createCatalogRole(catalog.getName(), catalogRoleName); |
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.
Why create a custom admin role? The service_admin already has the default catalog admin role that was created when the Catalog was created.
new ClientCredentials( | ||
principal.getCredentials().getClientId(), | ||
principal.getCredentials().getClientSecret(), | ||
"dummy-principal")); |
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.
use the principal name?
Introduce new module:
integration-tests
to contain the test code for backbox integration testsRefactors existing main integration tests to avoid relying on Dropwizard internals.
Add new test extension for managing the test environment with custom server managers discovered via
ServiceLoader
Use Dropwizard test extentions for the reference implementation of
PolarisServerManager
. Custom server builds can provide their own environment-specific implementations.Add helper classes for REST API (Management and Catalog)
Run reusable tests by extending them in the DW module. Using test suites is also possible, but it only uses one gradle test worker, so test parallelism is reduced. At the same time running tests in parallel withing the same JVM using JUnit5 threads currently leads to errors.
This PR is meant to be the first step towards #524. Subsequent PRs can certainly enhance the testing framework more.