|
@@ -0,0 +1,265 @@
|
|
|
|
|
+package space.anyi.s3.cloudflare.r2;
|
|
|
|
|
+
|
|
|
|
|
+import org.junit.jupiter.api.BeforeEach;
|
|
|
|
|
+import org.junit.jupiter.api.Test;
|
|
|
|
|
+import org.mockito.Mock;
|
|
|
|
|
+import org.mockito.MockitoAnnotations;
|
|
|
|
|
+import software.amazon.awssdk.awscore.exception.AwsErrorDetails;
|
|
|
|
|
+import software.amazon.awssdk.core.ResponseInputStream;
|
|
|
|
|
+import software.amazon.awssdk.core.sync.RequestBody;
|
|
|
|
|
+import software.amazon.awssdk.services.s3.S3Client;
|
|
|
|
|
+import software.amazon.awssdk.services.s3.model.*;
|
|
|
|
|
+
|
|
|
|
|
+import static org.junit.jupiter.api.Assertions.*;
|
|
|
|
|
+import static org.mockito.ArgumentMatchers.any;
|
|
|
|
|
+import static org.mockito.Mockito.*;
|
|
|
|
|
+
|
|
|
|
|
+class R2HandlerTest {
|
|
|
|
|
+
|
|
|
|
|
+ @Mock
|
|
|
|
|
+ private R2Configuration configuration;
|
|
|
|
|
+
|
|
|
|
|
+ @Mock
|
|
|
|
|
+ private S3Client s3Client;
|
|
|
|
|
+
|
|
|
|
|
+ private R2Handler handler;
|
|
|
|
|
+
|
|
|
|
|
+ @BeforeEach
|
|
|
|
|
+ void setUp() {
|
|
|
|
|
+ MockitoAnnotations.openMocks(this);
|
|
|
|
|
+ when(configuration.buildClient()).thenReturn(s3Client);
|
|
|
|
|
+ handler = new R2Handler(configuration);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testConstructorInitializesHandler() {
|
|
|
|
|
+ assertNotNull(handler);
|
|
|
|
|
+ verify(configuration, times(1)).buildClient();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testUploadObjectSuccess() {
|
|
|
|
|
+ byte[] data = "test data".getBytes();
|
|
|
|
|
+ when(s3Client.putObject(any(PutObjectRequest.class), any(RequestBody.class)))
|
|
|
|
|
+ .thenReturn(PutObjectResponse.builder().build());
|
|
|
|
|
+
|
|
|
|
|
+ boolean result = handler.uploadObject("test-bucket", "test-object", data);
|
|
|
|
|
+
|
|
|
|
|
+ assertTrue(result);
|
|
|
|
|
+ verify(s3Client, times(1)).putObject(any(PutObjectRequest.class), any(RequestBody.class));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testUploadObjectFailure() {
|
|
|
|
|
+ byte[] data = "test data".getBytes();
|
|
|
|
|
+ when(s3Client.putObject(any(PutObjectRequest.class), any(RequestBody.class)))
|
|
|
|
|
+ .thenThrow(S3Exception.builder()
|
|
|
|
|
+ .awsErrorDetails(AwsErrorDetails.builder().errorMessage("Upload failed").build())
|
|
|
|
|
+ .build());
|
|
|
|
|
+
|
|
|
|
|
+ boolean result = handler.uploadObject("test-bucket", "test-object", data);
|
|
|
|
|
+
|
|
|
|
|
+ assertFalse(result);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testDownloadObjectSuccess() {
|
|
|
|
|
+ byte[] expectedData = "test data".getBytes();
|
|
|
|
|
+ ResponseInputStream<GetObjectResponse> responseInputStream =
|
|
|
|
|
+ new ResponseInputStream<>(GetObjectResponse.builder().build(),
|
|
|
|
|
+ new java.io.ByteArrayInputStream(expectedData));
|
|
|
|
|
+ when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(responseInputStream);
|
|
|
|
|
+
|
|
|
|
|
+ byte[] result = handler.downloadObject("test-bucket", "test-object");
|
|
|
|
|
+
|
|
|
|
|
+ assertNotNull(result);
|
|
|
|
|
+ assertArrayEquals(expectedData, result);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testDownloadObjectFailure() {
|
|
|
|
|
+ when(s3Client.getObject(any(GetObjectRequest.class)))
|
|
|
|
|
+ .thenThrow(S3Exception.builder()
|
|
|
|
|
+ .awsErrorDetails(AwsErrorDetails.builder().errorMessage("Download failed").build())
|
|
|
|
|
+ .build());
|
|
|
|
|
+
|
|
|
|
|
+ byte[] result = handler.downloadObject("test-bucket", "test-object");
|
|
|
|
|
+
|
|
|
|
|
+ assertNull(result);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testDeleteObjectSuccess() {
|
|
|
|
|
+ when(s3Client.deleteObject(any(DeleteObjectRequest.class)))
|
|
|
|
|
+ .thenReturn(DeleteObjectResponse.builder().build());
|
|
|
|
|
+
|
|
|
|
|
+ boolean result = handler.deleteObject("test-bucket", "test-object");
|
|
|
|
|
+
|
|
|
|
|
+ assertTrue(result);
|
|
|
|
|
+ verify(s3Client, times(1)).deleteObject(any(DeleteObjectRequest.class));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testDeleteObjectFailure() {
|
|
|
|
|
+ when(s3Client.deleteObject(any(DeleteObjectRequest.class)))
|
|
|
|
|
+ .thenThrow(S3Exception.builder()
|
|
|
|
|
+ .awsErrorDetails(AwsErrorDetails.builder().errorMessage("Delete failed").build())
|
|
|
|
|
+ .build());
|
|
|
|
|
+
|
|
|
|
|
+ boolean result = handler.deleteObject("test-bucket", "test-object");
|
|
|
|
|
+
|
|
|
|
|
+ assertFalse(result);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testBucketExistsTrue() {
|
|
|
|
|
+ when(s3Client.headBucket(any(HeadBucketRequest.class)))
|
|
|
|
|
+ .thenReturn(HeadBucketResponse.builder().build());
|
|
|
|
|
+
|
|
|
|
|
+ boolean result = handler.bucketExists("test-bucket");
|
|
|
|
|
+
|
|
|
|
|
+ assertTrue(result);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testBucketExistsFalse() {
|
|
|
|
|
+ when(s3Client.headBucket(any(HeadBucketRequest.class)))
|
|
|
|
|
+ .thenThrow(S3Exception.builder().statusCode(404).build());
|
|
|
|
|
+
|
|
|
|
|
+ boolean result = handler.bucketExists("test-bucket");
|
|
|
|
|
+
|
|
|
|
|
+ assertFalse(result);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testCreateBucketSuccess() {
|
|
|
|
|
+ when(s3Client.headBucket(any(HeadBucketRequest.class)))
|
|
|
|
|
+ .thenThrow(S3Exception.builder().statusCode(404).build());
|
|
|
|
|
+ when(s3Client.createBucket(any(CreateBucketRequest.class)))
|
|
|
|
|
+ .thenReturn(CreateBucketResponse.builder().build());
|
|
|
|
|
+
|
|
|
|
|
+ boolean result = handler.createBucket("new-bucket");
|
|
|
|
|
+
|
|
|
|
|
+ assertTrue(result);
|
|
|
|
|
+ verify(s3Client, times(1)).createBucket(any(CreateBucketRequest.class));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testCreateBucketAlreadyExists() {
|
|
|
|
|
+ when(s3Client.headBucket(any(HeadBucketRequest.class)))
|
|
|
|
|
+ .thenReturn(HeadBucketResponse.builder().build());
|
|
|
|
|
+
|
|
|
|
|
+ boolean result = handler.createBucket("existing-bucket");
|
|
|
|
|
+
|
|
|
|
|
+ assertFalse(result);
|
|
|
|
|
+ verify(s3Client, never()).createBucket(any(CreateBucketRequest.class));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testListObjectsSuccess() {
|
|
|
|
|
+ ListObjectsV2Response mockResponse = ListObjectsV2Response.builder()
|
|
|
|
|
+ .contents(new java.util.ArrayList<>())
|
|
|
|
|
+ .build();
|
|
|
|
|
+ when(s3Client.listObjectsV2(any(ListObjectsV2Request.class))).thenReturn(mockResponse);
|
|
|
|
|
+
|
|
|
|
|
+ ListObjectsV2Response result = handler.listObjects("test-bucket");
|
|
|
|
|
+
|
|
|
|
|
+ assertNotNull(result);
|
|
|
|
|
+ verify(s3Client, times(1)).listObjectsV2(any(ListObjectsV2Request.class));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testListObjectsFailure() {
|
|
|
|
|
+ when(s3Client.listObjectsV2(any(ListObjectsV2Request.class)))
|
|
|
|
|
+ .thenThrow(S3Exception.builder()
|
|
|
|
|
+ .awsErrorDetails(AwsErrorDetails.builder().errorMessage("List failed").build())
|
|
|
|
|
+ .build());
|
|
|
|
|
+
|
|
|
|
|
+ ListObjectsV2Response result = handler.listObjects("test-bucket");
|
|
|
|
|
+
|
|
|
|
|
+ assertNull(result);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testCopyObjectSuccess() {
|
|
|
|
|
+ when(s3Client.copyObject(any(CopyObjectRequest.class)))
|
|
|
|
|
+ .thenReturn(CopyObjectResponse.builder().build());
|
|
|
|
|
+
|
|
|
|
|
+ boolean result = handler.copyObject("source-bucket", "source-key", "dest-bucket", "dest-key");
|
|
|
|
|
+
|
|
|
|
|
+ assertTrue(result);
|
|
|
|
|
+ verify(s3Client, times(1)).copyObject(any(CopyObjectRequest.class));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testCopyObjectFailure() {
|
|
|
|
|
+ when(s3Client.copyObject(any(CopyObjectRequest.class)))
|
|
|
|
|
+ .thenThrow(S3Exception.builder()
|
|
|
|
|
+ .awsErrorDetails(AwsErrorDetails.builder().errorMessage("Copy failed").build())
|
|
|
|
|
+ .build());
|
|
|
|
|
+
|
|
|
|
|
+ boolean result = handler.copyObject("source-bucket", "source-key", "dest-bucket", "dest-key");
|
|
|
|
|
+
|
|
|
|
|
+ assertFalse(result);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testShutdown() {
|
|
|
|
|
+ handler.shutdown();
|
|
|
|
|
+
|
|
|
|
|
+ verify(s3Client, times(1)).close();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testUploadFileSuccess() {
|
|
|
|
|
+ java.nio.file.Path tempFile = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ tempFile = java.nio.file.Files.createTempFile("test", ".txt");
|
|
|
|
|
+ java.nio.file.Files.writeString(tempFile, "test content");
|
|
|
|
|
+
|
|
|
|
|
+ when(s3Client.putObject(any(PutObjectRequest.class), any(RequestBody.class)))
|
|
|
|
|
+ .thenReturn(PutObjectResponse.builder().build());
|
|
|
|
|
+
|
|
|
|
|
+ boolean result = handler.uploadFile("test-bucket", "test-object", tempFile);
|
|
|
|
|
+
|
|
|
|
|
+ assertTrue(result);
|
|
|
|
|
+ verify(s3Client, times(1)).putObject(any(PutObjectRequest.class), any(RequestBody.class));
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ fail("Test failed due to exception: " + e.getMessage());
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ if (tempFile != null) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ java.nio.file.Files.deleteIfExists(tempFile);
|
|
|
|
|
+ } catch (Exception ignored) {
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void testUploadFileFailure() {
|
|
|
|
|
+ java.nio.file.Path tempFile = null;
|
|
|
|
|
+ try {
|
|
|
|
|
+ tempFile = java.nio.file.Files.createTempFile("test", ".txt");
|
|
|
|
|
+ java.nio.file.Files.writeString(tempFile, "test content");
|
|
|
|
|
+
|
|
|
|
|
+ when(s3Client.putObject(any(PutObjectRequest.class), any(RequestBody.class)))
|
|
|
|
|
+ .thenThrow(S3Exception.builder()
|
|
|
|
|
+ .awsErrorDetails(AwsErrorDetails.builder().errorMessage("Upload failed").build())
|
|
|
|
|
+ .build());
|
|
|
|
|
+
|
|
|
|
|
+ boolean result = handler.uploadFile("test-bucket", "test-object", tempFile);
|
|
|
|
|
+
|
|
|
|
|
+ assertFalse(result);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ fail("Test failed due to exception: " + e.getMessage());
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ if (tempFile != null) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ java.nio.file.Files.deleteIfExists(tempFile);
|
|
|
|
|
+ } catch (Exception ignored) {
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|