* fix(cloudwatch): reject PutMetricData datums without a MetricName MetricName is the one required member of MetricDatum. The JSON handler stored a nameless datum under an empty name, and the Query handler treated a member without MetricName as the end of the list, silently dropping it and every later datum while still storing the earlier ones. Both handlers now reject a missing or empty MetricName in top-level MetricData and in EntityMetricData[].MetricData with MissingParameter (400), the error PutMetricData declares for a missing required input, naming the offending member. A whitespace name is still accepted, since AWS constrains MetricName only to 1 to 255 characters. Every datum is validated before any is stored, so a rejected request leaves no state behind. On Query, a member index with no keys at all still ends that MetricData list. * fix(cloudwatch): return MissingRequiredParameterException on JSON and CBOR CloudWatch is awsQueryCompatible. MissingParameter is the awsQueryError code of the MissingRequiredParameterException shape, so it belongs in the Query <Code> and the x-amzn-query-error header, while a JSON 1.0 or CBOR body's __type names the shape. With the code in __type the AWS SDK v2 raised a generic CloudWatchException instead of the modelled one. A package-private CloudWatchMetricsException keeps the Query code as its error code and overrides jsonType() with the shape name, the same split SwfException makes. The shared query-code table in AwsException is left alone because SQS reports MissingParameter as its JSON type. (cherry picked from commit b8d87df05413ea8c4f9497fa05f388c19d4124ec)
sdk-test-java
Compatibility tests for Floci using the AWS SDK for Java v2 (2.31.8).
Runs 352 tests across 17 test classes against a live Floci instance — no mocks.
Services Covered
| Test class | Description |
|---|---|
SsmTest |
Parameter Store — put, get, path, tags |
SqsTest |
Queues, send/receive/delete, DLQ, visibility |
SnsTest |
Topics, subscriptions, publish, SQS delivery |
S3Test |
Buckets, objects, tagging, copy, multipart, batch delete |
DynamoDbTest |
Tables, CRUD, batch, TTL, tags, streams |
DynamoDbScanConditionTests |
Scan filter and condition expressions |
LambdaTest |
Create/invoke/update/delete functions |
IamTest |
Users, roles, policies, access keys |
StsTest |
GetCallerIdentity, AssumeRole, GetSessionToken |
SecretsManagerTest |
Create/get/put/list/delete secrets, versioning, tags |
KmsTest |
Keys, aliases, encrypt/decrypt, data keys, sign/verify |
CloudWatchTest |
PutMetricData, ListMetrics, GetMetricStatistics, alarms |
CloudFormationVirtualHostTests |
Virtual host style S3 access via CloudFormation |
ApigwSfnJsonataCrudlTests |
API Gateway + Step Functions JSONata CRUDL integration |
ApiGatewayV2WebSocketAndExtendedOpsTest |
API GW v2 WebSocket APIs, Update ops, Route/Integration Responses, Models, Tagging |
Ec2Tests |
EC2 instances, VPCs, security groups, subnets |
AppSyncTest |
GraphQL API CRUDL, data sources, resolvers, functions, types, API keys, tags, schema validation |
EcsTests |
ECS clusters, task definitions, services |
Adding a New Test
Create a standard JUnit 5 test class in src/test/java/com/floci/test/. Tests run against a live Floci instance using real AWS SDK clients.
Requirements
- Java 17+
- Maven
Running
# All tests
mvn test -q
# Specific test class
mvn test -Dtest=S3Test
# Via just (from compatibility-tests/)
just test-java
Configuration
| Variable | Default | Description |
|---|---|---|
FLOCI_ENDPOINT |
http://localhost:4566 |
Floci emulator endpoint |
AWS credentials are always test / test / us-east-1.
Metric filter publishing checks
CloudWatchLogsMetricFilterTest and CloudFormationLogsMetricFilterTest run
with the rest of the suite. Against a server on another port:
# From compatibility-tests/sdk-test-java
FLOCI_ENDPOINT=http://127.0.0.1:18084 ../../mvnw test \
-Dtest=CloudWatchLogsMetricFilterTest,CloudFormationLogsMetricFilterTest
The publishing tests read their expected values from
src/test/resources/cloudwatchlogs/metric-filter-publishing-aws.json, a
byte-identical copy of the root fixture recorded from AWS. MetricFilterFixturePackagingTest
checks the copy loads from the classpath, and the root
CloudWatchLogsMetricFilterFixturePackagingTest fails when either SDK module
copy drifts from the root file. The SDK selects the CloudWatch JSON protocol;
MetricFilterQueryAssertions signs the same reads as legacy form-encoded Query
requests, so GetMetricStatistics and GetMetricData on both wire formats are
asserted against every statistic the fixture records (Sum, SampleCount, Minimum,
Maximum). Reads poll for the sample, since the server publishes it shortly after
PutLogEvents returns. Passing
these tests shows Floci matches the recorded values; it is not live AWS
verification. For the opt-in replay against AWS see ../sdk-test-python/README.md.
Docker
docker build -t floci-sdk-java .
docker run --rm --network host floci-sdk-java
# Custom endpoint (macOS/Windows)
docker run --rm -e FLOCI_ENDPOINT=http://host.docker.internal:4566 floci-sdk-java