diff --git a/gp2gp-translator/build.gradle b/gp2gp-translator/build.gradle index 6f6e8d5ee..048b5560e 100644 --- a/gp2gp-translator/build.gradle +++ b/gp2gp-translator/build.gradle @@ -50,6 +50,7 @@ dependencies { testImplementation 'org.skyscreamer:jsonassert:1.5.3' testImplementation 'org.awaitility:awaitility:4.2.2' testImplementation 'io.findify:s3mock_2.13:0.2.6' + testImplementation "org.testcontainers:testcontainers-azure:2.0.5" pitest 'com.arcmutate:base:1.3.2' pitest 'com.arcmutate:pitest-git-plugin:2.0.0' diff --git a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/storage/AzureStorageService.java b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/storage/AzureStorageService.java index 81e19f2fb..55fe8e2d9 100644 --- a/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/storage/AzureStorageService.java +++ b/gp2gp-translator/src/main/java/uk/nhs/adaptors/pss/translator/storage/AzureStorageService.java @@ -11,7 +11,9 @@ import com.azure.storage.blob.BlobServiceClientBuilder; import com.azure.storage.blob.specialized.BlockBlobClient; import com.azure.storage.common.StorageSharedKeyCredential; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +@SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "BlobServiceClient is immutable and thread-safe.") public class AzureStorageService implements StorageService { // Consistent objects @@ -32,6 +34,11 @@ public AzureStorageService(StorageServiceConfiguration configuration) { } } + public AzureStorageService(BlobServiceClient blobServiceClient, StorageServiceConfiguration configuration) { + this.blobServiceClient = blobServiceClient; + this.containerName = configuration.getContainerName(); + } + public void uploadFile(String filename, byte[] fileAsString) throws StorageException { try { addFileStringToMainContainer(filename, fileAsString); diff --git a/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/storage/AzureStorageServiceTest.java b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/storage/AzureStorageServiceTest.java new file mode 100644 index 000000000..18be68e98 --- /dev/null +++ b/gp2gp-translator/src/test/java/uk/nhs/adaptors/pss/translator/storage/AzureStorageServiceTest.java @@ -0,0 +1,105 @@ +package uk.nhs.adaptors.pss.translator.storage; + +import com.azure.core.util.BinaryData; +import com.azure.storage.blob.BlobServiceClient; +import com.azure.storage.blob.BlobServiceClientBuilder; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.testcontainers.azure.AzuriteContainer; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import static org.junit.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class AzureStorageServiceTest { + + private static final String CONTAINER_NAME = "azurecontainer"; + private static final String FILE_NAME = "testfile.txt"; + + private AzureStorageService azureStorageService; + private AzuriteContainer azuriteContainer; + private StorageServiceConfiguration config; + private BlobServiceClient blobServiceClient; + + @BeforeEach + void setUp() { + azuriteContainer = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0"); + azuriteContainer.start(); + + blobServiceClient = new BlobServiceClientBuilder() + .connectionString(azuriteContainer.getConnectionString()) + .buildClient(); + blobServiceClient.createBlobContainer(CONTAINER_NAME); + + config = new StorageServiceConfiguration(); + config.setContainerName(CONTAINER_NAME); + + azureStorageService = new AzureStorageService(blobServiceClient, config); + } + + @AfterEach + void tearDown() { + azuriteContainer.stop(); + } + + @Test + void uploadToStorageTest() throws IOException { + String uploadContent = "uploadcontent"; + + azureStorageService.uploadFile(FILE_NAME, uploadContent.getBytes(StandardCharsets.UTF_8)); + + byte[] downloaded = blobServiceClient + .getBlobContainerClient(CONTAINER_NAME) + .getBlobClient(FILE_NAME).downloadContent().toBytes(); + + Assertions.assertEquals(uploadContent, new String(downloaded, StandardCharsets.UTF_8)); + } + + @Test + void downloadFromStorageTest() { + + String fileContent = "dummy-content"; + + blobServiceClient + .getBlobContainerClient(CONTAINER_NAME) + .getBlobClient(FILE_NAME).upload(BinaryData.fromString(fileContent)); + + byte[] response = azureStorageService.downloadFile(FILE_NAME); + String downloadedContent = new String(response, StandardCharsets.UTF_8); + + assertNotNull(response); + Assertions.assertEquals(fileContent, downloadedContent); + } + + @Test + void deleteFileTest() { + + String fileContent = "dummy-content"; + blobServiceClient + .getBlobContainerClient(CONTAINER_NAME) + .getBlobClient(FILE_NAME).upload(BinaryData.fromString(fileContent)); + + azureStorageService.deleteFile(FILE_NAME); + + Exception exception = assertThrows(Exception.class, () -> azureStorageService.downloadFile(FILE_NAME)); + + Assertions.assertEquals("Status code 404, BlobNotFound", exception.getMessage()); + } + + @Test + void getFileLocationTest() { + String fileContent = "dummy-content"; + blobServiceClient + .getBlobContainerClient(CONTAINER_NAME) + .getBlobClient(FILE_NAME).upload(BinaryData.fromString(fileContent)); + + String response = azureStorageService.getFileLocation(FILE_NAME); + + assertNotNull(response); + Assertions.assertTrue(response.contains(FILE_NAME)); + } +}