-
Notifications
You must be signed in to change notification settings - Fork 45
Add integration tests #48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
34f27a9
Add first integration test function
sfirrin 840f7cd
Deploy, invoke, fetch logs, and compare to snapshot
sfirrin b3ebc80
Make integration test work for async metrics
sfirrin e364319
Log HTTP requests if DD_INTEGRATION_TEST=true; normalize snapshots more
sfirrin 165f78a
Fix formatting
sfirrin 6c1a992
Normalize logged HTTP requests
sfirrin 7b900f0
Fix formatting
sfirrin 583bd56
Readability tweaks for shell script
sfirrin db7ec15
Refactor sed calls for better readability
sfirrin 68f47ee
Remove accidental file
sfirrin bf82854
Rename functions to format handler-name_runtime
sfirrin 44c9d2a
Restructure snapshots dir, add input events
sfirrin be881ab
Edit script for readability
sfirrin be6186f
Generate snapshots in script if they don't exist yet
sfirrin 041825b
Parse data out of input events to include in responses
sfirrin 1ced36e
Replace account IDs with XXXX
sfirrin 8d7b0c6
Clarify instructions for re-running
sfirrin ea661a6
Replace minor version in tag with XX to make tests less brittle
sfirrin f47d412
Clarify echo messages
sfirrin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,3 +36,6 @@ nosetests.xml | |
.eggs/ | ||
.env/ | ||
.idea/ | ||
|
||
|
||
**/.serverless/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
#!/bin/bash | ||
|
||
# Usage - run commands from repo root: | ||
# To check if new changes to the layer cause changes to any snapshots: | ||
# BUILD_LAYERS=true DD_API_KEY=XXXX aws-vault exec sandbox-account-admin -- ./scripts/run_integration_tests | ||
# To regenerate snapshots: | ||
# UPDATE_SNAPSHOTS=true DD_API_KEY=XXXX aws-vault exec sandbox-account-admin -- ./scripts/run_integration_tests | ||
|
||
set -e | ||
|
||
# These values need to be in sync with serverless.yml, where there needs to be a function | ||
# defined for every handler_runtime combination | ||
LAMBDA_HANDLERS=("async-metrics" "sync-metrics" "http-requests") | ||
RUNTIMES=("python27" "python36" "python37" "python38") | ||
|
||
LOGS_WAIT_SECONDS=20 | ||
|
||
script_path=${BASH_SOURCE[0]} | ||
scripts_dir=$(dirname $script_path) | ||
repo_dir=$(dirname $scripts_dir) | ||
integration_tests_dir="$repo_dir/tests/integration" | ||
|
||
script_start_time=$(date --iso-8601=seconds) | ||
|
||
mismatch_found=false | ||
|
||
if [ -z "$DD_API_KEY" ]; then | ||
echo "No DD_API_KEY env var set, exiting" | ||
exit 1 | ||
fi | ||
|
||
if [ -n "$UPDATE_SNAPSHOTS" ]; then | ||
echo "Overwriting snapshots in this execution" | ||
fi | ||
|
||
if [ -n "$BUILD_LAYERS" ]; then | ||
echo "Building layers that will be deployed with our test functions" | ||
source $scripts_dir/build_layers.sh | ||
else | ||
echo "Not building layers, ensure they've already been built or re-run with 'BUILD_LAYERS=true DD_API_KEY=XXXX ./scripts/run_integration_tests.sh'" | ||
fi | ||
|
||
cd $integration_tests_dir | ||
input_event_files=$(ls ./input_events) | ||
# Sort event files by name so that snapshots stay consistent | ||
input_event_files=($(for file_name in ${input_event_files[@]}; do echo $file_name; done | sort)) | ||
|
||
echo "Deploying functions" | ||
serverless deploy | ||
|
||
echo "Invoking functions" | ||
set +e # Don't exit this script if an invocation fails or there's a diff | ||
for handler_name in "${LAMBDA_HANDLERS[@]}"; do | ||
for runtime in "${RUNTIMES[@]}"; do | ||
function_name="${handler_name}_${runtime}" | ||
# Invoke function once for each input event | ||
for input_event_file in "${input_event_files[@]}"; do | ||
# Get event name without trailing ".json" so we can build the snapshot file name | ||
input_event_name=$(echo "$input_event_file" | sed "s/.json//") | ||
# Return value snapshot file format is snapshots/return_values/{handler}_{runtime}_{input-event} | ||
snapshot_path="./snapshots/return_values/${function_name}_${input_event_name}.json" | ||
|
||
return_value=$(serverless invoke -f $function_name --path "./input_events/$input_event_file") | ||
|
||
if [ ! -f $snapshot_path ]; then | ||
# If the snapshot file doesn't exist yet, we create it | ||
echo "Writing return value to $snapshot_path because no snapshot exists yet" | ||
echo "$return_value" >$snapshot_path | ||
elif [ -n "$UPDATE_SNAPSHOTS" ]; then | ||
# If $UPDATE_SNAPSHOTS is set to true, write the new logs over the current snapshot | ||
echo "Overwriting return value snapshot for $snapshot_path" | ||
echo "$return_value" >$snapshot_path | ||
else | ||
# Compare new return value to snapshot | ||
diff_output=$(echo "$return_value" | diff - $snapshot_path) | ||
if [ $? -eq 1 ]; then | ||
echo "Failed: Return value for $function_name does not match snapshot:" | ||
echo "$diff_output" | ||
mismatch_found=true | ||
else | ||
echo "Ok: Return value for $function_name with $input_event_name event matches snapshot" | ||
fi | ||
fi | ||
done | ||
|
||
done | ||
|
||
done | ||
set -e | ||
|
||
echo "Sleeping $LOGS_WAIT_SECONDS seconds to wait for logs to appear in CloudWatch..." | ||
sleep $LOGS_WAIT_SECONDS | ||
|
||
echo "Fetching logs for invocations and comparing to snapshots" | ||
for handler_name in "${LAMBDA_HANDLERS[@]}"; do | ||
for runtime in "${RUNTIMES[@]}"; do | ||
function_name="${handler_name}_${runtime}" | ||
function_snapshot_path="./snapshots/logs/$function_name.log" | ||
|
||
# Fetch logs with serverless cli | ||
raw_logs=$(serverless logs -f $function_name --startTime $script_start_time) | ||
|
||
# Replace invocation-specific data like timestamps and IDs with XXXX to normalize logs across executions | ||
logs=$( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also pretty cool trick |
||
echo "$raw_logs" | | ||
# Filter serverless cli errors | ||
sed '/Serverless: Recoverable error occurred/d' | | ||
# Remove blank lines | ||
sed '/^$/d' | | ||
# Normalize Lambda runtime report logs | ||
sed -E 's/(RequestId|TraceId|SegmentId|Duration|Memory Used|"e"): [a-z0-9\.\-]+/\1: XXXX/g' | | ||
# Normalize DD APM headers and AWS account ID | ||
sed -E "s/(x-datadog-parent-id:|x-datadog-trace-id:|account_id:)[0-9]+/\1XXXX/g" | | ||
# Normalize timestamps in datapoints POSTed to DD | ||
sed -E 's/"points": \[\[[0-9\.]+,/"points": \[\[XXXX,/g' | | ||
# Strip API key from logged requests | ||
sed -E "s/(api_key=|'api_key': ')[a-z0-9\.\-]+/\1XXXX/g" | | ||
# Normalize minor package version so that these snapshots aren't broken on version bumps | ||
sed -E "s/(dd_lambda_layer:datadog-python[0-9]+_2\.)[0-9]+\.0/\1XX\.0/g" | ||
) | ||
|
||
if [ ! -f $function_snapshot_path ]; then | ||
# If no snapshot file exists yet, we create one | ||
echo "Writing logs to $function_snapshot_path because no snapshot exists yet" | ||
echo "$logs" >$function_snapshot_path | ||
elif [ -n "$UPDATE_SNAPSHOTS" ]; then | ||
# If $UPDATE_SNAPSHOTS is set to true write the new logs over the current snapshot | ||
echo "Overwriting log snapshot for $function_snapshot_path" | ||
echo "$logs" >$function_snapshot_path | ||
else | ||
# Compare new logs to snapshots | ||
set +e # Don't exit this script if there is a diff | ||
diff_output=$(echo "$logs" | diff - $function_snapshot_path) | ||
if [ $? -eq 1 ]; then | ||
echo "Failed: Mismatch found between new $function_name logs (first) and snapshot (second):" | ||
echo "$diff_output" | ||
mismatch_found=true | ||
else | ||
echo "Ok: New logs for $function_name match snapshot" | ||
fi | ||
set -e | ||
fi | ||
done | ||
done | ||
|
||
if [ "$mismatch_found" = true ]; then | ||
echo "FAILURE: A mismatch between new data and a snapshot was found and printed above." | ||
echo "If the change is expected, generate new snapshots by running 'UPDATE_SNAPSHOTS=true DD_API_KEY=XXXX ./scripts/run_integration_tests.sh'" | ||
exit 1 | ||
fi | ||
|
||
if [ -n "$UPDATE_SNAPSHOTS" ]; then | ||
echo "SUCCESS: Wrote new snapshots for all functions" | ||
exit 0 | ||
fi | ||
|
||
echo "SUCCESS: No difference found between snapshots and new return values or logs" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import json | ||
|
||
from datadog_lambda.metric import lambda_metric | ||
from datadog_lambda.wrapper import datadog_lambda_wrapper | ||
|
||
|
||
@datadog_lambda_wrapper | ||
def handle(event, context): | ||
# Parse request ID and record ids out of the event to include in the response | ||
request_id = event.get("requestContext", {}).get("requestId") | ||
event_records = event.get("Records", []) | ||
|
||
record_ids = [] | ||
for record in event_records: | ||
# SQS | ||
if record.get("messageId"): | ||
record_ids.append(record["messageId"]) | ||
# SNS | ||
if record.get("Sns", {}).get("MessageId"): | ||
record_ids.append(record["Sns"]["MessageId"]) | ||
|
||
lambda_metric("hello.dog", 1, tags=["team:serverless", "role:hello"]) | ||
lambda_metric( | ||
"tests.integration.count", 21, tags=["test:integration", "role:hello"] | ||
) | ||
|
||
return { | ||
"statusCode": 200, | ||
"body": { | ||
"message": "hello, dog!", | ||
"request_id": request_id, | ||
"event_record_ids": record_ids, | ||
}, | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import json | ||
import requests | ||
|
||
from datadog_lambda.metric import lambda_metric | ||
from datadog_lambda.wrapper import datadog_lambda_wrapper | ||
|
||
|
||
@datadog_lambda_wrapper | ||
def handle(event, context): | ||
lambda_metric("hello.dog", 1, tags=["team:serverless", "role:hello"]) | ||
lambda_metric( | ||
"tests.integration.count", 21, tags=["test:integration", "role:hello"] | ||
) | ||
|
||
us_response = requests.get("https://ip-ranges.datadoghq.com/") | ||
eu_response = requests.get("https://ip-ranges.datadoghq.eu/") | ||
|
||
return {"statusCode": 200, "body": {"message": "hello, dog!"}} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The invoke with return value is a neat trick