prosgarz35 commented on PR #3197:
URL: https://github.com/apache/james-project/pull/3197#issuecomment-5792064937

   # Detailed Test Suite & Verification Report: File BlobStore Folder Hierarchy
   
   ## Overview
   
   This document provides a comprehensive breakdown of the test suite 
implemented, verified, and used to validate the **File BlobStore Folder 
Hierarchy** enhancement in Apache James.
   
   Following review feedback from lead committer Benoit Tellier (`chibenwa`), 
the solution leverages the existing folder hierarchy strategy 
(`MinIOGenerationAwareBlobId`), which introduces `/` path separators into blob 
identifiers:
   ```
   <family>/<generation>/<c1>/<c2>/<remaining-entropy>
   e.g.: 1/628/M/f/emXjFVhqwZi9eYtmKc5A
   ```
   This architecture naturally creates nested directory structures directly 
through `new File(bucketRoot, blobId.asString())`, avoiding directory bloat 
(100+ million objects safely partitioned across subdirectories).
   
   ---
   
   ## 1. Test Suite Modules & Executed Classes
   
   ### Module: `server/blob/blob-file`
   
   This module is the core implementation module for filesystem-based blob 
storage. The full test suite was executed using Apache Maven and JDK 25:
   
   ```bash
   mvn test -pl server/blob/blob-file
   ```
   
   #### Results Summary:
   * **Total Tests Run:** 339
   * **Failures:** 0
   * **Errors:** 0
   * **Skipped:** 0
   * **Build Status:** SUCCESS
   
   ---
   
   ## 2. Detailed Breakdown of Test Classes
   
   ### 2.1. `FileWithMinIOGenerationAwareBlobIdTest` (New Test Suite)
   * **File:** 
