Skip to content

Conversation

@0lai0
Copy link
Contributor

@0lai0 0lai0 commented Dec 7, 2025

What changes were proposed in this pull request?

Adding PutObjectTagging, GetObjectTagging, DeleteObjectTagging SDK integration tests to validate.

What is the link to the Apache JIRA

https://issues.apache.org/jira/browse/HDDS-13081

Copy link
Contributor

@Gargi-jais11 Gargi-jais11 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @0lai0 for the patch.
I have few more test case suggestions which could be added.

@Gargi-jais11
Copy link
Contributor

More Edge Cases which can be tested:

  1. testPutObjectTaggingExceedsLimit() — Test 11 tags and validate it throws error there is 10-tag limit.
  2. testPutObjectTaggingReplacesExistingTags() — verifies replacement behavior (Initially put 2 tags then replace it with 1 tag and check the last replcaed tag is only applied)
  3. testPutObjectTaggingInvalidConstraints - This can be a parameterised test like below:
private static Stream<Arguments> invalidTagConstraintsProvider() {
    return Stream.of(
        // Test 1: Tag key exceeds maximum length (128 bytes)
        Arguments.of(
            "Tag key exceeding 128 bytes should be rejected",
            Arrays.asList(Tag.builder().key("a".repeat(129)).value("value").build()),
            400,
            "exceeds the maximum length"
        ),
        
        // Test 2: Tag value exceeds maximum length (256 bytes)
        Arguments.of(
            "Tag value exceeding 256 bytes should be rejected",
            Arrays.asList(Tag.builder().key("valid-key").value("b".repeat(257)).build()),
            400,
            "exceeds the maximum length"
        ),
        // Test 3: Tag key with invalid characters (@, #, $, (, {, ....)
        Arguments.of(
            "Tag key with invalid characters should be rejected",
            Arrays.asList(Tag.builder().key("t$ag@#invalid").value("value").build()),
            400,
            "does not have a valid pattern"
        ), 
        // Test 4: Tag key starting with "aws:" prefix
        Arguments.of(
            "Tag key starting with 'aws:' prefix should be rejected",
            Arrays.asList(Tag.builder().key("aws:test").value("value").build()),
            400,
            "cannot start with \"aws:\"" 
        )
    );
    }
@ParameterizedTest
@MethodSource("invalidTagConstraintsProvider")
public void testPutObjectTaggingInvalidConstraints(
    String testCaseName,
    List<Tag> invalidTags,
    int expectedStatusCode,
    String expectedErrorMessage) {
    // your code
}
  1. testPutAndGetObjectTaggingOnNonExistentObject() - Verify NoSuchKeyException occurs and 404 status code.
  2. testDeleteObjectTaggingOnNonExistentObject() - Verify NoSuchKeyException occurs and 404 status code.

Copy link
Contributor

@Tejaskriya Tejaskriya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this @0lai0 , I second the suggestion of @Gargi-jais11 , the tests added mostly look good, but they are mainly the positive cases. Can we add tests for the error cases?

Also, multiple related test cases could be put in one test method to avoid duplication.

@Gargi-jais11
Copy link
Contributor

Thanks for working on this @0lai0 , I second the suggestion of @Gargi-jais11 , the tests added mostly look good, but they are mainly the positive cases. Can we add tests for the error cases?

Also, multiple related test cases could be put in one test method to avoid duplication.

Yes correct @Tejaskriya above test cases can be added to check for error cases.

@0lai0
Copy link
Contributor Author

0lai0 commented Dec 10, 2025

Thanks @Gargi-jais11 and @Tejaskriya review, I'll add error cases.

Copy link
Contributor

@ivandika3 ivandika3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding the tests. Overall LGTM. Could you also add similar tests to the AbstractS3SDKV1Tests as well?

Please also help to check this failure in your latest test run https://github.com/0lai0/ozone/actions/runs/20160679799/job/57874354964
(org.apache.hadoop.ozone.s3.awssdk.v2.AbstractS3SDKV2Tests$S3BucketOwnershipVerificationConditionsTests$LinkBucketTests)

@Gargi-jais11
Copy link
Contributor

@0lai0 Thanks for updating the patch. It LGTM.

Could you also add similar tests to the AbstractS3SDKV1Tests as well?

Once this is done the patch will be good to go.

@0lai0
Copy link
Contributor Author

0lai0 commented Dec 15, 2025

Thanks @ivandika3, @Gargi-jais11 and @echonesis for review.I'll push a fix right away.

@echonesis
Copy link
Contributor

Thanks @0lai0 , left some comments.

Copy link
Contributor

@echonesis echonesis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @0lai0 for updating the patch, left some comments.


