Admin: Add tests for Java SDK (#6002)

This commit is contained in:
Bert Blommers 2023-03-02 13:28:21 -01:00 committed by GitHub
parent c5a91e6cc6
commit d525423f94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 381 additions and 8 deletions

View File

@ -70,6 +70,35 @@ jobs:
run:
make lint
javatest:
name: Test behaviour for Java SDK
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: "3.8"
- name: Start MotoServer
run: |
pip install build
python -m build
docker run --rm -t --name motoserver -e TEST_SERVER_MODE=true -e AWS_SECRET_ACCESS_KEY=server_secret -e AWS_ACCESS_KEY_ID=server_key -v `pwd`:/moto -p 5000:5000 -v /var/run/docker.sock:/var/run/docker.sock python:3.7-buster /moto/scripts/ci_moto_server.sh &
python scripts/ci_wait_for_server.py
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
cache: 'maven'
- name: Build with Maven
run: |
mkdir ~/.aws && touch ~/.aws/credentials && echo -e "[default]\naws_access_key_id = test\naws_secret_access_key = test" > ~/.aws/credentials
cd other_langs/tests_java && mvn test
test:
name: Unit test
runs-on: ubuntu-latest
@ -182,7 +211,7 @@ jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
needs: [test, testserver ]
needs: [javatest, test, testserver ]
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'getmoto/moto' }}
strategy:
matrix:

1
.gitignore vendored
View File

@ -30,3 +30,4 @@ htmlcov/
docs/_build
moto_recording
.hypothesis
other_langs/tests_java/target

View File

@ -71,10 +71,14 @@ class RESTError(HTTPException):
self, *args: Any, **kwargs: Any # pylint: disable=unused-argument
) -> List[Tuple[str, str]]:
return [
("X-Amzn-ErrorType", self.error_type or "UnknownError"),
("X-Amzn-ErrorType", self.relative_error_type or "UnknownError"),
("Content-Type", self.content_type),
]
@property
def relative_error_type(self) -> str:
return self.error_type
def get_body(
self, *args: Any, **kwargs: Any # pylint: disable=unused-argument
) -> str:
@ -95,6 +99,12 @@ class JsonRESTError(RESTError):
)
self.content_type = "application/json"
@property
def relative_error_type(self) -> str:
# https://smithy.io/2.0/aws/protocols/aws-json-1_1-protocol.html
# If a # character is present, then take only the contents after the first # character in the value
return self.error_type.split("#")[-1]
def get_body(self, *args: Any, **kwargs: Any) -> str:
return self.description

View File

@ -315,9 +315,9 @@ class TableAlreadyExistsException(JsonRESTError):
class ResourceInUseException(JsonRESTError):
def __init__(self) -> None:
def __init__(self, msg: Optional[str] = None) -> None:
er = ERROR_TYPE_PREFIX + "ResourceInUseException"
super().__init__(er, "Resource in use")
super().__init__(er, msg or "Resource in use")
class StreamAlreadyEnabledException(JsonRESTError):

View File

@ -60,7 +60,7 @@ class DynamoDBBackend(BaseBackend):
def create_table(self, name: str, **params: Any) -> Table:
if name in self.tables:
raise ResourceInUseException
raise ResourceInUseException(f"Table already exists: {name}")
table = Table(
name, account_id=self.account_id, region=self.region_name, **params
)

View File

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>moto.tests</groupId>
<artifactId>java-tests</artifactId>
<version>1.0-SNAPSHOT</version>
<name>java-tests</name>
<url>docs.getmoto.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.20.14</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>dynamodb</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<exclusions>
<exclusion>
<groupId>software.amazon.awssdk</groupId>
<artifactId>netty-nio-client</artifactId>
</exclusion>
<exclusion>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>url-connection-client</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>apache-client</artifactId>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@ -0,0 +1,51 @@
package moto.tests;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.SdkHttpConfigurationOption;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.utils.AttributeMap;
import java.net.URI;
import java.time.Duration;
/**
* The module containing all dependencies required by the {@link Handler}.
*/
public class DependencyFactory {
private static final URI MOTO_URI = URI.create("http://localhost:5000");
private DependencyFactory() {}
/**
* @return an instance of S3Client
*/
public static S3Client s3Client() {
return S3Client.builder()
.region(Region.US_EAST_1)
.httpClientBuilder(ApacheHttpClient.builder())
.endpointOverride(MOTO_URI)
.build();
}
public static DynamoDbClient dynamoClient() {
final AttributeMap attributeMap = AttributeMap.builder()
.put(SdkHttpConfigurationOption.TRUST_ALL_CERTIFICATES, true)
.build();
// Not in use at the moment, but useful for testing
SdkHttpClient proxy_client = UrlConnectionHttpClient.builder()
.socketTimeout(Duration.ofMinutes(1))
.proxyConfiguration(proxy -> proxy.endpoint(URI.create("http://localhost:8080")))
.buildWithDefaults(attributeMap);
return DynamoDbClient.builder()
.region(Region.US_EAST_1)
// .httpClient(client)
.httpClientBuilder(ApacheHttpClient.builder())
.endpointOverride(MOTO_URI)
.build();
}
}

View File

@ -0,0 +1,42 @@
package moto.tests;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput;
import software.amazon.awssdk.services.dynamodb.model.KeyType;
import software.amazon.awssdk.services.dynamodb.model.CreateTableResponse;
public class DynamoLogic {
private final DynamoDbClient client;
public DynamoLogic() {
client = DependencyFactory.dynamoClient();
}
public String createTable(String tableName, String key) {
CreateTableRequest request = CreateTableRequest.builder()
.attributeDefinitions(AttributeDefinition.builder()
.attributeName(key)
.attributeType(ScalarAttributeType.S)
.build())
.keySchema(KeySchemaElement.builder()
.attributeName(key)
.keyType(KeyType.HASH)
.build())
.provisionedThroughput(ProvisionedThroughput.builder()
.readCapacityUnits(new Long(10))
.writeCapacityUnits(new Long(10))
.build())
.tableName(tableName)
.build();
System.out.println("Prepared CreateTableRequest");
CreateTableResponse response = this.client.createTable(request);
System.out.println(response.tableDescription());
return response.tableDescription().tableName();
}
}

View File

@ -0,0 +1,83 @@
package moto.tests;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
import software.amazon.awssdk.services.s3.model.DeleteBucketRequest;
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
/**
* Example class as provided by AWS - verify that basic S3 functions work
*/
public class Handler {
private final S3Client s3Client;
public Handler() {
s3Client = DependencyFactory.s3Client();
}
public void sendRequest() {
String bucket = "bucket" + System.currentTimeMillis();
String key = "key";
tutorialSetup(s3Client, bucket);
System.out.println("Uploading object...");
s3Client.putObject(PutObjectRequest.builder().bucket(bucket).key(key)
.build(),
RequestBody.fromString("Testing with the {sdk-java}"));
System.out.println("Upload complete");
System.out.printf("%n");
cleanUp(s3Client, bucket, key);
System.out.println("Closing the connection to {S3}");
s3Client.close();
System.out.println("Connection closed");
System.out.println("Exiting...");
}
public static void tutorialSetup(S3Client s3Client, String bucketName) {
try {
s3Client.createBucket(CreateBucketRequest
.builder()
.bucket(bucketName)
.build());
System.out.println("Creating bucket: " + bucketName);
s3Client.waiter().waitUntilBucketExists(HeadBucketRequest.builder()
.bucket(bucketName)
.build());
System.out.println(bucketName + " is ready.");
System.out.printf("%n");
} catch (S3Exception e) {
System.err.println(e.awsErrorDetails().errorMessage());
System.exit(1);
}
}
public static void cleanUp(S3Client s3Client, String bucketName, String keyName) {
System.out.println("Cleaning up...");
try {
System.out.println("Deleting object: " + keyName);
DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder().bucket(bucketName).key(keyName).build();
s3Client.deleteObject(deleteObjectRequest);
System.out.println(keyName + " has been deleted.");
System.out.println("Deleting bucket: " + bucketName);
DeleteBucketRequest deleteBucketRequest = DeleteBucketRequest.builder().bucket(bucketName).build();
s3Client.deleteBucket(deleteBucketRequest);
System.out.println(bucketName + " has been deleted.");
System.out.printf("%n");
} catch (S3Exception e) {
System.err.println(e.awsErrorDetails().errorMessage());
System.exit(1);
}
System.out.println("Cleanup complete");
System.out.printf("%n");
}
}

View File

@ -0,0 +1,31 @@
package moto.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import software.amazon.awssdk.services.dynamodb.model.ResourceInUseException;
public class DynamoTest {
@Test
public void testSingleTableExists() {
DynamoLogic logic = new DynamoLogic();
String table_name = logic.createTable("table", "key");
assertEquals("table", table_name);
}
@Test
public void testTableCannotBeCreatedTwice() {
DynamoLogic logic = new DynamoLogic();
// Going once...
logic.createTable("table2", "key");
try {
// Going twice should throw a specific exception
logic.createTable("table2", "key");
} catch (ResourceInUseException riue) {
assertTrue(riue.getMessage().startsWith("Table already exists: table2"));
}
}
}

View File

@ -0,0 +1,16 @@
package moto.tests;
import org.junit.Test;
/**
* Unit test for simple App.
*/
public class S3Test
{
@Test
public void connectToS3() {
Handler handler = new Handler();
handler.sendRequest();
}
}

View File

@ -24,9 +24,7 @@ def test_table_list():
res = test_client.post(
"/", headers=headers, data=json.dumps({"TableName": "test-table2"})
)
res.headers.should.have.key("X-Amzn-ErrorType").equals(
"com.amazonaws.dynamodb.v20120810#ResourceNotFoundException"
)
res.headers.should.have.key("X-Amzn-ErrorType").equals("ResourceNotFoundException")
body = json.loads(res.data.decode("utf-8"))
body.should.equal(
{