Skip to content

Commit

Permalink
chore(integ-tests): Applying type coercion to byte array when necessa…
Browse files Browse the repository at this point in the history
…ry (#27092)

#27009 introduced support for `Uint8Array` if users want to send data with the same types as those declared in the SDK v3 API. But existing tests, that use strings, will break.

Apply type coercion when necessary.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
otaviomacedo authored and Mike Wrighton committed Sep 14, 2023
1 parent cbeecf3 commit fe76f95
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 31,969 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
{
"version": "34.0.0",
"files": {
"020364985d409cf8bf611edf535aedca3c0d7c0dd7f21ba847b79a41d9bf0dce": {
"e6687baf1807038e7f7c1491f44379c5b84bec1eac25667aaa6b38ef78dff400": {
"source": {
"path": "asset.020364985d409cf8bf611edf535aedca3c0d7c0dd7f21ba847b79a41d9bf0dce.bundle",
"path": "asset.e6687baf1807038e7f7c1491f44379c5b84bec1eac25667aaa6b38ef78dff400.bundle",
"packaging": "zip"
},
"destinations": {
"current_account-current_region": {
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
"objectKey": "020364985d409cf8bf611edf535aedca3c0d7c0dd7f21ba847b79a41d9bf0dce.zip",
"objectKey": "e6687baf1807038e7f7c1491f44379c5b84bec1eac25667aaa6b38ef78dff400.zip",
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
}
}
},
"d10734fe0522d2d30eb5916fd9a45d4ddf9ec42fd308c30e000cbd7ad11f7a39": {
"e89e8285f3bd8e37ab8fb821889173f1bf1426ff88fd9f62a60f7a40376618aa": {
"source": {
"path": "integtestDefaultTestDeployAssert24D5C536.template.json",
"packaging": "file"
},
"destinations": {
"current_account-current_region": {
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
"objectKey": "d10734fe0522d2d30eb5916fd9a45d4ddf9ec42fd308c30e000cbd7ad11f7a39.json",
"objectKey": "e89e8285f3bd8e37ab8fb821889173f1bf1426ff88fd9f62a60f7a40376618aa.json",
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
}
},
"flattenResponse": "false",
"salt": "1693996483504"
"salt": "1694426182342"
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete"
Expand Down Expand Up @@ -63,6 +63,24 @@
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"lambda:Invoke"
],
"Effect": "Allow",
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": [
"*"
]
},
{
"Action": [
"lambda:Invoke"
Expand Down Expand Up @@ -95,7 +113,7 @@
"S3Bucket": {
"Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"
},
"S3Key": "020364985d409cf8bf611edf535aedca3c0d7c0dd7f21ba847b79a41d9bf0dce.zip"
"S3Key": "e6687baf1807038e7f7c1491f44379c5b84bec1eac25667aaa6b38ef78dff400.zip"
},
"Timeout": 120,
"Handler": "index.handler",
Expand All @@ -106,6 +124,40 @@
]
}
}
},
"AwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4": {
"Type": "Custom::DeployAssert@SdkCallLambdainvoke",
"Properties": {
"ServiceToken": {
"Fn::GetAtt": [
"SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F",
"Arn"
]
},
"service": "Lambda",
"api": "invoke",
"expected": "{\"$ObjectLike\":{\"Payload\":{\"name\":\"world\"}}}",
"parameters": {
"FunctionName": {
"Fn::Join": [
"",
[
"\"",
{
"Fn::ImportValue": "IntegBinaryPayload:ExportsOutputReffn5FF616E3BE1A8BD6"
},
"\""
]
]
},
"InvocationType": "\"RequestResponse\"",
"Payload": "\"{\\\"name\\\":\\\"world\\\"}\""
},
"flattenResponse": "false",
"salt": "1694426182343"
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete"
}
},
"Outputs": {
Expand All @@ -116,6 +168,14 @@
"assertion"
]
}
},
"AssertionResultsAwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4": {
"Value": {
"Fn::GetAtt": [
"AwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4",
"assertion"
]
}
}
},
"Parameters": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"validateOnSynth": false,
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}",
"cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}",
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/d10734fe0522d2d30eb5916fd9a45d4ddf9ec42fd308c30e000cbd7ad11f7a39.json",
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/e89e8285f3bd8e37ab8fb821889173f1bf1426ff88fd9f62a60f7a40376618aa.json",
"requiresBootstrapStackVersion": 6,
"bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version",
"additionalDependencies": [
Expand Down Expand Up @@ -123,6 +123,18 @@
"data": "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F"
}
],
"/integ-test/DefaultTest/DeployAssert/AwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4/Default/Default": [
{
"type": "aws:cdk:logicalId",
"data": "AwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4"
}
],
"/integ-test/DefaultTest/DeployAssert/AwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4/AssertionResults": [
{
"type": "aws:cdk:logicalId",
"data": "AssertionResultsAwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4"
}
],
"/integ-test/DefaultTest/DeployAssert/BootstrapVersion": [
{
"type": "aws:cdk:logicalId",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,60 @@
"version": "10.2.70"
}
},
"AwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4": {
"id": "AwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4",
"path": "integ-test/DefaultTest/DeployAssert/AwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4",
"children": {
"SdkProvider": {
"id": "SdkProvider",
"path": "integ-test/DefaultTest/DeployAssert/AwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4/SdkProvider",
"children": {
"AssertionsProvider": {
"id": "AssertionsProvider",
"path": "integ-test/DefaultTest/DeployAssert/AwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4/SdkProvider/AssertionsProvider",
"constructInfo": {
"fqn": "constructs.Construct",
"version": "10.2.70"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/integ-tests-alpha.AssertionsProvider",
"version": "0.0.0"
}
},
"Default": {
"id": "Default",
"path": "integ-test/DefaultTest/DeployAssert/AwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4/Default",
"children": {
"Default": {
"id": "Default",
"path": "integ-test/DefaultTest/DeployAssert/AwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4/Default/Default",
"constructInfo": {
"fqn": "aws-cdk-lib.CfnResource",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "aws-cdk-lib.CustomResource",
"version": "0.0.0"
}
},
"AssertionResults": {
"id": "AssertionResults",
"path": "integ-test/DefaultTest/DeployAssert/AwsApiCallLambdainvokefadfa108bb2726119308f73d0e24d8d4/AssertionResults",
"constructInfo": {
"fqn": "aws-cdk-lib.CfnOutput",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/integ-tests-alpha.AwsApiCall",
"version": "0.0.0"
}
},
"BootstrapVersion": {
"id": "BootstrapVersion",
"path": "integ-test/DefaultTest/DeployAssert/BootstrapVersion",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ const fn = new Function(stack, 'fn', {
`),
});

const buf = Buffer.from(JSON.stringify({ name: 'world' }));
const inputString = JSON.stringify({ name: 'world' });
const buf = Buffer.from(inputString);
const data = new Uint8Array(
buf.buffer,
buf.byteOffset,
Expand All @@ -26,16 +27,31 @@ const testCase = new IntegTest(app, 'integ-test', {
testCases: [stack],
});

const invoke = testCase.assertions.awsApiCall('Lambda', 'invoke', {
const invokeWithByteArray = testCase.assertions.awsApiCall('Lambda', 'invoke', {
FunctionName: fn.functionName,
InvocationType: 'RequestResponse',
Payload: data,
});

invoke.provider.addToRolePolicy({
invokeWithByteArray.provider.addToRolePolicy({
Effect: 'Allow',
Action: ['lambda:InvokeFunction'],
Resource: ['*'],
});

invoke.expect(ExpectedResult.objectLike({ Payload: { name: 'world' } }));
const invokeWithString = testCase.assertions.awsApiCall('Lambda', 'invoke', {
FunctionName: fn.functionName,
InvocationType: 'RequestResponse',
Payload: inputString,
});

invokeWithString.provider.addToRolePolicy({
Effect: 'Allow',
Action: ['lambda:InvokeFunction'],
Resource: ['*'],
});

// Expect the same behaviour, regardless of whether the input is a string or a byte array
invokeWithByteArray.expect(ExpectedResult.objectLike({ Payload: { name: 'world' } }));
invokeWithString.expect(ExpectedResult.objectLike({ Payload: { name: 'world' } }));

Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/* eslint-disable no-console */
import { CustomResourceHandler } from './base';
import { AwsApiCallRequest, AwsApiCallResult } from './types';
import { getV3ClientPackageName, findV3ClientConstructor } from '@aws-cdk/sdk-v2-to-v3-adapter';
import {
getV3ClientPackageName,
findV3ClientConstructor,
coerceApiParametersToUint8Array,
} from '@aws-cdk/sdk-v2-to-v3-adapter';
import { decodeParameters, parseJsonPayload } from './utils';

/**
Expand Down Expand Up @@ -80,7 +84,8 @@ export class AwsApiCallHandler extends CustomResourceHandler<AwsApiCallRequest,
const client = getServiceClient(sdkPkg);

const Command = getSdkCommand(sdkPkg, request.api);
const commandInput = (request.parameters && decodeParameters(request.parameters)) ?? {};
const parameters = (request.parameters && decodeParameters(request.parameters)) ?? {};
const commandInput = coerceApiParametersToUint8Array(request.service, request.api, parameters);

console.log(`SDK request to ${sdkPkg.service}.${request.api} with parameters ${JSON.stringify(commandInput)}`);
const response = await client.send(new Command(commandInput));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
import { S3Client, ListObjectsOutput, ListObjectsCommand } from '@aws-sdk/client-s3';
import { S3Client, ListObjectsOutput, ListObjectsCommand, PutObjectCommand } from '@aws-sdk/client-s3';
import { DescribeInstancesCommand, EC2Client } from '@aws-sdk/client-ec2';
import { mockClient } from 'aws-sdk-client-mock';
import { AwsApiCallRequest, AwsApiCallResult } from '../../../../lib/assertions';
Expand Down Expand Up @@ -157,6 +157,31 @@ describe('SdkHandler', () => {
// THEN
expect(ec2Mock).toHaveReceivedCommandWith(DescribeInstancesCommand, { NextToken: 'To"ken' });
});

test('byte array coercion', async () => {
// GIVEN
s3Mock.on(PutObjectCommand).resolves({ });
const handler = sdkHandler() as any;
const request: AwsApiCallRequest = {
service: 'S3',
api: 'putObject',
parameters: {
Bucket: '"myBucket"',
Key: '"foo"',
Body: '"abc"',
},
};

// WHEN
await handler.processEvent(request);

// THEN
expect(s3Mock).toHaveReceivedCommandWith(PutObjectCommand, {
Bucket: 'myBucket',
Key: 'foo',
Body: Uint8Array.from([97, 98, 99]),
});
});
});

test('restrict output path', async () => {
Expand Down

0 comments on commit fe76f95

Please sign in to comment.