From e6fcbef69495a300c43265e6e9c3809f7e2ecc83 Mon Sep 17 00:00:00 2001 From: vorotamoroz Date: Sun, 1 Nov 2026 10:42:27 +0000 Subject: [PATCH] Bound journal recovery fixture bucket names --- test/e2e-cli/test-journal-chunk-recovery.ts | 24 ++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/test/e2e-cli/test-journal-chunk-recovery.ts b/test/e2e-cli/test-journal-chunk-recovery.ts index cbddea52..345fbc88 100644 --- a/test/e2e-cli/test-journal-chunk-recovery.ts +++ b/test/e2e-cli/test-journal-chunk-recovery.ts @@ -15,6 +15,13 @@ function requireEnv(...keys: string[]): string { throw new Error(`Required env var is missing: ${keys.join(" or ")}`); } +function createJournalRecoveryBucketName(baseBucket: string, suffix: string): string { + const bucketSuffix = `journal-recovery-${suffix}`; + const maxBaseLength = 63 - bucketSuffix.length - 1; + const truncatedBase = baseBucket.slice(0, maxBaseLength).replace(/-+$/, ""); + return truncatedBase ? `${truncatedBase}-${bucketSuffix}` : bucketSuffix; +} + function createJournalFixture(): string { return [ "Journal chunk recovery fixture: UTF-8, newlines, and backslashes.\n", @@ -32,7 +39,7 @@ async function runScenario(encrypt: boolean): Promise { const minioEndpoint = requireEnv("MINIO_ENDPOINT", "minioEndpoint").replace(/\/$/, ""); const minioAccessKey = requireEnv("MINIO_ACCESS_KEY", "accessKey"); const minioSecretKey = requireEnv("MINIO_SECRET_KEY", "secretKey"); - const minioBucket = `${requireEnv("MINIO_BUCKET_NAME", "bucketName")}-journal-recovery-${suffix}`; + const minioBucket = createJournalRecoveryBucketName(requireEnv("MINIO_BUCKET_NAME", "bucketName"), suffix); const passphrase = "e2e-passphrase"; const fileContent = createJournalFixture(); const expectedBytes = Buffer.from(fileContent, "utf8"); @@ -184,6 +191,21 @@ async function runScenario(encrypt: boolean): Promise { } } +test("journal recovery bucket name construction stays within S3 limits", () => { + const ciBucket = createJournalRecoveryBucketName("livesync-test-bucket-ci", "enc0-1793522628122-62377"); + assert.ok(ciBucket.length <= 63, "The CI fixture must stay within the S3 bucket-name length limit"); + assert.match(ciBucket, /^[a-z0-9][a-z0-9-]*[a-z0-9]$/); + + const longBase = "a".repeat(63); + const unencryptedBucket = createJournalRecoveryBucketName(longBase, "enc0-1793522628122-62377"); + const encryptedBucket = createJournalRecoveryBucketName(longBase, "enc1-1793522628122-62377"); + assert.ok(unencryptedBucket.length <= 63); + assert.ok(encryptedBucket.length <= 63); + assert.match(unencryptedBucket, /^[a-z0-9][a-z0-9-]*[a-z0-9]$/); + assert.match(encryptedBucket, /^[a-z0-9][a-z0-9-]*[a-z0-9]$/); + assert.notEqual(unencryptedBucket, encryptedBucket, "Encryption scenarios should have distinct buckets"); +}); + test("journal chunk recovery through MINIO", async (t) => { await t.test("without encryption", async () => runScenario(false)); await t.test("with encryption", async () => runScenario(true));