use of com.github.ambry.rest.MockRestResponseChannel in project ambry by linkedin.
the class GetStatsReportHandlerTest method handleBadCaseTest.
@Test
public void handleBadCaseTest() throws Exception {
ThrowingBiConsumer<RestRequest, RestServiceErrorCode> testAction = (request, expectedErrorCode) -> {
TestUtils.assertException(RestServiceException.class, () -> sendRequestGetResponse(request, new MockRestResponseChannel()), e -> assertEquals(expectedErrorCode, e.getErrorCode()));
};
RestRequest request = createRestRequest("WRONG_CLUSTER", StatsReportType.ACCOUNT_REPORT.name());
testAction.accept(request, RestServiceErrorCode.NotFound);
request = createRestRequest(null, StatsReportType.ACCOUNT_REPORT.name());
testAction.accept(request, RestServiceErrorCode.MissingArgs);
request = createRestRequest(CLUSTER_NAME, "WRONG_STATS_REPORT_TYPE");
testAction.accept(request, RestServiceErrorCode.BadRequest);
request = createRestRequest(CLUSTER_NAME, null);
testAction.accept(request, RestServiceErrorCode.MissingArgs);
}
use of com.github.ambry.rest.MockRestResponseChannel in project ambry by linkedin.
the class PostAccountContainersHandlerTest method validRequestsTest.
/**
* Test valid request cases.
* @throws Exception
*/
@Test
public void validRequestsTest() throws Exception {
String accountName = theAccount.getName();
short accountId = theAccount.getId();
ThrowingConsumer<Collection<Container>> testAction = inputContainers -> {
String requestBody = new String(AccountCollectionSerde.serializeContainersInJson(inputContainers));
RestResponseChannel restResponseChannel = new MockRestResponseChannel();
RestRequest request = createRestRequest(requestBody, accountName, null);
ReadableStreamChannel responseChannel = sendRequestGetResponse(request, restResponseChannel);
assertNotNull("Date has not been set", restResponseChannel.getHeader(RestUtils.Headers.DATE));
assertEquals("Content-length is not as expected", responseChannel.getSize(), Integer.parseInt((String) restResponseChannel.getHeader(RestUtils.Headers.CONTENT_LENGTH)));
assertEquals("Account id in response header is not as expected", accountId, Short.parseShort((String) restResponseChannel.getHeader(RestUtils.Headers.TARGET_ACCOUNT_ID)));
RetainingAsyncWritableChannel asyncWritableChannel = new RetainingAsyncWritableChannel((int) responseChannel.getSize());
responseChannel.readInto(asyncWritableChannel, null).get();
Collection<Container> outputContainers = AccountCollectionSerde.containersFromInputStreamInJson(asyncWritableChannel.consumeContentAsInputStream(), accountId);
assertEquals("Unexpected count returned", inputContainers.size(), outputContainers.size());
for (Container container : outputContainers) {
assertEquals("Container in account service not as expected", container, accountService.getContainerByName(accountName, container.getName()));
}
};
// add new container
testAction.accept(Collections.singleton(accountService.getRandomContainer(accountId)));
// add multiple containers
List<Container> containerList = new ArrayList<>();
for (int j = 0; j < 10; j++) {
containerList.add(new ContainerBuilder(Container.UNKNOWN_CONTAINER_ID, "Test-" + j, Container.ContainerStatus.ACTIVE, "", accountId).build());
}
testAction.accept(containerList);
// TODO: update existing containers when support is added
}
use of com.github.ambry.rest.MockRestResponseChannel in project ambry by linkedin.
the class PostBlobHandlerTest method doChunkUploadTest.
// chunkUploadTest() helpers
/**
* Make a post request and verify behavior related to chunk uploads (for stitched blobs).
* @param contentLength the size of the blob to upload.
* @param chunkUpload {@code true} to send the "x-ambry-chunk-upload" header, or {@code false} to test full uploads.
* @param uploadSession the value for the "x-ambry-chunk-upload-session" request header, or null to not set it.
* @param maxUploadSize the value for the "x-ambry-max-upload-size" request header, or null to not set it.
* @param blobTtlSecs the blob TTL to use.
* @param errorChecker if non-null, expect an exception to be thrown by the post flow and verify it using this
* {@link ThrowingConsumer}.
* @throws Exception
*/
private void doChunkUploadTest(int contentLength, boolean chunkUpload, String uploadSession, Integer maxUploadSize, long blobTtlSecs, ThrowingConsumer<ExecutionException> errorChecker) throws Exception {
JSONObject headers = new JSONObject();
FrontendRestRequestServiceTest.setAmbryHeadersForPut(headers, blobTtlSecs, !REF_CONTAINER.isCacheable(), SERVICE_ID, CONTENT_TYPE, OWNER_ID, REF_ACCOUNT.getName(), REF_CONTAINER.getName(), null);
if (chunkUpload) {
headers.put(RestUtils.Headers.CHUNK_UPLOAD, true);
}
if (uploadSession != null) {
headers.put(RestUtils.Headers.SESSION, uploadSession);
}
if (maxUploadSize != null) {
headers.put(RestUtils.Headers.MAX_UPLOAD_SIZE, maxUploadSize);
}
byte[] content = TestUtils.getRandomBytes(contentLength);
RestRequest request = getRestRequest(headers, "/", content);
long creationTimeMs = System.currentTimeMillis();
time.setCurrentMilliseconds(creationTimeMs);
RestResponseChannel restResponseChannel = new MockRestResponseChannel();
FutureResult<Void> future = new FutureResult<>();
idConverterFactory.lastInput = null;
postBlobHandler.handle(request, restResponseChannel, future::done);
if (errorChecker == null) {
future.get(TIMEOUT_SECS, TimeUnit.SECONDS);
assertEquals("Unexpected converted ID", CONVERTED_ID, restResponseChannel.getHeader(RestUtils.Headers.LOCATION));
Object metadata = request.getArgs().get(RestUtils.InternalKeys.SIGNED_ID_METADATA_KEY);
if (chunkUpload) {
Map<String, String> expectedMetadata = new HashMap<>(3);
expectedMetadata.put(RestUtils.Headers.BLOB_SIZE, Integer.toString(contentLength));
expectedMetadata.put(RestUtils.Headers.SESSION, uploadSession);
expectedMetadata.put(PostBlobHandler.EXPIRATION_TIME_MS_KEY, Long.toString(Utils.addSecondsToEpochTime(creationTimeMs, blobTtlSecs)));
assertEquals("Unexpected signed ID metadata", expectedMetadata, metadata);
} else {
assertNull("Signed id metadata should not be set on non-chunk uploads", metadata);
}
InMemoryRouter.InMemoryBlob blob = router.getActiveBlobs().get(idConverterFactory.lastInput);
assertEquals("Unexpected blob content stored", ByteBuffer.wrap(content), blob.getBlob());
assertEquals("Unexpected ttl stored", blobTtlSecs, blob.getBlobProperties().getTimeToLiveInSeconds());
// check that blob size matches the actual upload size
assertEquals("Invalid blob size", Integer.toString(contentLength), restResponseChannel.getHeader(RestUtils.Headers.BLOB_SIZE));
} else {
TestUtils.assertException(ExecutionException.class, () -> future.get(TIMEOUT_SECS, TimeUnit.SECONDS), errorChecker);
}
}
use of com.github.ambry.rest.MockRestResponseChannel in project ambry by linkedin.
the class PostBlobHandlerTest method stitchBlobAndVerify.
/**
* Make a stitch blob call using {@link PostBlobHandler} and verify the result of the operation.
* @param requestBody the body of the stitch request to supply.
* @param expectedStitchedChunks the expected chunks stitched together.
* @param errorChecker if non-null, expect an exception to be thrown by the post flow and verify it using this
* {@link ThrowingConsumer}.
* @throws Exception
*/
private void stitchBlobAndVerify(byte[] requestBody, List<ChunkInfo> expectedStitchedChunks, ThrowingConsumer<ExecutionException> errorChecker) throws Exception {
JSONObject headers = new JSONObject();
FrontendRestRequestServiceTest.setAmbryHeadersForPut(headers, TestUtils.TTL_SECS, !REF_CONTAINER.isCacheable(), SERVICE_ID, CONTENT_TYPE, OWNER_ID, REF_ACCOUNT.getName(), REF_CONTAINER.getName(), null);
RestRequest request = getRestRequest(headers, "/" + Operations.STITCH, requestBody);
RestResponseChannel restResponseChannel = new MockRestResponseChannel();
FutureResult<Void> future = new FutureResult<>();
idConverterFactory.lastInput = null;
postBlobHandler.handle(request, restResponseChannel, future::done);
if (errorChecker == null) {
future.get(TIMEOUT_SECS, TimeUnit.SECONDS);
assertEquals("Unexpected converted ID", CONVERTED_ID, restResponseChannel.getHeader(RestUtils.Headers.LOCATION));
InMemoryRouter.InMemoryBlob blob = router.getActiveBlobs().get(idConverterFactory.lastInput);
assertEquals("List of chunks stitched does not match expected", expectedStitchedChunks, blob.getStitchedChunks());
ByteArrayOutputStream expectedContent = new ByteArrayOutputStream();
expectedStitchedChunks.stream().map(chunkInfo -> router.getActiveBlobs().get(chunkInfo.getBlobId()).getBlob().array()).forEach(buf -> expectedContent.write(buf, 0, buf.length));
assertEquals("Unexpected blob content stored", ByteBuffer.wrap(expectedContent.toByteArray()), blob.getBlob());
// check actual size of stitched blob
assertEquals("Unexpected blob size", Long.toString(getStitchedBlobSize(expectedStitchedChunks)), restResponseChannel.getHeader(RestUtils.Headers.BLOB_SIZE));
} else {
TestUtils.assertException(ExecutionException.class, () -> future.get(TIMEOUT_SECS, TimeUnit.SECONDS), errorChecker);
}
}
use of com.github.ambry.rest.MockRestResponseChannel in project ambry by linkedin.
the class FrontendTestUrlSigningServiceFactory method doConditionalDeleteTest.
/**
* Tests blob conditional DELETE operations on the given {@code container}.
* @param toPostAccount the {@link Account} to use in post headers. Can be {@code null} if only using service ID.
* @param toPostContainer the {@link Container} to use in post headers. Can be {@code null} if only using service ID.
* @param serviceId the serviceId to use for the POST
* @param isPrivate the isPrivate flag to pass as part of the POST
* @param expectedAccount the {@link Account} details that are eventually expected to be populated.
* @param expectedContainer the {@link Container} details that are eventually expected to be populated.
* @throws Exception
*/
private void doConditionalDeleteTest(Account toPostAccount, Container toPostContainer, String serviceId, boolean isPrivate, Account expectedAccount, Container expectedContainer) throws Exception {
final int CONTENT_LENGTH = 1024;
ByteBuffer content = ByteBuffer.wrap(TestUtils.getRandomBytes(CONTENT_LENGTH));
String contentType = "application/octet-stream";
String ownerId = "postGetHeadDeleteOwnerID";
JSONObject headers = new JSONObject();
String accountNameInPost = toPostAccount != null ? toPostAccount.getName() : null;
String containerNameInPost = toPostContainer != null ? toPostContainer.getName() : null;
setAmbryHeadersForPut(headers, 7200, isPrivate, serviceId, contentType, ownerId, accountNameInPost, containerNameInPost);
Map<String, String> userMetadata = new HashMap<>();
userMetadata.put(RestUtils.Headers.USER_META_DATA_HEADER_PREFIX + "key1", "value1");
userMetadata.put(RestUtils.Headers.USER_META_DATA_HEADER_PREFIX + "key2", "value2");
RestUtilsTest.setUserMetadataHeaders(headers, userMetadata);
// perform POST, GET, HEAD successfully before DELETE
String blobId = postBlobAndVerify(headers, content, expectedAccount, expectedContainer);
headers.put(RestUtils.Headers.BLOB_SIZE, (long) CONTENT_LENGTH);
getBlobAndVerify(blobId, null, null, headers, content, expectedAccount, expectedContainer);
getHeadAndVerify(blobId, null, null, headers, expectedAccount, expectedContainer);
// test Conditional Delete failure because only container name is set
RestResponseChannel restResponseChannel = new MockRestResponseChannel();
JSONObject headers2 = new JSONObject();
setAccountAndContainerHeaders(headers2, null, containerNameInPost);
RestRequest restRequest = createRestRequest(RestMethod.DELETE, blobId, headers2, null);
try {
doOperation(restRequest, restResponseChannel);
fail("Operation should have failed because only container name is set");
} catch (RestServiceException e) {
assertEquals("AmbryBlobStorageService should have thrown a BadRequest exception", RestServiceErrorCode.BadRequest, e.getErrorCode());
}
// test Conditional Delete failure because of incorrect account name
restResponseChannel = new MockRestResponseChannel();
setAccountAndContainerHeaders(headers, "INCORRECT_ACCOUNT_NAME", containerNameInPost);
restRequest = createRestRequest(RestMethod.DELETE, blobId, headers, null);
try {
doOperation(restRequest, restResponseChannel);
fail("Operation should have failed because incorrect account name");
} catch (RestServiceException e) {
assertEquals("AmbryBlobStorageService should have thrown a PreconditionFailed exception", RestServiceErrorCode.PreconditionFailed, e.getErrorCode());
}
// test Conditional Delete failure because of incorrect container name
restResponseChannel = new MockRestResponseChannel();
setAccountAndContainerHeaders(headers, accountNameInPost, "INCORRECT_CONTAINER_NAME");
restRequest = createRestRequest(RestMethod.DELETE, blobId, headers, null);
try {
doOperation(restRequest, restResponseChannel);
fail("Operation should have failed because incorrect container name");
} catch (RestServiceException e) {
assertEquals("AmbryBlobStorageService should have thrown a PreconditionFailed exception", RestServiceErrorCode.PreconditionFailed, e.getErrorCode());
}
// test Conditional Delete succeeds
setAccountAndContainerHeaders(headers, accountNameInPost, containerNameInPost);
restRequest = createRestRequest(RestMethod.DELETE, blobId, headers, null);
verifyDeleteAccepted(restRequest);
// check GET, HEAD and DELETE after delete.
verifyOperationsAfterDelete(blobId, headers, content, expectedAccount, expectedContainer);
}
Aggregations