@Nested
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class BucketOwnershipLinkBucketTests {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could keep it consistent with the V2 class

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we should keep the name consistent with the V2 class as LinkBucketTests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'll get on this.

*
*/
@TestMethodOrder(MethodOrderer.MethodName.class)
public abstract class AbstractS3SDKV1Tests extends OzoneTestBase {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removal of OzoneTestBase should be consistent between V1 and V2.

The V2 version still extends OzoneTestBase, so getTestName() returns a fixed test method name instead of a random string. This could cause naming conflicts in parallel test execution.

Consider removing OzoneTestBase from V2 as well and adding the same random-based getTestName() method.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe AbstractS3SDKV1Tests should extend OzoneTestBase .
OzoneTestBase.getTestName() returns the actual test method name (e.g., "testCreateBucket"), ensuring unique resource names per test

  • Without it, tests may interfere with each other and debugging becomes difficult
  • This is a standard pattern used across all Ozone test classes

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is test name may not be unique (e.g. for parameterized test). #9517 adds a method in OzoneTestBase to help with that, and changes these S3 tests to use uniqueObjectName() instead of just getTestName().

+1 for keeping OzoneTestBase.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@0lai0 HDDS-14197 is merged, now you can keep extends OzoneTestBase here and don't need to implement custom getTestName().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks everyone for the discussion, and thanks @adoroszlai for the update on HDDS-14197. I'll keep OzoneTestBase and remove the custom getTestName() implementation.

Copy link
Contributor

@Gargi-jais11 Gargi-jais11 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments below.

.withExpectedBucketOwner("wrong-owner");
AmazonServiceException wrongOwner = assertThrows(AmazonServiceException.class,
() -> s3Client.getBucketAcl(wrongRequest));
assertEquals(403, wrongOwner.getStatusCode());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use HttpURLConnection.HTTP_FORBIDDEN

.withExpectedBucketOwner("wrong-owner");
AmazonServiceException wrongOwner = assertThrows(AmazonServiceException.class,
() -> s3Client.getBucketAcl(wrongRequest));
assertEquals(403, wrongOwner.getStatusCode());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use HttpURLConnection.HTTP_FORBIDDEN

Comment on lines 528 to 540
400
),
Arguments.of(
Arrays.asList(Tag.builder().key("valid-key").value(repeatChar('b', 257)).build()),
400
),
Arguments.of(
Arrays.asList(Tag.builder().key("t$ag@#invalid").value("value").build()),
400
),
Arguments.of(
Arrays.asList(Tag.builder().key("aws:test").value("value").build()),
400
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use HTTP_BAD_REQUEST in this Parameterised test.

Comment on lines 1547 to 1550
private String getTestName() {
return RandomStringUtils.secure().nextAlphanumeric(8).toLowerCase(Locale.ROOT);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@0lai0 is there any specific purpose because of which you are creating getTestName explicity over here and not using OzoneTestBase#getTestName?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for point this out , I'll remove it.

@Gargi-jais11
Copy link
Contributor

@0lai0 After addressing the review comments please mark it as resolved.

@ivandika3
Copy link
Contributor

ivandika3 commented Dec 18, 2025

@0lai0 After addressing the review comments please mark it as resolved.

@Gargi-jais11 IMO the responsibility of resolving comments is in the reviewer since it signals that that the comments are already addressed to the reviewer's satisfaction.

@0lai0
Copy link
Contributor Author

0lai0 commented Dec 19, 2025

Thanks for all the feedback. I'll review and make changes based on the comments.

@adoroszlai
Copy link
Contributor

Thanks @0lai0 for updating the patch. There are some test failures:

Error:  Tests run: 31, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 0.045 s <<< FAILURE! -- in org.apache.hadoop.ozone.s3.awssdk.v1.AbstractS3SDKV1Tests$LinkBucketTests
Error:  org.apache.hadoop.ozone.s3.awssdk.v1.AbstractS3SDKV1Tests$LinkBucketTests.testDanglingBucket -- Time elapsed: 0.016 s <<< FAILURE!
org.opentest4j.AssertionFailedError: expected: <AccessDenied> but was: <Access Denied>
...
	at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1145)
	at org.apache.hadoop.ozone.s3.awssdk.v1.AbstractS3SDKV1Tests$LinkBucketTests.testDanglingBucket(AbstractS3SDKV1Tests.java:1432)
...

Error:  org.apache.hadoop.ozone.s3.awssdk.v1.AbstractS3SDKV1Tests$LinkBucketTests.setBucketVerificationOnLinkBucket -- Time elapsed: 0.020 s <<< FAILURE!
org.opentest4j.AssertionFailedError: expected: <AccessDenied> but was: <Access Denied>
...
	at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1145)
	at org.apache.hadoop.ozone.s3.awssdk.v1.AbstractS3SDKV1Tests$LinkBucketTests.setBucketVerificationOnLinkBucket(AbstractS3SDKV1Tests.java:1407)

https://github.com/0lai0/ozone/actions/runs/20396880835/job/58614335876#step:13:6020

@0lai0
Copy link
Contributor Author

0lai0 commented Dec 29, 2025

Thanks @adoroszlai for review. I've pushed a commit to address test failures by AssertionFailedError.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants