From e0243e31c59a4b458e1719b52ed45d53333f9bb8 Mon Sep 17 00:00:00 2001 From: Marko Topolnik Date: Fri, 11 Sep 2026 11:01:28 +0200 Subject: [PATCH] Make token-store rename retry test deterministic Add a private per-call retry hook so the test restores directory write permissions after a real denied rename on the calling thread. Assert that exactly one retry completes the atomic replacement and consumes the temporary file. Remove the helper thread and its scheduling dependency on the short retry budget. Keep production retry limits and interrupt handling unchanged, and update the test's platform-scope comments. Validation: all 90 FileTokenStoreTest tests pass through Maven on macOS arm64 with Java 8 and Java 25. --- .../client/cutlass/auth/FileTokenStore.java | 8 ++++ .../test/cutlass/auth/FileTokenStoreTest.java | 40 ++++++------------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/core/src/main/java/io/questdb/client/cutlass/auth/FileTokenStore.java b/core/src/main/java/io/questdb/client/cutlass/auth/FileTokenStore.java index 489ef213..cde281bb 100644 --- a/core/src/main/java/io/questdb/client/cutlass/auth/FileTokenStore.java +++ b/core/src/main/java/io/questdb/client/cutlass/auth/FileTokenStore.java @@ -987,6 +987,10 @@ private static void releaseProcessLock(String identity) { private static void replaceTarget(Path tmp, Path target) throws IOException { + replaceTarget(tmp, target, null); + } + + private static void replaceTarget(Path tmp, Path target, Runnable beforeRetryForTesting) throws IOException { // atomically rename tmp over target. On Windows a concurrent reader in any process holding target open // can make the rename fail transiently with AccessDeniedException (a sharing violation); retry a few // times on a short backoff before giving up, so a routine read/write overlap does not needlessly degrade @@ -1010,6 +1014,10 @@ private static void replaceTarget(Path tmp, Path target) throws IOException { Thread.currentThread().interrupt(); break; } + // Tests clear a real permission denial before the next move attempt. + if (beforeRetryForTesting != null) { + beforeRetryForTesting.run(); + } } try { Files.move(tmp, target, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING); diff --git a/core/src/test/java/io/questdb/client/test/cutlass/auth/FileTokenStoreTest.java b/core/src/test/java/io/questdb/client/test/cutlass/auth/FileTokenStoreTest.java index 264c11b5..7d66ce3f 100644 --- a/core/src/test/java/io/questdb/client/test/cutlass/auth/FileTokenStoreTest.java +++ b/core/src/test/java/io/questdb/client/test/cutlass/auth/FileTokenStoreTest.java @@ -73,8 +73,7 @@ /** * Coverage for {@link FileTokenStore}. *

- * PLATFORM SCOPE. CI runs Linux only, so the store's Windows-motivated arms are covered here to the extent a - * POSIX host can reach them, and no further: + * PLATFORM SCOPE. POSIX hosts cover the store's Windows-motivated arms only to the extent described below: *