prosgarz35 opened a new pull request, #3228:
URL: https://github.com/apache/james-project/pull/3228
## Summary
This PR integrates **Google Jimfs** (`com.google.jimfs:jimfs:1.3.2`) into
Apache James test infrastructure and introduces a reusable JUnit 5 extension
(`JimfsExtension`) to drastically speed up file-related unit and integration
tests while eliminating native OS file locking issues (especially on Windows /
CI).
## Rationale & Problem Statement
Currently, many tests in Apache James that test configuration hierarchies,
MIME/RFC-822 stream parsing, or cryptographic certificates rely on disk-backed
temporary folders (`@TempDir`, `Files.createTempDirectory`, or
`TemporaryFolderExtension`).
On physical disks (and particularly under Windows or loaded CI builders like
Jenkins):
1. **I/O bottleneck & High latency:** Disk write/flush/read/delete cycles
are bounded by OS filesystem metadata flushes (10–15 MB/s on average with ~7 ms
per-operation latency).
2. **File locking & Flaky tests:** Native OS file locks frequently cause
`AccessDeniedException` during `@AfterEach` directory cleanup when background
threads hold file handles.
3. **OS-specific paths:** Windows paths (`\`) vs. UNIX POSIX paths (`/`) can
cause non-deterministic behavior across development environments and Linux CI
containers.
## Solution
We introduce Google Jimfs as an in-memory Java NIO FileSystem provider
conforming to POSIX/Unix filesystem semantics:
1. **`pom.xml` (root):**
- Added property `<jimfs.version>1.3.2</jimfs.version>`.
- Added `com.google.jimfs:jimfs` to `<dependencyManagement>` in exact
alphabetical order.
2. **`server/testing/pom.xml`:**
- Added `com.google.jimfs:jimfs` dependency (managed version).
3. **`server/testing/.../JimfsExtension.java`:**
- A lightweight, idiomatic JUnit 5 extension (`ParameterResolver`,
`BeforeEachCallback`, `AfterEachCallback`).
- Automatically provides an isolated in-memory Unix
`java.nio.file.FileSystem` or `java.nio.file.Path` to test methods.
- Non-intrusive: explicitly yields parameter resolution when `@TempDir`
is present to prevent collisions.
- Automatically closes and frees the in-memory filesystem upon test
completion (`afterEach`).
4. **`server/testing/.../JimfsExtensionTest.java`:**
- Full test coverage for parameter injection (`FileSystem` and `Path`).
- Validates memory-backed configuration parsing (`conf/smtpserver.xml`).
- Validates in-memory RFC-822 email payload stream processing.
- Verifies test isolation across executions.
- Includes a direct comparative benchmark against disk-backed `@TempDir`.
## Measured Benchmark Results
Benchmarking 1,000 cycles (create $\to$ write 64 KB payload $\to$ read $\to$
delete) directly within `JimfsExtensionTest`:
| Metric | Physical Disk (`@TempDir`) | Jimfs In-Memory (`JimfsExtension`) |
Improvement / Advantage |
| :--- | :--- | :--- | :--- |
| **Execution Time** | **8 280 ms** | **223 ms** | **37.1x faster** (97.3%
time saved) |
| **Throughput (Read + Write)** | **15.10 MB/s** | **560.54 MB/s** | **37.1x
higher throughput** |
| **Latency p50 (Median)** | **7 330.00 µs** (~7.3 ms) | **45.50 µs**
(~0.045 ms) | **161.1x lower latency** |
| **Latency p95** | **11 734.80 µs** (~11.7 ms) | **366.30 µs** (~0.36 ms) |
**32.0x lower latency** |
## Design Principles Adherence
- **KISS:** Zero custom annotation boilerplate required; simply
`@ExtendWith(JimfsExtension.class)` and inject standard `Path` or `FileSystem`.
- **DRY:** Centralized in `james-server-testing`, immediately available
across all 60+ server submodules without modifying individual POMs.
- **YAGNI:** Kept strictly minimal (85 LOC), avoiding premature abstractions
or changes to legacy `java.io.File` subsystems.
- **Checkstyle & Standards:** 0 Checkstyle violations, formatted per Apache
James rules, full ALv2 license headers included.
--
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]