Skip to content

Commit d73c105

Browse files
authored
Merge pull request #2503 from adobe/code-optimizations
Fail PUT object with match on non-existent keys & code optimizations
2 parents f19053b + 6fea3e0 commit d73c105

File tree

24 files changed

+129
-75
lines changed

24 files changed

+129
-75
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ target/
77
.settings/
88
*.springBeans
99
.mvn/wrapper/maven-wrapper.jar
10+
.vscode
11+
.cursor

CHANGELOG.md

Lines changed: 25 additions & 2 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.6.0 - PLANNED](#460---planned)
11+
* [4.7.0 - PLANNED](#470---planned)
12+
* [4.6.0](#460)
1213
* [4.5.1](#451)
1314
* [4.5.0](#450)
1415
* [4.4.0](#440)
@@ -146,7 +147,7 @@ Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Jav
146147

147148
**The current major version 4 will receive new features, dependency updates and bug fixes on a continuous basis.**
148149

149-
## 4.6.0 - PLANNED
150+
## 4.7.0 - PLANNED
150151
Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Java integration.
151152

152153
* Features and fixes
@@ -158,6 +159,28 @@ Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Jav
158159
* Version updates (build dependencies)
159160
* TBD
160161

162+
## 4.6.0
163+
Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Java integration.
164+
165+
* Features and fixes
166+
* Fail PUT object with match on non-existent keys (fixes #2502)
167+
* Refactorings
168+
* Remove unused imports
169+
* Fix Kotlin 2.2 usage
170+
* Ignore .vscode and .cursor configurations
171+
* Minor refactorings for clarity.
172+
* Use fixed list of StorageClass values in tests. New values added by AWS sometimes break tests. We want to make sure to test a few different storage classes, no need to test every one.
173+
* Version updates (deliverable dependencies)
174+
* Bump aws-v2.version from 2.31.67 to 2.31.77
175+
* Bump testcontainers.version from 1.21.2 to 1.21.3
176+
* Version updates (build dependencies)
177+
* Bump aws.sdk.kotlin:s3-jvm from 1.4.109 to 1.4.119
178+
* Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.7 to 3.2.8
179+
* Bump org.apache.maven.plugins:maven-enforcer-plugin from 3.5.0 to 3.6.0
180+
* Bump com.puppycrawl.tools:checkstyle from 10.26.0 to 10.26.1
181+
* Bump github/codeql-action from 3.29.1 to 3.29.2
182+
* Bump step-security/harden-runner from 2.12.1 to 2.12.2
183+
161184
## 4.5.1
162185
Version 4.x is JDK17 LTS bytecode compatible, with Docker and JUnit / direct Java integration.
163186

Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.PHONY: build verify install
2+
.DEFAULT_GOAL := build
3+
4+
build: verify
5+
6+
verify:
7+
./mvnw -B -V -Dstyle.color=always clean verify
8+
9+
install:
10+
./mvnw -B -V -Dstyle.color=always clean install

build-config/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<parent>
2222
<groupId>com.adobe.testing</groupId>
2323
<artifactId>s3mock-parent</artifactId>
24-
<version>4.5.2-SNAPSHOT</version>
24+
<version>4.6.0-SNAPSHOT</version>
2525
</parent>
2626

2727
<artifactId>s3mock-build-config</artifactId>

docker/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<parent>
2323
<groupId>com.adobe.testing</groupId>
2424
<artifactId>s3mock-parent</artifactId>
25-
<version>4.5.2-SNAPSHOT</version>
25+
<version>4.6.0-SNAPSHOT</version>
2626
</parent>
2727

2828
<artifactId>s3mock-docker</artifactId>

integration-tests/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<parent>
2323
<groupId>com.adobe.testing</groupId>
2424
<artifactId>s3mock-parent</artifactId>
25-
<version>4.5.2-SNAPSHOT</version>
25+
<version>4.6.0-SNAPSHOT</version>
2626
</parent>
2727

2828
<artifactId>s3mock-integration-tests</artifactId>

integration-tests/src/test/kotlin/com/adobe/testing/s3mock/its/GetPutDeleteObjectIT.kt

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package com.adobe.testing.s3mock.its
1818

19-
import com.adobe.testing.s3mock.its.S3TestBase.Companion.UPLOAD_FILE
2019
import com.adobe.testing.s3mock.util.DigestUtil
2120
import org.assertj.core.api.Assertions.assertThat
2221
import org.assertj.core.api.Assertions.assertThatThrownBy
@@ -912,6 +911,21 @@ internal class GetPutDeleteObjectIT : S3TestBase() {
912911
.hasMessageContaining("Service: S3, Status Code: 412")
913912
}
914913

914+
@Test
915+
@S3VerifiedSuccess(year = 2025)
916+
fun `PUT object succeeds with if-none-match on non-existing object`(testInfo: TestInfo) {
917+
val nonMatchingEtag = WILDCARD
918+
val bucketName = givenBucket(testInfo)
919+
920+
s3Client.putObject(
921+
{
922+
it.bucket(bucketName)
923+
it.key(UPLOAD_FILE_NAME)
924+
it.ifNoneMatch(nonMatchingEtag)
925+
}, RequestBody.fromFile(UPLOAD_FILE)
926+
)
927+
}
928+
915929
@Test
916930
@S3VerifiedSuccess(year = 2025)
917931
fun `PUT object fails with if-match=false`(testInfo: TestInfo) {
@@ -930,6 +944,24 @@ internal class GetPutDeleteObjectIT : S3TestBase() {
930944
.hasMessageContaining("Service: S3, Status Code: 412")
931945
}
932946

947+
@Test
948+
@S3VerifiedSuccess(year = 2025)
949+
fun `PUT object fails with if-match on non-existing object`(testInfo: TestInfo) {
950+
val nonMatchingEtag = "\"$randomName\""
951+
val bucketName = givenBucket(testInfo)
952+
953+
assertThatThrownBy {
954+
s3Client.putObject(
955+
{
956+
it.bucket(bucketName)
957+
it.key(UPLOAD_FILE_NAME)
958+
it.ifMatch(nonMatchingEtag)
959+
}, RequestBody.fromFile(UPLOAD_FILE)
960+
)
961+
}.isInstanceOf(S3Exception::class.java)
962+
.hasMessageContaining("Service: S3, Status Code: 404")
963+
}
964+
933965
@Test
934966
@S3VerifiedFailure(year = 2025,
935967
reason = "Supported only on directory buckets. S3 returns: A header you provided implies functionality that is not implemented.")

integration-tests/src/test/kotlin/com/adobe/testing/s3mock/its/S3TestBase.kt

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -627,16 +627,14 @@ internal abstract class S3TestBase {
627627

628628
@JvmStatic
629629
protected fun storageClasses(): Stream<StorageClass> {
630-
return StorageClass
631-
.entries
632-
.filter { it != StorageClass.UNKNOWN_TO_SDK_VERSION }
633-
.filter { it != StorageClass.SNOW }
634-
.filter { it != StorageClass.EXPRESS_ONEZONE }
635-
.filter { it != StorageClass.GLACIER }
636-
.filter { it != StorageClass.DEEP_ARCHIVE }
637-
.filter { it != StorageClass.OUTPOSTS }
638-
.map { it }
639-
.stream()
630+
return listOf(
631+
StorageClass.STANDARD,
632+
StorageClass.REDUCED_REDUNDANCY,
633+
StorageClass.STANDARD_IA,
634+
StorageClass.ONEZONE_IA,
635+
StorageClass.INTELLIGENT_TIERING,
636+
StorageClass.GLACIER,
637+
).stream()
640638
}
641639

642640
@JvmStatic

integration-tests/src/test/kotlin/com/adobe/testing/s3mock/its/S3VerifiedFailure.java renamed to integration-tests/src/test/kotlin/com/adobe/testing/s3mock/its/S3VerifiedFailure.kt

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2023 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.
@@ -13,22 +13,15 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
package com.adobe.testing.s3mock.its
1617

17-
package com.adobe.testing.s3mock.its;
18-
19-
import java.lang.annotation.Retention;
20-
import java.lang.annotation.RetentionPolicy;
21-
import org.junit.jupiter.api.extension.ExtendWith;
18+
import org.junit.jupiter.api.extension.ExtendWith
2219

2320
/**
2421
* A test has been verified as failing against S3 APIs.
2522
* Some tests can't ever run successfully against the S3 API.
2623
* The reason will tell us why.
2724
*/
28-
@Retention(RetentionPolicy.RUNTIME)
29-
@ExtendWith(RealS3BackendUsedCondition.class)
30-
public @interface S3VerifiedFailure {
31-
String reason();
32-
33-
int year();
34-
}
25+
@Retention(AnnotationRetention.RUNTIME)
26+
@ExtendWith(RealS3BackendUsedCondition::class)
27+
annotation class S3VerifiedFailure(val reason: String, val year: Int)

integration-tests/src/test/kotlin/com/adobe/testing/s3mock/its/S3VerifiedSuccess.java renamed to integration-tests/src/test/kotlin/com/adobe/testing/s3mock/its/S3VerifiedSuccess.kt

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2023 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.
@@ -13,20 +13,13 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
package com.adobe.testing.s3mock.its
1617

17-
package com.adobe.testing.s3mock.its;
18-
19-
import java.lang.annotation.Retention;
20-
import java.lang.annotation.RetentionPolicy;
21-
import org.junit.jupiter.api.extension.ExtendWith;
18+
import org.junit.jupiter.api.extension.ExtendWith
2219

2320
/**
2421
* A test has been verified successfully against S3 APIs.
2522
*/
26-
@Retention(RetentionPolicy.RUNTIME)
27-
@ExtendWith(RealS3BackendUsedCondition.class)
28-
public @interface S3VerifiedSuccess {
29-
30-
int year();
31-
32-
}
23+
@Retention(AnnotationRetention.RUNTIME)
24+
@ExtendWith(RealS3BackendUsedCondition::class)
25+
annotation class S3VerifiedSuccess(val year: Int)

0 commit comments

Comments
 (0)