This is an automated email from the ASF dual-hosted git repository.
adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 15f9307b346 HDDS-14222. Reduce duplication in TestObjectPut (#9539)
15f9307b346 is described below
commit 15f9307b346cbec68669335077774c50a52e2a04
Author: Doroszlai, Attila <[email protected]>
AuthorDate: Tue Dec 23 11:46:29 2025 +0100
HDDS-14222. Reduce duplication in TestObjectPut (#9539)
---
hadoop-ozone/client/pom.xml | 5 +
.../hadoop/ozone/client/OzoneClientTestUtils.java | 56 +++
hadoop-ozone/integration-test/pom.xml | 6 +
.../ozone/client/rpc/OzoneRpcClientTests.java | 15 +-
.../TestOzoneRpcClientWithKeyLatestVersion.java | 11 +-
.../hadoop/ozone/client/rpc/TestReadRetries.java | 2 +-
hadoop-ozone/s3gateway/pom.xml | 6 +
.../ozone/s3/endpoint/EndpointTestUtils.java | 90 ++++
.../hadoop/ozone/s3/endpoint/TestObjectPut.java | 537 ++++++---------------
pom.xml | 6 +
10 files changed, 321 insertions(+), 413 deletions(-)
diff --git a/hadoop-ozone/client/pom.xml b/hadoop-ozone/client/pom.xml
index 603a87e3fe6..6d817fa3163 100644
--- a/hadoop-ozone/client/pom.xml
+++ b/hadoop-ozone/client/pom.xml
@@ -97,6 +97,11 @@
</dependency>
<!-- Test dependencies -->
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.apache.ozone</groupId>
<artifactId>hdds-client</artifactId>
diff --git
a/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/OzoneClientTestUtils.java
b/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/OzoneClientTestUtils.java
new file mode 100644
index 00000000000..7fb2345bc15
--- /dev/null
+++
b/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/OzoneClientTestUtils.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.ozone.client;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+import java.io.IOException;
+import java.io.InputStream;
+import org.apache.commons.io.IOUtils;
+
+/** Utilities for tests using Ozone client. */
+public final class OzoneClientTestUtils {
+
+ /** Verify contents of a key.
+ * @return key details for convenience (further checks) */
+ public static OzoneKeyDetails assertKeyContent(
+ OzoneBucket bucket,
+ String keyName,
+ String expected
+ ) throws IOException {
+ return assertKeyContent(bucket, keyName, expected.getBytes(UTF_8));
+ }
+
+ /** Verify contents of a key.
+ * @return key details for convenience (further checks) */
+ public static OzoneKeyDetails assertKeyContent(
+ OzoneBucket bucket,
+ String keyName,
+ byte[] expected
+ ) throws IOException {
+ try (InputStream is = bucket.readKey(keyName)) {
+ assertArrayEquals(expected, IOUtils.readFully(is, expected.length));
+ }
+ return bucket.getKey(keyName);
+ }
+
+ private OzoneClientTestUtils() {
+ // no instances
+ }
+}
diff --git a/hadoop-ozone/integration-test/pom.xml
b/hadoop-ozone/integration-test/pom.xml
index df9da45b3b6..10e851ba9d4 100644
--- a/hadoop-ozone/integration-test/pom.xml
+++ b/hadoop-ozone/integration-test/pom.xml
@@ -384,6 +384,12 @@
<artifactId>ozone-client</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.ozone</groupId>
+ <artifactId>ozone-client</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.apache.ozone</groupId>
<artifactId>ozone-common</artifactId>
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/OzoneRpcClientTests.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/OzoneRpcClientTests.java
index 554b125ddbe..2832a281ebb 100644
---
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/OzoneRpcClientTests.java
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/OzoneRpcClientTests.java
@@ -38,6 +38,7 @@
import static org.apache.hadoop.ozone.OzoneConsts.GB;
import static org.apache.hadoop.ozone.OzoneConsts.MD5_HASH;
import static org.apache.hadoop.ozone.OzoneConsts.OZONE_URI_DELIMITER;
+import static
org.apache.hadoop.ozone.client.OzoneClientTestUtils.assertKeyContent;
import static
org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_DIR_DELETING_SERVICE_INTERVAL;
import static
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.KEY_NOT_FOUND;
import static
org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.NO_SUCH_MULTIPART_UPLOAD_ERROR;
@@ -1405,20 +1406,6 @@ private static void rewriteKey(
}
}
- private static OzoneKeyDetails assertKeyContent(
- OzoneBucket bucket, String keyName, byte[] expectedContent
- ) throws IOException {
- OzoneKeyDetails updatedKeyDetails = bucket.getKey(keyName);
-
- try (OzoneInputStream is = bucket.readKey(keyName)) {
- byte[] fileContent = new byte[expectedContent.length];
- IOUtils.readFully(is, fileContent);
- assertArrayEquals(expectedContent, fileContent);
- }
-
- return updatedKeyDetails;
- }
-
private OzoneBucket createBucket(BucketLayout layout) throws IOException {
String volumeName = UUID.randomUUID().toString();
String bucketName = UUID.randomUUID().toString();
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClientWithKeyLatestVersion.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClientWithKeyLatestVersion.java
index b437aa72026..703b37964f2 100644
---
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClientWithKeyLatestVersion.java
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestOzoneRpcClientWithKeyLatestVersion.java
@@ -19,15 +19,13 @@
import static
org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor.THREE;
import static
org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_CLIENT_KEY_LATEST_VERSION_LOCATION;
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static
org.apache.hadoop.ozone.client.OzoneClientTestUtils.assertKeyContent;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.io.IOException;
-import java.io.InputStream;
import java.util.List;
import java.util.UUID;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.hadoop.hdds.client.RatisReplicationConfig;
import org.apache.hadoop.hdds.client.ReplicationConfig;
@@ -107,13 +105,6 @@ private static void writeKey(OzoneBucket bucket, String
key, byte[] content,
TestDataUtil.createKey(bucket, key, replication, content);
}
- public static void assertKeyContent(OzoneBucket bucket, String key,
- byte[] expected) throws Exception {
- try (InputStream in = bucket.readKey(key)) {
- assertArrayEquals(expected, IOUtils.readFully(in, expected.length));
- }
- }
-
private void assertListStatus(OzoneBucket bucket, String keyName,
int expectedVersionCount) throws Exception {
List<OzoneFileStatus> files = bucket.listStatus(keyName, false, "", 1);
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestReadRetries.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestReadRetries.java
index af28265e823..70989f07e5f 100644
---
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestReadRetries.java
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/TestReadRetries.java
@@ -18,7 +18,7 @@
package org.apache.hadoop.ozone.client.rpc;
import static
org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor.THREE;
-import static
org.apache.hadoop.ozone.client.rpc.TestOzoneRpcClientWithKeyLatestVersion.assertKeyContent;
+import static
org.apache.hadoop.ozone.client.OzoneClientTestUtils.assertKeyContent;
import static
org.apache.hadoop.ozone.om.request.OMRequestTestUtils.configureFSOptimizedPaths;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
diff --git a/hadoop-ozone/s3gateway/pom.xml b/hadoop-ozone/s3gateway/pom.xml
index af45d311798..aa510ae6a0f 100644
--- a/hadoop-ozone/s3gateway/pom.xml
+++ b/hadoop-ozone/s3gateway/pom.xml
@@ -227,6 +227,12 @@
<artifactId>weld-servlet-shaded</artifactId>
<scope>runtime</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.ozone</groupId>
+ <artifactId>ozone-client</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
diff --git
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/EndpointTestUtils.java
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/EndpointTestUtils.java
new file mode 100644
index 00000000000..c6eff8066cd
--- /dev/null
+++
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/EndpointTestUtils.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.ozone.s3.endpoint;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import javax.ws.rs.core.Response;
+import org.apache.hadoop.ozone.s3.exception.OS3Exception;
+import org.apache.http.HttpStatus;
+import org.apache.ratis.util.function.CheckedSupplier;
+
+/** Utilities for unit-testing S3 endpoints. */
+public final class EndpointTestUtils {
+
+ /** Put without content. */
+ public static Response putDir(
+ ObjectEndpoint subject,
+ String bucket,
+ String key
+ ) throws IOException, OS3Exception {
+ return put(subject, bucket, key, 0, null, null);
+ }
+
+ /** Put with content. */
+ public static Response put(
+ ObjectEndpoint subject,
+ String bucket,
+ String key,
+ String content
+ ) throws IOException, OS3Exception {
+ return put(subject, bucket, key, 0, null, content);
+ }
+
+ /** Put with content, part number, upload ID. */
+ public static Response put(
+ ObjectEndpoint subject,
+ String bucket,
+ String key,
+ int partNumber,
+ String uploadID,
+ String content
+ ) throws IOException, OS3Exception {
+ if (content == null) {
+ return subject.put(bucket, key, 0, partNumber, uploadID, null, null,
null);
+ } else {
+ final long length = content.length();
+ try (ByteArrayInputStream body = new
ByteArrayInputStream(content.getBytes(UTF_8))) {
+ return subject.put(bucket, key, length, partNumber, uploadID, null,
null, body);
+ }
+ }
+ }
+
+ /** Verify response is success for {@code request}. */
+ public static <E extends Exception> void
assertSucceeds(CheckedSupplier<Response, E> request) throws E {
+ try (Response response = request.get()) {
+ assertEquals(HttpStatus.SC_OK, response.getStatus());
+ }
+ }
+
+ /** Verify error response for {@code request} matching {@code expected}
{@link OS3Exception}. */
+ public static OS3Exception assertErrorResponse(OS3Exception expected,
CheckedSupplier<Response, ?> request) {
+ OS3Exception actual = assertThrows(OS3Exception.class, () ->
request.get().close());
+ assertEquals(expected.getCode(), actual.getCode());
+ assertEquals(expected.getHttpCode(), actual.getHttpCode());
+ return actual;
+ }
+
+ private EndpointTestUtils() {
+ // no instances
+ }
+}
diff --git
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestObjectPut.java
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestObjectPut.java
index e5c34fb4e46..a561343a518 100644
---
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestObjectPut.java
+++
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestObjectPut.java
@@ -17,14 +17,21 @@
package org.apache.hadoop.ozone.s3.endpoint;
-import static java.nio.charset.StandardCharsets.UTF_8;
+import static
org.apache.hadoop.ozone.client.OzoneClientTestUtils.assertKeyContent;
+import static
org.apache.hadoop.ozone.s3.endpoint.EndpointTestUtils.assertErrorResponse;
+import static
org.apache.hadoop.ozone.s3.endpoint.EndpointTestUtils.assertSucceeds;
+import static org.apache.hadoop.ozone.s3.endpoint.EndpointTestUtils.put;
+import static org.apache.hadoop.ozone.s3.endpoint.EndpointTestUtils.putDir;
import static
org.apache.hadoop.ozone.s3.exception.S3ErrorTable.INVALID_ARGUMENT;
+import static
org.apache.hadoop.ozone.s3.exception.S3ErrorTable.INVALID_REQUEST;
import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.INVALID_TAG;
+import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.NO_SUCH_BUCKET;
import static org.apache.hadoop.ozone.s3.util.S3Consts.COPY_SOURCE_HEADER;
import static
org.apache.hadoop.ozone.s3.util.S3Consts.CUSTOM_METADATA_COPY_DIRECTIVE_HEADER;
import static
org.apache.hadoop.ozone.s3.util.S3Consts.CUSTOM_METADATA_HEADER_PREFIX;
import static
org.apache.hadoop.ozone.s3.util.S3Consts.DECODED_CONTENT_LENGTH_HEADER;
import static org.apache.hadoop.ozone.s3.util.S3Consts.STORAGE_CLASS_HEADER;
+import static
org.apache.hadoop.ozone.s3.util.S3Consts.STREAMING_AWS4_HMAC_SHA256_PAYLOAD;
import static org.apache.hadoop.ozone.s3.util.S3Consts.TAG_DIRECTIVE_HEADER;
import static org.apache.hadoop.ozone.s3.util.S3Consts.TAG_HEADER;
import static org.apache.hadoop.ozone.s3.util.S3Consts.TAG_KEY_LENGTH_LIMIT;
@@ -36,9 +43,8 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.fail;
-import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.spy;
@@ -46,7 +52,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import java.io.ByteArrayInputStream;
+import com.google.common.collect.ImmutableMap;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -63,28 +69,23 @@
import org.apache.hadoop.hdds.client.ECReplicationConfig;
import org.apache.hadoop.hdds.client.RatisReplicationConfig;
import org.apache.hadoop.hdds.client.ReplicationConfig;
-import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.ozone.OzoneConfigKeys;
import org.apache.hadoop.ozone.OzoneConsts;
import org.apache.hadoop.ozone.client.BucketArgs;
import org.apache.hadoop.ozone.client.OzoneBucket;
import org.apache.hadoop.ozone.client.OzoneClient;
-import org.apache.hadoop.ozone.client.OzoneClientStub;
import org.apache.hadoop.ozone.client.OzoneKeyDetails;
import org.apache.hadoop.ozone.client.OzoneVolume;
-import org.apache.hadoop.ozone.client.io.OzoneInputStream;
import org.apache.hadoop.ozone.om.helpers.BucketLayout;
import org.apache.hadoop.ozone.s3.exception.OS3Exception;
import org.apache.hadoop.ozone.s3.exception.S3ErrorTable;
-import org.apache.http.HttpStatus;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.MockedStatic;
-import org.mockito.Mockito;
/**
* Test put object.
@@ -96,12 +97,12 @@ class TestObjectPut {
private static final String KEY_NAME = "key=value/1";
private static final String DEST_BUCKET_NAME = "b2";
private static final String DEST_KEY = "key=value/2";
- private static final String NO_SUCH_BUCKET = "nonexist";
+ private static final String NONEXISTENT_BUCKET = "nonexist";
- private OzoneClient clientStub;
private ObjectEndpoint objectEndpoint;
private HttpHeaders headers;
private OzoneBucket bucket;
+ private OzoneBucket destBucket;
private OzoneBucket fsoBucket;
static Stream<Arguments> argumentsForPutObject() {
@@ -117,29 +118,17 @@ static Stream<Arguments> argumentsForPutObject() {
@BeforeEach
void setup() throws IOException {
- OzoneConfiguration config = new OzoneConfiguration();
+ headers = newMockHttpHeaders();
+ objectEndpoint =
spy(EndpointBuilder.newObjectEndpointBuilder().setHeaders(headers).build());
- //Create client stub and object store stub.
- clientStub = new OzoneClientStub();
-
- // Create bucket
+ // Create buckets
+ OzoneClient clientStub = objectEndpoint.getClient();
clientStub.getObjectStore().createS3Bucket(BUCKET_NAME);
bucket = clientStub.getObjectStore().getS3Bucket(BUCKET_NAME);
clientStub.getObjectStore().createS3Bucket(DEST_BUCKET_NAME);
+ destBucket = clientStub.getObjectStore().getS3Bucket(DEST_BUCKET_NAME);
- headers = mock(HttpHeaders.class);
-
when(headers.getHeaderString(X_AMZ_CONTENT_SHA256)).thenReturn("mockSignature");
-
- // Create PutObject and setClient to OzoneClientStub
- objectEndpoint = EndpointBuilder.newObjectEndpointBuilder()
- .setClient(clientStub)
- .setConfig(config)
- .setHeaders(headers)
- .build();
-
- objectEndpoint = spy(objectEndpoint);
-
- String volumeName = config.get(OzoneConfigKeys.OZONE_S3_VOLUME_NAME,
+ String volumeName =
objectEndpoint.getOzoneConfiguration().get(OzoneConfigKeys.OZONE_S3_VOLUME_NAME,
OzoneConfigKeys.OZONE_S3_VOLUME_NAME_DEFAULT);
OzoneVolume volume = clientStub.getObjectStore().getVolume(volumeName);
BucketArgs fsoBucketArgs = BucketArgs.newBuilder()
@@ -151,25 +140,17 @@ void setup() throws IOException {
@ParameterizedTest
@MethodSource("argumentsForPutObject")
- void testPutObject(int length, ReplicationConfig replication) throws
IOException, OS3Exception {
+ void testPutObject(int length, ReplicationConfig replication) throws
Exception {
//GIVEN
final String content = RandomStringUtils.secure().nextAlphanumeric(length);
- ByteArrayInputStream body = new
ByteArrayInputStream(content.getBytes(UTF_8));
bucket.setReplicationConfig(replication);
//WHEN
- Response response = objectEndpoint.put(BUCKET_NAME, KEY_NAME, length, 1,
null, null, null, body);
+ assertSucceeds(() -> putObject(content));
//THEN
- assertEquals(200, response.getStatus());
-
- String keyContent;
- try (InputStream input = bucket.readKey(KEY_NAME)) {
- keyContent = IOUtils.toString(input, UTF_8);
- }
- assertEquals(content, keyContent);
-
- OzoneKeyDetails keyDetails = bucket.getKey(KEY_NAME);
+ OzoneKeyDetails keyDetails = assertKeyContent(bucket, KEY_NAME, content);
+ assertEquals(content.length(), keyDetails.getDataSize());
assertEquals(replication, keyDetails.getReplicationConfig());
assertNotNull(keyDetails.getMetadata());
assertThat(keyDetails.getMetadata().get(OzoneConsts.ETAG)).isNotEmpty();
@@ -177,145 +158,54 @@ void testPutObject(int length, ReplicationConfig
replication) throws IOException
}
@Test
- void testPutObjectContentLength() throws IOException, OS3Exception {
- // The contentLength specified when creating the Key should be the same as
- // the Content-Length, the key Commit will compare the Content-Length with
- // the actual length of the data written.
- ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
- long dataSize = CONTENT.length();
-
- objectEndpoint.put(BUCKET_NAME, KEY_NAME, dataSize, 0, null, null, null,
body);
- assertEquals(dataSize, getKeyDataSize());
- }
-
- @Test
- void testPutObjectContentLengthForStreaming()
- throws IOException, OS3Exception {
- String chunkedContent = "0a;chunk-signature=signature\r\n"
- + "1234567890\r\n"
- + "05;chunk-signature=signature\r\n"
- + "abcde\r\n";
-
- when(headers.getHeaderString("x-amz-content-sha256"))
- .thenReturn("STREAMING-AWS4-HMAC-SHA256-PAYLOAD");
-
- when(headers.getHeaderString(DECODED_CONTENT_LENGTH_HEADER))
- .thenReturn("15");
- objectEndpoint.put(BUCKET_NAME, KEY_NAME, chunkedContent.length(), 0,
null, null,
- null, new ByteArrayInputStream(chunkedContent.getBytes(UTF_8)));
- assertEquals(15, getKeyDataSize());
- }
-
- @Test
- public void testPutObjectWithTags() throws IOException, OS3Exception {
- HttpHeaders headersWithTags = Mockito.mock(HttpHeaders.class);
-
when(headersWithTags.getHeaderString(X_AMZ_CONTENT_SHA256)).thenReturn("mockSignature");
-
when(headersWithTags.getHeaderString(TAG_HEADER)).thenReturn("tag1=value1&tag2=value2");
+ public void testPutObjectWithTags() throws Exception {
+
when(headers.getHeaderString(TAG_HEADER)).thenReturn("tag1=value1&tag2=value2");
- ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
- objectEndpoint.setHeaders(headersWithTags);
+ assertSucceeds(() -> putObject(CONTENT));
- Response response = objectEndpoint.put(BUCKET_NAME, KEY_NAME,
CONTENT.length(),
- 1, null, null, null, body);
-
- assertEquals(200, response.getStatus());
-
- OzoneKeyDetails keyDetails =
- clientStub.getObjectStore().getS3Bucket(BUCKET_NAME).getKey(KEY_NAME);
- Map<String, String> tags = keyDetails.getTags();
+ Map<String, String> tags = bucket.getKey(KEY_NAME).getTags();
assertEquals(2, tags.size());
assertEquals("value1", tags.get("tag1"));
assertEquals("value2", tags.get("tag2"));
}
@Test
- public void testPutObjectWithOnlyTagKey() throws Exception {
- ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
- HttpHeaders headerWithOnlyTagKey = Mockito.mock(HttpHeaders.class);
-
when(headerWithOnlyTagKey.getHeaderString(X_AMZ_CONTENT_SHA256)).thenReturn("mockSignature");
+ public void testPutObjectWithOnlyTagKey() {
// Try to send with only the key (no value)
- when(headerWithOnlyTagKey.getHeaderString(TAG_HEADER)).thenReturn("tag1");
- objectEndpoint.setHeaders(headerWithOnlyTagKey);
-
- try {
- objectEndpoint.put(BUCKET_NAME, KEY_NAME, CONTENT.length(),
- 1, null, null, null, body);
- fail("request with invalid query param should fail");
- } catch (OS3Exception ex) {
- assertEquals(INVALID_TAG.getCode(), ex.getCode());
- assertThat(ex.getErrorMessage()).contains("Some tag values are not
specified");
- assertEquals(INVALID_TAG.getHttpCode(), ex.getHttpCode());
- }
+ when(headers.getHeaderString(TAG_HEADER)).thenReturn("tag1");
+
+ OS3Exception ex = assertErrorResponse(INVALID_TAG, () ->
putObject(CONTENT));
+ assertThat(ex.getErrorMessage()).contains("Some tag values are not
specified");
}
@Test
- public void testPutObjectWithDuplicateTagKey() throws Exception {
- ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
- HttpHeaders headersWithDuplicateTagKey = Mockito.mock(HttpHeaders.class);
-
when(headersWithDuplicateTagKey.getHeaderString(X_AMZ_CONTENT_SHA256)).thenReturn("mockSignature");
-
when(headersWithDuplicateTagKey.getHeaderString(TAG_HEADER)).thenReturn("tag1=value1&tag1=value2");
- objectEndpoint.setHeaders(headersWithDuplicateTagKey);
- try {
- objectEndpoint.put(BUCKET_NAME, KEY_NAME, CONTENT.length(),
- 1, null, null, null, body);
- fail("request with duplicate tag key should fail");
- } catch (OS3Exception ex) {
- assertEquals(INVALID_TAG.getCode(), ex.getCode());
- assertThat(ex.getErrorMessage()).contains("There are tags with duplicate
tag keys");
- assertEquals(INVALID_TAG.getHttpCode(), ex.getHttpCode());
- }
+ public void testPutObjectWithDuplicateTagKey() {
+
when(headers.getHeaderString(TAG_HEADER)).thenReturn("tag1=value1&tag1=value2");
+
+ OS3Exception ex = assertErrorResponse(INVALID_TAG, () ->
putObject(CONTENT));
+ assertThat(ex.getErrorMessage()).contains("There are tags with duplicate
tag keys");
}
@Test
- public void testPutObjectWithLongTagKey() throws Exception {
- ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
- HttpHeaders headersWithLongTagKey = Mockito.mock(HttpHeaders.class);
-
when(headersWithLongTagKey.getHeaderString(X_AMZ_CONTENT_SHA256)).thenReturn("mockSignature");
+ public void testPutObjectWithLongTagKey() {
String longTagKey = StringUtils.repeat('k', TAG_KEY_LENGTH_LIMIT + 1);
-
when(headersWithLongTagKey.getHeaderString(TAG_HEADER)).thenReturn(longTagKey +
"=value1");
- objectEndpoint.setHeaders(headersWithLongTagKey);
- try {
- objectEndpoint.put(BUCKET_NAME, KEY_NAME, CONTENT.length(),
- 1, null, null, null, body);
- fail("request with tag key exceeding the length limit should fail");
- } catch (OS3Exception ex) {
- assertEquals(INVALID_TAG.getCode(), ex.getCode());
- assertThat(ex.getErrorMessage()).contains("The tag key exceeds the
maximum length");
- assertEquals(INVALID_TAG.getHttpCode(), ex.getHttpCode());
- }
+ when(headers.getHeaderString(TAG_HEADER)).thenReturn(longTagKey +
"=value1");
+
+ OS3Exception ex = assertErrorResponse(INVALID_TAG, () ->
putObject(CONTENT));
+ assertThat(ex.getErrorMessage()).contains("The tag key exceeds the maximum
length");
}
@Test
- public void testPutObjectWithLongTagValue() throws Exception {
- ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
- HttpHeaders headersWithLongTagValue = Mockito.mock(HttpHeaders.class);
-
when(headersWithLongTagValue.getHeaderString(X_AMZ_CONTENT_SHA256)).thenReturn("mockSignature");
- objectEndpoint.setHeaders(headersWithLongTagValue);
+ public void testPutObjectWithLongTagValue() {
String longTagValue = StringUtils.repeat('v', TAG_VALUE_LENGTH_LIMIT + 1);
-
when(headersWithLongTagValue.getHeaderString(TAG_HEADER)).thenReturn("tag1=" +
longTagValue);
- try {
- objectEndpoint.put(BUCKET_NAME, KEY_NAME, CONTENT.length(),
- 1, null, null, null, body);
- fail("request with tag value exceeding the length limit should fail");
- } catch (OS3Exception ex) {
- assertEquals(INVALID_TAG.getCode(), ex.getCode());
- assertThat(ex.getErrorMessage()).contains("The tag value exceeds the
maximum length");
- assertEquals(INVALID_TAG.getHttpCode(), ex.getHttpCode());
- }
+ when(headers.getHeaderString(TAG_HEADER)).thenReturn("tag1=" +
longTagValue);
+
+ OS3Exception ex = assertErrorResponse(INVALID_TAG, () ->
putObject(CONTENT));
+ assertThat(ex.getErrorMessage()).contains("The tag value exceeds the
maximum length");
}
@Test
- public void testPutObjectWithTooManyTags() throws Exception {
- ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
- HttpHeaders headersWithTooManyTags = Mockito.mock(HttpHeaders.class);
-
when(headersWithTooManyTags.getHeaderString(X_AMZ_CONTENT_SHA256)).thenReturn("mockSignature");
+ public void testPutObjectWithTooManyTags() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < TAG_NUM_LIMIT + 1; i++) {
sb.append(String.format("tag%d=value%d", i, i));
@@ -323,57 +213,37 @@ public void testPutObjectWithTooManyTags() throws
Exception {
sb.append('&');
}
}
-
when(headersWithTooManyTags.getHeaderString(TAG_HEADER)).thenReturn(sb.toString());
- objectEndpoint.setHeaders(headersWithTooManyTags);
- try {
- objectEndpoint.put(BUCKET_NAME, KEY_NAME, CONTENT.length(),
- 1, null, null, null, body);
- fail("request with number of tags exceeding limit should fail");
- } catch (OS3Exception ex) {
- assertEquals(INVALID_TAG.getCode(), ex.getCode());
- assertThat(ex.getErrorMessage()).contains("exceeded the maximum number
of tags");
- assertEquals(INVALID_TAG.getHttpCode(), ex.getHttpCode());
- }
- }
+ when(headers.getHeaderString(TAG_HEADER)).thenReturn(sb.toString());
- private long getKeyDataSize() throws IOException {
- return clientStub.getObjectStore().getS3Bucket(BUCKET_NAME)
- .getKey(KEY_NAME).getDataSize();
+ OS3Exception ex = assertErrorResponse(INVALID_TAG, () ->
putObject(CONTENT));
+ assertThat(ex.getErrorMessage()).contains("exceeded the maximum number of
tags");
}
@Test
- void testPutObjectWithSignedChunks() throws IOException, OS3Exception {
+ void testPutObjectWithSignedChunks() throws Exception {
//GIVEN
String chunkedContent = "0a;chunk-signature=signature\r\n"
+ "1234567890\r\n"
+ "05;chunk-signature=signature\r\n"
+ "abcde\r\n";
- when(headers.getHeaderString("x-amz-content-sha256"))
- .thenReturn("STREAMING-AWS4-HMAC-SHA256-PAYLOAD");
+ when(headers.getHeaderString(X_AMZ_CONTENT_SHA256))
+ .thenReturn(STREAMING_AWS4_HMAC_SHA256_PAYLOAD);
when(headers.getHeaderString(DECODED_CONTENT_LENGTH_HEADER))
.thenReturn("15");
//WHEN
- Response response = objectEndpoint.put(BUCKET_NAME, KEY_NAME,
- chunkedContent.length(), 1, null, null, null,
- new ByteArrayInputStream(chunkedContent.getBytes(UTF_8)));
+ assertSucceeds(() -> putObject(chunkedContent));
//THEN
- OzoneInputStream ozoneInputStream =
- clientStub.getObjectStore().getS3Bucket(BUCKET_NAME)
- .readKey(KEY_NAME);
- String keyContent = IOUtils.toString(ozoneInputStream, UTF_8);
- OzoneKeyDetails keyDetails =
clientStub.getObjectStore().getS3Bucket(BUCKET_NAME).getKey(KEY_NAME);
-
- assertEquals(200, response.getStatus());
- assertEquals("1234567890abcde", keyContent);
+ OzoneKeyDetails keyDetails = assertKeyContent(bucket, KEY_NAME,
"1234567890abcde");
assertNotNull(keyDetails.getMetadata());
assertThat(keyDetails.getMetadata().get(OzoneConsts.ETAG)).isNotEmpty();
+ assertEquals(15, keyDetails.getDataSize());
}
@Test
- public void testPutObjectMessageDigestResetDuringException() throws
OS3Exception {
+ public void testPutObjectMessageDigestResetDuringException() {
MessageDigest messageDigest = mock(MessageDigest.class);
try (MockedStatic<IOUtils> mocked = mockStatic(IOUtils.class)) {
// For example, EOFException during put-object due to client cancelling
the operation before it completes
@@ -382,52 +252,35 @@ public void
testPutObjectMessageDigestResetDuringException() throws OS3Exception
.thenThrow(IOException.class);
when(objectEndpoint.getMessageDigestInstance()).thenReturn(messageDigest);
- ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
- try {
- objectEndpoint.put(BUCKET_NAME, KEY_NAME, CONTENT
- .length(), 1, null, null, null, body);
- fail("Should throw IOException");
- } catch (IOException ignored) {
- // Verify that the message digest is reset so that the instance can be
reused for the
- // next request in the same thread
- verify(messageDigest, times(1)).reset();
- }
+ assertThrows(IOException.class, () -> putObject(CONTENT).close());
+
+ // Verify that the message digest is reset so that the instance can be
reused for the
+ // next request in the same thread
+ verify(messageDigest, times(1)).reset();
}
}
@Test
- void testCopyObject() throws IOException, OS3Exception {
+ void testCopyObject() throws Exception {
// Put object in to source bucket
- ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
// Add some custom metadata
+ Map<String, String> customMetadata = ImmutableMap.of(
+ "custom-key-1", "custom-value-1",
+ "custom-key-2", "custom-value-2");
MultivaluedMap<String, String> metadataHeaders = new
MultivaluedHashMap<>();
- metadataHeaders.putSingle(CUSTOM_METADATA_HEADER_PREFIX + "custom-key-1",
"custom-value-1");
- metadataHeaders.putSingle(CUSTOM_METADATA_HEADER_PREFIX + "custom-key-2",
"custom-value-2");
+ customMetadata.forEach((k, v) ->
metadataHeaders.putSingle(CUSTOM_METADATA_HEADER_PREFIX + k, v));
when(headers.getRequestHeaders()).thenReturn(metadataHeaders);
// Add COPY metadata directive (default)
when(headers.getHeaderString(CUSTOM_METADATA_COPY_DIRECTIVE_HEADER)).thenReturn("COPY");
- Response response = objectEndpoint.put(BUCKET_NAME, KEY_NAME,
- CONTENT.length(), 1, null, null, null, body);
-
- OzoneInputStream ozoneInputStream = clientStub.getObjectStore()
- .getS3Bucket(BUCKET_NAME)
- .readKey(KEY_NAME);
+ assertSucceeds(() -> putObject(CONTENT));
- String keyContent = IOUtils.toString(ozoneInputStream, UTF_8);
- OzoneKeyDetails keyDetails =
clientStub.getObjectStore().getS3Bucket(BUCKET_NAME).getKey(KEY_NAME);
-
- assertEquals(200, response.getStatus());
- assertEquals(CONTENT, keyContent);
+ OzoneKeyDetails keyDetails = assertKeyContent(bucket, KEY_NAME, CONTENT);
assertNotNull(keyDetails.getMetadata());
- assertThat(keyDetails.getMetadata().get(OzoneConsts.ETAG)).isNotEmpty();
-
assertThat(keyDetails.getMetadata().get("custom-key-1")).isEqualTo("custom-value-1");
-
assertThat(keyDetails.getMetadata().get("custom-key-2")).isEqualTo("custom-value-2");
-
String sourceETag = keyDetails.getMetadata().get(OzoneConsts.ETAG);
+ assertThat(sourceETag).isNotEmpty();
+ assertThat(keyDetails.getMetadata()).containsAllEntriesOf(customMetadata);
// This will be ignored since the copy directive is COPY
metadataHeaders.putSingle(CUSTOM_METADATA_HEADER_PREFIX + "custom-key-3",
"custom-value-3");
@@ -436,126 +289,79 @@ void testCopyObject() throws IOException, OS3Exception {
when(headers.getHeaderString(COPY_SOURCE_HEADER)).thenReturn(
BUCKET_NAME + "/" + urlEncode(KEY_NAME));
- response = objectEndpoint.put(DEST_BUCKET_NAME, DEST_KEY,
CONTENT.length(), 1,
- null, null, null, body);
+ assertSucceeds(() -> put(objectEndpoint, DEST_BUCKET_NAME, DEST_KEY,
CONTENT));
// Check destination key and response
- ozoneInputStream =
clientStub.getObjectStore().getS3Bucket(DEST_BUCKET_NAME)
- .readKey(DEST_KEY);
-
- keyContent = IOUtils.toString(ozoneInputStream, UTF_8);
- OzoneKeyDetails sourceKeyDetails = clientStub.getObjectStore()
- .getS3Bucket(BUCKET_NAME).getKey(KEY_NAME);
- OzoneKeyDetails destKeyDetails = clientStub.getObjectStore()
- .getS3Bucket(DEST_BUCKET_NAME).getKey(DEST_KEY);
-
- assertEquals(200, response.getStatus());
- assertEquals(CONTENT, keyContent);
- assertNotNull(keyDetails.getMetadata());
- assertThat(keyDetails.getMetadata().get(OzoneConsts.ETAG)).isNotEmpty();
+ OzoneKeyDetails destKeyDetails = assertKeyContent(destBucket, DEST_KEY,
CONTENT);
+ keyDetails = bucket.getKey(KEY_NAME);
// Source key eTag should remain unchanged and the dest key should have
// the same Etag since the key content is the same
- assertEquals(sourceETag,
sourceKeyDetails.getMetadata().get(OzoneConsts.ETAG));
+ assertEquals(sourceETag, keyDetails.getMetadata().get(OzoneConsts.ETAG));
assertEquals(sourceETag,
destKeyDetails.getMetadata().get(OzoneConsts.ETAG));
-
assertThat(destKeyDetails.getMetadata().get("custom-key-1")).isEqualTo("custom-value-1");
-
assertThat(destKeyDetails.getMetadata().get("custom-key-2")).isEqualTo("custom-value-2");
-
assertThat(destKeyDetails.getMetadata().containsKey("custom-key-3")).isFalse();
+ assertThat(destKeyDetails.getMetadata())
+ .containsAllEntriesOf(customMetadata)
+ .doesNotContainKey("custom-key-3");
// Now use REPLACE metadata directive (default) and remove some custom
metadata used in the source key
when(headers.getHeaderString(CUSTOM_METADATA_COPY_DIRECTIVE_HEADER)).thenReturn("REPLACE");
metadataHeaders.remove(CUSTOM_METADATA_HEADER_PREFIX + "custom-key-1");
metadataHeaders.remove(CUSTOM_METADATA_HEADER_PREFIX + "custom-key-2");
- response = objectEndpoint.put(DEST_BUCKET_NAME, DEST_KEY,
CONTENT.length(), 1,
- null, null, null, body);
-
- ozoneInputStream =
clientStub.getObjectStore().getS3Bucket(DEST_BUCKET_NAME)
- .readKey(DEST_KEY);
+ assertSucceeds(() -> put(objectEndpoint, DEST_BUCKET_NAME, DEST_KEY,
CONTENT));
- keyContent = IOUtils.toString(ozoneInputStream, UTF_8);
- sourceKeyDetails = clientStub.getObjectStore()
- .getS3Bucket(BUCKET_NAME).getKey(KEY_NAME);
- destKeyDetails = clientStub.getObjectStore()
- .getS3Bucket(DEST_BUCKET_NAME).getKey(DEST_KEY);
-
- assertEquals(200, response.getStatus());
- assertEquals(CONTENT, keyContent);
+ destKeyDetails = assertKeyContent(destBucket, DEST_KEY, CONTENT);
assertNotNull(keyDetails.getMetadata());
- assertThat(keyDetails.getMetadata().get(OzoneConsts.ETAG)).isNotEmpty();
// Source key eTag should remain unchanged and the dest key should have
// the same Etag since the key content is the same
- assertEquals(sourceETag,
sourceKeyDetails.getMetadata().get(OzoneConsts.ETAG));
+ assertEquals(sourceETag, keyDetails.getMetadata().get(OzoneConsts.ETAG));
assertEquals(sourceETag,
destKeyDetails.getMetadata().get(OzoneConsts.ETAG));
-
assertThat(destKeyDetails.getMetadata().containsKey("custom-key-1")).isFalse();
-
assertThat(destKeyDetails.getMetadata().containsKey("custom-key-2")).isFalse();
-
assertThat(destKeyDetails.getMetadata().get("custom-key-3")).isEqualTo("custom-value-3");
+ assertThat(destKeyDetails.getMetadata())
+ .doesNotContainKeys("custom-key-1", "custom-key-2")
+ .containsEntry("custom-key-3", "custom-value-3");
// wrong copy metadata directive
when(headers.getHeaderString(CUSTOM_METADATA_COPY_DIRECTIVE_HEADER)).thenReturn("INVALID");
- OS3Exception e = assertThrows(OS3Exception.class, () -> objectEndpoint.put(
- DEST_BUCKET_NAME, DEST_KEY, CONTENT.length(), 1, null, null, null,
body),
- "test copy object failed");
- assertThat(e.getHttpCode()).isEqualTo(400);
- assertThat(e.getCode()).isEqualTo("InvalidArgument");
+ OS3Exception e = assertErrorResponse(INVALID_ARGUMENT,
+ () -> put(objectEndpoint, DEST_BUCKET_NAME, DEST_KEY, CONTENT));
assertThat(e.getErrorMessage()).contains("The metadata copy directive
specified is invalid");
when(headers.getHeaderString(CUSTOM_METADATA_COPY_DIRECTIVE_HEADER)).thenReturn("COPY");
// source and dest same
- e = assertThrows(OS3Exception.class, () -> objectEndpoint.put(
- BUCKET_NAME, KEY_NAME, CONTENT.length(), 1, null, null, null,
body),
- "test copy object failed");
+ e = assertErrorResponse(INVALID_REQUEST, () -> putObject(CONTENT));
assertThat(e.getErrorMessage()).contains("This copy request is illegal");
// source bucket not found
when(headers.getHeaderString(COPY_SOURCE_HEADER)).thenReturn(
- NO_SUCH_BUCKET + "/" + urlEncode(KEY_NAME));
- e = assertThrows(OS3Exception.class, () ->
objectEndpoint.put(DEST_BUCKET_NAME,
- DEST_KEY, CONTENT.length(), 1, null, null, null, body), "test copy
object failed");
- assertThat(e.getCode()).contains("NoSuchBucket");
+ NONEXISTENT_BUCKET + "/" + urlEncode(KEY_NAME));
+ assertErrorResponse(NO_SUCH_BUCKET,
+ () -> put(objectEndpoint, DEST_BUCKET_NAME, DEST_KEY, CONTENT));
// dest bucket not found
when(headers.getHeaderString(COPY_SOURCE_HEADER)).thenReturn(
BUCKET_NAME + "/" + urlEncode(KEY_NAME));
- e = assertThrows(OS3Exception.class, () ->
objectEndpoint.put(NO_SUCH_BUCKET,
- DEST_KEY, CONTENT.length(), 1, null, null, null, body), "test copy
object failed");
- assertThat(e.getCode()).contains("NoSuchBucket");
+ assertErrorResponse(NO_SUCH_BUCKET,
+ () -> put(objectEndpoint, NONEXISTENT_BUCKET, DEST_KEY, CONTENT));
//Both source and dest bucket not found
when(headers.getHeaderString(COPY_SOURCE_HEADER)).thenReturn(
- NO_SUCH_BUCKET + "/" + urlEncode(KEY_NAME));
- e = assertThrows(OS3Exception.class, () ->
objectEndpoint.put(NO_SUCH_BUCKET,
- DEST_KEY, CONTENT.length(), 1, null, null, null, body), "test copy
object failed");
- assertThat(e.getCode()).contains("NoSuchBucket");
+ NONEXISTENT_BUCKET + "/" + urlEncode(KEY_NAME));
+ assertErrorResponse(NO_SUCH_BUCKET,
+ () -> put(objectEndpoint, NONEXISTENT_BUCKET, DEST_KEY, CONTENT));
// source key not found
when(headers.getHeaderString(COPY_SOURCE_HEADER)).thenReturn(
- BUCKET_NAME + "/" + urlEncode(NO_SUCH_BUCKET));
- e = assertThrows(OS3Exception.class, () -> objectEndpoint.put(
- "nonexistent", KEY_NAME, CONTENT.length(), 1, null, null, null, body),
- "test copy object failed");
- assertThat(e.getCode()).contains("NoSuchBucket");
+ BUCKET_NAME + "/" + urlEncode(NONEXISTENT_BUCKET));
+ assertErrorResponse(NO_SUCH_BUCKET,
+ () -> put(objectEndpoint, "nonexistent", KEY_NAME, CONTENT));
}
@Test
- public void testCopyObjectMessageDigestResetDuringException() throws
IOException, OS3Exception {
- // Put object in to source bucket
- ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
-
- Response response = objectEndpoint.put(BUCKET_NAME, KEY_NAME,
- CONTENT.length(), 1, null, null, null, body);
-
- OzoneInputStream ozoneInputStream = clientStub.getObjectStore()
- .getS3Bucket(BUCKET_NAME)
- .readKey(KEY_NAME);
-
- String keyContent = IOUtils.toString(ozoneInputStream, UTF_8);
- OzoneKeyDetails keyDetails =
clientStub.getObjectStore().getS3Bucket(BUCKET_NAME).getKey(KEY_NAME);
+ public void testCopyObjectMessageDigestResetDuringException() throws
Exception {
+ assertSucceeds(() -> putObject(CONTENT));
- assertEquals(200, response.getStatus());
- assertEquals(CONTENT, keyContent);
+ OzoneKeyDetails keyDetails = assertKeyContent(bucket, KEY_NAME, CONTENT);
assertNotNull(keyDetails.getMetadata());
assertThat(keyDetails.getMetadata().get(OzoneConsts.ETAG)).isNotEmpty();
@@ -571,55 +377,40 @@ public void
testCopyObjectMessageDigestResetDuringException() throws IOException
when(headers.getHeaderString(COPY_SOURCE_HEADER)).thenReturn(
BUCKET_NAME + "/" + urlEncode(KEY_NAME));
- try {
- objectEndpoint.put(DEST_BUCKET_NAME, DEST_KEY, CONTENT.length(), 1,
- null, null, null, body);
- fail("Should throw IOException");
- } catch (IOException ignored) {
- // Verify that the message digest is reset so that the instance can be
reused for the
- // next request in the same thread
- verify(messageDigest, times(1)).reset();
- }
+ assertThrows(IOException.class, () -> putObject(DEST_BUCKET_NAME,
DEST_KEY).close());
+ // Verify that the message digest is reset so that the instance can be
reused for the
+ // next request in the same thread
+ verify(messageDigest, times(1)).reset();
}
}
@Test
- public void testCopyObjectWithTags() throws IOException, OS3Exception {
+ public void testCopyObjectWithTags() throws Exception {
// Put object in to source bucket
- HttpHeaders headersForPut = Mockito.mock(HttpHeaders.class);
-
when(headersForPut.getHeaderString(X_AMZ_CONTENT_SHA256)).thenReturn("mockSignature");
+ HttpHeaders headersForPut = newMockHttpHeaders();
when(headersForPut.getHeaderString(TAG_HEADER)).thenReturn("tag1=value1&tag2=value2");
- ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
objectEndpoint.setHeaders(headersForPut);
String sourceKeyName = "sourceKey";
- Response putResponse = objectEndpoint.put(BUCKET_NAME, sourceKeyName,
- CONTENT.length(), 1, null, null, null, body);
- OzoneKeyDetails keyDetails =
-
clientStub.getObjectStore().getS3Bucket(BUCKET_NAME).getKey(sourceKeyName);
+ assertSucceeds(() -> putObject(BUCKET_NAME, sourceKeyName));
- assertEquals(200, putResponse.getStatus());
- Map<String, String> tags = keyDetails.getTags();
+ Map<String, String> tags = bucket.getKey(sourceKeyName).getTags();
assertEquals(2, tags.size());
assertEquals("value1", tags.get("tag1"));
assertEquals("value2", tags.get("tag2"));
// Copy object without x-amz-tagging-directive (default to COPY)
String destKey = "key=value/2";
- HttpHeaders headersForCopy = Mockito.mock(HttpHeaders.class);
-
when(headersForCopy.getHeaderString(X_AMZ_CONTENT_SHA256)).thenReturn("mockSignature");
+ HttpHeaders headersForCopy = newMockHttpHeaders();
when(headersForCopy.getHeaderString(COPY_SOURCE_HEADER)).thenReturn(
BUCKET_NAME + "/" + urlEncode(sourceKeyName));
-
objectEndpoint.setHeaders(headersForCopy);
- Response copyResponse = objectEndpoint.put(DEST_BUCKET_NAME, destKey,
CONTENT.length(), 1, null, null, null, body);
- OzoneKeyDetails destKeyDetails = clientStub.getObjectStore()
- .getS3Bucket(DEST_BUCKET_NAME).getKey(destKey);
+ assertSucceeds(() -> putObject(DEST_BUCKET_NAME, destKey));
+
+ OzoneKeyDetails destKeyDetails = destBucket.getKey(destKey);
- assertEquals(200, copyResponse.getStatus());
Map<String, String> destKeyTags = destKeyDetails.getTags();
// Since the default directive is COPY, it will copy the source key's tags
@@ -633,11 +424,9 @@ public void testCopyObjectWithTags() throws IOException,
OS3Exception {
// With x-amz-tagging-directive = COPY with a different x-amz-tagging
when(headersForCopy.getHeaderString(TAG_HEADER)).thenReturn("tag3=value3");
- copyResponse = objectEndpoint.put(DEST_BUCKET_NAME, destKey,
CONTENT.length(), 1, null, null, null, body);
- assertEquals(200, copyResponse.getStatus());
+ assertSucceeds(() -> putObject(DEST_BUCKET_NAME, destKey));
- destKeyDetails = clientStub.getObjectStore()
- .getS3Bucket(DEST_BUCKET_NAME).getKey(destKey);
+ destKeyDetails = destBucket.getKey(destKey);
destKeyTags = destKeyDetails.getTags();
// Since the x-amz-tagging-directive is COPY, we ignore the x-amz-tagging
@@ -648,11 +437,9 @@ public void testCopyObjectWithTags() throws IOException,
OS3Exception {
// Copy object with x-amz-tagging-directive = REPLACE
when(headersForCopy.getHeaderString(TAG_DIRECTIVE_HEADER)).thenReturn("REPLACE");
- copyResponse = objectEndpoint.put(DEST_BUCKET_NAME, destKey,
CONTENT.length(), 1, null, null, null, body);
- assertEquals(200, copyResponse.getStatus());
+ assertSucceeds(() -> putObject(DEST_BUCKET_NAME, destKey));
- destKeyDetails = clientStub.getObjectStore()
- .getS3Bucket(DEST_BUCKET_NAME).getKey(destKey);
+ destKeyDetails = destBucket.getKey(destKey);
destKeyTags = destKeyDetails.getTags();
// Since the x-amz-tagging-directive is REPLACE, we replace the source key
@@ -660,66 +447,41 @@ public void testCopyObjectWithTags() throws IOException,
OS3Exception {
assertEquals(1, destKeyTags.size());
assertEquals("value3", destKeyTags.get("tag3"));
assertThat(destKeyTags).doesNotContainKeys("tag1", "tag2");
- }
- @Test
- public void testCopyObjectWithInvalidTagCopyDirective() throws Exception {
- ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
// Copy object with invalid x-amz-tagging-directive
- HttpHeaders headersForCopy = Mockito.mock(HttpHeaders.class);
when(headersForCopy.getHeaderString(TAG_DIRECTIVE_HEADER)).thenReturn("INVALID");
- try {
- objectEndpoint.put(DEST_BUCKET_NAME, "somekey", CONTENT.length(), 1,
null, null, null, body);
- } catch (OS3Exception ex) {
- assertEquals(INVALID_ARGUMENT.getCode(), ex.getCode());
- assertThat(ex.getErrorMessage()).contains("The tagging copy directive
specified is invalid");
- assertEquals(INVALID_ARGUMENT.getHttpCode(), ex.getHttpCode());
- }
+ OS3Exception e = assertErrorResponse(INVALID_ARGUMENT,
+ () -> put(objectEndpoint, DEST_BUCKET_NAME, "somekey", CONTENT));
+ assertThat(e.getErrorMessage()).contains("The tagging copy directive
specified is invalid");
}
@Test
void testInvalidStorageType() {
- ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
when(headers.getHeaderString(STORAGE_CLASS_HEADER)).thenReturn("random");
- OS3Exception e = assertThrows(OS3Exception.class, () -> objectEndpoint.put(
- BUCKET_NAME, KEY_NAME, CONTENT.length(), 1, null, null, null, body));
- assertEquals(S3ErrorTable.INVALID_STORAGE_CLASS.getErrorMessage(),
- e.getErrorMessage());
+ OS3Exception e = assertErrorResponse(S3ErrorTable.INVALID_STORAGE_CLASS,
() -> putObject(CONTENT));
assertEquals("random", e.getResource());
}
@Test
- void testEmptyStorageType() throws IOException, OS3Exception {
- ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
+ void testEmptyStorageType() throws Exception {
when(headers.getHeaderString(STORAGE_CLASS_HEADER)).thenReturn("");
- objectEndpoint.put(BUCKET_NAME, KEY_NAME, CONTENT
- .length(), 1, null, null, null, body);
- OzoneKeyDetails key =
- clientStub.getObjectStore().getS3Bucket(BUCKET_NAME)
- .getKey(KEY_NAME);
+ assertSucceeds(() -> putObject(CONTENT));
//default type is set
assertEquals(
RatisReplicationConfig.getInstance(HddsProtos.ReplicationFactor.THREE),
- key.getReplicationConfig());
+ bucket.getKey(KEY_NAME).getReplicationConfig());
}
@Test
- void testDirectoryCreation() throws IOException,
- OS3Exception {
+ void testDirectoryCreation() throws Exception {
// GIVEN
final String path = "dir/";
// WHEN
- try (Response response = objectEndpoint.put(fsoBucket.getName(), path,
- 0L, 0, "", null, null, null)) {
- assertEquals(HttpStatus.SC_OK, response.getStatus());
- }
+ assertSucceeds(() -> putDir(objectEndpoint, fsoBucket.getName(), path));
// THEN
OzoneKeyDetails key = fsoBucket.getKey(path);
@@ -727,35 +489,34 @@ void testDirectoryCreation() throws IOException,
}
@Test
- void testDirectoryCreationOverFile() throws IOException, OS3Exception {
+ void testDirectoryCreationOverFile() throws Exception {
// GIVEN
final String path = "key";
- final ByteArrayInputStream body =
- new ByteArrayInputStream(CONTENT.getBytes(UTF_8));
- objectEndpoint.put(FSO_BUCKET_NAME, path, CONTENT.length(), 0, "", null,
null, body);
-
- // WHEN
- final OS3Exception exception = assertThrows(OS3Exception.class,
- () -> objectEndpoint
- .put(FSO_BUCKET_NAME, path + "/", 0, 0, "", null, null, null)
- .close());
+ assertSucceeds(() -> putObject(FSO_BUCKET_NAME, path));
- // THEN
- assertEquals(S3ErrorTable.NO_OVERWRITE.getCode(), exception.getCode());
- assertEquals(S3ErrorTable.NO_OVERWRITE.getHttpCode(),
exception.getHttpCode());
+ assertErrorResponse(S3ErrorTable.NO_OVERWRITE,
+ () -> putDir(objectEndpoint, FSO_BUCKET_NAME, path + "/"));
}
@Test
- public void testPutEmptyObject() throws IOException, OS3Exception {
- HttpHeaders headersWithTags = Mockito.mock(HttpHeaders.class);
-
when(headersWithTags.getHeaderString(X_AMZ_CONTENT_SHA256)).thenReturn("mockSignature");
- String emptyString = "";
- ByteArrayInputStream body = new
ByteArrayInputStream(emptyString.getBytes(UTF_8));
- objectEndpoint.setHeaders(headersWithTags);
-
- Response putResponse = objectEndpoint.put(BUCKET_NAME, KEY_NAME,
emptyString.length(), 1, null, null, null, body);
- assertEquals(200, putResponse.getStatus());
- OzoneKeyDetails keyDetails =
clientStub.getObjectStore().getS3Bucket(BUCKET_NAME).getKey(KEY_NAME);
- assertEquals(0, keyDetails.getDataSize());
+ public void testPutEmptyObject() throws Exception {
+ assertSucceeds(() -> putObject(""));
+ assertEquals(0, bucket.getKey(KEY_NAME).getDataSize());
+ }
+
+ private HttpHeaders newMockHttpHeaders() {
+ HttpHeaders httpHeaders = mock(HttpHeaders.class);
+
when(httpHeaders.getHeaderString(X_AMZ_CONTENT_SHA256)).thenReturn("mockSignature");
+ return httpHeaders;
+ }
+
+ /** Put object at {@code bucketName}/{@code keyName} with pre-defined {@link
#CONTENT}. */
+ private Response putObject(String bucketName, String keyName) throws
IOException, OS3Exception {
+ return put(objectEndpoint, bucketName, keyName, CONTENT);
+ }
+
+ /** Put object at {@link #BUCKET_NAME}/{@link #KEY_NAME} with the specified
content. */
+ private Response putObject(String content) throws IOException, OS3Exception {
+ return put(objectEndpoint, BUCKET_NAME, KEY_NAME, content);
}
}
diff --git a/pom.xml b/pom.xml
index 9fcee28d5af..73ed23ae01f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1129,6 +1129,12 @@
<artifactId>ozone-client</artifactId>
<version>${ozone.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.ozone</groupId>
+ <artifactId>ozone-client</artifactId>
+ <version>${ozone.version}</version>
+ <type>test-jar</type>
+ </dependency>
<dependency>
<groupId>org.apache.ozone</groupId>
<artifactId>ozone-common</artifactId>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]