diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 17097e06..43e7b530 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -4,7 +4,7 @@ This pull request closes # . # Acceptance Test -* [ ] Building the code with `mvn clean install -Pintegration-tests` still works. +* [ ] Building the code with `mvn clean install -Punit-tests,it-minio,it-s3` still works. # Questions diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cbb73ac9..1fd6ff84 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,13 +14,11 @@ on: - '-**/*.md' jobs: - build-and-test: + build-matrix: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - # Commenting Windows out in order to preserve our free minutes. - # We can re-enable it, if we get a sponsor. os: [ubuntu-latest, windows-latest, macos-latest] java: [ 8, 11.0.3 ] env: @@ -44,11 +42,15 @@ jobs: uses: actions/cache@v2 with: path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + # https://github.com/actions/cache/issues/2#issuecomment-673493515 + # Example: unix timestamp + key: ${{ runner.os }}-maven-${{ secrets.MVN_CACHE_VERSION }}-${{ hashFiles('**/pom.xml') }} restore-keys: | - ${{ runner.os }}-maven- - - name: Build with Maven - run: mvn clean install -Pjacoco-code-coverage + ${{ runner.os }}-maven-${{ secrets.MVN_CACHE_VERSION }}- + - name: Maven Version + run: mvn --version + - name: Build, unit test and coverage. + run: mvn clean install -Punit-tests -Pjacoco-code-coverage - name: Publish code analysis to Sonarcloud # [WARNING] The version of Java 1.8 you have used to run this analysis is deprecated and we will stop accepting # it from October 2020. Please update to at least Java 11. @@ -58,4 +60,101 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: mvn org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Pjacoco-code-coverage -DskipTests + run: mvn org.sonarsource.scanner.maven:sonar-maven-plugin:sonar + continue-on-error: true + + run-it-minio: + runs-on: ${{ matrix.os }} + needs: [build-matrix] + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + java: [ 8, 11.0.3 ] + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Java ${{ matrix.java }} + uses: actions/setup-java@v1 + with: + java-version: ${{ matrix.java }} + - name: Cache local Maven repository + uses: actions/cache@v2 + with: + path: ~/.m2/repository + # https://github.com/actions/cache/issues/2#issuecomment-673493515 + # Example: unix timestamp + key: ${{ runner.os }}-maven-${{ secrets.MVN_CACHE_VERSION }}-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven-${{ secrets.MVN_CACHE_VERSION }}- + - name: Cache Docker images + id: docker-cache + uses: actions/cache@v2 + with: + path: ${{ github.workspace }}/docker-image-cache.tar + # https://github.com/actions/cache/issues/2#issuecomment-673493515 + # Example: unix timestamp + key: ${{ runner.os }}-docker-${{ secrets.DOCKER_CACHE_VERSION }}-${{ hashFiles('${{ github.workspace }}/docker-image-cache.tar') }} + restore-keys: | + ${{ runner.os }}-docker-${{ secrets.DOCKER_CACHE_VERSION }}- + - name: Load docker image cache + if: steps.docker-cache.outputs.cache-hit == 'true' + run: | + cat ${{ github.workspace }}/docker-image-cache.tar | docker load + docker images | grep -iE "minio|testcontainers" + - name: Docker info + run: docker info + - name: Maven Version + run: mvn --version + - name: MinIO integration tests. + run: mvn clean install -Pit-minio + env: + S3FS_BUCKET_NAME: ${{ secrets.S3FS_BUCKET_NAME }} + # access key must be >= 3 chars or authentication will fail. + S3FS_ACCESS_KEY: "access_key" + # secret key must be >= 8 chars or authentication will fail. + S3FS_SECRET_KEY: "secret_key" + S3FS_PROTOCOL: "http" + # TODO: These are necessary since the current logic in EnvironmentBuilder assumes we are using S3. + S3FS_REGION: "local" + # TODO: Adding this env var in advance, we might or might not need it after the test containers task is completed. + # https://github.com/carlspring/s3fs-nio/issues/60 + S3FS_PORT: 9000 + - name: Save docker images + run: docker save minio/minio testcontainers/ryuk > ${{ github.workspace }}/docker-image-cache.tar + + run-it-s3: + needs: [run-it-minio] + runs-on: ${{ matrix.os }} + strategy: + fail-fast: true + matrix: + # TODO: We should, at some point, have the same matrix as `build-matrix`. + os: [ubuntu-latest, windows-latest] + java: [ 8 ] + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Java ${{ matrix.java }} + uses: actions/setup-java@v1 + with: + java-version: ${{ matrix.java }} + - name: Cache local Maven repository + uses: actions/cache@v2 + with: + path: ~/.m2/repository + # https://github.com/actions/cache/issues/2#issuecomment-673493515 + # Example: unix timestamp + key: ${{ runner.os }}-maven-${{ secrets.MVN_CACHE_VERSION }}-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven-${{ secrets.MVN_CACHE_VERSION }}- + - name: Maven Version + run: mvn --version + - name: S3 integration tests. + run: mvn clean install -Pit-s3 + env: + S3FS_BUCKET_NAME: ${{ secrets.S3FS_BUCKET_NAME }} + S3FS_ACCESS_KEY: ${{ secrets.S3FS_ACCESS_KEY }} + S3FS_SECRET_KEY: ${{ secrets.S3FS_SECRET_KEY }} + S3FS_REGION: ${{ secrets.S3FS_REGION }} + S3FS_PROTOCOL: "https" \ No newline at end of file diff --git a/docs/content/assets/resources/s3fs-nio-strict-policy.json b/docs/content/assets/resources/s3fs-nio-strict-policy.json new file mode 100644 index 00000000..843dcb1d --- /dev/null +++ b/docs/content/assets/resources/s3fs-nio-strict-policy.json @@ -0,0 +1,29 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "VisualEditor0", + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:GetObjectAcl", + "s3:GetObject", + "s3:DeleteObjectVersion", + "s3:PutReplicationConfiguration", + "s3:ListBucket", + "s3:DeleteObject", + "s3:GetBucketAcl" + ], + "Resource": [ + "arn:aws:s3:::YOUR_BUCKET_NAME", + "arn:aws:s3:::YOUR_BUCKET_NAME/*" + ] + }, + { + "Sid": "VisualEditor1", + "Effect": "Allow", + "Action": "s3:ListAllMyBuckets", + "Resource": "*" + } + ] +} \ No newline at end of file diff --git a/docs/content/contributing/developer-guide/index.md b/docs/content/contributing/developer-guide/index.md index b442cb21..2a1df46b 100644 --- a/docs/content/contributing/developer-guide/index.md +++ b/docs/content/contributing/developer-guide/index.md @@ -21,6 +21,49 @@ contributors to help with are marked with the following labels: [![GitHub issues by-label help-wanted-link][help-wanted-badge]][help-wanted-link] [![GitHub issues by-label hacktoberfest-link][hacktoberfest-badge]][hacktoberfest-link] +## Preparing credentials + +### S3 - Easy + +!!! warning "Gives access to **all** buckets which could be dangerous!" + +The easiest way to get started would be to: + +1. Go to the [Identity and Access Management (IAM)][s3-iam] +2. Go to `Users` -> `Add User`: + * Username: `my-s3fs-username` (or whatever) + * Access Type: `Programmatic access` must be selected! +3. `Set Permissions`: + * Select `Attach existing policies directly` + * Search for `AmazonS3FullAccess` and select it. +4. Continue with next steps (apply changes if necessary) +5. At the final step you will receive an `Access Key` and `Secret Access Key` - copy those into your + `amazon-test.properties` or export them as `S3FS_**` env variable name (if running in a container). + + +### S3 - Advanced + +!!! success "Allows access to a specific bucket and is safer if you have multiple buckets in your account." + +1. Go to the [Identity and Access Management (IAM)][s3-iam] +2. Go to `Policies`: + * Create a new policy + * Switch to `JSON` editor and copy the policy below which will limit the access to only a specific bucket: + ``` + --8<-- "./content/assets/resources/s3fs-nio-strict-policy.json" + ``` + * Replace `YOUR_BUCKET_NAME` with your actual bucket name. + * Give a name and save (i.e. `s3fs-full-access-to-YOUR_BUCKET_NAME`) +3. Go to `Users` -> `Add User`: + * Username: `my-s3fs-username` (or whatever) + * Access Type: `Programmatic access` must be selected! +4. `Set Permissions`: + * Select `Attach existing policies directly` + * Search for `s3fs-full-access-to-YOUR_BUCKET_NAME` and select it + * Continue with next steps (apply changes if necessary) +5. At the final step you will receive an `Access Key` and `Secret Access Key` - copy those into your + `amazon-test.properties` or export them as `S3FS_**` env variable name (if running in a container). + ## Building the code @@ -69,3 +112,6 @@ TODO: Add a guide to run tests with MinIO and docker-compose [help-wanted-badge]: https://img.shields.io/github/issues-raw/carlspring/s3fs-nio/help%20wanted.svg?label=help%20wanted&color=%23856bf9& [hacktoberfest-link]: {{ repo_url }}/issues?q=is%3Aissue+is%3Aopen+label%3A%22hacktoberfest%22 [hacktoberfest-badge]: https://img.shields.io/github/issues-raw/carlspring/s3fs-nio/hacktoberfest.svg?label=hacktoberfest&color=orange + +[<--# S3 -->]: # +[s3-iam]: https://console.aws.amazon.com/iam/home \ No newline at end of file diff --git a/docs/content/index.md b/docs/content/index.md index 6f517c71..13cd6da0 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -33,7 +33,7 @@ 2. Open [IAM] and go to `Add User` 3. Set `Access Type` to `Programmatic Access` or you will get `403 Forbidden` errors. 4. Select `Attach an existing policies directly` -5. Select `AmazonS3FullAccess` policy and `Create user` +5. Select `AmazonS3FullAccess` policy and `Create user` (if you prefer more fine-grained access [click here](./contributing/developer-guide/index.md#s3-advanced)) 6. Copy `Access key ID` and `Secret access key` - you will need them later! ### Example diff --git a/pom.xml b/pom.xml index dc26a209..3246d5cb 100644 --- a/pom.xml +++ b/pom.xml @@ -86,9 +86,9 @@ 1.25 3.0.2 5.7.0 - 1.7.0 3.7.7 2.1.0 + 3.0.0-M5 @@ -103,15 +103,17 @@ UTF-8 + org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M5 - - - **/*ITTest* - - + ${version.surefire} + + + default-test + none + + org.apache.maven.plugins @@ -242,10 +244,11 @@ ${version.junit} test + - org.junit.platform - junit-platform-runner - ${version.junit.platform.runner} + org.apache.commons + commons-lang3 + 3.11 test @@ -286,9 +289,90 @@ + + + unit-tests + + true + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${version.surefire} + + + true + + * + + + + unit-tests + + test + + + + + + + + + + - integration-tests + + it-minio + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.0.0-M5 + + + true + + **/*IT.java + + + + minio + + + + + it-minio + integration-test + + integration-test + + + + + + it-minio + * + + + + it-minio-verify + verify + + verify + + + + + + + + + it-s3 @@ -296,23 +380,33 @@ maven-failsafe-plugin 3.0.0-M5 + + true - **/*ITSuite.java + **/*IT.java - - **/**Test.java - + + + s3 + - integration-test + it-s3 integration-test integration-test + + + + + it-s3 + * + - verify + it-s3-verify verify verify @@ -323,6 +417,7 @@ + jacoco-code-coverage diff --git a/src/main/java/org/carlspring/cloud/storage/s3fs/S3FileStore.java b/src/main/java/org/carlspring/cloud/storage/s3fs/S3FileStore.java index 79d4de49..cf9324d9 100644 --- a/src/main/java/org/carlspring/cloud/storage/s3fs/S3FileStore.java +++ b/src/main/java/org/carlspring/cloud/storage/s3fs/S3FileStore.java @@ -117,6 +117,12 @@ public Bucket getBucket() return getBucket(name); } + /** + * This code requires `s3:ListAllMyBuckets` permission. + * + * @param bucketName + * @return + */ private Bucket getBucket(final String bucketName) { for (Bucket buck : getClient().listBuckets().buckets()) diff --git a/src/main/java/org/carlspring/cloud/storage/s3fs/S3Path.java b/src/main/java/org/carlspring/cloud/storage/s3fs/S3Path.java index 0b3315a9..a1ad2485 100644 --- a/src/main/java/org/carlspring/cloud/storage/s3fs/S3Path.java +++ b/src/main/java/org/carlspring/cloud/storage/s3fs/S3Path.java @@ -64,8 +64,8 @@ public class S3Path */ public S3Path(S3FileSystem fileSystem, String first, String... more) { - Preconditions.checkArgument(first != null, "first path must be not null"); - Preconditions.checkArgument(!first.startsWith("//"), "first path doesnt start with '//'. Miss bucket"); + Preconditions.checkArgument(first != null, "The first path must not be null. Perhaps you forgot to set the bucket name?"); + Preconditions.checkArgument(!first.startsWith("//"), "The first path doesn't start with '//'. Missing bucket."); // see tests org.carlspring.cloud.storage.s3fs.Path.EndsWithTest#endsWithRelativeBlankAbsolute() boolean hasBucket = first.startsWith("/"); diff --git a/src/main/java/org/carlspring/cloud/storage/s3fs/util/S3Utils.java b/src/main/java/org/carlspring/cloud/storage/s3fs/util/S3Utils.java index 06343fae..87376601 100644 --- a/src/main/java/org/carlspring/cloud/storage/s3fs/util/S3Utils.java +++ b/src/main/java/org/carlspring/cloud/storage/s3fs/util/S3Utils.java @@ -164,7 +164,8 @@ public S3BasicFileAttributes getS3FileAttributes(S3Path s3Path) } /** - * get the S3PosixFileAttributes for a S3Path + * Get the S3PosixFileAttributes for a S3Path + * This requires `s3:GetBucketAcl` and `s3:GetObjectAcl` * * @param s3Path Path mandatory not null * @return S3PosixFileAttributes never null diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/AmazonS3ITSuite.java b/src/test/java/org/carlspring/cloud/storage/s3fs/AmazonS3ITSuite.java deleted file mode 100644 index 62ca5035..00000000 --- a/src/test/java/org/carlspring/cloud/storage/s3fs/AmazonS3ITSuite.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.carlspring.cloud.storage.s3fs; - -import org.junit.platform.runner.JUnitPlatform; -import org.junit.platform.suite.api.IncludeTags; -import org.junit.platform.suite.api.SelectPackages; -import org.junit.runner.RunWith; - -/** - * @author carlspring - */ -@RunWith(JUnitPlatform.class) -@IncludeTags({ "s3-integration-test" }) -@SelectPackages({ "org.carlspring.cloud.storage.s3fs" }) -public class AmazonS3ITSuite -{ -} diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/FileSystemsITTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/FileSystemsIT.java similarity index 94% rename from src/test/java/org/carlspring/cloud/storage/s3fs/FileSystemsITTest.java rename to src/test/java/org/carlspring/cloud/storage/s3fs/FileSystemsIT.java index f81216ef..440ef0f0 100644 --- a/src/test/java/org/carlspring/cloud/storage/s3fs/FileSystemsITTest.java +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/FileSystemsIT.java @@ -1,5 +1,6 @@ package org.carlspring.cloud.storage.s3fs; +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; import org.carlspring.cloud.storage.s3fs.util.EnvironmentBuilder; import java.io.IOException; @@ -9,14 +10,13 @@ import java.nio.file.FileSystems; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import static org.carlspring.cloud.storage.s3fs.util.S3EndpointConstant.S3_GLOBAL_URI_IT; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertSame; -@Tag("s3-integration-test") -class FileSystemsITTest +@S3IntegrationTest +class FileSystemsIT { private static final URI uriEurope = URI.create("s3://s3-eu-west-1.amazonaws.com/"); diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/FilesITTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/FilesIT.java similarity index 97% rename from src/test/java/org/carlspring/cloud/storage/s3fs/FilesITTest.java rename to src/test/java/org/carlspring/cloud/storage/s3fs/FilesIT.java index a1f6be99..49c46ec1 100644 --- a/src/test/java/org/carlspring/cloud/storage/s3fs/FilesITTest.java +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/FilesIT.java @@ -1,5 +1,6 @@ package org.carlspring.cloud.storage.s3fs; +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; import org.carlspring.cloud.storage.s3fs.util.CopyDirVisitor; import org.carlspring.cloud.storage.s3fs.util.EnvironmentBuilder; @@ -8,15 +9,7 @@ import java.io.OutputStream; import java.net.URI; import java.nio.channels.SeekableByteChannel; -import java.nio.file.DirectoryStream; -import java.nio.file.FileSystem; -import java.nio.file.FileSystemNotFoundException; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardOpenOption; +import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.EnumSet; import java.util.Map; @@ -24,7 +17,6 @@ import com.github.marschall.memoryfilesystem.MemoryFileSystemBuilder; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.services.s3.S3Client; @@ -32,14 +24,10 @@ import software.amazon.awssdk.services.s3.model.HeadObjectResponse; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import static org.carlspring.cloud.storage.s3fs.util.S3EndpointConstant.S3_GLOBAL_URI_IT; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -@Tag("s3-integration-test") -class FilesITTest +import static org.junit.jupiter.api.Assertions.*; + +@S3IntegrationTest +class FilesIT { private static final String bucket = EnvironmentBuilder.getBucket(); diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/S3ClientITTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/S3ClientIT.java similarity index 97% rename from src/test/java/org/carlspring/cloud/storage/s3fs/S3ClientITTest.java rename to src/test/java/org/carlspring/cloud/storage/s3fs/S3ClientIT.java index f9bb2d7f..99e159ee 100644 --- a/src/test/java/org/carlspring/cloud/storage/s3fs/S3ClientITTest.java +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/S3ClientIT.java @@ -1,5 +1,6 @@ package org.carlspring.cloud.storage.s3fs; +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; import org.carlspring.cloud.storage.s3fs.util.EnvironmentBuilder; import java.io.ByteArrayInputStream; @@ -11,7 +12,6 @@ import java.util.Map; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.AwsCredentials; @@ -29,8 +29,8 @@ import static org.carlspring.cloud.storage.s3fs.util.EnvironmentBuilder.getRealEnv; import static org.junit.jupiter.api.Assertions.assertNotNull; -@Tag("s3-integration-test") -class S3ClientITTest +@S3IntegrationTest +class S3ClientIT { S3Client client; diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/S3UtilsITTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/S3UtilsIT.java similarity index 99% rename from src/test/java/org/carlspring/cloud/storage/s3fs/S3UtilsITTest.java rename to src/test/java/org/carlspring/cloud/storage/s3fs/S3UtilsIT.java index 15247390..f59108e0 100644 --- a/src/test/java/org/carlspring/cloud/storage/s3fs/S3UtilsITTest.java +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/S3UtilsIT.java @@ -2,6 +2,7 @@ import org.carlspring.cloud.storage.s3fs.attribute.S3BasicFileAttributes; import org.carlspring.cloud.storage.s3fs.attribute.S3PosixFileAttributes; +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; import org.carlspring.cloud.storage.s3fs.util.CopyDirVisitor; import org.carlspring.cloud.storage.s3fs.util.EnvironmentBuilder; import org.carlspring.cloud.storage.s3fs.util.S3Utils; @@ -19,7 +20,6 @@ import com.github.marschall.memoryfilesystem.MemoryFileSystemBuilder; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.services.s3.S3Client; @@ -34,8 +34,8 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; -@Tag("s3-integration-test") -class S3UtilsITTest +@S3IntegrationTest +class S3UtilsIT { private static final String bucket = EnvironmentBuilder.getBucket(); diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/GetFileSystemITTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/GetFileSystemIT.java similarity index 95% rename from src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/GetFileSystemITTest.java rename to src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/GetFileSystemIT.java index a3963715..009cba86 100644 --- a/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/GetFileSystemITTest.java +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/GetFileSystemIT.java @@ -1,6 +1,7 @@ package org.carlspring.cloud.storage.s3fs.fileSystemProvider; import org.carlspring.cloud.storage.s3fs.S3FileSystemProvider; +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; import java.io.IOException; import java.nio.file.FileSystem; @@ -11,7 +12,6 @@ import com.google.common.collect.ImmutableMap; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import static org.carlspring.cloud.storage.s3fs.S3Factory.ACCESS_KEY; import static org.carlspring.cloud.storage.s3fs.S3Factory.REGION; @@ -24,8 +24,8 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; -@Tag("s3-integration-test") -class GetFileSystemITTest +@S3IntegrationTest +class GetFileSystemIT { private S3FileSystemProvider provider; diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewAsynchronousFileChannelITTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewAsynchronousFileChannelTestIT.java similarity index 98% rename from src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewAsynchronousFileChannelITTest.java rename to src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewAsynchronousFileChannelTestIT.java index dcf706d6..d2c61e61 100644 --- a/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewAsynchronousFileChannelITTest.java +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewAsynchronousFileChannelTestIT.java @@ -2,6 +2,7 @@ import org.carlspring.cloud.storage.s3fs.S3FileSystemProvider; import org.carlspring.cloud.storage.s3fs.S3UnitTestBase; +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; import org.carlspring.cloud.storage.s3fs.util.CopyDirVisitor; import org.carlspring.cloud.storage.s3fs.util.EnvironmentBuilder; @@ -27,7 +28,6 @@ import com.github.marschall.memoryfilesystem.MemoryFileSystemBuilder; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import static org.carlspring.cloud.storage.s3fs.util.S3EndpointConstant.S3_GLOBAL_URI_IT; import static org.junit.jupiter.api.Assertions.assertArrayEquals; @@ -35,8 +35,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -@Tag("s3-integration-test") -class NewAsynchronousFileChannelITTest +@S3IntegrationTest +class NewAsynchronousFileChannelTestIT extends S3UnitTestBase { diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewByteChannelITTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewByteChannelIT.java similarity index 98% rename from src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewByteChannelITTest.java rename to src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewByteChannelIT.java index c4cd2cca..bfc14949 100644 --- a/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewByteChannelITTest.java +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewByteChannelIT.java @@ -2,6 +2,7 @@ import org.carlspring.cloud.storage.s3fs.S3FileSystemProvider; import org.carlspring.cloud.storage.s3fs.S3UnitTestBase; +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; import org.carlspring.cloud.storage.s3fs.util.CopyDirVisitor; import org.carlspring.cloud.storage.s3fs.util.EnvironmentBuilder; @@ -22,7 +23,6 @@ import com.github.marschall.memoryfilesystem.MemoryFileSystemBuilder; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import static org.carlspring.cloud.storage.s3fs.util.S3EndpointConstant.S3_GLOBAL_URI_IT; import static org.junit.jupiter.api.Assertions.assertArrayEquals; @@ -30,8 +30,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -@Tag("s3-integration-test") -class NewByteChannelITTest +@S3IntegrationTest +class NewByteChannelIT extends S3UnitTestBase { diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewFileSystemITTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewFileSystemIT.java similarity index 97% rename from src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewFileSystemITTest.java rename to src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewFileSystemIT.java index d13eee58..8ebc1900 100644 --- a/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewFileSystemITTest.java +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/fileSystemProvider/NewFileSystemIT.java @@ -1,6 +1,7 @@ package org.carlspring.cloud.storage.s3fs.fileSystemProvider; import org.carlspring.cloud.storage.s3fs.S3FileSystemProvider; +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; import java.io.IOException; import java.net.URI; @@ -12,7 +13,6 @@ import com.google.common.collect.ImmutableMap; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import static org.carlspring.cloud.storage.s3fs.S3Factory.ACCESS_KEY; import static org.carlspring.cloud.storage.s3fs.S3Factory.SECRET_KEY; @@ -28,8 +28,8 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -@Tag("s3-integration-test") -class NewFileSystemITTest +@S3IntegrationTest +class NewFileSystemIT { private S3FileSystemProvider provider; diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/BaseAnnotationTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/BaseAnnotationTest.java new file mode 100644 index 00000000..e8b5fd02 --- /dev/null +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/BaseAnnotationTest.java @@ -0,0 +1,57 @@ +package org.carlspring.cloud.storage.s3fs.junit.annotations; + +public abstract class BaseAnnotationTest +{ + + /** + * Check if there is an {@link S3IntegrationTest} annotation at a class level. + * + * @param clazz + * @return + */ + protected static boolean hasS3Annotation(Class clazz) + { + return clazz.getAnnotation(S3IntegrationTest.class) != null; + } + + /** + * Check if there is an {@link S3IntegrationTest} annotation at a method level (and pick-up class level) + * + * @param clazz + * @param methodName + * @return + * @throws NoSuchMethodException + */ + protected static boolean hasS3Annotation(Class clazz, + String methodName) + throws NoSuchMethodException + { + return hasS3Annotation(clazz) || clazz.getMethod(methodName).getAnnotation(S3IntegrationTest.class) != null; + } + + /** + * Check if there is an {@link MinioIntegrationTest} annotation at a class level. + * + * @param clazz + * @return + */ + protected static boolean hasMinioAnnotation(Class clazz) + { + return clazz.getAnnotation(MinioIntegrationTest.class) != null; + } + + /** + * Check if there is an {@link MinioIntegrationTest} annotation at a method level (and pick-up class level) + * + * @param clazz + * @param methodName + * @return + * @throws NoSuchMethodException + */ + protected static boolean hasMinioAnnotation(Class clazz, + String methodName) + throws NoSuchMethodException + { + return hasMinioAnnotation(clazz) || clazz.getMethod(methodName).getAnnotation(MinioIntegrationTest.class) != null; + } +} diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/MinioIntegrationTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/MinioIntegrationTest.java new file mode 100644 index 00000000..f168ba90 --- /dev/null +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/MinioIntegrationTest.java @@ -0,0 +1,21 @@ +package org.carlspring.cloud.storage.s3fs.junit.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.jupiter.api.Tag; + +/** + * This annotation should be used for integration tests which are specific to MinIO. + * It is possible to combine it with {@link S3IntegrationTest} for test cases which are compatible with both (i.e. can + * run on S3 and MinIO) + */ +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Tag("it-minio") +public @interface MinioIntegrationTest +{ + +} diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/MinioIntegrationTestAnnotationTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/MinioIntegrationTestAnnotationTest.java new file mode 100644 index 00000000..14b5f70b --- /dev/null +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/MinioIntegrationTestAnnotationTest.java @@ -0,0 +1,41 @@ +package org.carlspring.cloud.storage.s3fs.junit.annotations; + + +import org.carlspring.cloud.storage.s3fs.junit.examples.*; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class MinioIntegrationTestAnnotationTest + extends BaseAnnotationTest +{ + + @Test + void testClassLevelAnnotation() + { + assertTrue(hasMinioAnnotation(MinioClassAnnotationIT.class)); + assertTrue(hasMinioAnnotation(CombinedMinioS3IT.class)); + + assertFalse(hasMinioAnnotation(S3ClassAnnotationIT.class)); + assertFalse(hasMinioAnnotation(CombinedS3MinioIT.class)); + + assertTrue(hasMinioAnnotation(CombinedIT.class)); + } + + @Test + void testMethodLevelAnnotation() + throws NoSuchMethodException + { + assertTrue(hasMinioAnnotation(MinioMethodAnnotationIT.class, "testShouldExecuteBecauseOfMethodAnnotation")); + + assertTrue(hasMinioAnnotation(CombinedIT.class, "testMinioMethodShouldExecuteBecauseOfClassLevelAnnotation")); + assertTrue(hasMinioAnnotation(CombinedIT.class, "testMinioMethodShouldExecuteBecauseOfClassLevelAnnotation")); + + assertTrue(hasMinioAnnotation(CombinedS3MinioIT.class, "testMinioMethodShouldExecuteBecauseOfMethodLevelAnnotation")); + assertTrue(hasMinioAnnotation(CombinedMinioS3IT.class, "testMinioMethodShouldExecuteBecauseOfClassLevelAnnotation")); + + assertFalse(hasS3Annotation(MinioMethodAnnotationIT.class, "testShouldExecuteBecauseOfMethodAnnotation")); + } + +} diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/S3IntegrationTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/S3IntegrationTest.java new file mode 100644 index 00000000..b6ff4773 --- /dev/null +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/S3IntegrationTest.java @@ -0,0 +1,21 @@ +package org.carlspring.cloud.storage.s3fs.junit.annotations; + +import org.junit.jupiter.api.Tag; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation should be used for integration tests which are specific to the official S3 API. + * It is possible to combine it with {@link MinioIntegrationTest} for test cases which are compatible with both (i.e. can + * run on S3 and MinIO) + */ +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Tag("it-s3") +public @interface S3IntegrationTest +{ + +} diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/S3IntegrationTestAnnotationTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/S3IntegrationTestAnnotationTest.java new file mode 100644 index 00000000..c1bda43c --- /dev/null +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/annotations/S3IntegrationTestAnnotationTest.java @@ -0,0 +1,38 @@ +package org.carlspring.cloud.storage.s3fs.junit.annotations; + + +import org.carlspring.cloud.storage.s3fs.junit.examples.*; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +class S3IntegrationTestAnnotationTest + extends BaseAnnotationTest +{ + + @Test + void testClassLevelAnnotation() + { + assertTrue(hasS3Annotation(S3ClassAnnotationIT.class)); + assertTrue(hasS3Annotation(CombinedS3MinioIT.class)); + + assertFalse(hasS3Annotation(MinioClassAnnotationIT.class)); + assertFalse(hasS3Annotation(CombinedMinioS3IT.class)); + + assertTrue(hasS3Annotation(CombinedIT.class)); + } + + @Test + void testMethodLevelAnnotation() + throws NoSuchMethodException + { + assertTrue(hasS3Annotation(S3MethodAnnotationIT.class, "testShouldExecuteBecauseOfMethodAnnotation")); + assertTrue(hasS3Annotation(CombinedIT.class, "testMinioMethodShouldExecuteBecauseOfClassLevelAnnotation")); + assertTrue(hasS3Annotation(CombinedIT.class, "testS3MethodShouldExecuteBecauseOfClassLevelAnnotation")); + assertTrue(hasS3Annotation(CombinedS3MinioIT.class, "testS3MethodShouldExecuteBecauseOfClassLevelAnnotation")); + assertTrue(hasS3Annotation(CombinedMinioS3IT.class, "testS3MethodShouldExecuteBecauseOfMethodLevelAnnotation")); + + assertFalse(hasS3Annotation(MinioMethodAnnotationIT.class, "testShouldExecuteBecauseOfMethodAnnotation")); + } + +} diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/CombinedIT.java b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/CombinedIT.java new file mode 100644 index 00000000..4ad528fe --- /dev/null +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/CombinedIT.java @@ -0,0 +1,35 @@ +package org.carlspring.cloud.storage.s3fs.junit.examples; + +import org.carlspring.cloud.storage.s3fs.junit.annotations.MinioIntegrationTest; +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; + +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Class level {@link MinioIntegrationTest} annotation and class level {@link S3IntegrationTest} annotation. + */ +@MinioIntegrationTest +@S3IntegrationTest +public class CombinedIT +{ + + private static final Logger logger = LoggerFactory.getLogger(S3MethodAnnotationIT.class); + + @Test + public void testS3MethodShouldExecuteBecauseOfClassLevelAnnotation() + { + logger.debug(new Exception().getStackTrace()[0].getMethodName()); + assertTrue(true); + } + + @Test + public void testMinioMethodShouldExecuteBecauseOfClassLevelAnnotation() + { + logger.debug(new Exception().getStackTrace()[0].getMethodName()); + assertTrue(true); + } + +} diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/CombinedMinioS3IT.java b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/CombinedMinioS3IT.java new file mode 100644 index 00000000..5442e6df --- /dev/null +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/CombinedMinioS3IT.java @@ -0,0 +1,35 @@ +package org.carlspring.cloud.storage.s3fs.junit.examples; + +import org.carlspring.cloud.storage.s3fs.junit.annotations.MinioIntegrationTest; +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; + +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Class level {@link MinioIntegrationTest} annotation and method level {@link S3IntegrationTest} annotation. + */ +@MinioIntegrationTest +public class CombinedMinioS3IT +{ + + private static final Logger logger = LoggerFactory.getLogger(S3MethodAnnotationIT.class); + + @Test + @S3IntegrationTest + public void testS3MethodShouldExecuteBecauseOfMethodLevelAnnotation() + { + logger.debug(new Exception().getStackTrace()[0].getMethodName()); + assertTrue(true); + } + + @Test + public void testMinioMethodShouldExecuteBecauseOfClassLevelAnnotation() + { + logger.debug(new Exception().getStackTrace()[0].getMethodName()); + assertTrue(true); + } + +} diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/CombinedS3MinioIT.java b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/CombinedS3MinioIT.java new file mode 100644 index 00000000..ee953d34 --- /dev/null +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/CombinedS3MinioIT.java @@ -0,0 +1,35 @@ +package org.carlspring.cloud.storage.s3fs.junit.examples; + +import org.carlspring.cloud.storage.s3fs.junit.annotations.MinioIntegrationTest; +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; + +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Class level {@link S3IntegrationTest} annotation and method level {@link MinioIntegrationTest} annotation. + */ +@S3IntegrationTest +public class CombinedS3MinioIT +{ + + private static final Logger logger = LoggerFactory.getLogger(S3MethodAnnotationIT.class); + + @Test + public void testS3MethodShouldExecuteBecauseOfClassLevelAnnotation() + { + logger.debug(new Exception().getStackTrace()[0].getMethodName()); + assertTrue(true); + } + + @Test + @MinioIntegrationTest + public void testMinioMethodShouldExecuteBecauseOfMethodLevelAnnotation() + { + logger.debug(new Exception().getStackTrace()[0].getMethodName()); + assertTrue(true); + } + +} diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/MinioClassAnnotationIT.java b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/MinioClassAnnotationIT.java new file mode 100644 index 00000000..f487013c --- /dev/null +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/MinioClassAnnotationIT.java @@ -0,0 +1,23 @@ +package org.carlspring.cloud.storage.s3fs.junit.examples; + +import org.carlspring.cloud.storage.s3fs.junit.annotations.MinioIntegrationTest; + +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@MinioIntegrationTest +public class MinioClassAnnotationIT +{ + + private static final Logger logger = LoggerFactory.getLogger(MinioClassAnnotationIT.class); + + @Test + public void testShouldExecuteBecauseOfClassAnnotation() + { + logger.debug(new Exception().getStackTrace()[0].getMethodName()); + assertTrue(true); + } + +} diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/MinioMethodAnnotationIT.java b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/MinioMethodAnnotationIT.java new file mode 100644 index 00000000..4dc2f674 --- /dev/null +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/MinioMethodAnnotationIT.java @@ -0,0 +1,22 @@ +package org.carlspring.cloud.storage.s3fs.junit.examples; + +import org.carlspring.cloud.storage.s3fs.junit.annotations.MinioIntegrationTest; + +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class MinioMethodAnnotationIT +{ + + private static final Logger logger = LoggerFactory.getLogger(MinioMethodAnnotationIT.class); + + @Test + @MinioIntegrationTest + public void testShouldExecuteBecauseOfMethodAnnotation() + { + logger.debug(new Exception().getStackTrace()[0].getMethodName()); + assertTrue(true); + } +} diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/S3ClassAnnotationIT.java b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/S3ClassAnnotationIT.java new file mode 100644 index 00000000..990496de --- /dev/null +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/S3ClassAnnotationIT.java @@ -0,0 +1,23 @@ +package org.carlspring.cloud.storage.s3fs.junit.examples; + +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; + +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@S3IntegrationTest +public class S3ClassAnnotationIT +{ + + private static final Logger logger = LoggerFactory.getLogger(S3ClassAnnotationIT.class); + + @Test + public void testShouldExecuteBecauseOfClassAnnotation() + { + logger.debug(new Exception().getStackTrace()[0].getMethodName()); + assertTrue(true); + } + +} diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/S3MethodAnnotationIT.java b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/S3MethodAnnotationIT.java new file mode 100644 index 00000000..a24aba5c --- /dev/null +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/junit/examples/S3MethodAnnotationIT.java @@ -0,0 +1,22 @@ +package org.carlspring.cloud.storage.s3fs.junit.examples; + +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; + +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class S3MethodAnnotationIT +{ + + private static final Logger logger = LoggerFactory.getLogger(S3MethodAnnotationIT.class); + + @Test + @S3IntegrationTest + public void testShouldExecuteBecauseOfMethodAnnotation() + { + logger.debug(new Exception().getStackTrace()[0].getMethodName()); + assertTrue(true); + } +} diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/path/ToURLITTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/path/ToURLIT.java similarity index 97% rename from src/test/java/org/carlspring/cloud/storage/s3fs/path/ToURLITTest.java rename to src/test/java/org/carlspring/cloud/storage/s3fs/path/ToURLIT.java index 5d8bd70e..b44d9ca2 100644 --- a/src/test/java/org/carlspring/cloud/storage/s3fs/path/ToURLITTest.java +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/path/ToURLIT.java @@ -2,6 +2,7 @@ import org.carlspring.cloud.storage.s3fs.S3FileSystemProvider; import org.carlspring.cloud.storage.s3fs.S3Path; +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; import org.carlspring.cloud.storage.s3fs.util.EnvironmentBuilder; import java.io.IOException; @@ -13,7 +14,6 @@ import java.util.HashMap; import java.util.Map; -import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import static org.carlspring.cloud.storage.s3fs.S3Factory.PATH_STYLE_ACCESS; import static org.carlspring.cloud.storage.s3fs.S3Factory.PROTOCOL; @@ -23,8 +23,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; -@Tag("s3-integration-test") -public class ToURLITTest +@S3IntegrationTest +class ToURLIT { private static final URI uriGlobal = EnvironmentBuilder.getS3URI(S3_GLOBAL_URI_IT); diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/spike/EnvironmentITTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/spike/EnvironmentIT.java similarity index 73% rename from src/test/java/org/carlspring/cloud/storage/s3fs/spike/EnvironmentITTest.java rename to src/test/java/org/carlspring/cloud/storage/s3fs/spike/EnvironmentIT.java index e3b4f4ab..ea4ea2b1 100644 --- a/src/test/java/org/carlspring/cloud/storage/s3fs/spike/EnvironmentITTest.java +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/spike/EnvironmentIT.java @@ -1,5 +1,7 @@ package org.carlspring.cloud.storage.s3fs.spike; +import org.carlspring.cloud.storage.s3fs.junit.annotations.MinioIntegrationTest; +import org.carlspring.cloud.storage.s3fs.junit.annotations.S3IntegrationTest; import org.carlspring.cloud.storage.s3fs.util.EnvironmentBuilder; import java.util.Map; @@ -9,7 +11,9 @@ import static org.carlspring.cloud.storage.s3fs.S3Factory.SECRET_KEY; import static org.junit.jupiter.api.Assertions.assertNotNull; -class EnvironmentITTest +@S3IntegrationTest +@MinioIntegrationTest +class EnvironmentIT { @Test void couldCreateFileSystem() diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/util/EnvironmentBuilder.java b/src/test/java/org/carlspring/cloud/storage/s3fs/util/EnvironmentBuilder.java index ef61b915..77794380 100644 --- a/src/test/java/org/carlspring/cloud/storage/s3fs/util/EnvironmentBuilder.java +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/util/EnvironmentBuilder.java @@ -7,7 +7,11 @@ import java.util.Properties; import com.google.common.collect.ImmutableMap; +import org.apache.commons.lang3.StringUtils; import org.apache.http.client.utils.URIBuilder; + +import javax.annotation.Nonnull; + import static org.carlspring.cloud.storage.s3fs.S3Factory.ACCESS_KEY; import static org.carlspring.cloud.storage.s3fs.S3Factory.PROTOCOL; import static org.carlspring.cloud.storage.s3fs.S3Factory.REGION; @@ -32,18 +36,20 @@ public static Map getRealEnv() { Map env; - String accessKey = System.getenv(ACCESS_KEY); - String secretKey = System.getenv(SECRET_KEY); - String region = System.getenv(REGION); - String protocol = System.getenv(PROTOCOL); + String accessKey = getEnvValue(ACCESS_KEY); + String secretKey = getEnvValue(SECRET_KEY); + String region = getEnvValue(REGION); + String protocol = getEnvValue(PROTOCOL); + String bucket = getEnvValue(BUCKET_NAME_KEY); - if (accessKey != null && secretKey != null && region != null && protocol != null) + if (accessKey != null && secretKey != null && region != null && protocol != null && bucket != null) { env = ImmutableMap.builder().put(ACCESS_KEY, accessKey) - .put(SECRET_KEY, secretKey) - .put(REGION, region) - .put(PROTOCOL, protocol) - .build(); + .put(SECRET_KEY, secretKey) + .put(REGION, region) + .put(PROTOCOL, protocol) + .put(BUCKET_NAME_KEY, bucket) + .build(); } else { @@ -59,15 +65,51 @@ public static Map getRealEnv() } env = ImmutableMap.builder().put(ACCESS_KEY, props.getProperty(ACCESS_KEY)) - .put(SECRET_KEY, props.getProperty(SECRET_KEY)) - .put(REGION, props.getProperty(REGION)) - .put(PROTOCOL, props.getProperty(PROTOCOL)) - .build(); + .put(SECRET_KEY, props.getProperty(SECRET_KEY)) + .put(REGION, props.getProperty(REGION)) + .put(PROTOCOL, props.getProperty(PROTOCOL)) + .put(BUCKET_NAME_KEY, props.getProperty(BUCKET_NAME_KEY)) + .build(); } return env; } + /** + * Attempt to retrieve OS Environment Variable + * @return + */ + private static String getEnvValue(@Nonnull String key) + { + String envKeyName = getS3EnvName(key); + String value = System.getenv(envKeyName); + + return value; + } + + /** + * @param key Non-prefixed environment name (i.e. bucket.name) + * @return Prefixed uppercase environment name (i.e. S3FS_BUCKET_NAME || S3FS_MINIO_BUCKET_NAME) + */ + private static String getS3EnvName(@Nonnull String key) + { + // Sometimes the key will contain `S3FS_` or `s3fs.property.name` which is why we need to sanitize the string + // to ensure consistency. + String sanitized = StringUtils.removeStartIgnoreCase(key, "S3FS."); + sanitized = StringUtils.removeStartIgnoreCase(sanitized, "S3FS_"); + sanitized = sanitized.replaceAll("\\.", "_").toUpperCase(); + + String integrationSuite = System.getProperty("running.it"); + if(integrationSuite != null && integrationSuite.equalsIgnoreCase("minio")) + { + sanitized = "MINIO_" + sanitized; + } + + sanitized = "S3FS_" + sanitized; + + return sanitized; + } + /** * get default bucket name * @@ -75,7 +117,7 @@ public static Map getRealEnv() */ public static String getBucket() { - String bucketName = System.getenv(BUCKET_NAME_KEY); + String bucketName = getEnvValue(BUCKET_NAME_KEY); if (bucketName != null) { if (!bucketName.endsWith("/"))