[`server/blob/blob-file/src/test/java/org/apache/james/blob/file/FileWithMinIOGenerationAwareBlobIdTest.java`](file:///C:/soft/git_blob/server/blob/blob-file/src/test/java/org/apache/james/blob/file/FileWithMinIOGenerationAwareBlobIdTest.java)
   * **Description:** Dedicated contract and integration test suite asserting 
`FileBlobStore` behavior when configured with 
`MinIOGenerationAwareBlobId.Factory`. Mirrors 
`S3WithMinIOGenerationAwareBlobIdTest` from `blob-s3`.
   * **Total Tests:** 77 tests
   
   #### Key Test Scenarios:
   1. **Blob Storage Contract Compliance (`BlobStoreContract` / 
`BucketBlobStoreContract`):**
      * Verifies standard blob store operations: `save`, `read`, `readBytes`, 
`readReactive`, `listBlobs`, `listBuckets`, `deleteBucket`.
      * Covers all storage policies: `LOW_COST`, `SIZE_BASED`, and 
`HIGH_PERFORMANCE`.
      * Tests payloads of various sizes: empty byte array, short strings, 11 KB 
streams, and large multi-megabyte streams (12 MB).
   
   2. **Folder Hierarchy Formatting & Entropy Generation:**
      * **Test:** `saveShouldReturnBlobIdOfString(BlobStore.StoragePolicy 
storagePolicy)`
      * **Assertion:**
        ```java
        assertThat(blobIdString).isEqualTo("1/628/M/f/emXjFVhqwZi9eYtmKc5A");
        assertThat(blobId).isEqualTo(blobIdFactory().parse(blobIdString));
        ```
      * **Validation:** Validates that saving a blob creates the expected 
generation prefix (`1/628/`) and the 2-level subfolder path (`M/f/`) with the 
truncated base64url content-addressed hash.
   
   3. **Pruning of Empty Parent Directories on Deletion:**
      * **Test:** `deleteShouldPruneEmptyParentDirectories()`
      * **Scenario:**
        * Saves a blob with `MinIOGenerationAwareBlobId`.
        * Verifies that the nested file `default/1/628/M/f/<hash>` and its 
intermediate directories exist on disk.
        * Invokes `fileBlobStoreDAO.delete(defaultBucketName, blobId)`.
        * Asserts that `blobFile.doesNotExist()` and `parentDir.doesNotExist()`.
      * **Importance:** Prevents intermediate directory accumulation when blobs 
are purged or collected by GC.
   
   4. **Backward & Forward Compatibility (`Nested class Compatible`):**
      * 
**`readWithMinIOGenerationAwareShouldSuccessWhenBlobWasStoredByGenerationAware`**:
        Verifies that a blob written using legacy flat `GenerationAwareBlobId` 
(`1_628_<hash>`) can be read seamlessly by a store running 
`MinIOGenerationAwareBlobId`.
      * 
**`listBlobsShouldReturnCorrectBlobIdWhenBlobWasStoredByGenerationAware`**:
        Verifies that `listBlobs()` returns the correct `BlobId` instance for 
legacy blobs, allowing data to be read without loss.
      * 
**`readWithGenerationAwareShouldSuccessWhenBlobWasStoredByMinIOGenerationAware`**:
        Verifies that a store configured with `GenerationAwareBlobId` can parse 
and read hierarchical blobs (`1/628/M/f/...`).
      * 
**`listBlobsShouldReturnCorrectBlobIdWhenBlobWasStoredByMinIOGenerationAware`**:
        Verifies cross-store listing compatibility between hierarchical and 
flat representations.
   
   ---
   
   ### 2.2. `FileBlobStoreTest` (Existing Regression Suite)
   * **File:** 
[`server/blob/blob-file/src/test/java/org/apache/james/blob/file/FileBlobStoreTest.java`](file:///C:/soft/git_blob/server/blob/blob-file/src/test/java/org/apache/james/blob/file/FileBlobStoreTest.java)
   * **Description:** Standard deduplication file blob store suite implementing 
`MetricableBlobStoreContract` and `DeduplicationBlobStoreContract`.
   * **Total Tests:** 85 tests (All passed)
   * **Coverage:** Validates deduplication, metrics collection, stream 
read/write pipelines, and basic blob store behaviors with `PlainBlobId`.
   
   ---
   
   ### 2.3. `FileBlobStorePassThroughTest` (Existing Regression Suite)
   * **File:** 
`server/blob/blob-file/src/test/java/org/apache/james/blob/file/FileBlobStorePassThroughTest.java`
   * **Description:** Tests the `PassThroughBlobStore` strategy on top of 
`FileBlobStoreDAO`.
   * **Total Tests:** 86 tests (All passed)
   * **Coverage:** Validates that passthrough mode without deduplication 
functions reliably without collisions.
   
   ---
   
   ### 2.4. `FileBlobStoreGCAlgorithmTest` (Garbage Collection Suite)
   * **File:** 
[`server/blob/blob-file/src/test/java/org/apache/james/blob/file/FileBlobStoreGCAlgorithmTest.java`](file:///C:/soft/git_blob/server/blob/blob-file/src/test/java/org/apache/james/blob/file/FileBlobStoreGCAlgorithmTest.java)
   * **Description:** Verifies Bloom filter GC algorithm contracts 
(`BloomFilterGCAlgorithmContract`) using `FileBlobStoreDAO`.
   * **Total Tests:** 23 tests (All passed)
   * **Coverage:** Generation awareness, orphan detection, reference tracking, 
and multiple GC cycles.
   
   ---
   
   ### 2.5. `FileBlobStoreDAOTest` (DAO Unit Suite)
   * **File:** 
[`server/blob/blob-file/src/test/java/org/apache/james/blob/file/FileBlobStoreDAOTest.java`](file:///C:/soft/git_blob/server/blob/blob-file/src/test/java/org/apache/james/blob/file/FileBlobStoreDAOTest.java)
   * **Description:** Unit and integration contract tests for `BlobStoreDAO` 
and extended file metadata attribute operations 
(`MetadataAwareBlobStoreDAOContract`).
   * **Total Tests:** 68 tests (All passed)
   * **Coverage:** User-defined file attribute views (XATTRs), reactive and 
blocking streams, atomic file movement via temporary files, and bucket deletion 
idempotency.
   
   ---
   
   ## 3. Module: `server/container/guice/blob/deduplication-gc`
   
   * **File Modified:** 
[`server/container/guice/blob/deduplication-gc/src/main/java/org/apache/james/modules/blobstore/BlobDeduplicationGCModule.java`](file:///C:/soft/git_blob/server/container/guice/blob/deduplication-gc/src/main/java/org/apache/james/modules/blobstore/BlobDeduplicationGCModule.java)
   * **Compilation & Checkstyle Status:**
     ```bash
     mvn test-compile -pl server/container/guice/blob/deduplication-gc
     ```
     * `BUILD SUCCESS` (10 goals executed, 0 checkstyle violations).
   * **Logic Verified:**
     Guice provider `generationAwareBlobIdFactory` resolves the active mode 
using the prioritized fallback:
     ```java
     boolean compatibilityModeActivated = 
Optional.ofNullable(System.getProperty("james.blobstore.folder.hierarchy"))
         .or(() -> 
Optional.ofNullable(System.getProperty("james.s3.minio.compatibility.mode")))
         .map(Boolean::parseBoolean)
         .orElse(false);
     ```
     Returns `MinIOGenerationAwareBlobId.Factory` when enabled, or 
`GenerationAwareBlobId.Factory` when disabled.
   
   ---
   
   ## 4. Configuration & Documentation Verification
   
   ### 4.1. Sample Configuration (`server/apps/postgres-app`)
   * **File:** 
[`server/apps/postgres-app/sample-configuration/jvm.properties`](file:///C:/soft/git_blob/server/apps/postgres-app/sample-configuration/jvm.properties)
   * **Added Property:**
     ```properties
     # Enable folder hierarchy across subdirectories for blob storage (S3/MinIO 
and FileBlobStore) to avoid directory bloat
     james.blobstore.folder.hierarchy=true
     ```
   
   ### 4.2. Documentation (`docs/modules/servers`)
   * **File:** 
[`docs/modules/servers/partials/configure/blobstore.adoc`](file:///C:/soft/git_blob/docs/modules/servers/partials/configure/blobstore.adoc)
   * **Anchor Preserved:** `[[_improve_listing_support_for_minio]]` to 
guarantee that existing URLs and permalinks (such as 
`blobstore.html#_improve_listing_support_for_minio`) remain valid.
   * **Content:** Accurately documents folder hierarchy benefits for both MinIO 
and `FileBlobStore`, the new property alias, default enablement in the Postgres 
distribution, and backward-compatible legacy property support.
   
   ---
   
   ## 5. Summary Matrix
   
   | Test Suite / Area | Tests Run | Result | Key Capabilities Verified |
   | :--- | :---: | :---: | :--- |
   | `FileWithMinIOGenerationAwareBlobIdTest` | 77 | **PASS** | 
Sharding/hierarchy formatting, parent pruning, cross-compatibility |
   | `FileBlobStoreTest` | 85 | **PASS** | Deduplication, content hashing, 
metric wrappers |
   | `FileBlobStorePassThroughTest` | 86 | **PASS** | Passthrough streaming 
without deduplication |
   | `FileBlobStoreDAOTest` | 68 | **PASS** | Atomic replace, XATTR metadata, 
bucket lifecycle |
   | `FileBlobStoreGCAlgorithmTest` | 23 | **PASS** | Bloom filter garbage 
collection cycles |
   | **Total `blob-file` Suite** | **339** | **PASS** | **100% test pass rate** 
|
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to