Skip to content

Commit 7575b81

Browse files
authored
Merge pull request #2571 from adobe/junie-tasks-ctd
Junie tasks ctd
2 parents f2cfa63 + b3fcd06 commit 7575b81

26 files changed

+3350
-152
lines changed

.junie/guidelines.md

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,28 @@ Troubleshooting
3030
- SSL errors: trust self‑signed cert or switch to HTTP.
3131
- Docker errors: ensure Docker is running and you have permissions.
3232

33+
## Junie Operations Playbook (Critical)
34+
To ensure tests execute successfully in this environment, follow these strict rules:
35+
36+
- Default test scope: server module only. Do NOT run full project builds by default.
37+
- Use the test tool, not shell, to run tests:
38+
- Preferred: run_test on specific test files, e.g., "server/src/test/kotlin/com/adobe/testing/s3mock/store/ObjectStoreTest.kt".
39+
- One test by name: use run_test with full path and the test method name parameter.
40+
- Note: Directory-wide runs via run_test may not be supported in this environment. If you need to run all server tests, use Maven with: ./mvnw -pl server -DskipDocker test.
41+
- Avoid integration tests unless explicitly requested and Docker availability is confirmed. If requested, run via Maven lifecycle only.
42+
- If a build is required, prefer fast builds:
43+
- Use ./mvnw -pl server -am -DskipDocker clean test or rely on run_test which compiles as needed.
44+
- Only run ./mvnw clean install (full) when the user explicitly asks for a full build or cross-module changes demand it.
45+
- Never run mvnw verify without confirming Docker is available; if not available, add -DskipDocker.
46+
- Java 17+ required; if build fails due to JDK, report and stop, do not retry with different commands.
47+
- Decision tree:
48+
1) Need to validate changes in server module? -> run_test on one or more specific test files (fast path). If you truly need all server tests, use: ./mvnw -pl server -DskipDocker test.
49+
2) Need a specific server test? -> run_test on that file.
50+
3) Need ITs and Docker is confirmed? -> mvnw -pl integration-tests -am verify; otherwise skip.
51+
4) Need a build artifact quickly? -> mvnw clean install -DskipDocker.
52+
53+
Note: Always summarize which scope you ran and why.
54+
3355
3456

3557
## Build and Configuration Instructions
@@ -95,7 +117,7 @@ The main test base class for integration tests is `S3TestBase` which provides ut
95117

96118
The server module contains several types of tests:
97119

98-
1. **Controller Tests**: Use `@SpringBootTest` with `WebEnvironment.RANDOM_PORT` and `TestRestTemplate` to test HTTP endpoints. These tests mock the service layer using `@MockBean`.
120+
1. **Controller Tests**: Use `@SpringBootTest` with `WebEnvironment.RANDOM_PORT` and `TestRestTemplate` to test HTTP endpoints. These tests mock the service layer using `@MockitoBean`.
99121

100122
2. **Store Tests**: Use `@SpringBootTest` with `WebEnvironment.NONE` to test the data storage layer. These tests often use `@Autowired` to inject the component under test.
101123

@@ -213,20 +235,20 @@ The server module uses different testing approaches depending on what's being te
213235
1. **Controller Tests**:
214236
- Extend `BaseControllerTest` to inherit XML serialization setup
215237
- Use `@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)`
216-
- Use `@MockBean` to mock service dependencies
238+
- Use `@MockitoBean` to mock service dependencies
217239
- Inject `TestRestTemplate` to make HTTP requests to the controller
218240

219241
Example controller test:
220242

