/* * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed 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://aws.amazon.com/apache2.0 * * This file 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 com.amazonaws.mobileconnectors.kinesis.kinesisrecorder; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import com.amazonaws.AmazonClientException; import com.amazonaws.AmazonServiceException; import com.amazonaws.RequestClientOptions.Marker; import com.amazonaws.services.kinesis.AmazonKinesis; import com.amazonaws.services.kinesis.model.PutRecordsRequest; import com.amazonaws.services.kinesis.model.PutRecordsResult; import com.amazonaws.services.kinesis.model.PutRecordsResultEntry; import com.amazonaws.services.kinesisfirehose.model.InvalidArgumentException; import com.amazonaws.util.StringUtils; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class KinesisStreamRecordSenderTest { private static final String USER_AGENT = "test_agent"; private KinesisStreamRecordSender sender; private AmazonKinesis client; @Before public void setup() { client = Mockito.mock(AmazonKinesis.class); sender = new KinesisStreamRecordSender(client, USER_AGENT); } @Test public void testSendBatch() { String streamName = "stream"; int count = 10; // create an ok result PutRecordsResult result = new PutRecordsResult(); List<PutRecordsResultEntry> entries = new ArrayList<PutRecordsResultEntry>(); result.setFailedRecordCount(0); for (int i = 0; i < count; i++) { PutRecordsResultEntry entry = new PutRecordsResultEntry(); entry.setSequenceNumber("record_id_" + i); entries.add(entry); } result.setRecords(entries); // create data List<byte[]> data = new ArrayList<byte[]>(); for (int i = 0; i < count; i++) { data.add(("record" + i).getBytes(StringUtils.UTF8)); } Mockito.when(client.putRecords(any(PutRecordsRequest.class))).thenReturn(result); List<byte[]> failures = sender.sendBatch(streamName, data); ArgumentCaptor<PutRecordsRequest> argument = ArgumentCaptor .forClass(PutRecordsRequest.class); Mockito.verify(client).putRecords(argument.capture()); String userAgent = argument.getValue().getRequestClientOptions() .getClientMarker(Marker.USER_AGENT); // For some reason userAgent has a leading space assertTrue("user agent", userAgent.contains(USER_AGENT)); assertTrue("no failures", failures.isEmpty()); } @Test public void testSendBatchWithFailure() { String streamName = "stream"; int count = 10; // create a result with failures PutRecordsResult result = new PutRecordsResult(); List<PutRecordsResultEntry> entries = new ArrayList<PutRecordsResultEntry>(); result.setFailedRecordCount(5); for (int i = 0; i < count; i++) { PutRecordsResultEntry entry = new PutRecordsResultEntry(); // fail every other record if (i % 2 == 0) { entry.setSequenceNumber("record_id_" + i); } else { entry.setErrorCode("ServiceUnavailable"); } entries.add(entry); } result.setRecords(entries); // create data List<byte[]> data = new ArrayList<byte[]>(); for (int i = 0; i < count; i++) { data.add(("record" + i).getBytes(StringUtils.UTF8)); } Mockito.when(client.putRecords(any(PutRecordsRequest.class))).thenReturn(result); List<byte[]> failures = sender.sendBatch(streamName, data); assertTrue("has 5 failures", failures.size() == 5); for (int i = 0; i < 5; i++) { String failedRecordString = "record" + (i * 2 + 1); assertEquals(failedRecordString, new String(failures.get(i), StringUtils.UTF8)); } } @Test(expected = AmazonClientException.class) public void testSendBatchException() { String streamName = "stream"; int count = 10; // create an ok result PutRecordsResult result = new PutRecordsResult(); List<PutRecordsResultEntry> entries = new ArrayList<PutRecordsResultEntry>(); result.setFailedRecordCount(0); for (int i = 0; i < count; i++) { PutRecordsResultEntry entry = new PutRecordsResultEntry(); entry.setSequenceNumber("record_id_" + i); entries.add(entry); } result.setRecords(entries); // create data List<byte[]> data = new ArrayList<byte[]>(); for (int i = 0; i < count; i++) { data.add(("record" + i).getBytes(StringUtils.UTF8)); } Mockito.when(client.putRecords(any(PutRecordsRequest.class))).thenThrow( new InvalidArgumentException("invalid argument")); sender.sendBatch(streamName, data); } @Test public void testIsRecoverableClientException() { AmazonClientException aceNoCause = new AmazonClientException("failure"); assertFalse(sender.isRecoverable(aceNoCause)); AmazonClientException aceOtherCause = new AmazonClientException("failure", new NullPointerException()); assertFalse(sender.isRecoverable(aceOtherCause)); AmazonClientException aceWithIOException = new AmazonClientException("failure", new IOException()); assertTrue(sender.isRecoverable(aceWithIOException)); } @Test public void testIsRecoverableServiceException() { assertFalse(sender.isRecoverable(getServiceException(""))); assertTrue(sender.isRecoverable(getServiceException("InternalFailure"))); assertTrue(sender.isRecoverable(getServiceException("ServiceUnavailable"))); assertTrue(sender.isRecoverable(getServiceException("Throttling"))); assertTrue(sender .isRecoverable(getServiceException("ProvisionedThroughputExceededException"))); } private AmazonServiceException getServiceException(String errorCode) { AmazonServiceException ase = new AmazonServiceException("some error message"); ase.setErrorCode(errorCode); return ase; } }