Skip to content

Commit

Permalink
Compare query strings based on set of components in ec2 integration t…
Browse files Browse the repository at this point in the history
…ests (#3859)

## Motivation and Context
Avoids comparing raw strings in ec2 integration tests

## Description
With a updated service model for ec2, we have run into the following
test failures in its integration tests,
```
----- paginators_handle_unset_tokens stdout ----
body did not match. left=expected, right=actual
Diff < left / right > :
<Action=DescribeSpotPriceHistory&Version=2016-11-15&·[1;48;5;52;31mAvailabilityZone=eu-north-1a&InstanceType.1=g5.48xlarge&ProductDescription.1=Linux%2FUNIX
>Action=DescribeSpotPriceHistory&Version=2016-11-15&InstanceType.1=g5.48xlarge&ProductDescription.1=Linux%2FUNIX·[1;48;5;22;32m&AvailabilityZone=eu-north-1a
 
thread 'paginators_handle_unset_tokens' panicked at sdk/aws-smithy-runtime/src/client/http/test_util/replay.rs:98:43:

---- paginators_handle_empty_tokens stdout ----
body did not match. left=expected, right=actual
Diff < left / right > :
<Action=DescribeSpotPriceHistory&Version=2016-11-15&·[1;48;5;52;31mAvailabilityZone=eu-north-1a&InstanceType.1=g5.48xlarge&ProductDescription.1=Linux%2FUNIX
>Action=DescribeSpotPriceHistory&Version=2016-11-15&InstanceType.1=g5.48xlarge&ProductDescription.1=Linux%2FUNIX·[1;48;5;22;32m&AvailabilityZone=eu-north-1a

thread 'paginators_handle_empty_tokens' panicked at sdk/aws-smithy-runtime/src/client/http/test_util/replay.rs:98:43:
```

We don't know exactly how a generated ec2 SDK built up query strings in
a different order from what it is today, but whatever the root cause is,
the ultimate fix remains the same. Comparing raw query strings can be
unreliable, so this PR will fix that by comparing sets of strings
derived from query strings.

## Testing
Ran the edited tests against the generated ec2 SDK in question and it
passed (without this PR, it did fail).

----

_By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice._
  • Loading branch information
ysaito1001 authored Oct 3, 2024
1 parent 4d0b838 commit 2c0274c
Showing 1 changed file with 27 additions and 27 deletions.
54 changes: 27 additions & 27 deletions aws/sdk/integration-tests/ec2/tests/paginators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@

use aws_runtime::user_agent::test_util::assert_ua_contains_metric_values;
use aws_sdk_ec2::{config::Credentials, config::Region, types::InstanceType, Client, Config};
use aws_smithy_runtime::client::http::test_util::{
capture_request, ReplayEvent, StaticReplayClient,
};
use aws_smithy_runtime::client::http::test_util::capture_request;
use aws_smithy_runtime_api::client::http::HttpClient;
use aws_smithy_types::body::SdkBody;
use std::collections::HashSet;

fn stub_config(http_client: impl HttpClient + 'static) -> Config {
Config::builder()
Expand All @@ -19,28 +18,29 @@ fn stub_config(http_client: impl HttpClient + 'static) -> Config {
.build()
}

fn validate_query_string(expected: &str, actual: &str) {
let expected = expected.split('&').collect::<HashSet<&str>>();
let actual = actual.split('&').collect::<HashSet<&str>>();
assert_eq!(expected, actual);
assert_eq!(expected.len(), actual.len());
}

/// See https://github.com/awslabs/aws-sdk-rust/issues/391
///
/// EC2 replies with `<nextToken></nextToken>` which our XML parser parses as empty string and not "none"
#[tokio::test]
async fn paginators_handle_empty_tokens() {
let request= "Action=DescribeSpotPriceHistory&Version=2016-11-15&AvailabilityZone=eu-north-1a&InstanceType.1=g5.48xlarge&ProductDescription.1=Linux%2FUNIX";
let response = r#"<?xml version="1.0" encoding="UTF-8"?>
<DescribeSpotPriceHistoryResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
<requestId>edf3e86c-4baf-47c1-9228-9a5ea09542e8</requestId>
<spotPriceHistorySet/>
<nextToken></nextToken>
</DescribeSpotPriceHistoryResponse>"#;
let http_client = StaticReplayClient::new(vec![ReplayEvent::new(
http::Request::builder()
.uri("https://ec2.us-east-1.amazonaws.com/")
.body(request.into())
.unwrap(),
http::Response::builder()
.status(200)
.body(SdkBody::from(response))
.unwrap(),
)]);
let response = http::Response::builder()
.status(200)
.body(SdkBody::from(response))
.unwrap();
let (http_client, captured_request) = capture_request(Some(response));
let client = Client::from_conf(stub_config(http_client.clone()));
let instance_type = InstanceType::from("g5.48xlarge");
let mut paginator = client
Expand All @@ -53,30 +53,27 @@ async fn paginators_handle_empty_tokens() {
.send();
let first_item = paginator.try_next().await.expect("success");
assert_eq!(first_item, None);
http_client.assert_requests_match(&[]);
let req = captured_request.expect_request();
let actual_body = std::str::from_utf8(req.body().bytes().unwrap()).unwrap();
let expected_body = "Action=DescribeSpotPriceHistory&Version=2016-11-15&AvailabilityZone=eu-north-1a&InstanceType.1=g5.48xlarge&ProductDescription.1=Linux%2FUNIX";
validate_query_string(expected_body, actual_body);
}

/// See https://github.com/awslabs/aws-sdk-rust/issues/405
///
/// EC2 can also reply with the token truly unset which will be interpreted as `None`
#[tokio::test]
async fn paginators_handle_unset_tokens() {
let request= "Action=DescribeSpotPriceHistory&Version=2016-11-15&AvailabilityZone=eu-north-1a&InstanceType.1=g5.48xlarge&ProductDescription.1=Linux%2FUNIX";
let response = r#"<?xml version="1.0" encoding="UTF-8"?>
<DescribeSpotPriceHistoryResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
<requestId>edf3e86c-4baf-47c1-9228-9a5ea09542e8</requestId>
<spotPriceHistorySet/>
</DescribeSpotPriceHistoryResponse>"#;
let http_client = StaticReplayClient::new(vec![ReplayEvent::new(
http::Request::builder()
.uri("https://ec2.us-east-1.amazonaws.com/")
.body(request.into())
.unwrap(),
http::Response::builder()
.status(200)
.body(SdkBody::from(response))
.unwrap(),
)]);
let response = http::Response::builder()
.status(200)
.body(SdkBody::from(response))
.unwrap();
let (http_client, captured_request) = capture_request(Some(response));
let client = Client::from_conf(stub_config(http_client.clone()));
let instance_type = InstanceType::from("g5.48xlarge");
let mut paginator = client
Expand All @@ -89,7 +86,10 @@ async fn paginators_handle_unset_tokens() {
.send();
let first_item = paginator.try_next().await.expect("success");
assert_eq!(first_item, None);
http_client.assert_requests_match(&[]);
let req = captured_request.expect_request();
let actual_body = std::str::from_utf8(req.body().bytes().unwrap()).unwrap();
let expected_body = "Action=DescribeSpotPriceHistory&Version=2016-11-15&AvailabilityZone=eu-north-1a&InstanceType.1=g5.48xlarge&ProductDescription.1=Linux%2FUNIX";
validate_query_string(expected_body, actual_body);
}

#[tokio::test]
Expand Down

0 comments on commit 2c0274c

Please sign in to comment.