221243
```kotlin
222244
// BucketControllerTest.kt
223245
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
224-
@MockBean(classes = [BucketService::class, ObjectService::class, MultipartService::class])
246+
@MockitoBean(classes = [BucketService::class, ObjectService::class, MultipartService::class])
225247
internal class BucketControllerTest : BaseControllerTest() {
226248
@Autowired
227249
private lateinit var restTemplate: TestRestTemplate
228250

229-
@MockBean
251+
@MockitoBean
230252
private lateinit var bucketService: BucketService
231253

232254
@Test
@@ -254,7 +276,7 @@ Example store test:
254276
```kotlin
255277
// ObjectStoreTest.kt
256278
@SpringBootTest(classes = [StoreConfiguration::class], webEnvironment = SpringBootTest.WebEnvironment.NONE)
257-
@MockBean(classes = [KmsKeyStore::class, BucketStore::class])
279+
@MockitoBean(classes = [KmsKeyStore::class, BucketStore::class])
258280
internal class ObjectStoreTest : StoreTestBase() {
259281
@Autowired
260282
private lateinit var objectStore: ObjectStore
@@ -352,9 +374,13 @@ docker run -p 9090:9090 -p 9191:9191 -e debug=true -t adobe/s3mock
352374
### Recommended Development Workflow
353375

354376
1. Make changes to the code
355-
2. Run unit tests frequently to verify basic functionality
356-
- Unit tests should be run very frequently during development
357-
- No task can be declared as done without running a full Maven build successfully
358-
3. Run integration tests to verify end-to-end functionality
359-
4. Build the Docker image to verify packaging
360-
5. Test with your application to verify real-world usage
377+
2. Validate changes with server module tests first (fast path)
378+
- Use the run_test tool on "server/src/test" or on a specific test file/method.
379+
- Prefer this over invoking Maven directly; run_test compiles as needed.
380+
3. Only run a full Maven build when explicitly requested or when cross-module changes demand it
381+
- If building in this environment, prefer fast builds: ./mvnw -pl server -am -DskipDocker clean test
382+
- Do not run mvnw verify unless Docker is confirmed; otherwise add -DskipDocker
383+
4. Run integration tests only when Docker availability is confirmed and when explicitly requested
384+
- Execute via Maven lifecycle: ./mvnw -pl integration-tests -am verify (or add -DskipDocker to skip ITs)
385+
5. Optionally build the Docker image to verify packaging when needed
386+
6. Test with your application to verify real-world usage

CHANGELOG.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ Whenever a 3rd party library is updated, S3Mock will update it's MINOR version.
88
* [PLANNED - 5.x - RELEASE TBD](#planned---5x---release-tbd)
99
* [Planned changes](#planned-changes)
1010
* [CURRENT - 4.x - THIS VERSION IS UNDER ACTIVE DEVELOPMENT](#current---4x---this-version-is-under-active-development)
11-
* [4.8.0 - PLANNED](#480---planned)
11+
* [4.9.0 - PLANNED](#490---planned)
12+
* [4.8.0](#480)
1213
* [4.7.0](#470)
1314
* [4.6.0](#460)
1415
* [4.5.1](#451)
@@ -160,7 +161,7 @@ Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Jav
160161
* Version updates (build dependencies)
161162
* TBD
162163

163-
## 4.8.0 - PLANNED
164+
## 4.8.0
164165
Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Java integration.
165166

166167
* Features and fixes
@@ -171,14 +172,17 @@ Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Jav
171172
* Force convergence on the newest available transitive dependency versions.
172173
* Optimize file storage for large objects by using buffered streams.
173174
* Version updates (deliverable dependencies)
174-
*
175+
* Bump spring-boot.version from 3.5.4 to 3.5.5
176+
* Bump aws-v2.version from 2.32.7 to 2.32.23
175177
* Bump org.apache.commons:commons-compress from 1.27.1 to 1.28.0
176178
* Version updates (build dependencies)
177179
* Bump kotlin.version from 2.2.0 to 2.2.10
180+
* Bump aws.sdk.kotlin:s3-jvm from 1.4.125 to 1.5.19
178181
* Bump digital.pragmatech.testing:spring-test-profiler from 0.0.5 to 0.0.11
179182
* Bump com.puppycrawl.tools:checkstyle from 10.26.1 to 11.0.0
180-
* Bump github/codeql-action from 3.29.4 to 3.29.9
183+
* Bump github/codeql-action from 3.29.4 to 3.29.11
181184
* Bump actions/checkout from 4.2.2 to 5.0.0
185+
* Bump actions/setup-java from 4.7.1 to 5.0.0
182186

183187
## 4.7.0
184188
Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Java integration.
@@ -197,9 +201,11 @@ Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Jav
197201
* Version updates (build dependencies)
198202
* Bump aws.sdk.kotlin:s3-jvm from 1.4.109 to 1.4.125
199203
* Bump org.apache.maven.plugins:maven-enforcer-plugin from 3.6.0 to 3.6.1
204+
* Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.11.2 to 3.11.3
200205
* Bump org.mockito.kotlin:mockito-kotlin from 5.4.0 to 6.0.0
201206
* Bump step-security/harden-runner from 2.12.2 to 2.13.0
202-
* Bump github/codeql-action from 3.29.2 to 3.29.4
207+
* Bump github/codeql-action from 3.29.2 to 3.29.10
208+
* Bump actions/dependency-review-action from 4.7.1 to 4.7.2
203209

204210
## 4.6.0
205211
Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Java integration.

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,3 +837,6 @@ This project is licensed under the Apache V2 License. See [LICENSE](LICENSE) for
837837

838838
## Powered by
839839
[![IntelliJ IDEA logo.](https://resources.jetbrains.com/storage/products/company/brand/logos/IntelliJ_IDEA.svg)](https://jb.gg/OpenSourceSupport)
840+
841+
## Star History
842+
[![Star History Chart](https://api.star-history.com/svg?repos=adobe/S3Mock&type=Date)](https://www.star-history.com/#adobe/S3Mock&Date)

docs/tasks.md

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,75 @@ This document contains a list of potential improvements for the S3Mock project.
1717

1818
## Code Quality Improvements
1919

20-
11. [ ] Increase unit test coverage for service and store layers
20+
11. [ ] Increase unit test coverage for controller, service and store layers
21+
22+
### Task 11 – Test Coverage Plan (Components and Actions)
23+
24+
Scope and components to cover:
25+
- Controllers (HTTP): BucketController, ObjectController, MultipartController
26+
- Services (business logic): BucketService, ObjectService, MultipartService, Kms* services
27+
- Stores (persistence): BucketStore, ObjectStore, MultipartStore, KmsKeyStore
28+
- XML/DTOs and mappers: request/response XML models, serialization utils
29+
- Utilities: digest, ETag, headers, Range requests, SSE
30+
- Configuration: StoreConfiguration, controller advice/error mapping
31+
32+
Priorities (short-to-long horizon):
33+
1) High-value happy-path and error-path coverage for controllers with mocked services (fast feedback).
34+
2) Store layer correctness with Spring Boot WebEnvironment.NONE tests (file IO, metadata persistence, edge cases).
35+
3) Service layer behavior with mocked stores (parameter validation, branching, SSE/KMS interactions).
36+
4) XML serialization/deserialization fidelity for commonly used operations.
37+
5) Regression tests for known corner cases (range requests, conditional headers, multipart completion ordering, KMS key validation).
38+
39+
Concrete test additions (incremental):
40+
- Controllers
41+
- BucketController
42+
- listBuckets returns empty and non-empty results; XML schema shape
43+
- createBucket duplicate name -> proper S3 error code
44+
- deleteBucket non-empty -> proper error
45+
- ObjectController
46+
- putObject with/without Content-MD5; mismatched MD5 -> error
47+
- getObject with Range header (single range) -> 206 + Content-Range
48+
- getObject nonexistent -> 404 S3-style error
49+
- headObject verifies metadata and headers (ETag, Content-Length)
50+
- MultipartController
51+
- initiateMultipartUpload returns uploadId
52+
- uploadPart with invalid partNumber -> error mapping
53+
- completeMultipartUpload out-of-order parts -> consistent ETag behavior
54+
- Services
55+
- ObjectService.storeObject validates metadata, handles SSE headers routing to KMS
56+
- BucketService.deleteBucket checks emptiness guard
57+
- Stores
58+
- ObjectStore
59+
- storeS3ObjectMetadata and getS3ObjectMetadata roundtrip
60+
- list with prefix/delimiter, max-keys, continuation
61+
- delete removes metadata and data file
62+
- BucketStore
63+
- create, list, delete, exist checks
64+
- MultipartStore
65+
- init, addPart, complete, abort state transitions
66+
- XML/DTOs
67+
- Serialize/deserialize ListAllMyBucketsResult, CompleteMultipartUploadResult
68+
69+
Suggested file locations (server module):
70+
- Controllers: server/src/test/kotlin/com/adobe/testing/s3mock/itlike/controller/*Test.kt (extending BaseControllerTest)
71+
- Services: server/src/test/kotlin/com/adobe/testing/s3mock/service/*Test.kt
72+
- Stores: server/src/test/kotlin/com/adobe/testing/s3mock/store/*Test.kt (extend StoreTestBase)
73+
- DTOs: server/src/test/kotlin/com/adobe/testing/s3mock/xml/*Test.kt
74+
75+
Execution (fast path per repo guidelines):
76+
- One test class: ./mvnw -pl server test -Dtest=ObjectStoreTest
77+
- One method: ./mvnw -pl server test -Dtest=ObjectStoreTest#testStoreAndGetObject
78+
- Or via tool: run_test server/src/test/kotlin/com/adobe/testing/s3mock/store/ObjectStoreTest.kt
79+
80+
Acceptance targets for Task 11 completion:
81+
- +10–15% line coverage increase in server module, focusing on controllers and stores
82+
- At least one new test per component category listed above
83+
- Error-path assertions include correct HTTP status and S3 error codes/messages
84+
85+
Notes:
86+
- Avoid ITs unless Docker available; prefer WebEnvironment.RANDOM_PORT controller tests with mocked services.
87+
- Use provided test bases: BaseControllerTest, StoreTestBase, ServiceTestBase.
88+
- Reuse existing sample files: server/src/test/resources/sampleFile.txt, sampleFile_large.txt, sampleKMSFile.txt.
2189
12. [ ] Refactor synchronization mechanisms in store classes to improve concurrency handling
2290
13. [ ] Implement more comprehensive input validation for S3 API parameters
2391
14. [ ] Add more detailed logging throughout the application for better debugging
@@ -36,7 +104,7 @@ This document contains a list of potential improvements for the S3Mock project.
36104
24. [ ] Improve multipart upload performance
37105
25. [x] Reduce memory usage when handling large files
38106
26. [ ] Optimize XML serialization/deserialization
39-
27. [ ] Implement more efficient storage of object metadata
107+
27. [x] Keep object metadata storage as plain text (JSON) for inspectability (decided against more efficient/binary storage)
40108
28. [ ] Add support for conditional requests to reduce unnecessary data transfer
41109
29. [ ] Optimize concurrent access patterns
42110
30. [ ] Implement more efficient bucket and object locking mechanisms

integration-tests/pom.xml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,10 @@
5858
<artifactId>awaitility</artifactId>
5959
<scope>test</scope>
6060
</dependency>
61-
<dependency>
62-
<groupId>org.jetbrains.kotlin</groupId>
63-
<artifactId>kotlin-stdlib-jdk8</artifactId>
64-
<scope>test</scope>
65-
</dependency>
6661
<!-- Force Kotlin stdlib alignment to match aws-sdk-kotlin 1.5.x requirements -->
6762
<dependency>
6863
<groupId>org.jetbrains.kotlin</groupId>
6964
<artifactId>kotlin-stdlib</artifactId>
70-
<version>${kotlin.version}</version>
7165
<scope>test</scope>
7266
</dependency>
7367
<dependency>

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@
184184
</dependency>
185185
<dependency>
186186
<groupId>org.jetbrains.kotlin</groupId>
187-
<artifactId>kotlin-stdlib-jdk8</artifactId>
187+
<artifactId>kotlin-stdlib</artifactId>
188188
<version>${kotlin.version}</version>
189189
</dependency>
190190
<dependency>

server/pom.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@
5151
<groupId>com.fasterxml.jackson.datatype</groupId>
5252
<artifactId>jackson-datatype-jdk8</artifactId>
5353
</dependency>
54+
<dependency>
55+
<groupId>com.fasterxml.jackson.module</groupId>
56+
<artifactId>jackson-module-kotlin</artifactId>
57+
<scope>test</scope>
58+
</dependency>
5459
<dependency>
5560
<groupId>software.amazon.awssdk</groupId>
5661
<artifactId>regions</artifactId>
@@ -83,6 +88,10 @@
8388
<groupId>org.jspecify</groupId>
8489
<artifactId>jspecify</artifactId>
8590
</dependency>
91+
<dependency>
92+
<groupId>org.jetbrains.kotlin</groupId>
93+
<artifactId>kotlin-stdlib</artifactId>
94+
</dependency>
8695
<!-- Test Dependencies -->
8796
<dependency>
8897
<groupId>org.apache.httpcomponents</groupId>

server/src/main/java/com/adobe/testing/s3mock/MultipartController.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -140,16 +140,16 @@ public ResponseEntity<ListMultipartUploadsResult> listMultipartUploads(
140140
@RequestParam(name = UPLOAD_ID_MARKER, required = false) String uploadIdMarker) {
141141
bucketService.verifyBucketExists(bucketName);
142142

143-
return ResponseEntity.ok(multipartService.listMultipartUploads(
144-
bucketName,
145-
delimiter,
146-
encodingType,
147-
keyMarker,
148-
maxUploads,
149-
prefix,
150-
uploadIdMarker
151-
)
143+
var result = multipartService.listMultipartUploads(
144+
bucketName,
145+
delimiter,
146+
encodingType,
147+
keyMarker,
148+
maxUploads,
149+
prefix,
150+
uploadIdMarker
152151
);
152+
return ResponseEntity.ok(result);
153153
}
154154

155155
//================================================================================================
@@ -198,14 +198,15 @@ public ResponseEntity<ListPartsResult> listParts(
198198
bucketService.verifyBucketExists(bucketName);
199199
multipartService.verifyMultipartUploadExists(bucketName, uploadId);
200200

201+
var result = multipartService.getMultipartUploadParts(
202+
bucketName,
203+
key.key(),
204+
maxParts,
205+
partNumberMarker,
206+
uploadId
207+
);
201208
return ResponseEntity
202-
.ok(multipartService.getMultipartUploadParts(
203-
bucketName,
204-
key.key(),
205-
maxParts,
206-
partNumberMarker,
207-
uploadId)
208-
);
209+
.ok(result);
209210
}
210211

211212

server/src/main/java/com/adobe/testing/s3mock/dto/RegionSerializer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ public void serialize(Region value, JsonGenerator gen, SerializerProvider serial
3333
//API doc says to return "null" for the us-east-1 region.
3434
if ("us-east-1".equals(regionString)) {
3535
gen.writeString("null");
36+
} else {
37+
gen.writeString(regionString);
3638
}
37-
gen.writeString(regionString);
3839
}
3940
}
Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2024 Adobe.
2+
* Copyright 2017-2025 Adobe.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,23 +20,20 @@ import com.fasterxml.jackson.annotation.JsonInclude
2020
import com.fasterxml.jackson.dataformat.xml.XmlMapper
2121
import com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser
2222
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator
23-
import org.junit.jupiter.api.BeforeAll
2423

2524
internal abstract class BaseControllerTest {
2625
companion object {
27-
@JvmStatic
28-
protected lateinit var MAPPER: XmlMapper
26+
val MAPPER: XmlMapper = XmlMapper.builder()
27+
.findAndAddModules()
28+
.enable(ToXmlGenerator.Feature.WRITE_XML_DECLARATION)
29+
.enable(ToXmlGenerator.Feature.AUTO_DETECT_XSI_TYPE)
30+
.enable(FromXmlParser.Feature.AUTO_DETECT_XSI_TYPE)
31+
.build()
2932

30-
@JvmStatic
31-
@BeforeAll
32-
fun setup() {
33-
MAPPER = XmlMapper().enable(ToXmlGenerator.Feature.WRITE_XML_DECLARATION).apply {
34-
this as XmlMapper
35-
this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
36-
this.enable(ToXmlGenerator.Feature.AUTO_DETECT_XSI_TYPE)
37-
this.enable(FromXmlParser.Feature.AUTO_DETECT_XSI_TYPE)
38-
this.factory.xmlOutputFactory.setProperty(WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL, true)
39-
} as XmlMapper
33+
init {
34+
MAPPER.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
35+
MAPPER.factory.xmlOutputFactory
36+
.setProperty(WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL, true)
4037
}
4138
}
4239
}

0 commit comments

Comments
 (0)