This is an automated email from the ASF dual-hosted git repository.
lzljs3620320 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git
The following commit(s) were added to refs/heads/master by this push:
new 22758869fd [test] Fix flaky testDlfStSTokenPathAuth (#7309)
22758869fd is described below
commit 22758869fd7dc257fcd862e609bb2e49727ed28c
Author: Dapeng Sun(孙大鹏) <[email protected]>
AuthorDate: Thu Feb 26 16:46:42 2026 +0800
[test] Fix flaky testDlfStSTokenPathAuth (#7309)
Fix flaky `testDlfStSTokenPathAuth` (and `testDlfStSTokenAuth`) in
`MockRESTCatalogTest`.
The mock server and the client each called `Instant.now()` independently
to compute the DLF signature. When the two calls straddled a second
boundary, the formatted `x-dlf-date` diverged, causing a signature
mismatch and `NotAuthorizedException`.
Introduce a test-only `TestDLFAuthProvider` that reuses the sign headers
already present in the incoming request instead of generating a fresh
timestamp, so the server-side verification always uses the same
timestamp as the client.
---
.../apache/paimon/rest/MockRESTCatalogTest.java | 51 +++++++++++++++++++---
1 file changed, 45 insertions(+), 6 deletions(-)
diff --git
a/paimon-core/src/test/java/org/apache/paimon/rest/MockRESTCatalogTest.java
b/paimon-core/src/test/java/org/apache/paimon/rest/MockRESTCatalogTest.java
index 5d4f8dfc46..70380c2163 100644
--- a/paimon-core/src/test/java/org/apache/paimon/rest/MockRESTCatalogTest.java
+++ b/paimon-core/src/test/java/org/apache/paimon/rest/MockRESTCatalogTest.java
@@ -38,6 +38,7 @@ import org.apache.paimon.rest.auth.AuthProviderEnum;
import org.apache.paimon.rest.auth.BearTokenAuthProvider;
import org.apache.paimon.rest.auth.DLFAuthProvider;
import org.apache.paimon.rest.auth.DLFDefaultSigner;
+import org.apache.paimon.rest.auth.DLFToken;
import org.apache.paimon.rest.auth.DLFTokenLoader;
import org.apache.paimon.rest.auth.DLFTokenLoaderFactory;
import org.apache.paimon.rest.auth.RESTAuthParameter;
@@ -124,9 +125,8 @@ class MockRESTCatalogTest extends RESTCatalogTest {
String securityToken = "securityToken" + UUID.randomUUID();
String uri = "https://cn-hangzhou-vpc.dlf.aliyuncs.com";
String region = "cn-hangzhou";
- this.authProvider =
- DLFAuthProvider.fromAccessKey(
- akId, akSecret, securityToken, uri, region,
DLFDefaultSigner.IDENTIFIER);
+ DLFToken dlfToken = new DLFToken(akId, akSecret, securityToken, null);
+ this.authProvider = new TestDLFAuthProvider(dlfToken, uri, region);
this.authMap =
ImmutableMap.of(
RESTCatalogOptions.TOKEN_PROVIDER.key(),
AuthProviderEnum.DLF.identifier(),
@@ -150,9 +150,8 @@ class MockRESTCatalogTest extends RESTCatalogTest {
new Options(
ImmutableMap.of(
RESTCatalogOptions.DLF_TOKEN_PATH.key(), tokenPath)));
- this.authProvider =
- DLFAuthProvider.fromTokenLoader(
- tokenLoader, uri, region, DLFDefaultSigner.IDENTIFIER);
+ DLFToken dlfToken = tokenLoader.loadToken();
+ this.authProvider = new TestDLFAuthProvider(dlfToken, uri, region);
this.authMap =
ImmutableMap.of(
RESTCatalogOptions.TOKEN_PROVIDER.key(),
AuthProviderEnum.DLF.identifier(),
@@ -456,4 +455,44 @@ class MockRESTCatalogTest extends RESTCatalogTest {
}
return new RESTCatalog(CatalogContext.create(options));
}
+
+ private static String extractHost(String uri) {
+ String withoutProtocol = uri.replaceFirst("^https?://", "");
+ int pathIndex = withoutProtocol.indexOf('/');
+ return pathIndex >= 0 ? withoutProtocol.substring(0, pathIndex) :
withoutProtocol;
+ }
+
+ /**
+ * A test-only {@link DLFAuthProvider} variant used on the mock server
side. Unlike the
+ * production {@link DLFAuthProvider#mergeAuthHeader} which generates a
fresh timestamp via
+ * {@link java.time.Instant#now()}, this subclass reuses the sign headers
already present in the
+ * incoming request to recompute the expected authorization. This avoids
flaky signature
+ * mismatches when the client's signing time and the server's verification
time cross a second
+ * boundary.
+ */
+ private static class TestDLFAuthProvider extends DLFAuthProvider {
+
+ private final DLFDefaultSigner signer;
+ private final String host;
+
+ TestDLFAuthProvider(DLFToken token, String uri, String region) {
+ super(null, token, uri, region, DLFDefaultSigner.IDENTIFIER);
+ this.signer = new DLFDefaultSigner(region);
+ this.host = extractHost(uri);
+ }
+
+ @Override
+ public Map<String, String> mergeAuthHeader(
+ Map<String, String> baseHeader, RESTAuthParameter
restAuthParameter) {
+ try {
+ String authorization =
+ signer.authorization(restAuthParameter, token, host,
baseHeader);
+ Map<String, String> headersWithAuth = new
HashMap<>(baseHeader);
+ headersWithAuth.put(DLF_AUTHORIZATION_HEADER_KEY,
authorization);
+ return headersWithAuth;
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to verify authorization
header", e);
+ }
+ }
+ }
}