From 0f224ac5e5ad54eb6a5c6e1c24e36ddaa887b612 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 24 Apr 2025 10:29:38 -0700 Subject: [PATCH 01/48] Add waiters to weather model --- model/weather.smithy | 31 +++++++- projections/shapes/lib/shapes/schema.rb | 60 +++++++-------- .../spec/shapes/endpoint_provider_spec.rb | 6 +- projections/weather/lib/weather.rb | 1 + .../weather/lib/weather/auth_parameters.rb | 1 + .../weather/lib/weather/auth_resolver.rb | 2 +- projections/weather/lib/weather/client.rb | 5 +- .../lib/weather/endpoint_parameters.rb | 3 +- .../weather/lib/weather/endpoint_provider.rb | 7 +- projections/weather/lib/weather/errors.rb | 2 +- projections/weather/lib/weather/paginators.rb | 6 +- .../weather/lib/weather/plugins/auth.rb | 10 +-- .../weather/lib/weather/plugins/endpoint.rb | 4 +- projections/weather/lib/weather/schema.rb | 73 ++++++++++--------- projections/weather/lib/weather/types.rb | 3 + projections/weather/sig/weather/client.rbs | 1 + projections/weather/sig/weather/types.rbs | 2 + .../spec/weather/endpoint_provider_spec.rb | 12 +-- .../weather/spec/weather/protocol_spec.rb | 4 +- smithy-build.json | 5 ++ 20 files changed, 144 insertions(+), 94 deletions(-) diff --git a/model/weather.smithy b/model/weather.smithy index 2634de1fb..7fa03c72d 100644 --- a/model/weather.smithy +++ b/model/weather.smithy @@ -1,6 +1,7 @@ $version: "2" namespace example.weather +use smithy.waiters#waitable /// Provides weather forecasts. @paginated(inputToken: "nextToken", outputToken: "nextToken", pageSize: "pageSize") @@ -26,7 +27,7 @@ resource City { resource Forecast { identifiers: { cityId: CityId } - properties: { chanceOfRain: Float } + properties: { chanceOfRain: Float, status: String } read: GetForecast } @@ -124,6 +125,33 @@ operation GetCurrentTime { } @readonly +@waitable( + ForecastExists: { + documentation: "Waits until forecast is created" + acceptors: [ + { + state: "failure" + matcher: { + output: { + path: "status" + comparator: "stringEquals" + expected: "failed" + } + } + } + { + state: "success" + matcher: { + output: { + path: "status" + comparator: "stringEquals" + expected: "success" + } + } + } + ] + } +) operation GetForecast { input := for Forecast { // "cityId" provides the only identifier for the resource since @@ -134,5 +162,6 @@ operation GetForecast { output := for Forecast { $chanceOfRain + status: String } } \ No newline at end of file diff --git a/projections/shapes/lib/shapes/schema.rb b/projections/shapes/lib/shapes/schema.rb index 864d0b0f4..1de609236 100644 --- a/projections/shapes/lib/shapes/schema.rb +++ b/projections/shapes/lib/shapes/schema.rb @@ -7,35 +7,35 @@ module ShapeService module Schema include Smithy::Schema::Shapes - BigDecimal = BigDecimalShape.new(id: 'smithy.ruby.tests#BigDecimal', traits: {"smithy.ruby.tests#shape" => {}}) - BigInteger = IntegerShape.new(id: 'smithy.ruby.tests#BigInteger', traits: {"smithy.ruby.tests#shape" => {}}) - Blob = BlobShape.new(id: 'smithy.ruby.tests#Blob', traits: {"smithy.ruby.tests#shape" => {}}) - Boolean = BooleanShape.new(id: 'smithy.ruby.tests#Boolean', traits: {"smithy.ruby.tests#shape" => {}}) - Byte = IntegerShape.new(id: 'smithy.ruby.tests#Byte', traits: {"smithy.ruby.tests#shape" => {}}) - Document = DocumentShape.new(id: 'smithy.ruby.tests#Document', traits: {"smithy.ruby.tests#shape" => {}}) - Double = FloatShape.new(id: 'smithy.ruby.tests#Double', traits: {"smithy.ruby.tests#shape" => {}}) - Enum = EnumShape.new(id: 'smithy.ruby.tests#Enum', traits: {"smithy.ruby.tests#shape" => {}}) - Float = FloatShape.new(id: 'smithy.ruby.tests#Float', traits: {"smithy.ruby.tests#shape" => {}}) - IntEnum = IntEnumShape.new(id: 'smithy.ruby.tests#IntEnum', traits: {"smithy.ruby.tests#shape" => {}}) - Integer = IntegerShape.new(id: 'smithy.ruby.tests#Integer', traits: {"smithy.ruby.tests#shape" => {}}) - List = ListShape.new(id: 'smithy.ruby.tests#List', traits: {"smithy.ruby.tests#shape" => {}}) - Long = IntegerShape.new(id: 'smithy.ruby.tests#Long', traits: {"smithy.ruby.tests#shape" => {}}) - Map = MapShape.new(id: 'smithy.ruby.tests#Map', traits: {"smithy.ruby.tests#shape" => {}}) + BigDecimal = BigDecimalShape.new(id: 'smithy.ruby.tests#BigDecimal', traits: {"smithy.ruby.tests#shape"=>{}}) + BigInteger = IntegerShape.new(id: 'smithy.ruby.tests#BigInteger', traits: {"smithy.ruby.tests#shape"=>{}}) + Blob = BlobShape.new(id: 'smithy.ruby.tests#Blob', traits: {"smithy.ruby.tests#shape"=>{}}) + Boolean = BooleanShape.new(id: 'smithy.ruby.tests#Boolean', traits: {"smithy.ruby.tests#shape"=>{}}) + Byte = IntegerShape.new(id: 'smithy.ruby.tests#Byte', traits: {"smithy.ruby.tests#shape"=>{}}) + Document = DocumentShape.new(id: 'smithy.ruby.tests#Document', traits: {"smithy.ruby.tests#shape"=>{}}) + Double = FloatShape.new(id: 'smithy.ruby.tests#Double', traits: {"smithy.ruby.tests#shape"=>{}}) + Enum = EnumShape.new(id: 'smithy.ruby.tests#Enum', traits: {"smithy.ruby.tests#shape"=>{}}) + Float = FloatShape.new(id: 'smithy.ruby.tests#Float', traits: {"smithy.ruby.tests#shape"=>{}}) + IntEnum = IntEnumShape.new(id: 'smithy.ruby.tests#IntEnum', traits: {"smithy.ruby.tests#shape"=>{}}) + Integer = IntegerShape.new(id: 'smithy.ruby.tests#Integer', traits: {"smithy.ruby.tests#shape"=>{}}) + List = ListShape.new(id: 'smithy.ruby.tests#List', traits: {"smithy.ruby.tests#shape"=>{}}) + Long = IntegerShape.new(id: 'smithy.ruby.tests#Long', traits: {"smithy.ruby.tests#shape"=>{}}) + Map = MapShape.new(id: 'smithy.ruby.tests#Map', traits: {"smithy.ruby.tests#shape"=>{}}) OperationInputOutput = StructureShape.new(id: 'smithy.ruby.tests#OperationInputOutput') - Short = IntegerShape.new(id: 'smithy.ruby.tests#Short', traits: {"smithy.ruby.tests#shape" => {}}) - String = StringShape.new(id: 'smithy.ruby.tests#String', traits: {"smithy.ruby.tests#shape" => {}}) - Structure = StructureShape.new(id: 'smithy.ruby.tests#Structure', traits: {"smithy.ruby.tests#shape" => {}}) - Timestamp = TimestampShape.new(id: 'smithy.ruby.tests#Timestamp', traits: {"smithy.ruby.tests#shape" => {}}) - Union = UnionShape.new(id: 'smithy.ruby.tests#Union', traits: {"smithy.ruby.tests#shape" => {}}) + Short = IntegerShape.new(id: 'smithy.ruby.tests#Short', traits: {"smithy.ruby.tests#shape"=>{}}) + String = StringShape.new(id: 'smithy.ruby.tests#String', traits: {"smithy.ruby.tests#shape"=>{}}) + Structure = StructureShape.new(id: 'smithy.ruby.tests#Structure', traits: {"smithy.ruby.tests#shape"=>{}}) + Timestamp = TimestampShape.new(id: 'smithy.ruby.tests#Timestamp', traits: {"smithy.ruby.tests#shape"=>{}}) + Union = UnionShape.new(id: 'smithy.ruby.tests#Union', traits: {"smithy.ruby.tests#shape"=>{}}) - Enum.add_member(:foo, 'FOO', Prelude::Unit, traits: {"smithy.api#enumValue" => "bar"}) + Enum.add_member(:foo, 'FOO', Prelude::Unit, traits: {"smithy.api#enumValue"=>"bar"}) - IntEnum.add_member(:baz, 'BAZ', Prelude::Unit, traits: {"smithy.api#enumValue" => 1}) + IntEnum.add_member(:baz, 'BAZ', Prelude::Unit, traits: {"smithy.api#enumValue"=>1}) - List.set_member(String, traits: {"smithy.ruby.tests#shape" => {}}) + List.set_member(String, traits: {"smithy.ruby.tests#shape"=>{}}) - Map.set_key(String, traits: {"smithy.ruby.tests#shape" => {}}) - Map.set_value(String, traits: {"smithy.ruby.tests#shape" => {}}) + Map.set_key(String, traits: {"smithy.ruby.tests#shape"=>{}}) + Map.set_value(String, traits: {"smithy.ruby.tests#shape"=>{}}) OperationInputOutput.add_member(:blob, 'blob', Blob) OperationInputOutput.add_member(:boolean, 'boolean', Boolean) @@ -58,12 +58,12 @@ module Schema OperationInputOutput.add_member(:union, 'union', Union) OperationInputOutput.type = Types::OperationInputOutput - Structure.add_member(:member, 'member', String, traits: {"smithy.ruby.tests#shape" => {}}) + Structure.add_member(:member, 'member', String, traits: {"smithy.ruby.tests#shape"=>{}}) Structure.type = Types::Structure - Union.add_member(:string, 'string', String, Types::Union::String, traits: {"smithy.ruby.tests#shape" => {}}) - Union.add_member(:structure, 'structure', Structure, Types::Union::Structure, traits: {"smithy.ruby.tests#shape" => {}}) - Union.add_member(:unit, 'unit', Prelude::Unit, Types::Union::Unit, traits: {"smithy.ruby.tests#shape" => {}}) + Union.add_member(:string, 'string', String, Types::Union::String, traits: {"smithy.ruby.tests#shape"=>{}}) + Union.add_member(:structure, 'structure', Structure, Types::Union::Structure, traits: {"smithy.ruby.tests#shape"=>{}}) + Union.add_member(:unit, 'unit', Prelude::Unit, Types::Union::Unit, traits: {"smithy.ruby.tests#shape"=>{}}) Union.add_member(:unknown, 'unknown', Prelude::Unit, Types::Union::Unknown) Union.type = Types::Union @@ -71,13 +71,13 @@ module Schema service.id = "smithy.ruby.tests#ShapeService" service.name = "ShapeService" service.version = "2018-10-31" - service.traits = {"smithy.ruby.tests#shape" => {}} + service.traits = {"smithy.ruby.tests#shape"=>{}} service.add_operation(:operation, OperationShape.new do |operation| operation.id = "smithy.ruby.tests#Operation" operation.name = "Operation" operation.input = OperationInputOutput operation.output = OperationInputOutput - operation.traits = {"smithy.ruby.tests#shape" => {}} + operation.traits = {"smithy.ruby.tests#shape"=>{}} end) end end diff --git a/projections/shapes/spec/shapes/endpoint_provider_spec.rb b/projections/shapes/spec/shapes/endpoint_provider_spec.rb index 4a984e3c4..ef6f43250 100644 --- a/projections/shapes/spec/shapes/endpoint_provider_spec.rb +++ b/projections/shapes/spec/shapes/endpoint_provider_spec.rb @@ -10,11 +10,11 @@ module ShapeService context "Endpoint set" do let(:expected) do - {"endpoint" => {"url" => "https://example.com"}} + {"endpoint"=>{"url"=>"https://example.com"}} end it 'produces the expected output from the EndpointProvider' do - params = EndpointParameters.new(**{endpoint: "https://example.com"}) + params = EndpointParameters.new(**{:endpoint=>"https://example.com"}) endpoint = subject.resolve(params) expect(endpoint.uri).to eq(expected['endpoint']['url']) expect(endpoint.headers).to eq(expected['endpoint']['headers'] || {}) @@ -25,7 +25,7 @@ module ShapeService context "Endpoint not set" do let(:expected) do - {"error" => "Endpoint is not set - you must configure an endpoint."} + {"error"=>"Endpoint is not set - you must configure an endpoint."} end it 'produces the expected output from the EndpointProvider' do diff --git a/projections/weather/lib/weather.rb b/projections/weather/lib/weather.rb index 696eb1636..35e2f6e63 100644 --- a/projections/weather/lib/weather.rb +++ b/projections/weather/lib/weather.rb @@ -4,6 +4,7 @@ require 'smithy-client' + module Weather VERSION = '1.0.0' end diff --git a/projections/weather/lib/weather/auth_parameters.rb b/projections/weather/lib/weather/auth_parameters.rb index c161b521d..cb752b9c5 100644 --- a/projections/weather/lib/weather/auth_parameters.rb +++ b/projections/weather/lib/weather/auth_parameters.rb @@ -13,6 +13,7 @@ module Weather :operation_name, keyword_init: true ) do + # @api private def self.create(context) # TODO: support more properties diff --git a/projections/weather/lib/weather/auth_resolver.rb b/projections/weather/lib/weather/auth_resolver.rb index fddb8b6a8..3f9e14769 100644 --- a/projections/weather/lib/weather/auth_resolver.rb +++ b/projections/weather/lib/weather/auth_resolver.rb @@ -7,7 +7,7 @@ module Weather class AuthResolver # @param [AuthParameters] parameters # @return [Smithy::Client::AuthOption] - def resolve(_parameters) + def resolve(parameters) options = [] options << Smithy::Client::AuthOption.new(scheme_id: 'smithy.api#noAuth', signer_properties: {}) options diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index beb259d4f..9c09e5f61 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -196,7 +196,8 @@ def get_current_time(params = {}, options = {}) # @example Response structure with placeholder values # output.to_h #=> # { - # chance_of_rain: 1.0 + # chance_of_rain: 1.0, + # status: "String" # } def get_forecast(params = {}, options = {}) input = build_input(:get_forecast, params) @@ -235,7 +236,7 @@ def build_input(operation_name, params) operation: config.service.operation(operation_name), client: self, params: params, - config: config + config: config, ) context[:gem_name] = 'weather' context[:gem_version] = '1.0.0' diff --git a/projections/weather/lib/weather/endpoint_parameters.rb b/projections/weather/lib/weather/endpoint_parameters.rb index b6fe75718..9283cf94a 100644 --- a/projections/weather/lib/weather/endpoint_parameters.rb +++ b/projections/weather/lib/weather/endpoint_parameters.rb @@ -13,6 +13,7 @@ module Weather :endpoint, keyword_init: true ) do + def initialize(options = {}) self.endpoint = options.fetch(:endpoint, nil) end @@ -21,7 +22,7 @@ def initialize(options = {}) def self.create(context) config = context.config new({ - endpoint: config.endpoint + endpoint: config.endpoint, }.compact) end end diff --git a/projections/weather/lib/weather/endpoint_provider.rb b/projections/weather/lib/weather/endpoint_provider.rb index f40951590..5dac5fa9d 100644 --- a/projections/weather/lib/weather/endpoint_provider.rb +++ b/projections/weather/lib/weather/endpoint_provider.rb @@ -9,9 +9,10 @@ class EndpointProvider # @return [Smithy::Client::EndpointRules::Endpoint] # @raise [ArgumentError] def resolve(parameters) - return Smithy::Client::EndpointRules::Endpoint.new(uri: parameters.endpoint) if Smithy::Client::EndpointRules.set?(parameters.endpoint) - - raise ArgumentError, 'Endpoint is not set - you must configure an endpoint.' + if Smithy::Client::EndpointRules.set?(parameters.endpoint) + return Smithy::Client::EndpointRules::Endpoint.new(uri: parameters.endpoint) + end + raise ArgumentError, "Endpoint is not set - you must configure an endpoint." end end end diff --git a/projections/weather/lib/weather/errors.rb b/projections/weather/lib/weather/errors.rb index 04bd932cf..db74790ee 100644 --- a/projections/weather/lib/weather/errors.rb +++ b/projections/weather/lib/weather/errors.rb @@ -35,7 +35,7 @@ class NoSuchResource < Smithy::Client::Errors::ServiceError # @param [String] message # @param [Weather::Types::NoSuchResource] data def initialize(context, message, data = Smithy::Schema::EmptyStructure.new) - super + super(context, message, data) end def resource_type diff --git a/projections/weather/lib/weather/paginators.rb b/projections/weather/lib/weather/paginators.rb index 8a95230a8..2541c0cdb 100644 --- a/projections/weather/lib/weather/paginators.rb +++ b/projections/weather/lib/weather/paginators.rb @@ -5,12 +5,13 @@ module Weather # @api private module Paginators + # @api private class ListCities def next_tokens(data) next_token = data.next_token return {} if next_token.nil? || next_token.empty? - + tokens = Hash.new { |h, k| h[k] = {} } tokens[:next_token] = next_token tokens @@ -19,7 +20,7 @@ def next_tokens(data) def prev_tokens(params) prev_token = params[:next_token] return {} if prev_token.nil? || prev_token.empty? - + tokens = Hash.new { |h, k| h[k] = {} } tokens[:next_token] = prev_token tokens @@ -29,5 +30,6 @@ def items(data) data.items end end + end end diff --git a/projections/weather/lib/weather/plugins/auth.rb b/projections/weather/lib/weather/plugins/auth.rb index 166f2fed6..f3b45dc1b 100644 --- a/projections/weather/lib/weather/plugins/auth.rb +++ b/projections/weather/lib/weather/plugins/auth.rb @@ -9,7 +9,7 @@ class Auth < Smithy::Client::Plugin option( :auth_resolver, doc_type: 'Weather::AuthResolver', - docstring: <<~DOCS) do |_config| + docstring: <<~DOCS) do |config| The auth resolver used to resolve authentication. Any object that responds to `#resolve(parameters)`. DOCS AuthResolver.new @@ -24,7 +24,7 @@ class Auth < Smithy::Client::Plugin and the value is an initialized auth scheme class. DOCS { - 'smithy.api#noAuth' => config.anonymous_auth_scheme + 'smithy.api#noAuth' => config.anonymous_auth_scheme, } end @@ -46,7 +46,7 @@ def resolve_auth(context, auth_options) raise 'No auth options were resolved' if auth_options.empty? identity_providers = { - Smithy::Client::Identities::Anonymous => context.config.anonymous_provider + Smithy::Client::Identities::Anonymous => context.config.anonymous_provider, } auth_options.each do |auth_option| @@ -68,14 +68,14 @@ def try_load_auth_scheme(auth_option, auth_scheme, identity_providers, failures) scheme_id = auth_option.scheme_id unless auth_scheme failures << "Auth scheme #{scheme_id} was not enabled " \ - 'for this request' + 'for this request' return end identity_provider = auth_scheme.identity_provider(identity_providers) unless identity_provider failures << "Auth scheme #{scheme_id} did not have an " \ - 'identity resolver configured' + 'identity resolver configured' return end diff --git a/projections/weather/lib/weather/plugins/endpoint.rb b/projections/weather/lib/weather/plugins/endpoint.rb index a009ed718..007b30147 100644 --- a/projections/weather/lib/weather/plugins/endpoint.rb +++ b/projections/weather/lib/weather/plugins/endpoint.rb @@ -9,7 +9,7 @@ class Endpoint < Smithy::Client::Plugin option( :endpoint_provider, doc_type: 'Weather::EndpointProvider', - docstring: <<~DOCS) do |_config| + docstring: <<~DOCS) do |config| The endpoint provider used to resolve endpoints. Any object that responds to `#resolve(parameters)`. DOCS EndpointProvider.new @@ -25,7 +25,7 @@ class Endpoint < Smithy::Client::Plugin class Handler < Smithy::Client::Handler def call(context) params = EndpointParameters.create(context) - endpoint = context.config.endpoint_provider.resolve(params) + endpoint = context.config.endpoint_provider.resolve(params)\ context.request.endpoint = endpoint.uri apply_endpoint_headers(context, endpoint.headers) diff --git a/projections/weather/lib/weather/schema.rb b/projections/weather/lib/weather/schema.rb index 7f7776b01..aab4edcde 100644 --- a/projections/weather/lib/weather/schema.rb +++ b/projections/weather/lib/weather/schema.rb @@ -8,42 +8,43 @@ module Schema include Smithy::Schema::Shapes CityCoordinates = StructureShape.new(id: 'example.weather#CityCoordinates') - CityId = StringShape.new(id: 'example.weather#CityId', traits: { 'smithy.api#pattern' => '^[A-Za-z0-9 ]+$' }) + CityId = StringShape.new(id: 'example.weather#CityId', traits: {"smithy.api#pattern"=>"^[A-Za-z0-9 ]+$"}) CitySummaries = ListShape.new(id: 'example.weather#CitySummaries') - CitySummary = StructureShape.new(id: 'example.weather#CitySummary', traits: { 'smithy.api#references' => [{ 'resource' => 'example.weather#City' }] }) - GetCityInput = StructureShape.new(id: 'example.weather#GetCityInput', traits: { 'smithy.api#input' => {} }) - GetCityOutput = StructureShape.new(id: 'example.weather#GetCityOutput', traits: { 'smithy.api#output' => {} }) - GetCurrentTimeOutput = StructureShape.new(id: 'example.weather#GetCurrentTimeOutput', traits: { 'smithy.api#output' => {} }) - GetForecastInput = StructureShape.new(id: 'example.weather#GetForecastInput', traits: { 'smithy.api#input' => {} }) - GetForecastOutput = StructureShape.new(id: 'example.weather#GetForecastOutput', traits: { 'smithy.api#output' => {} }) - ListCitiesInput = StructureShape.new(id: 'example.weather#ListCitiesInput', traits: { 'smithy.api#input' => {} }) - ListCitiesOutput = StructureShape.new(id: 'example.weather#ListCitiesOutput', traits: { 'smithy.api#output' => {} }) - NoSuchResource = StructureShape.new(id: 'example.weather#NoSuchResource', traits: { 'smithy.api#error' => 'client' }) + CitySummary = StructureShape.new(id: 'example.weather#CitySummary', traits: {"smithy.api#references"=>[{"resource"=>"example.weather#City"}]}) + GetCityInput = StructureShape.new(id: 'example.weather#GetCityInput', traits: {"smithy.api#input"=>{}}) + GetCityOutput = StructureShape.new(id: 'example.weather#GetCityOutput', traits: {"smithy.api#output"=>{}}) + GetCurrentTimeOutput = StructureShape.new(id: 'example.weather#GetCurrentTimeOutput', traits: {"smithy.api#output"=>{}}) + GetForecastInput = StructureShape.new(id: 'example.weather#GetForecastInput', traits: {"smithy.api#input"=>{}}) + GetForecastOutput = StructureShape.new(id: 'example.weather#GetForecastOutput', traits: {"smithy.api#output"=>{}}) + ListCitiesInput = StructureShape.new(id: 'example.weather#ListCitiesInput', traits: {"smithy.api#input"=>{}}) + ListCitiesOutput = StructureShape.new(id: 'example.weather#ListCitiesOutput', traits: {"smithy.api#output"=>{}}) + NoSuchResource = StructureShape.new(id: 'example.weather#NoSuchResource', traits: {"smithy.api#error"=>"client"}) - CityCoordinates.add_member(:latitude, 'latitude', Prelude::Float, traits: { 'smithy.api#required' => {} }) - CityCoordinates.add_member(:longitude, 'longitude', Prelude::Float, traits: { 'smithy.api#required' => {} }) + CityCoordinates.add_member(:latitude, 'latitude', Prelude::Float, traits: {"smithy.api#required"=>{}}) + CityCoordinates.add_member(:longitude, 'longitude', Prelude::Float, traits: {"smithy.api#required"=>{}}) CityCoordinates.type = Types::CityCoordinates CitySummaries.set_member(CitySummary) - CitySummary.add_member(:city_id, 'cityId', CityId, traits: { 'smithy.api#required' => {} }) - CitySummary.add_member(:name, 'name', Prelude::String, traits: { 'smithy.api#required' => {} }) + CitySummary.add_member(:city_id, 'cityId', CityId, traits: {"smithy.api#required"=>{}}) + CitySummary.add_member(:name, 'name', Prelude::String, traits: {"smithy.api#required"=>{}}) CitySummary.type = Types::CitySummary - GetCityInput.add_member(:city_id, 'cityId', CityId, traits: { 'smithy.api#required' => {} }) + GetCityInput.add_member(:city_id, 'cityId', CityId, traits: {"smithy.api#required"=>{}}) GetCityInput.type = Types::GetCityInput - GetCityOutput.add_member(:name, 'name', Prelude::String, traits: { 'smithy.api#notProperty' => {}, 'smithy.api#required' => {} }) - GetCityOutput.add_member(:coordinates, 'coordinates', CityCoordinates, traits: { 'smithy.api#required' => {} }) + GetCityOutput.add_member(:name, 'name', Prelude::String, traits: {"smithy.api#notProperty"=>{}, "smithy.api#required"=>{}}) + GetCityOutput.add_member(:coordinates, 'coordinates', CityCoordinates, traits: {"smithy.api#required"=>{}}) GetCityOutput.type = Types::GetCityOutput - GetCurrentTimeOutput.add_member(:time, 'time', Prelude::Timestamp, traits: { 'smithy.api#required' => {} }) + GetCurrentTimeOutput.add_member(:time, 'time', Prelude::Timestamp, traits: {"smithy.api#required"=>{}}) GetCurrentTimeOutput.type = Types::GetCurrentTimeOutput - GetForecastInput.add_member(:city_id, 'cityId', CityId, traits: { 'smithy.api#required' => {} }) + GetForecastInput.add_member(:city_id, 'cityId', CityId, traits: {"smithy.api#required"=>{}}) GetForecastInput.type = Types::GetForecastInput GetForecastOutput.add_member(:chance_of_rain, 'chanceOfRain', Prelude::Float) + GetForecastOutput.add_member(:status, 'status', Prelude::String) GetForecastOutput.type = Types::GetForecastOutput ListCitiesInput.add_member(:next_token, 'nextToken', Prelude::String) @@ -51,45 +52,45 @@ module Schema ListCitiesInput.type = Types::ListCitiesInput ListCitiesOutput.add_member(:next_token, 'nextToken', Prelude::String) - ListCitiesOutput.add_member(:items, 'items', CitySummaries, traits: { 'smithy.api#required' => {} }) + ListCitiesOutput.add_member(:items, 'items', CitySummaries, traits: {"smithy.api#required"=>{}}) ListCitiesOutput.type = Types::ListCitiesOutput - NoSuchResource.add_member(:resource_type, 'resourceType', Prelude::String, traits: { 'smithy.api#required' => {} }) + NoSuchResource.add_member(:resource_type, 'resourceType', Prelude::String, traits: {"smithy.api#required"=>{}}) NoSuchResource.type = Types::NoSuchResource SERVICE = ServiceShape.new do |service| - service.id = 'example.weather#Weather' - service.name = 'Weather' - service.version = '2006-03-01' + service.id = "example.weather#Weather" + service.name = "Weather" + service.version = "2006-03-01" service.traits = {} service.add_operation(:get_city, OperationShape.new do |operation| - operation.id = 'example.weather#GetCity' - operation.name = 'GetCity' + operation.id = "example.weather#GetCity" + operation.name = "GetCity" operation.input = GetCityInput operation.output = GetCityOutput - operation.traits = { 'smithy.api#readonly' => {} } + operation.traits = {"smithy.api#readonly"=>{}} operation.errors << NoSuchResource end) service.add_operation(:get_current_time, OperationShape.new do |operation| - operation.id = 'example.weather#GetCurrentTime' - operation.name = 'GetCurrentTime' + operation.id = "example.weather#GetCurrentTime" + operation.name = "GetCurrentTime" operation.input = Prelude::Unit operation.output = GetCurrentTimeOutput - operation.traits = { 'smithy.api#readonly' => {} } + operation.traits = {"smithy.api#readonly"=>{}} end) service.add_operation(:get_forecast, OperationShape.new do |operation| - operation.id = 'example.weather#GetForecast' - operation.name = 'GetForecast' + operation.id = "example.weather#GetForecast" + operation.name = "GetForecast" operation.input = GetForecastInput operation.output = GetForecastOutput - operation.traits = { 'smithy.api#readonly' => {} } + operation.traits = {"smithy.api#readonly"=>{}, "smithy.waiters#waitable"=>{"ForecastExists"=>{"documentation"=>"Waits until forecast is created", "acceptors"=>[{"state"=>"failure", "matcher"=>{"output"=>{"path"=>"status", "comparator"=>"stringEquals", "expected"=>"failed"}}}, {"state"=>"success", "matcher"=>{"output"=>{"path"=>"status", "comparator"=>"stringEquals", "expected"=>"success"}}}]}}} end) service.add_operation(:list_cities, OperationShape.new do |operation| - operation.id = 'example.weather#ListCities' - operation.name = 'ListCities' + operation.id = "example.weather#ListCities" + operation.name = "ListCities" operation.input = ListCitiesInput operation.output = ListCitiesOutput - operation.traits = { 'smithy.api#readonly' => {} } + operation.traits = {"smithy.api#readonly"=>{}} operation[:paginator] = Paginators::ListCities.new end) end diff --git a/projections/weather/lib/weather/types.rb b/projections/weather/lib/weather/types.rb index 862c38563..5ebcaf981 100644 --- a/projections/weather/lib/weather/types.rb +++ b/projections/weather/lib/weather/types.rb @@ -5,6 +5,7 @@ module Weather # This module contains the types returned by client operations. module Types + CityCoordinates = Struct.new( :latitude, :longitude, @@ -52,6 +53,7 @@ module Types GetForecastOutput = Struct.new( :chance_of_rain, + :status, keyword_init: true ) do include Smithy::Schema::Structure @@ -79,5 +81,6 @@ module Types ) do include Smithy::Schema::Structure end + end end diff --git a/projections/weather/sig/weather/client.rbs b/projections/weather/sig/weather/client.rbs index 0aedf65d6..5a1a46f6e 100644 --- a/projections/weather/sig/weather/client.rbs +++ b/projections/weather/sig/weather/client.rbs @@ -52,6 +52,7 @@ module Weather interface _GetForecastResponse include Smithy::Client::_Output[Types::GetForecastOutput] def chance_of_rain: () -> Float? + def status: () -> String? end def get_forecast: ( ?city_id: String diff --git a/projections/weather/sig/weather/types.rbs b/projections/weather/sig/weather/types.rbs index 6407a201c..0e9eecee3 100644 --- a/projections/weather/sig/weather/types.rbs +++ b/projections/weather/sig/weather/types.rbs @@ -78,10 +78,12 @@ module Weather def initialize: ( ?chance_of_rain: Float, + ?status: String, ) -> void | (?Hash[Symbol, untyped]) -> void attr_accessor chance_of_rain: Float? + attr_accessor status: String? end class ListCitiesInput diff --git a/projections/weather/spec/weather/endpoint_provider_spec.rb b/projections/weather/spec/weather/endpoint_provider_spec.rb index fd67160fe..5b7901ebd 100644 --- a/projections/weather/spec/weather/endpoint_provider_spec.rb +++ b/projections/weather/spec/weather/endpoint_provider_spec.rb @@ -8,23 +8,24 @@ module Weather describe EndpointProvider do subject { EndpointProvider.new } - context 'Endpoint set' do + context "Endpoint set" do let(:expected) do - { 'endpoint' => { 'url' => 'https://example.com' } } + {"endpoint"=>{"url"=>"https://example.com"}} end it 'produces the expected output from the EndpointProvider' do - params = EndpointParameters.new(endpoint: 'https://example.com') + params = EndpointParameters.new(**{:endpoint=>"https://example.com"}) endpoint = subject.resolve(params) expect(endpoint.uri).to eq(expected['endpoint']['url']) expect(endpoint.headers).to eq(expected['endpoint']['headers'] || {}) expect(endpoint.properties).to eq(expected['endpoint']['properties'] || {}) end + end - context 'Endpoint not set' do + context "Endpoint not set" do let(:expected) do - { 'error' => 'Endpoint is not set - you must configure an endpoint.' } + {"error"=>"Endpoint is not set - you must configure an endpoint."} end it 'produces the expected output from the EndpointProvider' do @@ -33,6 +34,7 @@ module Weather subject.resolve(params) end.to raise_error(ArgumentError, expected['error']) end + end end end diff --git a/projections/weather/spec/weather/protocol_spec.rb b/projections/weather/spec/weather/protocol_spec.rb index c41d17427..285748c19 100644 --- a/projections/weather/spec/weather/protocol_spec.rb +++ b/projections/weather/spec/weather/protocol_spec.rb @@ -1,11 +1,11 @@ -# frozen_string_literal: true - # This is generated code! require_relative '../spec_helper' + module Weather describe Client do let(:client) { Client.new(stub_responses: true) } + end end diff --git a/smithy-build.json b/smithy-build.json index cbfbe5d22..a1f229862 100644 --- a/smithy-build.json +++ b/smithy-build.json @@ -1,5 +1,10 @@ { "version": "1.0", + "maven": { + "dependencies": [ + "software.amazon.smithy:smithy-waiters:1.56.0" + ] + }, "projections": { "weather": { "plugins": { From bbcb6cc377d2289c0b98bedf4167b1c42199d88a Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 24 Apr 2025 13:39:27 -0700 Subject: [PATCH 02/48] Initial code generation for waiters --- gems/smithy/lib/smithy/generators/client.rb | 1 + .../lib/smithy/templates/client/waiters.erb | 31 ++++++ gems/smithy/lib/smithy/views/client.rb | 1 + gems/smithy/lib/smithy/views/client/module.rb | 2 +- .../smithy/lib/smithy/views/client/waiters.rb | 70 ++++++++++++ model/weather.smithy | 24 +++++ projections/shapes/lib/shapes.rb | 1 + projections/shapes/lib/shapes/waiters.rb | 9 ++ projections/weather/lib/weather.rb | 1 + projections/weather/lib/weather/schema.rb | 2 +- projections/weather/lib/weather/waiters.rb | 100 ++++++++++++++++++ 11 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 gems/smithy/lib/smithy/templates/client/waiters.erb create mode 100644 gems/smithy/lib/smithy/views/client/waiters.rb create mode 100644 projections/shapes/lib/shapes/waiters.rb create mode 100644 projections/weather/lib/weather/waiters.rb diff --git a/gems/smithy/lib/smithy/generators/client.rb b/gems/smithy/lib/smithy/generators/client.rb index 811e72c63..6ffd5384f 100644 --- a/gems/smithy/lib/smithy/generators/client.rb +++ b/gems/smithy/lib/smithy/generators/client.rb @@ -50,6 +50,7 @@ def source_files e.yield "lib/#{@gem_name}/endpoint_parameters.rb", Views::Client::EndpointParameters.new(@plan).render e.yield "lib/#{@gem_name}/endpoint_provider.rb", Views::Client::EndpointProvider.new(@plan).render e.yield "lib/#{@gem_name}/paginators.rb", Views::Client::Paginators.new(@plan).render + e.yield "lib/#{@gem_name}/waiters.rb", Views::Client::Waiters.new(@plan).render code_generated_plugins.each { |path, plugin| e.yield path, plugin.source } e.yield "lib/#{@gem_name}/types.rb", Views::Client::Types.new(@plan).render e.yield "lib/#{@gem_name}/schema.rb", Views::Client::Schema.new(@plan).render diff --git a/gems/smithy/lib/smithy/templates/client/waiters.erb b/gems/smithy/lib/smithy/templates/client/waiters.erb new file mode 100644 index 000000000..825815e25 --- /dev/null +++ b/gems/smithy/lib/smithy/templates/client/waiters.erb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# This is generated code! + +module <%= module_name %> + # @api private + module Waiters +<% waiters.each do |waiter| -%> + # @api private + class <%= waiter.name %> + def initialize(options = {}) + @client = options[:client] + @waiter = Waiter.new( + max_wait_time: options[:max_wait_time], + min_delay: options[:min_delay] || <%= waiter.min_delay %>, + max_delay: options[:max_delay] || <%= waiter.max_delay %>, + poller: Poller.new( + operation_name: <%= waiter.operation_name %>, +<%= waiter.acceptors %> + ) + ) + end + + def wait(params = {}) + @waiter.wait(@client, params) + end + end + +<% end -%> + end +end \ No newline at end of file diff --git a/gems/smithy/lib/smithy/views/client.rb b/gems/smithy/lib/smithy/views/client.rb index 8acf691e3..0333cb324 100644 --- a/gems/smithy/lib/smithy/views/client.rb +++ b/gems/smithy/lib/smithy/views/client.rb @@ -44,3 +44,4 @@ module Client; end require_relative 'client/spec_helper' require_relative 'client/types' require_relative 'client/types_rbs' +require_relative 'client/waiters' diff --git a/gems/smithy/lib/smithy/views/client/module.rb b/gems/smithy/lib/smithy/views/client/module.rb index f13ac82dc..10fdc2b20 100644 --- a/gems/smithy/lib/smithy/views/client/module.rb +++ b/gems/smithy/lib/smithy/views/client/module.rb @@ -43,7 +43,7 @@ def relative_requires return %i[customizations types schema] if @plan.type == :schema # paginators must come before schemas - %w[types paginators schema auth_parameters auth_resolver client customizations errors endpoint_parameters + %w[types paginators waiters schema auth_parameters auth_resolver client customizations errors endpoint_parameters endpoint_provider] end end diff --git a/gems/smithy/lib/smithy/views/client/waiters.rb b/gems/smithy/lib/smithy/views/client/waiters.rb new file mode 100644 index 000000000..1888f5a5e --- /dev/null +++ b/gems/smithy/lib/smithy/views/client/waiters.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +module Smithy + module Views + module Client + # @api private + class Waiters < View + def initialize(plan) + @plan = plan + @model = @plan.model + super() + end + + def module_name + @plan.module_name + end + + def waiters + Model::ServiceIndex + .new(@model) + .operations_for(@plan.service) + .map do |operation_id, operation| + waiters_from_trait = waitable_trait(operation) + next if waiters_from_trait.empty? + + operation_name = Model::Shape.name(operation_id).underscore + + waiters_from_trait.map do |waiter_name, waiter| + Waiter.new(operation_name, waiter_name, waiter) + end + end + .flatten + .compact + .sort_by(&:name) + end + + private + + def waitable_trait(operation) + operation.fetch('traits', {}).fetch('smithy.waiters#waitable', {}) + end + + # @api private + class Waiter + def initialize(operation, name, waiter) + @operation_name = operation + @name = name + @documentation = waiter['documentation'] + @acceptors = formatted_acceptors(waiter['acceptors']) + @min_delay = waiter['minDelay'] || 2 + @max_delay = waiter['maxDelay'] || 120 + @deprecated = waiter['deprecated'] + @tags = waiter['tags'] + end + + attr_reader :operation_name, :name, :documentation, :acceptors, :min_delay, :max_delay, :deprecated, :tags + + def formatted_acceptors(acceptors) + Util::HashFormatter.new( + wrap: false, + inline: false, + quote_strings: true, + indent: ' ' + ).format(acceptors: acceptors) + end + end + end + end + end +end diff --git a/model/weather.smithy b/model/weather.smithy index 7fa03c72d..2d9ab122c 100644 --- a/model/weather.smithy +++ b/model/weather.smithy @@ -36,6 +36,30 @@ resource Forecast { string CityId @readonly +@waitable( + CityExists: { + documentation: "Waits until city exists" + acceptors: [ + { + state: "success" + matcher: { + success: true + } + } + ] + } + CityDeleted: { + documentation: "Waits until city is deleted" + acceptors: [ + { + state: "success" + matcher: { + errorType: "NoSuchResource" + } + } + ] + } +) operation GetCity { input := for City { // "cityId" provides the identifier for the resource and diff --git a/projections/shapes/lib/shapes.rb b/projections/shapes/lib/shapes.rb index 64005248e..ed3018b54 100644 --- a/projections/shapes/lib/shapes.rb +++ b/projections/shapes/lib/shapes.rb @@ -11,6 +11,7 @@ module ShapeService require_relative 'shapes/types' require_relative 'shapes/paginators' +require_relative 'shapes/waiters' require_relative 'shapes/schema' require_relative 'shapes/auth_parameters' require_relative 'shapes/auth_resolver' diff --git a/projections/shapes/lib/shapes/waiters.rb b/projections/shapes/lib/shapes/waiters.rb new file mode 100644 index 000000000..58a5d6c79 --- /dev/null +++ b/projections/shapes/lib/shapes/waiters.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +# This is generated code! + +module ShapeService + # @api private + module Waiters + end +end \ No newline at end of file diff --git a/projections/weather/lib/weather.rb b/projections/weather/lib/weather.rb index 35e2f6e63..885d64c36 100644 --- a/projections/weather/lib/weather.rb +++ b/projections/weather/lib/weather.rb @@ -11,6 +11,7 @@ module Weather require_relative 'weather/types' require_relative 'weather/paginators' +require_relative 'weather/waiters' require_relative 'weather/schema' require_relative 'weather/auth_parameters' require_relative 'weather/auth_resolver' diff --git a/projections/weather/lib/weather/schema.rb b/projections/weather/lib/weather/schema.rb index aab4edcde..fd6f8467b 100644 --- a/projections/weather/lib/weather/schema.rb +++ b/projections/weather/lib/weather/schema.rb @@ -68,7 +68,7 @@ module Schema operation.name = "GetCity" operation.input = GetCityInput operation.output = GetCityOutput - operation.traits = {"smithy.api#readonly"=>{}} + operation.traits = {"smithy.api#readonly"=>{}, "smithy.waiters#waitable"=>{"CityExists"=>{"documentation"=>"Waits until city exists", "acceptors"=>[{"state"=>"success", "matcher"=>{"success"=>true}}]}, "CityDeleted"=>{"documentation"=>"Waits until city is deleted", "acceptors"=>[{"state"=>"success", "matcher"=>{"errorType"=>"NoSuchResource"}}]}}} operation.errors << NoSuchResource end) service.add_operation(:get_current_time, OperationShape.new do |operation| diff --git a/projections/weather/lib/weather/waiters.rb b/projections/weather/lib/weather/waiters.rb new file mode 100644 index 000000000..7131dfb1e --- /dev/null +++ b/projections/weather/lib/weather/waiters.rb @@ -0,0 +1,100 @@ +# frozen_string_literal: true + +# This is generated code! + +module Weather + # @api private + module Waiters + # @api private + class CityDeleted + def initialize(options = {}) + @client = options[:client] + @waiter = Waiter.new( + max_wait_time: options[:max_wait_time], + min_delay: options[:min_delay] || 2, + max_delay: options[:max_delay] || 120, + poller: Poller.new( + operation_name: get_city, + acceptors: [{ + "state" => "success", + "matcher" => { + "errorType" => "NoSuchResource" + } + }] + ) + ) + end + + def wait(params = {}) + @waiter.wait(@client, params) + end + end + + # @api private + class CityExists + def initialize(options = {}) + @client = options[:client] + @waiter = Waiter.new( + max_wait_time: options[:max_wait_time], + min_delay: options[:min_delay] || 2, + max_delay: options[:max_delay] || 120, + poller: Poller.new( + operation_name: get_city, + acceptors: [{ + "state" => "success", + "matcher" => { + "success" => true + } + }] + ) + ) + end + + def wait(params = {}) + @waiter.wait(@client, params) + end + end + + # @api private + class ForecastExists + def initialize(options = {}) + @client = options[:client] + @waiter = Waiter.new( + max_wait_time: options[:max_wait_time], + min_delay: options[:min_delay] || 2, + max_delay: options[:max_delay] || 120, + poller: Poller.new( + operation_name: get_forecast, + acceptors: [ + { + "state" => "failure", + "matcher" => { + "output" => { + "path" => "status", + "comparator" => "stringEquals", + "expected" => "failed" + } + } + }, + { + "state" => "success", + "matcher" => { + "output" => { + "path" => "status", + "comparator" => "stringEquals", + "expected" => "success" + } + } + } + ] + ) + ) + end + + def wait(params = {}) + @waiter.wait(@client, params) + end + end + + end +end \ No newline at end of file From 4da115bdc662d0a50c63d9bfb841de7ad21a0485 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 24 Apr 2025 14:15:06 -0700 Subject: [PATCH 03/48] Add conditional templating for waiters --- .../lib/smithy/templates/client/client.erb | 23 +++++++++++++++++++ gems/smithy/lib/smithy/views/client/client.rb | 16 +++++++++++++ projections/weather/lib/weather/client.rb | 22 ++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index 2fdd73b9b..fc9056db7 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -35,6 +35,13 @@ module <%= module_name %> input.send_request(options) end +<% end -%> +<% if waiters? -%> + def wait_until(waiter_name, params = {}, options = {}) + w = waiter(waiter_name, options) + w.wait(params) + end + <% end -%> private @@ -51,6 +58,22 @@ module <%= module_name %> context[:gem_version] = '<%= gem_version %>' Smithy::Client::Input.new(handlers: handlers, context: context) end +<% if waiters? %> + def waiter(waiter_name, options = {}) + waiter_class = waiters[waiter_name] + if waiter_class + waiter_class.new(options.merge(client: self)) + else + raise Errors::NoSuchWaiterError + end + end + + def waiters +<% waiters.each do |line| -%> + <%= line %> +<% end -%> + end +<% end -%> class << self # @api private diff --git a/gems/smithy/lib/smithy/views/client/client.rb b/gems/smithy/lib/smithy/views/client/client.rb index d2485dd21..01b29d032 100644 --- a/gems/smithy/lib/smithy/views/client/client.rb +++ b/gems/smithy/lib/smithy/views/client/client.rb @@ -60,6 +60,22 @@ def protocols @protocols ||= @plan.welds.map(&:protocols).reduce({}, :merge) end + def waiters + waiters = Views::Client::Waiters.new(@plan).waiters + code = [' {'] + waiters.each_with_index do |waiter, i| + line = ' ' + waiter.name.underscore + ': Waiters::' + waiter.name + ',' + line.chomp!(',') if i == waiters.length - 1 + code << line + end + code << ' }' + code + end + + def waiters? + Views::Client::Waiters.new(@plan).waiters.size > 0 + end + private def option_docstrings(option) diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index 9c09e5f61..16ab95a20 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -227,6 +227,11 @@ def list_cities(params = {}, options = {}) input.send_request(options) end + def wait_until(waiter_name, params = {}, options = {}) + w = waiter(waiter_name, options) + w.wait(params) + end + private def build_input(operation_name, params) @@ -243,6 +248,23 @@ def build_input(operation_name, params) Smithy::Client::Input.new(handlers: handlers, context: context) end + def waiter(waiter_name, options = {}) + waiter_class = waiters[waiter_name] + if waiter_class + waiter_class.new(options.merge(client: self)) + else + raise Errors::NoSuchWaiterError + end + end + + def waiters + { + city_deleted: Waiters::CityDeleted, + city_exists: Waiters::CityExists, + forecast_exists: Waiters::ForecastExists + } + end + class << self # @api private attr_reader :identifier From 33bf1da54e2497884996a3727fe403b12b1a833b Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 24 Apr 2025 14:46:52 -0700 Subject: [PATCH 04/48] Add initial Waiters module --- .../lib/smithy-client/waiters/errors.rb | 52 ++++++++++ .../lib/smithy-client/waiters/poller.rb | 96 +++++++++++++++++++ .../lib/smithy-client/waiters/waiter.rb | 50 ++++++++++ 3 files changed, 198 insertions(+) create mode 100644 gems/smithy-client/lib/smithy-client/waiters/errors.rb create mode 100644 gems/smithy-client/lib/smithy-client/waiters/poller.rb create mode 100644 gems/smithy-client/lib/smithy-client/waiters/waiter.rb diff --git a/gems/smithy-client/lib/smithy-client/waiters/errors.rb b/gems/smithy-client/lib/smithy-client/waiters/errors.rb new file mode 100644 index 000000000..caf1a4c5e --- /dev/null +++ b/gems/smithy-client/lib/smithy-client/waiters/errors.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +module Smithy + module Client + module Errors + + # Raised when a waiter detects a condition where the waiter can never + # succeed. + class WaiterFailed < StandardError; end + + class FailureStateError < WaiterFailed + MSG = "stopped waiting, encountered a failure state" + + def initialize(response) + @response = response + super(MSG) + end + + attr_reader :response + end + + class MaxWaitTimeExceededError < WaiterFailed + MSG = "stopped waiting after maximum wait time was exceeded" + + def initialize + super(MSG) + end + end + + class UnexpectedError < WaiterFailed + MSG = "stopped waiting due to an unexpected error: %s" + + def initialize(error) + @error = error + super(MSG % [error.message]) + end + + attr_reader :error + end + + # Raised when attempting to get a waiter by name and the waiter has not + # been defined. + class NoSuchWaiterError < ArgumentError + MSG = "no such waiter" + + def initialize + super(MSG) + end + end + end + end +end diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb new file mode 100644 index 000000000..e77fb4c94 --- /dev/null +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -0,0 +1,96 @@ +# frozen_string_literal: true + +module Smithy + module Client + module Waiters + class Poller + def initialize(operation_name, acceptors) + @operation_name = operation_name + @acceptors = acceptors + end + + def call(client, params) + resp = client.send(@operation_name, params) + status = evaluate_acceptors(resp) + [resp, status] + end + + def evaluate_acceptors(resp) + @acceptors.each do |acceptor| + return acceptor['state'] if acceptor_matches?(acceptor['matcher'], resp) + end + + # If none of the acceptors match and an error was encountered, + # transition to failure state. Otherwise, transition to retry state. + if resp.error? + 'error' + else + 'retry' + end + end + + def acceptor_matches?(matcher, resp) + matcher_type = matcher.keys[0] + send("matches_#{matcher_type}?") + end + + def matches_output?(path_matcher, resp) + return false if resp.error || resp.data.nil? + + actual = JMESPath.search(path_matcher['path'], resp.data) + is_equal?(actual, expected, path_matcher['comparator']) + end + + def matches_inputOutput?(path_matcher, resp) + return false if resp.error + + data = { + input: input, ### Where do we get this? + output: resp.data + } + + actual = JMESPath.search(path_matcher['path'], data) + is_equal?(actual, expected, path_matcher['comparator']) + end + + def matches_success?(path_matcher, resp) + if path_matcher['success'] + resp.error.nil? + else + resp.error? + end + end + + def matches_errorType?(path_matcher, resp) + return false unless resp.error + + error = path_matcher['errorType'].split('#').last.split('#').first + error == resp.error + end + + def is_equal?(actual, expected, comparator) + case comparator + when 'string_equals' + return actual == expected + when 'boolean_equals' + return actual.to_s == expected + when 'all_string_equals' + return false if actual.empty? + + actual.each do |value| + return false if value != expected + end + return true + when 'any_string_equals' + return false if actual.empty? + + actual.each do |value| + return true if value == expected + end + return false + end + end + end + end + end +end \ No newline at end of file diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb new file mode 100644 index 000000000..3f07b4814 --- /dev/null +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +module Smithy + module Client + module Waiters + class Waiter + def initialize(options = {}) + @remaining_time = options[:max_wait_time] + @min_delay = options[:min_delay] + @max_delay = options[:max_delay] + @poller = options[:poller] + end + + def wait(client, params) + poll(client, params) + end + + private + + def poll(client, params) + attempts = 0 + loop do + resp, status = @poller.call(client, params) + + case status + when :retry + when :success then return resp + when :failure then return Errors::FailureStateError + when :error then return Errors::UnexpectedError + end + + return Errors::MaxWaitTimeExceededError if @remaining_time == 0 + + delay = delay(attempts) + @remaining_time -= delay + sleep(delay) + end + end + + def delay(attempts) + attempt_ceiling = (Math.log(@max_delay / @min_delay) / Math.log(2)) + 1 + delay = attempts > attempt_ceiling ? @max_delay : @min_delay * 2 ** (attempts - 1) + delay = random(@min_delay, delay) + delay = @remaining_time if @remaining_time - delay <= @min_delay + delay + end + end + end + end +end \ No newline at end of file From ad953252a53f047069ef89eabac7c31543054b18 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 24 Apr 2025 14:57:15 -0700 Subject: [PATCH 05/48] Change casing --- gems/smithy-client/lib/smithy-client/waiters/poller.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index e77fb4c94..d8c20cf27 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -70,18 +70,18 @@ def matches_errorType?(path_matcher, resp) def is_equal?(actual, expected, comparator) case comparator - when 'string_equals' + when 'stringEquals' return actual == expected - when 'boolean_equals' + when 'booleanEquals' return actual.to_s == expected - when 'all_string_equals' + when 'allStringEquals' return false if actual.empty? actual.each do |value| return false if value != expected end return true - when 'any_string_equals' + when 'anyStringEquals' return false if actual.empty? actual.each do |value| From fd76a10dda680c06a111f60cdce008d4b257e626 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 25 Apr 2025 10:11:24 -0700 Subject: [PATCH 06/48] Start adding waiter tests --- .../lib/smithy-client/waiters/waiter.rb | 10 +- .../lib/smithy/templates/client/waiters.erb | 2 +- .../spec/fixtures/auth/auth_trait/model.json | 263 ++ .../auth/http_api_key_auth/model.json | 263 ++ .../fixtures/auth/http_basic_auth/model.json | 263 ++ .../fixtures/auth/http_bearer_auth/model.json | 263 ++ .../fixtures/auth/http_digest_auth/model.json | 263 ++ .../fixtures/auth/no_auth_trait/model.json | 263 ++ gems/smithy/spec/fixtures/errors/model.json | 400 ++ .../spec/fixtures/examples_trait/model.json | 400 ++ .../fixtures/mixins/apply-list/model.json | 400 ++ .../spec/fixtures/mixins/apply-map/model.json | 400 ++ .../mixins/apply-structure/model.json | 400 ++ .../fixtures/mixins/apply-union/model.json | 400 ++ .../spec/fixtures/mixins/composed/model.json | 400 ++ .../fixtures/mixins/local-traits/model.json | 400 ++ .../fixtures/mixins/member-order/model.json | 400 ++ .../spec/fixtures/mixins/multiple/model.json | 400 ++ .../fixtures/mixins/operations/model.json | 400 ++ .../spec/fixtures/mixins/redefine/model.json | 400 ++ .../mixins/replace-redefine/model.json | 400 ++ .../spec/fixtures/mixins/resources/model.json | 400 ++ .../spec/fixtures/mixins/services/model.json | 400 ++ .../mixins/trait-inheritance/model.json | 400 ++ .../fixtures/mixins/trait-order/model.json | 400 ++ .../fixtures/mixins/trait-override/model.json | 400 ++ .../fixtures/mixins/type-agnostic/model.json | 400 ++ .../spec/fixtures/mixins/vanilla/model.json | 400 ++ .../spec/fixtures/multi_service/model.json | 400 ++ .../spec/fixtures/no_protocol/model.json | 400 ++ .../spec/fixtures/no_service/model.json | 403 +- .../spec/fixtures/one_service/model.json | 400 ++ .../smithy/spec/fixtures/recursive/model.json | 3907 +++++++++++++++++ .../spec/fixtures/service_index/model.json | 47 + gems/smithy/spec/fixtures/shapes/model.json | 47 + .../spec/fixtures/syntax_examples/model.json | 47 + gems/smithy/spec/fixtures/waiters/model.json | 606 +++ .../smithy/spec/fixtures/waiters/model.smithy | 284 ++ .../spec/fixtures/waiters/smithy-build.json | 8 + gems/smithy/spec/fixtures/weather/model.json | 263 ++ .../spec/fixtures/weld_protocol/model.json | 263 ++ .../spec/interfaces/client/waiters_spec.rb | 15 + projections/weather/lib/weather/waiters.rb | 6 +- 43 files changed, 16676 insertions(+), 10 deletions(-) create mode 100644 gems/smithy/spec/fixtures/waiters/model.json create mode 100644 gems/smithy/spec/fixtures/waiters/model.smithy create mode 100644 gems/smithy/spec/fixtures/waiters/smithy-build.json create mode 100644 gems/smithy/spec/interfaces/client/waiters_spec.rb diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index 3f07b4814..6fcf30780 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -25,11 +25,11 @@ def poll(client, params) case status when :retry when :success then return resp - when :failure then return Errors::FailureStateError - when :error then return Errors::UnexpectedError + when :failure then return Errors::FailureStateError.new(resp) + when :error then return Errors::UnexpectedError.new(resp) end - return Errors::MaxWaitTimeExceededError if @remaining_time == 0 + return Errors::MaxWaitTimeExceededError.new if @remaining_time == 0 delay = delay(attempts) @remaining_time -= delay @@ -40,9 +40,9 @@ def poll(client, params) def delay(attempts) attempt_ceiling = (Math.log(@max_delay / @min_delay) / Math.log(2)) + 1 delay = attempts > attempt_ceiling ? @max_delay : @min_delay * 2 ** (attempts - 1) - delay = random(@min_delay, delay) + delay = rand(@min_delay..delay) delay = @remaining_time if @remaining_time - delay <= @min_delay - delay + delay end end end diff --git a/gems/smithy/lib/smithy/templates/client/waiters.erb b/gems/smithy/lib/smithy/templates/client/waiters.erb index 825815e25..b5fa7ac47 100644 --- a/gems/smithy/lib/smithy/templates/client/waiters.erb +++ b/gems/smithy/lib/smithy/templates/client/waiters.erb @@ -15,7 +15,7 @@ module <%= module_name %> min_delay: options[:min_delay] || <%= waiter.min_delay %>, max_delay: options[:max_delay] || <%= waiter.max_delay %>, poller: Poller.new( - operation_name: <%= waiter.operation_name %>, + operation_name: :<%= waiter.operation_name %>, <%= waiter.acceptors %> ) ) diff --git a/gems/smithy/spec/fixtures/auth/auth_trait/model.json b/gems/smithy/spec/fixtures/auth/auth_trait/model.json index 8c0af79fa..db88a755d 100644 --- a/gems/smithy/spec/fixtures/auth/auth_trait/model.json +++ b/gems/smithy/spec/fixtures/auth/auth_trait/model.json @@ -59,6 +59,269 @@ "smithy.api#httpBearerAuth": {}, "smithy.api#httpDigestAuth": {} } + }, + "smithy.waiters#Acceptor": { + "type": "structure", + "members": { + "state": { + "target": "smithy.waiters#AcceptorState", + "traits": { + "smithy.api#documentation": "The state the acceptor transitions to when matched.", + "smithy.api#required": {} + } + }, + "matcher": { + "target": "smithy.waiters#Matcher", + "traits": { + "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", + "smithy.api#private": {} + } + }, + "smithy.waiters#AcceptorState": { + "type": "enum", + "members": { + "SUCCESS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", + "smithy.api#enumValue": "success" + } + }, + "FAILURE": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", + "smithy.api#enumValue": "failure" + } + }, + "RETRY": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", + "smithy.api#enumValue": "retry" + } + } + }, + "traits": { + "smithy.api#documentation": "The transition state of a waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Acceptors": { + "type": "list", + "member": { + "target": "smithy.waiters#Acceptor" + }, + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#Matcher": { + "type": "union", + "members": { + "output": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." + } + }, + "inputOutput": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." + } + }, + "errorType": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." + } + }, + "success": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyString": { + "type": "string", + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyStringList": { + "type": "list", + "member": { + "target": "smithy.waiters#NonEmptyString" + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.waiters#PathComparator": { + "type": "enum", + "members": { + "STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", + "smithy.api#enumValue": "stringEquals" + } + }, + "BOOLEAN_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", + "smithy.api#enumValue": "booleanEquals" + } + }, + "ALL_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if all values in the list matches the expected string.", + "smithy.api#enumValue": "allStringEquals" + } + }, + "ANY_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if any value in the list matches the expected string.", + "smithy.api#enumValue": "anyStringEquals" + } + } + }, + "traits": { + "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", + "smithy.api#private": {} + } + }, + "smithy.waiters#PathMatcher": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", + "smithy.api#required": {} + } + }, + "expected": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected return value of the expression.", + "smithy.api#required": {} + } + }, + "comparator": { + "target": "smithy.waiters#PathComparator", + "traits": { + "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Waiter": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." + } + }, + "acceptors": { + "target": "smithy.waiters#Acceptors", + "traits": { + "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", + "smithy.api#required": {} + } + }, + "minDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 2, + "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." + } + }, + "maxDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 120, + "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." + } + }, + "deprecated": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." + } + }, + "tags": { + "target": "smithy.waiters#NonEmptyStringList", + "traits": { + "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines an individual operation waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#WaiterDelay": { + "type": "integer", + "traits": { + "smithy.api#range": { + "min": 1 + } + } + }, + "smithy.waiters#WaiterName": { + "type": "string", + "traits": { + "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" + } + }, + "smithy.waiters#waitable": { + "type": "map", + "key": { + "target": "smithy.waiters#WaiterName" + }, + "value": { + "target": "smithy.waiters#Waiter" + }, + "traits": { + "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#trait": { + "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" + } + } } } } diff --git a/gems/smithy/spec/fixtures/auth/http_api_key_auth/model.json b/gems/smithy/spec/fixtures/auth/http_api_key_auth/model.json index 33a8a7043..4a6c9278c 100644 --- a/gems/smithy/spec/fixtures/auth/http_api_key_auth/model.json +++ b/gems/smithy/spec/fixtures/auth/http_api_key_auth/model.json @@ -9,6 +9,269 @@ "in": "header" } } + }, + "smithy.waiters#Acceptor": { + "type": "structure", + "members": { + "state": { + "target": "smithy.waiters#AcceptorState", + "traits": { + "smithy.api#documentation": "The state the acceptor transitions to when matched.", + "smithy.api#required": {} + } + }, + "matcher": { + "target": "smithy.waiters#Matcher", + "traits": { + "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", + "smithy.api#private": {} + } + }, + "smithy.waiters#AcceptorState": { + "type": "enum", + "members": { + "SUCCESS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", + "smithy.api#enumValue": "success" + } + }, + "FAILURE": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", + "smithy.api#enumValue": "failure" + } + }, + "RETRY": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", + "smithy.api#enumValue": "retry" + } + } + }, + "traits": { + "smithy.api#documentation": "The transition state of a waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Acceptors": { + "type": "list", + "member": { + "target": "smithy.waiters#Acceptor" + }, + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#Matcher": { + "type": "union", + "members": { + "output": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." + } + }, + "inputOutput": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." + } + }, + "errorType": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." + } + }, + "success": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyString": { + "type": "string", + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyStringList": { + "type": "list", + "member": { + "target": "smithy.waiters#NonEmptyString" + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.waiters#PathComparator": { + "type": "enum", + "members": { + "STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", + "smithy.api#enumValue": "stringEquals" + } + }, + "BOOLEAN_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", + "smithy.api#enumValue": "booleanEquals" + } + }, + "ALL_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if all values in the list matches the expected string.", + "smithy.api#enumValue": "allStringEquals" + } + }, + "ANY_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if any value in the list matches the expected string.", + "smithy.api#enumValue": "anyStringEquals" + } + } + }, + "traits": { + "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", + "smithy.api#private": {} + } + }, + "smithy.waiters#PathMatcher": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", + "smithy.api#required": {} + } + }, + "expected": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected return value of the expression.", + "smithy.api#required": {} + } + }, + "comparator": { + "target": "smithy.waiters#PathComparator", + "traits": { + "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Waiter": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." + } + }, + "acceptors": { + "target": "smithy.waiters#Acceptors", + "traits": { + "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", + "smithy.api#required": {} + } + }, + "minDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 2, + "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." + } + }, + "maxDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 120, + "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." + } + }, + "deprecated": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." + } + }, + "tags": { + "target": "smithy.waiters#NonEmptyStringList", + "traits": { + "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines an individual operation waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#WaiterDelay": { + "type": "integer", + "traits": { + "smithy.api#range": { + "min": 1 + } + } + }, + "smithy.waiters#WaiterName": { + "type": "string", + "traits": { + "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" + } + }, + "smithy.waiters#waitable": { + "type": "map", + "key": { + "target": "smithy.waiters#WaiterName" + }, + "value": { + "target": "smithy.waiters#Waiter" + }, + "traits": { + "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#trait": { + "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" + } + } } } } diff --git a/gems/smithy/spec/fixtures/auth/http_basic_auth/model.json b/gems/smithy/spec/fixtures/auth/http_basic_auth/model.json index 7cd1ac5b5..19c418f2e 100644 --- a/gems/smithy/spec/fixtures/auth/http_basic_auth/model.json +++ b/gems/smithy/spec/fixtures/auth/http_basic_auth/model.json @@ -6,6 +6,269 @@ "traits": { "smithy.api#httpBasicAuth": {} } + }, + "smithy.waiters#Acceptor": { + "type": "structure", + "members": { + "state": { + "target": "smithy.waiters#AcceptorState", + "traits": { + "smithy.api#documentation": "The state the acceptor transitions to when matched.", + "smithy.api#required": {} + } + }, + "matcher": { + "target": "smithy.waiters#Matcher", + "traits": { + "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", + "smithy.api#private": {} + } + }, + "smithy.waiters#AcceptorState": { + "type": "enum", + "members": { + "SUCCESS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", + "smithy.api#enumValue": "success" + } + }, + "FAILURE": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", + "smithy.api#enumValue": "failure" + } + }, + "RETRY": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", + "smithy.api#enumValue": "retry" + } + } + }, + "traits": { + "smithy.api#documentation": "The transition state of a waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Acceptors": { + "type": "list", + "member": { + "target": "smithy.waiters#Acceptor" + }, + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#Matcher": { + "type": "union", + "members": { + "output": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." + } + }, + "inputOutput": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." + } + }, + "errorType": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." + } + }, + "success": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyString": { + "type": "string", + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyStringList": { + "type": "list", + "member": { + "target": "smithy.waiters#NonEmptyString" + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.waiters#PathComparator": { + "type": "enum", + "members": { + "STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", + "smithy.api#enumValue": "stringEquals" + } + }, + "BOOLEAN_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", + "smithy.api#enumValue": "booleanEquals" + } + }, + "ALL_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if all values in the list matches the expected string.", + "smithy.api#enumValue": "allStringEquals" + } + }, + "ANY_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if any value in the list matches the expected string.", + "smithy.api#enumValue": "anyStringEquals" + } + } + }, + "traits": { + "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", + "smithy.api#private": {} + } + }, + "smithy.waiters#PathMatcher": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", + "smithy.api#required": {} + } + }, + "expected": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected return value of the expression.", + "smithy.api#required": {} + } + }, + "comparator": { + "target": "smithy.waiters#PathComparator", + "traits": { + "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Waiter": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." + } + }, + "acceptors": { + "target": "smithy.waiters#Acceptors", + "traits": { + "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", + "smithy.api#required": {} + } + }, + "minDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 2, + "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." + } + }, + "maxDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 120, + "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." + } + }, + "deprecated": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." + } + }, + "tags": { + "target": "smithy.waiters#NonEmptyStringList", + "traits": { + "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines an individual operation waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#WaiterDelay": { + "type": "integer", + "traits": { + "smithy.api#range": { + "min": 1 + } + } + }, + "smithy.waiters#WaiterName": { + "type": "string", + "traits": { + "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" + } + }, + "smithy.waiters#waitable": { + "type": "map", + "key": { + "target": "smithy.waiters#WaiterName" + }, + "value": { + "target": "smithy.waiters#Waiter" + }, + "traits": { + "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#trait": { + "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" + } + } } } } diff --git a/gems/smithy/spec/fixtures/auth/http_bearer_auth/model.json b/gems/smithy/spec/fixtures/auth/http_bearer_auth/model.json index f5d48b8cc..4b3d56969 100644 --- a/gems/smithy/spec/fixtures/auth/http_bearer_auth/model.json +++ b/gems/smithy/spec/fixtures/auth/http_bearer_auth/model.json @@ -6,6 +6,269 @@ "traits": { "smithy.api#httpBearerAuth": {} } + }, + "smithy.waiters#Acceptor": { + "type": "structure", + "members": { + "state": { + "target": "smithy.waiters#AcceptorState", + "traits": { + "smithy.api#documentation": "The state the acceptor transitions to when matched.", + "smithy.api#required": {} + } + }, + "matcher": { + "target": "smithy.waiters#Matcher", + "traits": { + "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", + "smithy.api#private": {} + } + }, + "smithy.waiters#AcceptorState": { + "type": "enum", + "members": { + "SUCCESS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", + "smithy.api#enumValue": "success" + } + }, + "FAILURE": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", + "smithy.api#enumValue": "failure" + } + }, + "RETRY": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", + "smithy.api#enumValue": "retry" + } + } + }, + "traits": { + "smithy.api#documentation": "The transition state of a waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Acceptors": { + "type": "list", + "member": { + "target": "smithy.waiters#Acceptor" + }, + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#Matcher": { + "type": "union", + "members": { + "output": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." + } + }, + "inputOutput": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." + } + }, + "errorType": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." + } + }, + "success": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyString": { + "type": "string", + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyStringList": { + "type": "list", + "member": { + "target": "smithy.waiters#NonEmptyString" + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.waiters#PathComparator": { + "type": "enum", + "members": { + "STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", + "smithy.api#enumValue": "stringEquals" + } + }, + "BOOLEAN_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", + "smithy.api#enumValue": "booleanEquals" + } + }, + "ALL_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if all values in the list matches the expected string.", + "smithy.api#enumValue": "allStringEquals" + } + }, + "ANY_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if any value in the list matches the expected string.", + "smithy.api#enumValue": "anyStringEquals" + } + } + }, + "traits": { + "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", + "smithy.api#private": {} + } + }, + "smithy.waiters#PathMatcher": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", + "smithy.api#required": {} + } + }, + "expected": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected return value of the expression.", + "smithy.api#required": {} + } + }, + "comparator": { + "target": "smithy.waiters#PathComparator", + "traits": { + "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Waiter": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." + } + }, + "acceptors": { + "target": "smithy.waiters#Acceptors", + "traits": { + "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", + "smithy.api#required": {} + } + }, + "minDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 2, + "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." + } + }, + "maxDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 120, + "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." + } + }, + "deprecated": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." + } + }, + "tags": { + "target": "smithy.waiters#NonEmptyStringList", + "traits": { + "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines an individual operation waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#WaiterDelay": { + "type": "integer", + "traits": { + "smithy.api#range": { + "min": 1 + } + } + }, + "smithy.waiters#WaiterName": { + "type": "string", + "traits": { + "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" + } + }, + "smithy.waiters#waitable": { + "type": "map", + "key": { + "target": "smithy.waiters#WaiterName" + }, + "value": { + "target": "smithy.waiters#Waiter" + }, + "traits": { + "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#trait": { + "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" + } + } } } } diff --git a/gems/smithy/spec/fixtures/auth/http_digest_auth/model.json b/gems/smithy/spec/fixtures/auth/http_digest_auth/model.json index ca3b44225..2ac58ef65 100644 --- a/gems/smithy/spec/fixtures/auth/http_digest_auth/model.json +++ b/gems/smithy/spec/fixtures/auth/http_digest_auth/model.json @@ -6,6 +6,269 @@ "traits": { "smithy.api#httpDigestAuth": {} } + }, + "smithy.waiters#Acceptor": { + "type": "structure", + "members": { + "state": { + "target": "smithy.waiters#AcceptorState", + "traits": { + "smithy.api#documentation": "The state the acceptor transitions to when matched.", + "smithy.api#required": {} + } + }, + "matcher": { + "target": "smithy.waiters#Matcher", + "traits": { + "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", + "smithy.api#private": {} + } + }, + "smithy.waiters#AcceptorState": { + "type": "enum", + "members": { + "SUCCESS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", + "smithy.api#enumValue": "success" + } + }, + "FAILURE": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", + "smithy.api#enumValue": "failure" + } + }, + "RETRY": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", + "smithy.api#enumValue": "retry" + } + } + }, + "traits": { + "smithy.api#documentation": "The transition state of a waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Acceptors": { + "type": "list", + "member": { + "target": "smithy.waiters#Acceptor" + }, + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#Matcher": { + "type": "union", + "members": { + "output": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." + } + }, + "inputOutput": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." + } + }, + "errorType": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." + } + }, + "success": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyString": { + "type": "string", + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyStringList": { + "type": "list", + "member": { + "target": "smithy.waiters#NonEmptyString" + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.waiters#PathComparator": { + "type": "enum", + "members": { + "STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", + "smithy.api#enumValue": "stringEquals" + } + }, + "BOOLEAN_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", + "smithy.api#enumValue": "booleanEquals" + } + }, + "ALL_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if all values in the list matches the expected string.", + "smithy.api#enumValue": "allStringEquals" + } + }, + "ANY_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if any value in the list matches the expected string.", + "smithy.api#enumValue": "anyStringEquals" + } + } + }, + "traits": { + "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", + "smithy.api#private": {} + } + }, + "smithy.waiters#PathMatcher": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", + "smithy.api#required": {} + } + }, + "expected": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected return value of the expression.", + "smithy.api#required": {} + } + }, + "comparator": { + "target": "smithy.waiters#PathComparator", + "traits": { + "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Waiter": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." + } + }, + "acceptors": { + "target": "smithy.waiters#Acceptors", + "traits": { + "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", + "smithy.api#required": {} + } + }, + "minDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 2, + "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." + } + }, + "maxDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 120, + "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." + } + }, + "deprecated": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." + } + }, + "tags": { + "target": "smithy.waiters#NonEmptyStringList", + "traits": { + "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines an individual operation waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#WaiterDelay": { + "type": "integer", + "traits": { + "smithy.api#range": { + "min": 1 + } + } + }, + "smithy.waiters#WaiterName": { + "type": "string", + "traits": { + "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" + } + }, + "smithy.waiters#waitable": { + "type": "map", + "key": { + "target": "smithy.waiters#WaiterName" + }, + "value": { + "target": "smithy.waiters#Waiter" + }, + "traits": { + "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#trait": { + "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" + } + } } } } diff --git a/gems/smithy/spec/fixtures/auth/no_auth_trait/model.json b/gems/smithy/spec/fixtures/auth/no_auth_trait/model.json index f74113c77..cbbf2e25e 100644 --- a/gems/smithy/spec/fixtures/auth/no_auth_trait/model.json +++ b/gems/smithy/spec/fixtures/auth/no_auth_trait/model.json @@ -40,6 +40,269 @@ "smithy.api#httpBearerAuth": {}, "smithy.api#httpDigestAuth": {} } + }, + "smithy.waiters#Acceptor": { + "type": "structure", + "members": { + "state": { + "target": "smithy.waiters#AcceptorState", + "traits": { + "smithy.api#documentation": "The state the acceptor transitions to when matched.", + "smithy.api#required": {} + } + }, + "matcher": { + "target": "smithy.waiters#Matcher", + "traits": { + "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", + "smithy.api#private": {} + } + }, + "smithy.waiters#AcceptorState": { + "type": "enum", + "members": { + "SUCCESS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", + "smithy.api#enumValue": "success" + } + }, + "FAILURE": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", + "smithy.api#enumValue": "failure" + } + }, + "RETRY": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", + "smithy.api#enumValue": "retry" + } + } + }, + "traits": { + "smithy.api#documentation": "The transition state of a waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Acceptors": { + "type": "list", + "member": { + "target": "smithy.waiters#Acceptor" + }, + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#Matcher": { + "type": "union", + "members": { + "output": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." + } + }, + "inputOutput": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." + } + }, + "errorType": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." + } + }, + "success": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyString": { + "type": "string", + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyStringList": { + "type": "list", + "member": { + "target": "smithy.waiters#NonEmptyString" + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.waiters#PathComparator": { + "type": "enum", + "members": { + "STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", + "smithy.api#enumValue": "stringEquals" + } + }, + "BOOLEAN_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", + "smithy.api#enumValue": "booleanEquals" + } + }, + "ALL_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if all values in the list matches the expected string.", + "smithy.api#enumValue": "allStringEquals" + } + }, + "ANY_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if any value in the list matches the expected string.", + "smithy.api#enumValue": "anyStringEquals" + } + } + }, + "traits": { + "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", + "smithy.api#private": {} + } + }, + "smithy.waiters#PathMatcher": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", + "smithy.api#required": {} + } + }, + "expected": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected return value of the expression.", + "smithy.api#required": {} + } + }, + "comparator": { + "target": "smithy.waiters#PathComparator", + "traits": { + "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Waiter": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." + } + }, + "acceptors": { + "target": "smithy.waiters#Acceptors", + "traits": { + "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", + "smithy.api#required": {} + } + }, + "minDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 2, + "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." + } + }, + "maxDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 120, + "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." + } + }, + "deprecated": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." + } + }, + "tags": { + "target": "smithy.waiters#NonEmptyStringList", + "traits": { + "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines an individual operation waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#WaiterDelay": { + "type": "integer", + "traits": { + "smithy.api#range": { + "min": 1 + } + } + }, + "smithy.waiters#WaiterName": { + "type": "string", + "traits": { + "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" + } + }, + "smithy.waiters#waitable": { + "type": "map", + "key": { + "target": "smithy.waiters#WaiterName" + }, + "value": { + "target": "smithy.waiters#Waiter" + }, + "traits": { + "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#trait": { + "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" + } + } } } } diff --git a/gems/smithy/spec/fixtures/errors/model.json b/gems/smithy/spec/fixtures/errors/model.json index 92ca9db43..15885913b 100644 --- a/gems/smithy/spec/fixtures/errors/model.json +++ b/gems/smithy/spec/fixtures/errors/model.json @@ -118,6 +118,406 @@ "target": "smithy.api#String" } } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/examples_trait/model.json b/gems/smithy/spec/fixtures/examples_trait/model.json index 6991c174d..82b30edd0 100644 --- a/gems/smithy/spec/fixtures/examples_trait/model.json +++ b/gems/smithy/spec/fixtures/examples_trait/model.json @@ -139,6 +139,406 @@ "target": "smithy.api#String" } } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/apply-list/model.json b/gems/smithy/spec/fixtures/mixins/apply-list/model.json index ee9a4f1ee..8073d77e1 100644 --- a/gems/smithy/spec/fixtures/mixins/apply-list/model.json +++ b/gems/smithy/spec/fixtures/mixins/apply-list/model.json @@ -26,6 +26,406 @@ "traits": { "smithy.api#mixin": {} } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/apply-map/model.json b/gems/smithy/spec/fixtures/mixins/apply-map/model.json index cdda857fd..62c6c06d6 100644 --- a/gems/smithy/spec/fixtures/mixins/apply-map/model.json +++ b/gems/smithy/spec/fixtures/mixins/apply-map/model.json @@ -38,6 +38,406 @@ "traits": { "smithy.api#mixin": {} } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/apply-structure/model.json b/gems/smithy/spec/fixtures/mixins/apply-structure/model.json index 5ece222c8..a2bf46593 100644 --- a/gems/smithy/spec/fixtures/mixins/apply-structure/model.json +++ b/gems/smithy/spec/fixtures/mixins/apply-structure/model.json @@ -29,6 +29,406 @@ "traits": { "smithy.api#documentation": "Specific docs" } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/apply-union/model.json b/gems/smithy/spec/fixtures/mixins/apply-union/model.json index 6bc886eae..1e2fdcb86 100644 --- a/gems/smithy/spec/fixtures/mixins/apply-union/model.json +++ b/gems/smithy/spec/fixtures/mixins/apply-union/model.json @@ -29,6 +29,406 @@ "traits": { "smithy.api#documentation": "Specific docs" } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/composed/model.json b/gems/smithy/spec/fixtures/mixins/composed/model.json index f6b2d1d79..a17329d51 100644 --- a/gems/smithy/spec/fixtures/mixins/composed/model.json +++ b/gems/smithy/spec/fixtures/mixins/composed/model.json @@ -40,6 +40,406 @@ "traits": { "smithy.api#mixin": {} } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/local-traits/model.json b/gems/smithy/spec/fixtures/mixins/local-traits/model.json index c46d937e4..332ad9b16 100644 --- a/gems/smithy/spec/fixtures/mixins/local-traits/model.json +++ b/gems/smithy/spec/fixtures/mixins/local-traits/model.json @@ -25,6 +25,406 @@ } ], "members": {} + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/member-order/model.json b/gems/smithy/spec/fixtures/mixins/member-order/model.json index 290b16e84..359a034a9 100644 --- a/gems/smithy/spec/fixtures/mixins/member-order/model.json +++ b/gems/smithy/spec/fixtures/mixins/member-order/model.json @@ -41,6 +41,406 @@ "traits": { "smithy.api#mixin": {} } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/multiple/model.json b/gems/smithy/spec/fixtures/mixins/multiple/model.json index d8b0cdca3..9a9993db2 100644 --- a/gems/smithy/spec/fixtures/mixins/multiple/model.json +++ b/gems/smithy/spec/fixtures/mixins/multiple/model.json @@ -41,6 +41,406 @@ "traits": { "smithy.api#mixin": {} } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/operations/model.json b/gems/smithy/spec/fixtures/mixins/operations/model.json index d083d9185..dcd5dece4 100644 --- a/gems/smithy/spec/fixtures/mixins/operations/model.json +++ b/gems/smithy/spec/fixtures/mixins/operations/model.json @@ -72,6 +72,406 @@ "traits": { "smithy.api#error": "client" } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/redefine/model.json b/gems/smithy/spec/fixtures/mixins/redefine/model.json index 4fbb9f0f1..33674c412 100644 --- a/gems/smithy/spec/fixtures/mixins/redefine/model.json +++ b/gems/smithy/spec/fixtures/mixins/redefine/model.json @@ -46,6 +46,406 @@ "traits": { "smithy.api#required": {} } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/replace-redefine/model.json b/gems/smithy/spec/fixtures/mixins/replace-redefine/model.json index 5ece222c8..a2bf46593 100644 --- a/gems/smithy/spec/fixtures/mixins/replace-redefine/model.json +++ b/gems/smithy/spec/fixtures/mixins/replace-redefine/model.json @@ -29,6 +29,406 @@ "traits": { "smithy.api#documentation": "Specific docs" } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/resources/model.json b/gems/smithy/spec/fixtures/mixins/resources/model.json index 6dc2eff59..14b2734ab 100644 --- a/gems/smithy/spec/fixtures/mixins/resources/model.json +++ b/gems/smithy/spec/fixtures/mixins/resources/model.json @@ -15,6 +15,406 @@ "smithy.api#internal": {}, "smithy.api#mixin": {} } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/services/model.json b/gems/smithy/spec/fixtures/mixins/services/model.json index 7e8a95df9..8ef324b82 100644 --- a/gems/smithy/spec/fixtures/mixins/services/model.json +++ b/gems/smithy/spec/fixtures/mixins/services/model.json @@ -90,6 +90,406 @@ "output": { "target": "smithy.api#Unit" } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/trait-inheritance/model.json b/gems/smithy/spec/fixtures/mixins/trait-inheritance/model.json index 25dc4982c..03e2fb6fd 100644 --- a/gems/smithy/spec/fixtures/mixins/trait-inheritance/model.json +++ b/gems/smithy/spec/fixtures/mixins/trait-inheritance/model.json @@ -24,6 +24,406 @@ } ], "members": {} + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/trait-order/model.json b/gems/smithy/spec/fixtures/mixins/trait-order/model.json index d4a8490e7..a65191e3f 100644 --- a/gems/smithy/spec/fixtures/mixins/trait-order/model.json +++ b/gems/smithy/spec/fixtures/mixins/trait-order/model.json @@ -84,6 +84,406 @@ "traits": { "smithy.api#trait": {} } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/trait-override/model.json b/gems/smithy/spec/fixtures/mixins/trait-override/model.json index 60d84694c..24ae903a0 100644 --- a/gems/smithy/spec/fixtures/mixins/trait-override/model.json +++ b/gems/smithy/spec/fixtures/mixins/trait-override/model.json @@ -30,6 +30,406 @@ "replaced-tags" ] } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/type-agnostic/model.json b/gems/smithy/spec/fixtures/mixins/type-agnostic/model.json index 6e9a4d7c1..8c48c18b5 100644 --- a/gems/smithy/spec/fixtures/mixins/type-agnostic/model.json +++ b/gems/smithy/spec/fixtures/mixins/type-agnostic/model.json @@ -21,6 +21,406 @@ "max": 32 } } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/mixins/vanilla/model.json b/gems/smithy/spec/fixtures/mixins/vanilla/model.json index d76eda5d8..a73ec41fb 100644 --- a/gems/smithy/spec/fixtures/mixins/vanilla/model.json +++ b/gems/smithy/spec/fixtures/mixins/vanilla/model.json @@ -24,6 +24,406 @@ "traits": { "smithy.api#mixin": {} } + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/multi_service/model.json b/gems/smithy/spec/fixtures/multi_service/model.json index b427e9ff6..f8572e6db 100644 --- a/gems/smithy/spec/fixtures/multi_service/model.json +++ b/gems/smithy/spec/fixtures/multi_service/model.json @@ -6,6 +6,406 @@ }, "smithy.ruby.tests#Service2": { "type": "service" + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/no_protocol/model.json b/gems/smithy/spec/fixtures/no_protocol/model.json index 6803eb6e8..3dcfd96ad 100644 --- a/gems/smithy/spec/fixtures/no_protocol/model.json +++ b/gems/smithy/spec/fixtures/no_protocol/model.json @@ -3,6 +3,406 @@ "shapes": { "smithy.ruby.tests#NoProtocolService": { "type": "service" + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/no_service/model.json b/gems/smithy/spec/fixtures/no_service/model.json index 46240d48a..30e9b269d 100644 --- a/gems/smithy/spec/fixtures/no_service/model.json +++ b/gems/smithy/spec/fixtures/no_service/model.json @@ -1,4 +1,405 @@ { "smithy": "2.0", - "shapes": {} + "shapes": { + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + } + } } diff --git a/gems/smithy/spec/fixtures/one_service/model.json b/gems/smithy/spec/fixtures/one_service/model.json index 37aa2f545..08cb62164 100644 --- a/gems/smithy/spec/fixtures/one_service/model.json +++ b/gems/smithy/spec/fixtures/one_service/model.json @@ -3,6 +3,406 @@ "shapes": { "smithy.ruby.tests#Service1": { "type": "service" + }, + "smithy.rules#ClientContextParamDefinition": { + "type": "structure", + "members": { + "type": { + "target": "smithy.rules#ShapeType", + "traits": { + "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation string to be generated with the client parameter." + } + } + }, + "traits": { + "smithy.api#documentation": "A client context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointExpectation": { + "type": "structure", + "members": { + "url": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." + } + }, + "headers": { + "target": "smithy.rules#EndpointHeaders", + "traits": { + "smithy.api#documentation": "The transport headers to be set for this test case." + } + }, + "properties": { + "target": "smithy.rules#Properties", + "traits": { + "smithy.api#documentation": "The properties for the endpoint for this test case." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaderValue": { + "type": "list", + "member": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A transport header value." + } + }, + "traits": { + "smithy.api#documentation": "A list of transport header values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointHeaders": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The transport header name." + } + }, + "value": { + "target": "smithy.rules#EndpointHeaderValue", + "traits": { + "smithy.api#documentation": "The transport header values." + } + }, + "traits": { + "smithy.api#documentation": "A map of header names to list of values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTest": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation describing the test case." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." + } + }, + "operationInputs": { + "target": "smithy.rules#OperationInputs", + "traits": { + "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." + } + }, + "expect": { + "target": "smithy.rules#EndpointTestExpectation", + "traits": { + "smithy.api#documentation": "The expected outcome of the test case.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestExpectation": { + "type": "union", + "members": { + "error": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an error." + } + }, + "endpoint": { + "target": "smithy.rules#EndpointExpectation", + "traits": { + "smithy.api#documentation": "A test case expectation resulting in an endpoint." + } + } + }, + "traits": { + "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#EndpointTestList": { + "type": "list", + "member": { + "target": "smithy.rules#EndpointTest" + }, + "traits": { + "smithy.api#documentation": "A list of endpoint rule-set tests.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationContextParamDefinition": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "An operation context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInput": { + "type": "structure", + "members": { + "operationName": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the service operation targeted by the test.", + "smithy.api#required": {} + } + }, + "operationParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." + } + }, + "builtInParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." + } + }, + "clientParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the set of client configuration parameters to be set." + } + } + }, + "traits": { + "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#OperationInputs": { + "type": "list", + "member": { + "target": "smithy.rules#OperationInput", + "traits": { + "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." + } + }, + "traits": { + "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#Properties": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The property name." + } + }, + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The property value." + } + }, + "traits": { + "smithy.api#documentation": "A map of strings to document values.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#ShapeType": { + "type": "enum", + "members": { + "STRING": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy string shape type.", + "smithy.api#enumValue": "string" + } + }, + "BOOLEAN": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Indicates a Smithy boolean shape type.", + "smithy.api#enumValue": "boolean" + } + } + }, + "traits": { + "smithy.api#documentation": "An enum representing supported Smithy shape types.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#StaticContextParamDefinition": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "The value to set the associated rule-set parameter to.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "A static context parameter definition.", + "smithy.api#private": {}, + "smithy.api#unstable": {} + } + }, + "smithy.rules#clientContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#ClientContextParamDefinition", + "traits": { + "smithy.api#documentation": "The client parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#contextParam": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation -[input]-> structure > member" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointRuleSet": { + "type": "document", + "traits": { + "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#endpointTests": { + "type": "structure", + "members": { + "version": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The endpoint tests schema version.", + "smithy.api#required": {} + } + }, + "testCases": { + "target": "smithy.rules#EndpointTestList", + "traits": { + "smithy.api#documentation": "List of endpoint test cases." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#operationContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#OperationContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.rules#staticContextParams": { + "type": "map", + "key": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The rule-set parameter name." + } + }, + "value": { + "target": "smithy.rules#StaticContextParamDefinition", + "traits": { + "smithy.api#documentation": "The static parameter definition." + } + }, + "traits": { + "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } } } } diff --git a/gems/smithy/spec/fixtures/recursive/model.json b/gems/smithy/spec/fixtures/recursive/model.json index b56b8f3fb..90a3dd8d0 100644 --- a/gems/smithy/spec/fixtures/recursive/model.json +++ b/gems/smithy/spec/fixtures/recursive/model.json @@ -1,6 +1,3331 @@ { "smithy": "2.0", + "metadata": { + "validators": [ + { + "configuration": { + "selector": "operation :not(< service)" + }, + "id": "UnboundTestOperation", + "message": "This operation in the Smithy protocol tests is not bound to a service.", + "name": "EmitEachSelector", + "namespaces": [ + "smithy.protocoltests.rpcv2Cbor" + ], + "severity": "WARNING" + } + ] + }, "shapes": { + "smithy.framework#ValidationException": { + "type": "structure", + "members": { + "message": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A summary of the validation failure.", + "smithy.api#required": {} + } + }, + "fieldList": { + "target": "smithy.framework#ValidationExceptionFieldList", + "traits": { + "smithy.api#documentation": "A list of specific failures encountered while validating the input.\nA member can appear in this list more than once if it failed to satisfy multiple constraints." + } + } + }, + "traits": { + "smithy.api#documentation": "A standard error for input validation failures.\nThis should be thrown by services when a member of the input structure\nfalls outside of the modeled or documented constraints.", + "smithy.api#error": "client" + } + }, + "smithy.framework#ValidationExceptionField": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A JSONPointer expression to the structure member whose value failed to satisfy the modeled constraints.", + "smithy.api#required": {} + } + }, + "message": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A detailed description of the validation failure.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Describes one specific validation failure for an input member." + } + }, + "smithy.framework#ValidationExceptionFieldList": { + "type": "list", + "member": { + "target": "smithy.framework#ValidationExceptionField" + } + }, + "smithy.protocols#StringList": { + "type": "list", + "member": { + "target": "smithy.api#String" + }, + "traits": { + "smithy.api#documentation": "A list of String shapes.", + "smithy.api#private": {} + } + }, + "smithy.protocols#rpcv2Cbor": { + "type": "structure", + "members": { + "http": { + "target": "smithy.protocols#StringList", + "traits": { + "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions." + } + }, + "eventStreamHttp": { + "target": "smithy.protocols#StringList", + "traits": { + "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions\nthat are required when using event streams." + } + } + }, + "traits": { + "smithy.api#documentation": "An RPC-based protocol that serializes CBOR payloads.", + "smithy.api#protocolDefinition": { + "traits": [ + "smithy.api#cors", + "smithy.api#endpoint", + "smithy.api#hostLabel", + "smithy.api#httpError" + ] + }, + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#traitValidators": { + "rpcv2Cbor.NoDocuments": { + "selector": "service ~> member :test(> document)", + "message": "This protocol does not support document types" + } + } + } + }, + "smithy.protocoltests.rpcv2Cbor#ClientOptionalDefaults": { + "type": "structure", + "members": { + "member": { + "target": "smithy.api#Integer", + "traits": { + "smithy.api#clientOptional": {}, + "smithy.api#default": 0 + } + } + } + }, + "smithy.protocoltests.rpcv2Cbor#ComplexError": { + "type": "structure", + "members": { + "TopLevel": { + "target": "smithy.api#String" + }, + "Nested": { + "target": "smithy.protocoltests.rpcv2Cbor#ComplexNestedErrorData" + } + }, + "traits": { + "smithy.api#documentation": "This error is thrown when a request is invalid.", + "smithy.api#error": "client", + "smithy.test#httpResponseTests": [ + { + "id": "RpcV2CborComplexError", + "documentation": "Parses a complex error with no message member", + "protocol": "smithy.protocols#rpcv2Cbor", + "params": { + "TopLevel": "Top level", + "Nested": { + "Foo": "bar" + } + }, + "code": 400, + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "body": "v2ZfX3R5cGV4K3NtaXRoeS5wcm90b2NvbHRlc3RzLnJwY3YyQ2JvciNDb21wbGV4RXJyb3JoVG9wTGV2ZWxpVG9wIGxldmVsZk5lc3RlZL9jRm9vY2Jhcv//", + "bodyMediaType": "application/cbor" + }, + { + "id": "RpcV2CborEmptyComplexError", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 400, + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "body": "v2ZfX3R5cGV4K3NtaXRoeS5wcm90b2NvbHRlc3RzLnJwY3YyQ2JvciNDb21wbGV4RXJyb3L/", + "bodyMediaType": "application/cbor" + } + ] + } + }, + "smithy.protocoltests.rpcv2Cbor#ComplexNestedErrorData": { + "type": "structure", + "members": { + "Foo": { + "target": "smithy.api#String" + } + } + }, + "smithy.protocoltests.rpcv2Cbor#Defaults": { + "type": "structure", + "mixins": [ + { + "target": "smithy.protocoltests.rpcv2Cbor#DefaultsMixin" + } + ], + "members": {} + }, + "smithy.protocoltests.rpcv2Cbor#DefaultsMixin": { + "type": "structure", + "members": { + "defaultString": { + "target": "smithy.api#String", + "traits": { + "smithy.api#default": "hi" + } + }, + "defaultBoolean": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#default": true + } + }, + "defaultList": { + "target": "smithy.protocoltests.rpcv2Cbor#TestStringList", + "traits": { + "smithy.api#default": [] + } + }, + "defaultTimestamp": { + "target": "smithy.api#Timestamp", + "traits": { + "smithy.api#default": 0 + } + }, + "defaultBlob": { + "target": "smithy.api#Blob", + "traits": { + "smithy.api#default": "YWJj" + } + }, + "defaultByte": { + "target": "smithy.api#Byte", + "traits": { + "smithy.api#default": 1 + } + }, + "defaultShort": { + "target": "smithy.api#Short", + "traits": { + "smithy.api#default": 1 + } + }, + "defaultInteger": { + "target": "smithy.api#Integer", + "traits": { + "smithy.api#default": 10 + } + }, + "defaultLong": { + "target": "smithy.api#Long", + "traits": { + "smithy.api#default": 100 + } + }, + "defaultFloat": { + "target": "smithy.api#Float", + "traits": { + "smithy.api#default": 1.0 + } + }, + "defaultDouble": { + "target": "smithy.api#Double", + "traits": { + "smithy.api#default": 1.0 + } + }, + "defaultMap": { + "target": "smithy.protocoltests.rpcv2Cbor#TestStringMap", + "traits": { + "smithy.api#default": {} + } + }, + "defaultEnum": { + "target": "smithy.protocoltests.rpcv2Cbor#TestEnum", + "traits": { + "smithy.api#default": "FOO" + } + }, + "defaultIntEnum": { + "target": "smithy.protocoltests.rpcv2Cbor#TestIntEnum", + "traits": { + "smithy.api#default": 1 + } + }, + "emptyString": { + "target": "smithy.api#String", + "traits": { + "smithy.api#default": "" + } + }, + "falseBoolean": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#default": false + } + }, + "emptyBlob": { + "target": "smithy.api#Blob", + "traits": { + "smithy.api#default": "" + } + }, + "zeroByte": { + "target": "smithy.api#Byte", + "traits": { + "smithy.api#default": 0 + } + }, + "zeroShort": { + "target": "smithy.api#Short", + "traits": { + "smithy.api#default": 0 + } + }, + "zeroInteger": { + "target": "smithy.api#Integer", + "traits": { + "smithy.api#default": 0 + } + }, + "zeroLong": { + "target": "smithy.api#Long", + "traits": { + "smithy.api#default": 0 + } + }, + "zeroFloat": { + "target": "smithy.api#Float", + "traits": { + "smithy.api#default": 0.0 + } + }, + "zeroDouble": { + "target": "smithy.api#Double", + "traits": { + "smithy.api#default": 0.0 + } + } + }, + "traits": { + "smithy.api#mixin": {} + } + }, + "smithy.protocoltests.rpcv2Cbor#DenseBooleanMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.api#Boolean" + } + }, + "smithy.protocoltests.rpcv2Cbor#DenseNumberMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.api#Integer" + } + }, + "smithy.protocoltests.rpcv2Cbor#DenseSetMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.protocoltests.shared#StringSet" + } + }, + "smithy.protocoltests.rpcv2Cbor#DenseStringMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.api#String" + } + }, + "smithy.protocoltests.rpcv2Cbor#DenseStructMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.protocoltests.shared#GreetingStruct" + } + }, + "smithy.protocoltests.rpcv2Cbor#EmptyInputOutput": { + "type": "operation", + "input": { + "target": "smithy.protocoltests.rpcv2Cbor#EmptyStructure" + }, + "output": { + "target": "smithy.protocoltests.rpcv2Cbor#EmptyStructure" + }, + "traits": { + "smithy.test#httpRequestTests": [ + { + "id": "empty_input", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "When Input structure is empty we write CBOR equivalent of {}", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "forbidHeaders": [ + "X-Amz-Target" + ], + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/EmptyInputOutput", + "bodyMediaType": "application/cbor", + "body": "v/8=" + }, + { + "id": "empty_input_no_body", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "When Input structure is empty the server should accept an empty body", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Accept": "application/cbor", + "Content-Type": "application/cbor" + }, + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/EmptyInputOutput", + "bodyMediaType": "application/cbor", + "body": "", + "appliesTo": "server" + }, + { + "id": "empty_input_no_body_has_accept", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "When input structure, is empty the server should accept an empty body\neven if the Accept header is set.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Accept": "application/cbor", + "Content-Type": "application/cbor" + }, + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/EmptyInputOutput", + "bodyMediaType": "application/cbor", + "body": "", + "appliesTo": "server" + } + ], + "smithy.test#httpResponseTests": [ + { + "id": "empty_output", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "When output structure is empty we write CBOR equivalent of {}", + "body": "v/8=", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "code": 200 + }, + { + "id": "empty_output_no_body", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "When output structure is empty the client should accept an empty body", + "body": "", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "code": 200, + "appliesTo": "client" + } + ] + } + }, + "smithy.protocoltests.rpcv2Cbor#EmptyStructure": { + "type": "structure", + "members": {} + }, + "smithy.protocoltests.rpcv2Cbor#Float16": { + "type": "operation", + "input": { + "target": "smithy.api#Unit" + }, + "output": { + "target": "smithy.protocoltests.rpcv2Cbor#Float16Output" + }, + "traits": { + "smithy.api#tags": [ + "client-only" + ], + "smithy.test#httpResponseTests": [ + { + "id": "RpcV2CborFloat16Inf", + "documentation": "Ensures that clients can correctly parse float16 +Inf.", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "oWV2YWx1Zfl8AA==", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "value": "Infinity" + }, + "bodyMediaType": "application/cbor", + "appliesTo": "client" + }, + { + "id": "RpcV2CborFloat16NegInf", + "documentation": "Ensures that clients can correctly parse float16 -Inf.", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "oWV2YWx1Zfn8AA==", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "value": "-Infinity" + }, + "bodyMediaType": "application/cbor", + "appliesTo": "client" + }, + { + "id": "RpcV2CborFloat16LSBNaN", + "documentation": "Ensures that clients can correctly parse float16 NaN with high LSB.", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "oWV2YWx1Zfl8AQ==", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "value": "NaN" + }, + "bodyMediaType": "application/cbor", + "appliesTo": "client" + }, + { + "id": "RpcV2CborFloat16MSBNaN", + "documentation": "Ensures that clients can correctly parse float16 NaN with high MSB.", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "oWV2YWx1Zfl+AA==", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "value": "NaN" + }, + "bodyMediaType": "application/cbor", + "appliesTo": "client" + }, + { + "id": "RpcV2CborFloat16Subnormal", + "documentation": "Ensures that clients can correctly parse a subnormal float16.", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "oWV2YWx1ZfkAUA==", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "value": 4.76837158203125E-6 + }, + "bodyMediaType": "application/cbor", + "appliesTo": "client" + } + ] + } + }, + "smithy.protocoltests.rpcv2Cbor#Float16Output": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#Double" + } + } + }, + "smithy.protocoltests.rpcv2Cbor#FractionalSeconds": { + "type": "operation", + "input": { + "target": "smithy.api#Unit" + }, + "output": { + "target": "smithy.protocoltests.rpcv2Cbor#FractionalSecondsOutput" + }, + "traits": { + "smithy.api#tags": [ + "client-only" + ], + "smithy.test#httpResponseTests": [ + { + "id": "RpcV2CborDateTimeWithFractionalSeconds", + "documentation": "Ensures that clients can correctly parse timestamps with fractional seconds", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "v2hkYXRldGltZcH7Qcw32zgPvnf/", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "datetime": 9.46845296123E8 + }, + "bodyMediaType": "application/cbor", + "appliesTo": "client" + } + ] + } + }, + "smithy.protocoltests.rpcv2Cbor#FractionalSecondsOutput": { + "type": "structure", + "members": { + "datetime": { + "target": "smithy.protocoltests.shared#DateTime" + } + } + }, + "smithy.protocoltests.rpcv2Cbor#GreetingWithErrors": { + "type": "operation", + "input": { + "target": "smithy.api#Unit" + }, + "output": { + "target": "smithy.protocoltests.rpcv2Cbor#GreetingWithErrorsOutput" + }, + "errors": [ + { + "target": "smithy.protocoltests.rpcv2Cbor#ComplexError" + }, + { + "target": "smithy.protocoltests.rpcv2Cbor#InvalidGreeting" + } + ], + "traits": { + "smithy.api#documentation": "This operation has three possible return values:\n\n1. A successful response in the form of GreetingWithErrorsOutput\n2. An InvalidGreeting error.\n3. A ComplexError error.\n\nImplementations must be able to successfully take a response and\nproperly deserialize successful and error responses.", + "smithy.api#idempotent": {} + } + }, + "smithy.protocoltests.rpcv2Cbor#GreetingWithErrorsOutput": { + "type": "structure", + "members": { + "greeting": { + "target": "smithy.api#String" + } + } + }, + "smithy.protocoltests.rpcv2Cbor#InvalidGreeting": { + "type": "structure", + "members": { + "Message": { + "target": "smithy.api#String" + } + }, + "traits": { + "smithy.api#documentation": "This error is thrown when an invalid greeting value is provided.", + "smithy.api#error": "client", + "smithy.test#httpResponseTests": [ + { + "id": "RpcV2CborInvalidGreetingError", + "documentation": "Parses simple RpcV2 Cbor errors", + "protocol": "smithy.protocols#rpcv2Cbor", + "params": { + "Message": "Hi" + }, + "code": 400, + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "body": "v2ZfX3R5cGV4LnNtaXRoeS5wcm90b2NvbHRlc3RzLnJwY3YyQ2JvciNJbnZhbGlkR3JlZXRpbmdnTWVzc2FnZWJIaf8=", + "bodyMediaType": "application/cbor" + } + ] + } + }, + "smithy.protocoltests.rpcv2Cbor#NoInputOutput": { + "type": "operation", + "input": { + "target": "smithy.api#Unit" + }, + "output": { + "target": "smithy.api#Unit" + }, + "traits": { + "smithy.test#httpRequestTests": [ + { + "id": "no_input", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Body is empty and no Content-Type header if no input", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Accept": "application/cbor" + }, + "forbidHeaders": [ + "Content-Type", + "X-Amz-Target" + ], + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/NoInputOutput", + "body": "" + }, + { + "id": "NoInputServerAllowsEmptyCbor", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Servers should accept CBOR empty struct if no input.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Accept": "application/cbor", + "Content-Type": "application/cbor" + }, + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/NoInputOutput", + "body": "v/8=", + "appliesTo": "server" + }, + { + "id": "NoInputServerAllowsEmptyBody", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Servers should accept an empty body if there is no input. Additionally,\nthey should not raise an error if the `Accept` header is set.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Accept": "application/cbor", + "Content-Type": "application/cbor" + }, + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/NoInputOutput", + "body": "", + "appliesTo": "server" + } + ], + "smithy.test#httpResponseTests": [ + { + "id": "no_output", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "A `Content-Type` header should not be set if the response body is empty.", + "body": "", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor" + }, + "forbidHeaders": [ + "Content-Type" + ], + "code": 200 + }, + { + "id": "NoOutputClientAllowsEmptyCbor", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Clients should accept a CBOR empty struct if there is no output.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "code": 200, + "bodyMediaType": "application/cbor", + "body": "v/8=", + "appliesTo": "client" + }, + { + "id": "NoOutputClientAllowsEmptyBody", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Clients should accept an empty body if there is no output and\nshould not raise an error if the `Content-Type` header is set.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "code": 200, + "bodyMediaType": "application/cbor", + "body": "", + "appliesTo": "client" + } + ] + } + }, + "smithy.protocoltests.rpcv2Cbor#OperationWithDefaults": { + "type": "operation", + "input": { + "target": "smithy.protocoltests.rpcv2Cbor#OperationWithDefaultsInput" + }, + "output": { + "target": "smithy.protocoltests.rpcv2Cbor#OperationWithDefaultsOutput" + }, + "errors": [ + { + "target": "smithy.framework#ValidationException" + } + ], + "traits": { + "smithy.test#httpRequestTests": [ + { + "id": "RpcV2CborClientPopulatesDefaultValuesInInput", + "documentation": "Client populates default values in input.", + "protocol": "smithy.protocols#rpcv2Cbor", + "appliesTo": "client", + "tags": [ + "defaults" + ], + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/OperationWithDefaults", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "bodyMediaType": "application/cbor", + "body": "v2hkZWZhdWx0c79tZGVmYXVsdFN0cmluZ2JoaW5kZWZhdWx0Qm9vbGVhbvVrZGVmYXVsdExpc3Sf/3BkZWZhdWx0VGltZXN0YW1wwQBrZGVmYXVsdEJsb2JDYWJja2RlZmF1bHRCeXRlAWxkZWZhdWx0U2hvcnQBbmRlZmF1bHRJbnRlZ2VyCmtkZWZhdWx0TG9uZxhkbGRlZmF1bHRGbG9hdPo/gAAAbWRlZmF1bHREb3VibGX6P4AAAGpkZWZhdWx0TWFwv/9rZGVmYXVsdEVudW1jRk9PbmRlZmF1bHRJbnRFbnVtAWtlbXB0eVN0cmluZ2BsZmFsc2VCb29sZWFu9GllbXB0eUJsb2JAaHplcm9CeXRlAGl6ZXJvU2hvcnQAa3plcm9JbnRlZ2VyAGh6ZXJvTG9uZwBpemVyb0Zsb2F0+gAAAABqemVyb0RvdWJsZfoAAAAA//8", + "params": { + "defaults": {} + } + }, + { + "id": "RpcV2CborClientSkipsTopLevelDefaultValuesInInput", + "documentation": "Client skips top level default values in input.", + "appliesTo": "client", + "tags": [ + "defaults" + ], + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/OperationWithDefaults", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "body": "v/8=", + "params": {} + }, + { + "id": "RpcV2CborClientUsesExplicitlyProvidedMemberValuesOverDefaults", + "documentation": "Client uses explicitly provided member values over defaults", + "appliesTo": "client", + "tags": [ + "defaults" + ], + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/OperationWithDefaults", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "body": "v2hkZWZhdWx0c7dtZGVmYXVsdFN0cmluZ2NieWVuZGVmYXVsdEJvb2xlYW71a2RlZmF1bHRMaXN0gWFhcGRlZmF1bHRUaW1lc3RhbXDB+z/wAAAAAAAAa2RlZmF1bHRCbG9iQmhpa2RlZmF1bHRCeXRlAmxkZWZhdWx0U2hvcnQCbmRlZmF1bHRJbnRlZ2VyFGtkZWZhdWx0TG9uZxjIbGRlZmF1bHRGbG9hdPpAAAAAbWRlZmF1bHREb3VibGX7QAAAAAAAAABqZGVmYXVsdE1hcKFkbmFtZWRKYWNra2RlZmF1bHRFbnVtY0JBUm5kZWZhdWx0SW50RW51bQJrZW1wdHlTdHJpbmdjZm9vbGZhbHNlQm9vbGVhbvVpZW1wdHlCbG9iQmhpaHplcm9CeXRlAWl6ZXJvU2hvcnQBa3plcm9JbnRlZ2VyAWh6ZXJvTG9uZwFpemVyb0Zsb2F0+j+AAABqemVyb0RvdWJsZfs/8AAAAAAAAP8=", + "params": { + "defaults": { + "defaultString": "bye", + "defaultBoolean": true, + "defaultList": [ + "a" + ], + "defaultTimestamp": 1, + "defaultBlob": "hi", + "defaultByte": 2, + "defaultShort": 2, + "defaultInteger": 20, + "defaultLong": 200, + "defaultFloat": 2.0, + "defaultDouble": 2.0, + "defaultMap": { + "name": "Jack" + }, + "defaultEnum": "BAR", + "defaultIntEnum": 2, + "emptyString": "foo", + "falseBoolean": true, + "emptyBlob": "hi", + "zeroByte": 1, + "zeroShort": 1, + "zeroInteger": 1, + "zeroLong": 1, + "zeroFloat": 1.0, + "zeroDouble": 1.0 + } + } + }, + { + "id": "RpcV2CborServerPopulatesDefaultsWhenMissingInRequestBody", + "documentation": "Server populates default values when missing in request body.", + "appliesTo": "server", + "tags": [ + "defaults" + ], + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/OperationWithDefaults", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "body": "v2hkZWZhdWx0c6D/", + "params": { + "defaults": { + "defaultString": "hi", + "defaultBoolean": true, + "defaultList": [], + "defaultTimestamp": 0, + "defaultBlob": "abc", + "defaultByte": 1, + "defaultShort": 1, + "defaultInteger": 10, + "defaultLong": 100, + "defaultFloat": 1.0, + "defaultDouble": 1.0, + "defaultMap": {}, + "defaultEnum": "FOO", + "defaultIntEnum": 1, + "emptyString": "", + "falseBoolean": false, + "emptyBlob": "", + "zeroByte": 0, + "zeroShort": 0, + "zeroInteger": 0, + "zeroLong": 0, + "zeroFloat": 0.0, + "zeroDouble": 0.0 + }, + "topLevelDefault": "hi", + "otherTopLevelDefault": 0 + } + }, + { + "id": "RpcV2CborClientUsesExplicitlyProvidedValuesInTopLevel", + "documentation": "Any time a value is provided for a member in the top level of input, it is used, regardless of if its the default.", + "appliesTo": "client", + "tags": [ + "defaults" + ], + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/OperationWithDefaults", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "body": "v290b3BMZXZlbERlZmF1bHRiaGl0b3RoZXJUb3BMZXZlbERlZmF1bHQA/w==", + "params": { + "topLevelDefault": "hi", + "otherTopLevelDefault": 0 + } + }, + { + "id": "RpcV2CborClientIgnoresNonTopLevelDefaultsOnMembersWithClientOptional", + "documentation": "Typically, non top-level members would have defaults filled in, but if they have the clientOptional trait, the defaults should be ignored.", + "appliesTo": "client", + "tags": [ + "defaults" + ], + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/OperationWithDefaults", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "body": "v3ZjbGllbnRPcHRpb25hbERlZmF1bHRzoP8=", + "params": { + "clientOptionalDefaults": {} + } + } + ], + "smithy.test#httpResponseTests": [ + { + "id": "RpcV2CborClientPopulatesDefaultsValuesWhenMissingInResponse", + "documentation": "Client populates default values when missing in response.", + "appliesTo": "client", + "tags": [ + "defaults" + ], + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "body": "v/8=", + "params": { + "defaultString": "hi", + "defaultBoolean": true, + "defaultList": [], + "defaultTimestamp": 0, + "defaultBlob": "abc", + "defaultByte": 1, + "defaultShort": 1, + "defaultInteger": 10, + "defaultLong": 100, + "defaultFloat": 1.0, + "defaultDouble": 1.0, + "defaultMap": {}, + "defaultEnum": "FOO", + "defaultIntEnum": 1, + "emptyString": "", + "falseBoolean": false, + "emptyBlob": "", + "zeroByte": 0, + "zeroShort": 0, + "zeroInteger": 0, + "zeroLong": 0, + "zeroFloat": 0.0, + "zeroDouble": 0.0 + } + }, + { + "id": "RpcV2CborClientIgnoresDefaultValuesIfMemberValuesArePresentInResponse", + "documentation": "Client ignores default values if member values are present in the response.", + "appliesTo": "client", + "tags": [ + "defaults" + ], + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "body": "v21kZWZhdWx0U3RyaW5nY2J5ZW5kZWZhdWx0Qm9vbGVhbvRrZGVmYXVsdExpc3SBYWFwZGVmYXVsdFRpbWVzdGFtcMH7QAAAAAAAAABrZGVmYXVsdEJsb2JCaGlrZGVmYXVsdEJ5dGUCbGRlZmF1bHRTaG9ydAJuZGVmYXVsdEludGVnZXIUa2RlZmF1bHRMb25nGMhsZGVmYXVsdEZsb2F0+kAAAABtZGVmYXVsdERvdWJsZftAAAAAAAAAAGpkZWZhdWx0TWFwoWRuYW1lZEphY2trZGVmYXVsdEVudW1jQkFSbmRlZmF1bHRJbnRFbnVtAmtlbXB0eVN0cmluZ2Nmb29sZmFsc2VCb29sZWFu9WllbXB0eUJsb2JCaGloemVyb0J5dGUBaXplcm9TaG9ydAFremVyb0ludGVnZXIBaHplcm9Mb25nAWl6ZXJvRmxvYXT6P4AAAGp6ZXJvRG91Ymxl+z/wAAAAAAAA/w==", + "params": { + "defaultString": "bye", + "defaultBoolean": false, + "defaultList": [ + "a" + ], + "defaultTimestamp": 2, + "defaultBlob": "hi", + "defaultByte": 2, + "defaultShort": 2, + "defaultInteger": 20, + "defaultLong": 200, + "defaultFloat": 2.0, + "defaultDouble": 2.0, + "defaultMap": { + "name": "Jack" + }, + "defaultEnum": "BAR", + "defaultIntEnum": 2, + "emptyString": "foo", + "falseBoolean": true, + "emptyBlob": "hi", + "zeroByte": 1, + "zeroShort": 1, + "zeroInteger": 1, + "zeroLong": 1, + "zeroFloat": 1.0, + "zeroDouble": 1.0 + } + }, + { + "id": "RpcV2CborServerPopulatesDefaultsInResponseWhenMissingInParams", + "documentation": "Server populates default values in response when missing in params.", + "appliesTo": "server", + "tags": [ + "defaults" + ], + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "body": "v21kZWZhdWx0U3RyaW5nYmhpbmRlZmF1bHRCb29sZWFu9WtkZWZhdWx0TGlzdIBwZGVmYXVsdFRpbWVzdGFtcMH7AAAAAAAAAABrZGVmYXVsdEJsb2JDYWJja2RlZmF1bHRCeXRlAWxkZWZhdWx0U2hvcnQBbmRlZmF1bHRJbnRlZ2VyCmtkZWZhdWx0TG9uZxhkbGRlZmF1bHRGbG9hdPo/gAAAbWRlZmF1bHREb3VibGX7P/AAAAAAAABqZGVmYXVsdE1hcKBrZGVmYXVsdEVudW1jRk9PbmRlZmF1bHRJbnRFbnVtAWtlbXB0eVN0cmluZ2BsZmFsc2VCb29sZWFu9GllbXB0eUJsb2JAaHplcm9CeXRlAGl6ZXJvU2hvcnQAa3plcm9JbnRlZ2VyAGh6ZXJvTG9uZwBpemVyb0Zsb2F0+gAAAABqemVyb0RvdWJsZfsAAAAAAAAAAP8=", + "params": {} + } + ] + } + }, + "smithy.protocoltests.rpcv2Cbor#OperationWithDefaultsInput": { + "type": "structure", + "members": { + "defaults": { + "target": "smithy.protocoltests.rpcv2Cbor#Defaults" + }, + "clientOptionalDefaults": { + "target": "smithy.protocoltests.rpcv2Cbor#ClientOptionalDefaults" + }, + "topLevelDefault": { + "target": "smithy.api#String", + "traits": { + "smithy.api#default": "hi" + } + }, + "otherTopLevelDefault": { + "target": "smithy.api#Integer", + "traits": { + "smithy.api#default": 0 + } + } + }, + "traits": { + "smithy.api#input": {} + } + }, + "smithy.protocoltests.rpcv2Cbor#OperationWithDefaultsOutput": { + "type": "structure", + "mixins": [ + { + "target": "smithy.protocoltests.rpcv2Cbor#DefaultsMixin" + } + ], + "members": {}, + "traits": { + "smithy.api#output": {} + } + }, + "smithy.protocoltests.rpcv2Cbor#OptionalInputOutput": { + "type": "operation", + "input": { + "target": "smithy.protocoltests.rpcv2Cbor#SimpleStructure" + }, + "output": { + "target": "smithy.protocoltests.rpcv2Cbor#SimpleStructure" + }, + "traits": { + "smithy.test#httpRequestTests": [ + { + "id": "optional_input", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "When input is empty we write CBOR equivalent of {}", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "forbidHeaders": [ + "X-Amz-Target" + ], + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/OptionalInputOutput", + "bodyMediaType": "application/cbor", + "body": "v/8=" + } + ], + "smithy.test#httpResponseTests": [ + { + "id": "optional_output", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "When output is empty we write CBOR equivalent of {}", + "body": "v/8=", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "code": 200 + } + ] + } + }, + "smithy.protocoltests.rpcv2Cbor#RecursiveShapes": { + "type": "operation", + "input": { + "target": "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutput" + }, + "output": { + "target": "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutput" + }, + "traits": { + "smithy.test#httpRequestTests": [ + { + "id": "RpcV2CborRecursiveShapes", + "documentation": "Serializes recursive structures", + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/RecursiveShapes", + "body": "v2ZuZXN0ZWS/Y2Zvb2RGb28xZm5lc3RlZL9jYmFyZEJhcjFvcmVjdXJzaXZlTWVtYmVyv2Nmb29kRm9vMmZuZXN0ZWS/Y2JhcmRCYXIy//////8=", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "nested": { + "foo": "Foo1", + "nested": { + "bar": "Bar1", + "recursiveMember": { + "foo": "Foo2", + "nested": { + "bar": "Bar2" + } + } + } + } + } + } + ], + "smithy.test#httpResponseTests": [ + { + "id": "RpcV2CborRecursiveShapes", + "documentation": "Serializes recursive structures", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "v2ZuZXN0ZWS/Y2Zvb2RGb28xZm5lc3RlZL9jYmFyZEJhcjFvcmVjdXJzaXZlTWVtYmVyv2Nmb29kRm9vMmZuZXN0ZWS/Y2JhcmRCYXIy//////8=", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "nested": { + "foo": "Foo1", + "nested": { + "bar": "Bar1", + "recursiveMember": { + "foo": "Foo2", + "nested": { + "bar": "Bar2" + } + } + } + } + } + }, + { + "id": "RpcV2CborRecursiveShapesUsingDefiniteLength", + "documentation": "Deserializes recursive structures encoded using a map with definite length", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "oWZuZXN0ZWSiY2Zvb2RGb28xZm5lc3RlZKJjYmFyZEJhcjFvcmVjdXJzaXZlTWVtYmVyomNmb29kRm9vMmZuZXN0ZWShY2JhcmRCYXIy", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "nested": { + "foo": "Foo1", + "nested": { + "bar": "Bar1", + "recursiveMember": { + "foo": "Foo2", + "nested": { + "bar": "Bar2" + } + } + } + } + }, + "appliesTo": "client" + } + ] + } + }, + "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutput": { + "type": "structure", + "members": { + "nested": { + "target": "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutputNested1" + } + } + }, + "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutputNested1": { + "type": "structure", + "members": { + "foo": { + "target": "smithy.api#String" + }, + "nested": { + "target": "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutputNested2" + } + } + }, + "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutputNested2": { + "type": "structure", + "members": { + "bar": { + "target": "smithy.api#String" + }, + "recursiveMember": { + "target": "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutputNested1" + } + } + }, + "smithy.protocoltests.rpcv2Cbor#RpcV2CborDenseMaps": { + "type": "operation", + "input": { + "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborDenseMapsInputOutput" + }, + "output": { + "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborDenseMapsInputOutput" + }, + "errors": [ + { + "target": "smithy.framework#ValidationException" + } + ], + "traits": { + "smithy.api#documentation": "The example tests basic map serialization.", + "smithy.test#httpRequestTests": [ + { + "id": "RpcV2CborMaps", + "documentation": "Serializes maps", + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/RpcV2CborDenseMaps", + "body": "oW5kZW5zZVN0cnVjdE1hcKJjZm9voWJoaWV0aGVyZWNiYXqhYmhpY2J5ZQ==", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "denseStructMap": { + "foo": { + "hi": "there" + }, + "baz": { + "hi": "bye" + } + } + } + }, + { + "id": "RpcV2CborSerializesZeroValuesInMaps", + "documentation": "Ensure that 0 and false are sent over the wire in all maps and lists", + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/RpcV2CborDenseMaps", + "body": "om5kZW5zZU51bWJlck1hcKFheABvZGVuc2VCb29sZWFuTWFwoWF49A==", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "denseNumberMap": { + "x": 0 + }, + "denseBooleanMap": { + "x": false + } + } + }, + { + "id": "RpcV2CborSerializesDenseSetMap", + "documentation": "A request that contains a dense map of sets.", + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/RpcV2CborDenseMaps", + "body": "oWtkZW5zZVNldE1hcKJheIBheYJhYWFi", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "denseSetMap": { + "x": [], + "y": [ + "a", + "b" + ] + } + } + } + ], + "smithy.test#httpResponseTests": [ + { + "id": "RpcV2CborMaps", + "documentation": "Deserializes maps", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "oW5kZW5zZVN0cnVjdE1hcKJjZm9voWJoaWV0aGVyZWNiYXqhYmhpY2J5ZQ==", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "denseStructMap": { + "foo": { + "hi": "there" + }, + "baz": { + "hi": "bye" + } + } + } + }, + { + "id": "RpcV2CborDeserializesZeroValuesInMaps", + "documentation": "Ensure that 0 and false are sent over the wire in all maps and lists", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "om5kZW5zZU51bWJlck1hcKFheABvZGVuc2VCb29sZWFuTWFwoWF49A==", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "denseNumberMap": { + "x": 0 + }, + "denseBooleanMap": { + "x": false + } + } + }, + { + "id": "RpcV2CborDeserializesDenseSetMap", + "documentation": "A response that contains a dense map of sets", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "oWtkZW5zZVNldE1hcKJheIBheYJhYWFi", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "denseSetMap": { + "x": [], + "y": [ + "a", + "b" + ] + } + } + }, + { + "id": "RpcV2CborDeserializesDenseSetMapAndSkipsNull", + "documentation": "Clients SHOULD tolerate seeing a null value in a dense map, and they SHOULD\ndrop the null key-value pair.", + "protocol": "smithy.protocols#rpcv2Cbor", + "appliesTo": "client", + "code": 200, + "body": "oWtkZW5zZVNldE1hcKNheIBheYJhYWFiYXr2", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "denseSetMap": { + "x": [], + "y": [ + "a", + "b" + ] + } + } + } + ] + } + }, + "smithy.protocoltests.rpcv2Cbor#RpcV2CborDenseMapsInputOutput": { + "type": "structure", + "members": { + "denseStructMap": { + "target": "smithy.protocoltests.rpcv2Cbor#DenseStructMap" + }, + "denseNumberMap": { + "target": "smithy.protocoltests.rpcv2Cbor#DenseNumberMap" + }, + "denseBooleanMap": { + "target": "smithy.protocoltests.rpcv2Cbor#DenseBooleanMap" + }, + "denseStringMap": { + "target": "smithy.protocoltests.rpcv2Cbor#DenseStringMap" + }, + "denseSetMap": { + "target": "smithy.protocoltests.rpcv2Cbor#DenseSetMap" + } + } + }, + "smithy.protocoltests.rpcv2Cbor#RpcV2CborListInputOutput": { + "type": "structure", + "members": { + "stringList": { + "target": "smithy.protocoltests.shared#StringList" + }, + "stringSet": { + "target": "smithy.protocoltests.shared#StringSet" + }, + "integerList": { + "target": "smithy.protocoltests.shared#IntegerList" + }, + "booleanList": { + "target": "smithy.protocoltests.shared#BooleanList" + }, + "timestampList": { + "target": "smithy.protocoltests.shared#TimestampList" + }, + "enumList": { + "target": "smithy.protocoltests.shared#FooEnumList" + }, + "intEnumList": { + "target": "smithy.protocoltests.shared#IntegerEnumList" + }, + "nestedStringList": { + "target": "smithy.protocoltests.shared#NestedStringList" + }, + "structureList": { + "target": "smithy.protocoltests.rpcv2Cbor#StructureList" + }, + "blobList": { + "target": "smithy.protocoltests.shared#BlobList" + } + } + }, + "smithy.protocoltests.rpcv2Cbor#RpcV2CborLists": { + "type": "operation", + "input": { + "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborListInputOutput" + }, + "output": { + "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborListInputOutput" + }, + "errors": [ + { + "target": "smithy.framework#ValidationException" + } + ], + "traits": { + "smithy.api#documentation": "This test case serializes JSON lists for the following cases for both\ninput and output:\n\n1. Normal lists.\n2. Normal sets.\n3. Lists of lists.\n4. Lists of structures.", + "smithy.api#idempotent": {}, + "smithy.test#httpRequestTests": [ + { + "id": "RpcV2CborLists", + "documentation": "Serializes RpcV2 Cbor lists", + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/RpcV2CborLists", + "body": "v2pzdHJpbmdMaXN0gmNmb29jYmFyaXN0cmluZ1NldIJjZm9vY2JhcmtpbnRlZ2VyTGlzdIIBAmtib29sZWFuTGlzdIL19G10aW1lc3RhbXBMaXN0gsH7QdTX+/OAAADB+0HU1/vzgAAAaGVudW1MaXN0gmNGb29hMGtpbnRFbnVtTGlzdIIBAnBuZXN0ZWRTdHJpbmdMaXN0goJjZm9vY2JhcoJjYmF6Y3F1eG1zdHJ1Y3R1cmVMaXN0gqJhYWExYWJhMqJhYWEzYWJhNGhibG9iTGlzdIJDZm9vQ2Jhcv8=", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "stringList": [ + "foo", + "bar" + ], + "stringSet": [ + "foo", + "bar" + ], + "integerList": [ + 1, + 2 + ], + "booleanList": [ + true, + false + ], + "timestampList": [ + 1398796238, + 1398796238 + ], + "enumList": [ + "Foo", + "0" + ], + "intEnumList": [ + 1, + 2 + ], + "nestedStringList": [ + [ + "foo", + "bar" + ], + [ + "baz", + "qux" + ] + ], + "structureList": [ + { + "a": "1", + "b": "2" + }, + { + "a": "3", + "b": "4" + } + ], + "blobList": [ + "foo", + "bar" + ] + } + }, + { + "id": "RpcV2CborListsEmpty", + "documentation": "Serializes empty JSON lists", + "tags": [ + "client-indefinite" + ], + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/RpcV2CborLists", + "body": "v2pzdHJpbmdMaXN0n///", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "stringList": [] + } + }, + { + "id": "RpcV2CborListsEmptyUsingDefiniteLength", + "documentation": "Serializes empty JSON definite length lists", + "tags": [ + "client-definite" + ], + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/RpcV2CborLists", + "body": "oWpzdHJpbmdMaXN0gA==", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "stringList": [] + } + }, + { + "id": "RpcV2CborIndefiniteStringInsideIndefiniteList", + "documentation": "Can deserialize indefinite length text strings inside an indefinite length list", + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/RpcV2CborLists", + "body": "v2pzdHJpbmdMaXN0n394HUFuIGV4YW1wbGUgaW5kZWZpbml0ZSBzdHJpbmcsdyB3aGljaCB3aWxsIGJlIGNodW5rZWQsbiBvbiBlYWNoIGNvbW1h/394NUFub3RoZXIgZXhhbXBsZSBpbmRlZmluaXRlIHN0cmluZyB3aXRoIG9ubHkgb25lIGNodW5r/3ZUaGlzIGlzIGEgcGxhaW4gc3RyaW5n//8=", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "stringList": [ + "An example indefinite string, which will be chunked, on each comma", + "Another example indefinite string with only one chunk", + "This is a plain string" + ] + }, + "appliesTo": "server" + }, + { + "id": "RpcV2CborIndefiniteStringInsideDefiniteList", + "documentation": "Can deserialize indefinite length text strings inside a definite length list", + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/RpcV2CborLists", + "body": "oWpzdHJpbmdMaXN0g394HUFuIGV4YW1wbGUgaW5kZWZpbml0ZSBzdHJpbmcsdyB3aGljaCB3aWxsIGJlIGNodW5rZWQsbiBvbiBlYWNoIGNvbW1h/394NUFub3RoZXIgZXhhbXBsZSBpbmRlZmluaXRlIHN0cmluZyB3aXRoIG9ubHkgb25lIGNodW5r/3ZUaGlzIGlzIGEgcGxhaW4gc3RyaW5n", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "stringList": [ + "An example indefinite string, which will be chunked, on each comma", + "Another example indefinite string with only one chunk", + "This is a plain string" + ] + }, + "appliesTo": "server" + } + ], + "smithy.test#httpResponseTests": [ + { + "id": "RpcV2CborLists", + "documentation": "Serializes RpcV2 Cbor lists", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "v2pzdHJpbmdMaXN0n2Nmb29jYmFy/2lzdHJpbmdTZXSfY2Zvb2NiYXL/a2ludGVnZXJMaXN0nwEC/2tib29sZWFuTGlzdJ/19P9tdGltZXN0YW1wTGlzdJ/B+0HU1/vzgAAAwftB1Nf784AAAP9oZW51bUxpc3SfY0Zvb2Ew/2tpbnRFbnVtTGlzdJ8BAv9wbmVzdGVkU3RyaW5nTGlzdJ+fY2Zvb2NiYXL/n2NiYXpjcXV4//9tc3RydWN0dXJlTGlzdJ+/YWFhMWFiYTL/v2FhYTNhYmE0//9oYmxvYkxpc3SfQ2Zvb0NiYXL//w==", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "stringList": [ + "foo", + "bar" + ], + "stringSet": [ + "foo", + "bar" + ], + "integerList": [ + 1, + 2 + ], + "booleanList": [ + true, + false + ], + "timestampList": [ + 1398796238, + 1398796238 + ], + "enumList": [ + "Foo", + "0" + ], + "intEnumList": [ + 1, + 2 + ], + "nestedStringList": [ + [ + "foo", + "bar" + ], + [ + "baz", + "qux" + ] + ], + "structureList": [ + { + "a": "1", + "b": "2" + }, + { + "a": "3", + "b": "4" + } + ], + "blobList": [ + "foo", + "bar" + ] + } + }, + { + "id": "RpcV2CborListsEmpty", + "documentation": "Serializes empty RpcV2 Cbor lists", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "v2pzdHJpbmdMaXN0n///", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "stringList": [] + } + }, + { + "id": "RpcV2CborIndefiniteStringInsideIndefiniteListCanDeserialize", + "documentation": "Can deserialize indefinite length text strings inside an indefinite length list", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "v2pzdHJpbmdMaXN0n394HUFuIGV4YW1wbGUgaW5kZWZpbml0ZSBzdHJpbmcsdyB3aGljaCB3aWxsIGJlIGNodW5rZWQsbiBvbiBlYWNoIGNvbW1h/394NUFub3RoZXIgZXhhbXBsZSBpbmRlZmluaXRlIHN0cmluZyB3aXRoIG9ubHkgb25lIGNodW5r/3ZUaGlzIGlzIGEgcGxhaW4gc3RyaW5n//8=", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "stringList": [ + "An example indefinite string, which will be chunked, on each comma", + "Another example indefinite string with only one chunk", + "This is a plain string" + ] + }, + "appliesTo": "client" + }, + { + "id": "RpcV2CborIndefiniteStringInsideDefiniteListCanDeserialize", + "documentation": "Can deserialize indefinite length text strings inside a definite length list", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "oWpzdHJpbmdMaXN0g394HUFuIGV4YW1wbGUgaW5kZWZpbml0ZSBzdHJpbmcsdyB3aGljaCB3aWxsIGJlIGNodW5rZWQsbiBvbiBlYWNoIGNvbW1h/394NUFub3RoZXIgZXhhbXBsZSBpbmRlZmluaXRlIHN0cmluZyB3aXRoIG9ubHkgb25lIGNodW5r/3ZUaGlzIGlzIGEgcGxhaW4gc3RyaW5n", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "stringList": [ + "An example indefinite string, which will be chunked, on each comma", + "Another example indefinite string with only one chunk", + "This is a plain string" + ] + }, + "appliesTo": "client" + } + ] + } + }, + "smithy.protocoltests.rpcv2Cbor#RpcV2CborSparseMaps": { + "type": "operation", + "input": { + "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborSparseMapsInputOutput" + }, + "output": { + "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborSparseMapsInputOutput" + }, + "errors": [ + { + "target": "smithy.framework#ValidationException" + } + ], + "traits": { + "smithy.test#httpRequestTests": [ + { + "id": "RpcV2CborSparseMaps", + "documentation": "Serializes sparse maps", + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/RpcV2CborSparseMaps", + "body": "v29zcGFyc2VTdHJ1Y3RNYXC/Y2Zvb79iaGlldGhlcmX/Y2Jher9iaGljYnll////", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "sparseStructMap": { + "foo": { + "hi": "there" + }, + "baz": { + "hi": "bye" + } + } + } + }, + { + "id": "RpcV2CborSerializesNullMapValues", + "documentation": "Serializes null map values in sparse maps", + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/RpcV2CborSparseMaps", + "body": "v3BzcGFyc2VCb29sZWFuTWFwv2F49v9vc3BhcnNlTnVtYmVyTWFwv2F49v9vc3BhcnNlU3RyaW5nTWFwv2F49v9vc3BhcnNlU3RydWN0TWFwv2F49v//", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "sparseBooleanMap": { + "x": null + }, + "sparseNumberMap": { + "x": null + }, + "sparseStringMap": { + "x": null + }, + "sparseStructMap": { + "x": null + } + } + }, + { + "id": "RpcV2CborSerializesSparseSetMap", + "documentation": "A request that contains a sparse map of sets", + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/RpcV2CborSparseMaps", + "body": "v2xzcGFyc2VTZXRNYXC/YXif/2F5n2FhYWL///8=", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "sparseSetMap": { + "x": [], + "y": [ + "a", + "b" + ] + } + } + }, + { + "id": "RpcV2CborSerializesSparseSetMapAndRetainsNull", + "documentation": "A request that contains a sparse map of sets.", + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/RpcV2CborSparseMaps", + "body": "v2xzcGFyc2VTZXRNYXC/YXif/2F5n2FhYWL/YXr2//8=", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "sparseSetMap": { + "x": [], + "y": [ + "a", + "b" + ], + "z": null + } + } + }, + { + "id": "RpcV2CborSerializesZeroValuesInSparseMaps", + "documentation": "Ensure that 0 and false are sent over the wire in all maps and lists", + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/RpcV2CborSparseMaps", + "body": "v29zcGFyc2VOdW1iZXJNYXC/YXgA/3BzcGFyc2VCb29sZWFuTWFwv2F49P//", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "sparseNumberMap": { + "x": 0 + }, + "sparseBooleanMap": { + "x": false + } + } + } + ], + "smithy.test#httpResponseTests": [ + { + "id": "RpcV2CborSparseJsonMaps", + "documentation": "Deserializes sparse maps", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "v29zcGFyc2VTdHJ1Y3RNYXC/Y2Zvb79iaGlldGhlcmX/Y2Jher9iaGljYnll////", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "sparseStructMap": { + "foo": { + "hi": "there" + }, + "baz": { + "hi": "bye" + } + } + } + }, + { + "id": "RpcV2CborDeserializesNullMapValues", + "documentation": "Deserializes null map values", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "v3BzcGFyc2VCb29sZWFuTWFwv2F49v9vc3BhcnNlTnVtYmVyTWFwv2F49v9vc3BhcnNlU3RyaW5nTWFwv2F49v9vc3BhcnNlU3RydWN0TWFwv2F49v//", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "sparseBooleanMap": { + "x": null + }, + "sparseNumberMap": { + "x": null + }, + "sparseStringMap": { + "x": null + }, + "sparseStructMap": { + "x": null + } + } + }, + { + "id": "RpcV2CborDeserializesSparseSetMap", + "documentation": "A response that contains a sparse map of sets", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "v2xzcGFyc2VTZXRNYXC/YXmfYWFhYv9heJ////8=", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "sparseSetMap": { + "x": [], + "y": [ + "a", + "b" + ] + } + } + }, + { + "id": "RpcV2CborDeserializesSparseSetMapAndRetainsNull", + "documentation": "A response that contains a sparse map of sets with a null", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "v2xzcGFyc2VTZXRNYXC/YXif/2F5n2FhYWL/YXr2//8=", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "sparseSetMap": { + "x": [], + "y": [ + "a", + "b" + ], + "z": null + } + } + }, + { + "id": "RpcV2CborDeserializesZeroValuesInSparseMaps", + "documentation": "Ensure that 0 and false are sent over the wire in all maps and lists", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "v29zcGFyc2VOdW1iZXJNYXC/YXgA/3BzcGFyc2VCb29sZWFuTWFwv2F49P//", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "sparseNumberMap": { + "x": 0 + }, + "sparseBooleanMap": { + "x": false + } + } + } + ] + } + }, + "smithy.protocoltests.rpcv2Cbor#RpcV2CborSparseMapsInputOutput": { + "type": "structure", + "members": { + "sparseStructMap": { + "target": "smithy.protocoltests.rpcv2Cbor#SparseStructMap" + }, + "sparseNumberMap": { + "target": "smithy.protocoltests.rpcv2Cbor#SparseNumberMap" + }, + "sparseBooleanMap": { + "target": "smithy.protocoltests.rpcv2Cbor#SparseBooleanMap" + }, + "sparseStringMap": { + "target": "smithy.protocoltests.shared#SparseStringMap" + }, + "sparseSetMap": { + "target": "smithy.protocoltests.rpcv2Cbor#SparseSetMap" + } + } + }, + "smithy.protocoltests.rpcv2Cbor#RpcV2Protocol": { + "type": "service", + "version": "2020-07-14", + "operations": [ + { + "target": "smithy.protocoltests.rpcv2Cbor#EmptyInputOutput" + }, + { + "target": "smithy.protocoltests.rpcv2Cbor#Float16" + }, + { + "target": "smithy.protocoltests.rpcv2Cbor#FractionalSeconds" + }, + { + "target": "smithy.protocoltests.rpcv2Cbor#GreetingWithErrors" + }, + { + "target": "smithy.protocoltests.rpcv2Cbor#NoInputOutput" + }, + { + "target": "smithy.protocoltests.rpcv2Cbor#OperationWithDefaults" + }, + { + "target": "smithy.protocoltests.rpcv2Cbor#OptionalInputOutput" + }, + { + "target": "smithy.protocoltests.rpcv2Cbor#RecursiveShapes" + }, + { + "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborDenseMaps" + }, + { + "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborLists" + }, + { + "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborSparseMaps" + }, + { + "target": "smithy.protocoltests.rpcv2Cbor#SimpleScalarProperties" + }, + { + "target": "smithy.protocoltests.rpcv2Cbor#SparseNullsOperation" + } + ], + "traits": { + "smithy.api#title": "RpcV2 Protocol Service", + "smithy.protocols#rpcv2Cbor": {} + } + }, + "smithy.protocoltests.rpcv2Cbor#SimpleScalarProperties": { + "type": "operation", + "input": { + "target": "smithy.protocoltests.rpcv2Cbor#SimpleScalarStructure" + }, + "output": { + "target": "smithy.protocoltests.rpcv2Cbor#SimpleScalarStructure" + }, + "traits": { + "smithy.test#httpRequestTests": [ + { + "id": "RpcV2CborSimpleScalarProperties", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Serializes simple scalar properties", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", + "body": "v2lieXRlVmFsdWUFa2RvdWJsZVZhbHVl+z/+OVgQYk3TcWZhbHNlQm9vbGVhblZhbHVl9GpmbG9hdFZhbHVl+kD0AABsaW50ZWdlclZhbHVlGQEAaWxvbmdWYWx1ZRkmkWpzaG9ydFZhbHVlGSaqa3N0cmluZ1ZhbHVlZnNpbXBsZXB0cnVlQm9vbGVhblZhbHVl9WlibG9iVmFsdWVDZm9v/w==", + "params": { + "byteValue": 5, + "doubleValue": 1.889, + "falseBooleanValue": false, + "floatValue": 7.625, + "integerValue": 256, + "longValue": 9873, + "shortValue": 9898, + "stringValue": "simple", + "trueBooleanValue": true, + "blobValue": "foo" + } + }, + { + "id": "RpcV2CborSimpleScalarPropertiesUsingIndefiniteLength", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "The server should be capable of deserializing simple scalar properties\nencoded using a map with a definite length. The server should also be able to parse\na key encoded using an indefinite length string.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", + "body": "qmlieXRlVmFsdWUFf2Zkb3VibGVlVmFsdWX/+z/+OVgQYk3Tf2VmYWxzZWdCb29sZWFuZVZhbHVl//RqZmxvYXRWYWx1ZfpA9AAAbGludGVnZXJWYWx1ZRkBAGlsb25nVmFsdWUZJpFqc2hvcnRWYWx1ZRkmqn9mc3RyaW5nZVZhbHVl/2ZzaW1wbGVwdHJ1ZUJvb2xlYW5WYWx1ZfVpYmxvYlZhbHVlQ2Zvbw==", + "params": { + "byteValue": 5, + "doubleValue": 1.889, + "falseBooleanValue": false, + "floatValue": 7.625, + "integerValue": 256, + "longValue": 9873, + "shortValue": 9898, + "stringValue": "simple", + "trueBooleanValue": true, + "blobValue": "foo" + }, + "appliesTo": "server" + }, + { + "id": "RpcV2CborClientDoesntSerializeNullStructureValues", + "documentation": "RpcV2 Cbor should not serialize null structure values", + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", + "body": "v/8=", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": { + "stringValue": null + }, + "appliesTo": "client" + }, + { + "id": "RpcV2CborServerDoesntDeSerializeNullStructureValues", + "documentation": "RpcV2 Cbor should not deserialize null structure values", + "protocol": "smithy.protocols#rpcv2Cbor", + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", + "body": "v2tzdHJpbmdWYWx1Zfb/", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "params": {}, + "appliesTo": "server" + }, + { + "id": "RpcV2CborSupportsNaNFloatInputs", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Supports handling NaN float values.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", + "body": "v2tkb3VibGVWYWx1Zft/+AAAAAAAAGpmbG9hdFZhbHVl+n/AAAD/", + "params": { + "doubleValue": "NaN", + "floatValue": "NaN" + } + }, + { + "id": "RpcV2CborSupportsInfinityFloatInputs", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Supports handling Infinity float values.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", + "body": "v2tkb3VibGVWYWx1Zft/8AAAAAAAAGpmbG9hdFZhbHVl+n+AAAD/", + "params": { + "doubleValue": "Infinity", + "floatValue": "Infinity" + } + }, + { + "id": "RpcV2CborSupportsNegativeInfinityFloatInputs", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Supports handling Infinity float values.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", + "body": "v2tkb3VibGVWYWx1Zfv/8AAAAAAAAGpmbG9hdFZhbHVl+v+AAAD/", + "params": { + "doubleValue": "-Infinity", + "floatValue": "-Infinity" + } + }, + { + "id": "RpcV2CborIndefiniteLengthStringsCanBeDeserialized", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "The server should be capable of deserializing indefinite length text strings.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", + "body": "oWtzdHJpbmdWYWx1ZX94HUFuIGV4YW1wbGUgaW5kZWZpbml0ZSBzdHJpbmcscSBjaHVua2VkIG9uIGNvbW1h/w==", + "params": { + "stringValue": "An example indefinite string, chunked on comma" + }, + "appliesTo": "server" + }, + { + "id": "RpcV2CborIndefiniteLengthByteStringsCanBeDeserialized", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "The server should be capable of deserializing indefinite length byte strings.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", + "body": "oWlibG9iVmFsdWVfWCJBbiBleGFtcGxlIGluZGVmaW5pdGUtYnl0ZSBzdHJpbmcsUSBjaHVua2VkIG9uIGNvbW1h/w==", + "params": { + "blobValue": "An example indefinite-byte string, chunked on comma" + }, + "appliesTo": "server" + }, + { + "id": "RpcV2CborSupportsUpcastingData", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Supports upcasting from a smaller byte representation of the same data type.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", + "body": "v2tkb3VibGVWYWx1Zfk+AGpmbG9hdFZhbHVl+UegbGludGVnZXJWYWx1ZRg4aWxvbmdWYWx1ZRkBAGpzaG9ydFZhbHVlCv8=", + "params": { + "doubleValue": 1.5, + "floatValue": 7.625, + "integerValue": 56, + "longValue": 256, + "shortValue": 10 + }, + "appliesTo": "server" + }, + { + "id": "RpcV2CborExtraFieldsInTheBodyShouldBeSkippedByServers", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "The server should skip over additional fields that are not part of the structure. This allows a\nclient generated against a newer Smithy model to be able to communicate with a server that is\ngenerated against an older Smithy model.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", + "body": "v2lieXRlVmFsdWUFa2RvdWJsZVZhbHVl+z/+OVgQYk3TcWZhbHNlQm9vbGVhblZhbHVl9GpmbG9hdFZhbHVl+kD0AABrZXh0cmFPYmplY3S/c2luZGVmaW5pdGVMZW5ndGhNYXC/a3dpdGhBbkFycmF5nwECA///cWRlZmluaXRlTGVuZ3RoTWFwo3J3aXRoQURlZmluaXRlQXJyYXmDAQIDeB1hbmRTb21lSW5kZWZpbml0ZUxlbmd0aFN0cmluZ3gfdGhhdCBoYXMsIGJlZW4gY2h1bmtlZCBvbiBjb21tYWxub3JtYWxTdHJpbmdjZm9vanNob3J0VmFsdWUZJw9uc29tZU90aGVyRmllbGR2dGhpcyBzaG91bGQgYmUgc2tpcHBlZP9saW50ZWdlclZhbHVlGQEAaWxvbmdWYWx1ZRkmkWpzaG9ydFZhbHVlGSaqa3N0cmluZ1ZhbHVlZnNpbXBsZXB0cnVlQm9vbGVhblZhbHVl9WlibG9iVmFsdWVDZm9v/w==", + "params": { + "byteValue": 5, + "doubleValue": 1.889, + "falseBooleanValue": false, + "floatValue": 7.625, + "integerValue": 256, + "longValue": 9873, + "shortValue": 9898, + "stringValue": "simple", + "trueBooleanValue": true, + "blobValue": "foo" + }, + "appliesTo": "server" + }, + { + "id": "RpcV2CborServersShouldHandleNoAcceptHeader", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Servers should tolerate requests without an Accept header set.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "method": "POST", + "bodyMediaType": "application/cbor", + "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", + "body": "v2lieXRlVmFsdWUFa2RvdWJsZVZhbHVl+z/+OVgQYk3TcWZhbHNlQm9vbGVhblZhbHVl9GpmbG9hdFZhbHVl+kD0AABsaW50ZWdlclZhbHVlGQEAaWxvbmdWYWx1ZRkmkWpzaG9ydFZhbHVlGSaqa3N0cmluZ1ZhbHVlZnNpbXBsZXB0cnVlQm9vbGVhblZhbHVl9WlibG9iVmFsdWVDZm9v/w==", + "params": { + "byteValue": 5, + "doubleValue": 1.889, + "falseBooleanValue": false, + "floatValue": 7.625, + "integerValue": 256, + "longValue": 9873, + "shortValue": 9898, + "stringValue": "simple", + "trueBooleanValue": true, + "blobValue": "foo" + }, + "appliesTo": "server" + } + ], + "smithy.test#httpResponseTests": [ + { + "id": "RpcV2CborSimpleScalarProperties", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Serializes simple scalar properties", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "bodyMediaType": "application/cbor", + "body": "v3B0cnVlQm9vbGVhblZhbHVl9XFmYWxzZUJvb2xlYW5WYWx1ZfRpYnl0ZVZhbHVlBWtkb3VibGVWYWx1Zfs//jlYEGJN02pmbG9hdFZhbHVl+kD0AABsaW50ZWdlclZhbHVlGQEAanNob3J0VmFsdWUZJqprc3RyaW5nVmFsdWVmc2ltcGxlaWJsb2JWYWx1ZUNmb2//", + "code": 200, + "params": { + "trueBooleanValue": true, + "falseBooleanValue": false, + "byteValue": 5, + "doubleValue": 1.889, + "floatValue": 7.625, + "integerValue": 256, + "shortValue": 9898, + "stringValue": "simple", + "blobValue": "foo" + } + }, + { + "id": "RpcV2CborSimpleScalarPropertiesUsingDefiniteLength", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Deserializes simple scalar properties encoded using a map with definite length", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "bodyMediaType": "application/cbor", + "body": "qXB0cnVlQm9vbGVhblZhbHVl9XFmYWxzZUJvb2xlYW5WYWx1ZfRpYnl0ZVZhbHVlBWtkb3VibGVWYWx1Zfs//jlYEGJN02pmbG9hdFZhbHVl+kD0AABsaW50ZWdlclZhbHVlGQEAanNob3J0VmFsdWUZJqprc3RyaW5nVmFsdWVmc2ltcGxlaWJsb2JWYWx1ZUNmb28=", + "code": 200, + "params": { + "trueBooleanValue": true, + "falseBooleanValue": false, + "byteValue": 5, + "doubleValue": 1.889, + "floatValue": 7.625, + "integerValue": 256, + "shortValue": 9898, + "stringValue": "simple", + "blobValue": "foo" + }, + "appliesTo": "client" + }, + { + "id": "RpcV2CborClientDoesntDeserializeNullStructureValues", + "documentation": "RpcV2 Cbor should not deserialize null structure values", + "protocol": "smithy.protocols#rpcv2Cbor", + "body": "v2tzdHJpbmdWYWx1Zfb/", + "code": 200, + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": {}, + "appliesTo": "client" + }, + { + "id": "RpcV2CborServerDoesntSerializeNullStructureValues", + "documentation": "RpcV2 Cbor should not serialize null structure values", + "protocol": "smithy.protocols#rpcv2Cbor", + "body": "v/8=", + "code": 200, + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "stringValue": null + }, + "appliesTo": "server" + }, + { + "id": "RpcV2CborSupportsNaNFloatOutputs", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Supports handling NaN float values.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "code": 200, + "bodyMediaType": "application/cbor", + "body": "v2tkb3VibGVWYWx1Zft/+AAAAAAAAGpmbG9hdFZhbHVl+n/AAAD/", + "params": { + "doubleValue": "NaN", + "floatValue": "NaN" + } + }, + { + "id": "RpcV2CborSupportsInfinityFloatOutputs", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Supports handling Infinity float values.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "code": 200, + "bodyMediaType": "application/cbor", + "body": "v2tkb3VibGVWYWx1Zft/8AAAAAAAAGpmbG9hdFZhbHVl+n+AAAD/", + "params": { + "doubleValue": "Infinity", + "floatValue": "Infinity" + } + }, + { + "id": "RpcV2CborSupportsNegativeInfinityFloatOutputs", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Supports handling Negative Infinity float values.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "code": 200, + "bodyMediaType": "application/cbor", + "body": "v2tkb3VibGVWYWx1Zfv/8AAAAAAAAGpmbG9hdFZhbHVl+v+AAAD/", + "params": { + "doubleValue": "-Infinity", + "floatValue": "-Infinity" + } + }, + { + "id": "RpcV2CborSupportsUpcastingDataOnDeserialize", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "Supports upcasting from a smaller byte representation of the same data type.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "code": 200, + "bodyMediaType": "application/cbor", + "body": "v2tkb3VibGVWYWx1Zfk+AGpmbG9hdFZhbHVl+UegbGludGVnZXJWYWx1ZRg4aWxvbmdWYWx1ZRkBAGpzaG9ydFZhbHVlCv8=", + "params": { + "doubleValue": 1.5, + "floatValue": 7.625, + "integerValue": 56, + "longValue": 256, + "shortValue": 10 + }, + "appliesTo": "client" + }, + { + "id": "RpcV2CborExtraFieldsInTheBodyShouldBeSkippedByClients", + "protocol": "smithy.protocols#rpcv2Cbor", + "documentation": "The client should skip over additional fields that are not part of the structure. This allows a\nclient generated against an older Smithy model to be able to communicate with a server that is\ngenerated against a newer Smithy model.", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "code": 200, + "bodyMediaType": "application/cbor", + "body": "v2lieXRlVmFsdWUFa2RvdWJsZVZhbHVl+z/+OVgQYk3TcWZhbHNlQm9vbGVhblZhbHVl9GpmbG9hdFZhbHVl+kD0AABrZXh0cmFPYmplY3S/c2luZGVmaW5pdGVMZW5ndGhNYXC/a3dpdGhBbkFycmF5nwECA///cWRlZmluaXRlTGVuZ3RoTWFwo3J3aXRoQURlZmluaXRlQXJyYXmDAQIDeB1hbmRTb21lSW5kZWZpbml0ZUxlbmd0aFN0cmluZ3gfdGhhdCBoYXMsIGJlZW4gY2h1bmtlZCBvbiBjb21tYWxub3JtYWxTdHJpbmdjZm9vanNob3J0VmFsdWUZJw9uc29tZU90aGVyRmllbGR2dGhpcyBzaG91bGQgYmUgc2tpcHBlZP9saW50ZWdlclZhbHVlGQEAaWxvbmdWYWx1ZRkmkWpzaG9ydFZhbHVlGSaqa3N0cmluZ1ZhbHVlZnNpbXBsZXB0cnVlQm9vbGVhblZhbHVl9WlibG9iVmFsdWVDZm9v/w==", + "params": { + "byteValue": 5, + "doubleValue": 1.889, + "falseBooleanValue": false, + "floatValue": 7.625, + "integerValue": 256, + "longValue": 9873, + "shortValue": 9898, + "stringValue": "simple", + "trueBooleanValue": true, + "blobValue": "foo" + }, + "appliesTo": "client" + } + ] + } + }, + "smithy.protocoltests.rpcv2Cbor#SimpleScalarStructure": { + "type": "structure", + "members": { + "trueBooleanValue": { + "target": "smithy.api#Boolean" + }, + "falseBooleanValue": { + "target": "smithy.api#Boolean" + }, + "byteValue": { + "target": "smithy.api#Byte" + }, + "doubleValue": { + "target": "smithy.api#Double" + }, + "floatValue": { + "target": "smithy.api#Float" + }, + "integerValue": { + "target": "smithy.api#Integer" + }, + "longValue": { + "target": "smithy.api#Long" + }, + "shortValue": { + "target": "smithy.api#Short" + }, + "stringValue": { + "target": "smithy.api#String" + }, + "blobValue": { + "target": "smithy.api#Blob" + } + } + }, + "smithy.protocoltests.rpcv2Cbor#SimpleStructure": { + "type": "structure", + "members": { + "value": { + "target": "smithy.api#String" + } + } + }, + "smithy.protocoltests.rpcv2Cbor#SparseBooleanMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.api#Boolean" + }, + "traits": { + "smithy.api#sparse": {} + } + }, + "smithy.protocoltests.rpcv2Cbor#SparseNullsOperation": { + "type": "operation", + "input": { + "target": "smithy.protocoltests.rpcv2Cbor#SparseNullsOperationInputOutput" + }, + "output": { + "target": "smithy.protocoltests.rpcv2Cbor#SparseNullsOperationInputOutput" + }, + "traits": { + "smithy.test#httpRequestTests": [ + { + "id": "RpcV2CborSparseMapsSerializeNullValues", + "documentation": "Serializes null values in maps", + "protocol": "smithy.protocols#rpcv2Cbor", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "body": "v29zcGFyc2VTdHJpbmdNYXC/Y2Zvb/b//w==", + "params": { + "sparseStringMap": { + "foo": null + } + }, + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/SparseNullsOperation" + }, + { + "id": "RpcV2CborSparseListsSerializeNull", + "documentation": "Serializes null values in lists", + "protocol": "smithy.protocols#rpcv2Cbor", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor", + "Accept": "application/cbor" + }, + "requireHeaders": [ + "Content-Length" + ], + "body": "v3BzcGFyc2VTdHJpbmdMaXN0n/b//w==", + "params": { + "sparseStringList": [ + null + ] + }, + "method": "POST", + "uri": "/service/RpcV2Protocol/operation/SparseNullsOperation" + } + ], + "smithy.test#httpResponseTests": [ + { + "id": "RpcV2CborSparseMapsDeserializeNullValues", + "documentation": "Deserializes null values in maps", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "v29zcGFyc2VTdHJpbmdNYXC/Y2Zvb/b//w==", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "sparseStringMap": { + "foo": null + } + } + }, + { + "id": "RpcV2CborSparseListsDeserializeNull", + "documentation": "Deserializes null values in lists", + "protocol": "smithy.protocols#rpcv2Cbor", + "code": 200, + "body": "v3BzcGFyc2VTdHJpbmdMaXN0n/b//w==", + "bodyMediaType": "application/cbor", + "headers": { + "smithy-protocol": "rpc-v2-cbor", + "Content-Type": "application/cbor" + }, + "params": { + "sparseStringList": [ + null + ] + } + } + ] + } + }, + "smithy.protocoltests.rpcv2Cbor#SparseNullsOperationInputOutput": { + "type": "structure", + "members": { + "sparseStringList": { + "target": "smithy.protocoltests.shared#SparseStringList" + }, + "sparseStringMap": { + "target": "smithy.protocoltests.shared#SparseStringMap" + } + } + }, + "smithy.protocoltests.rpcv2Cbor#SparseNumberMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.api#Integer" + }, + "traits": { + "smithy.api#sparse": {} + } + }, + "smithy.protocoltests.rpcv2Cbor#SparseSetMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.protocoltests.shared#StringSet" + }, + "traits": { + "smithy.api#sparse": {} + } + }, + "smithy.protocoltests.rpcv2Cbor#SparseStructMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.protocoltests.shared#GreetingStruct" + }, + "traits": { + "smithy.api#sparse": {} + } + }, + "smithy.protocoltests.rpcv2Cbor#StructureList": { + "type": "list", + "member": { + "target": "smithy.protocoltests.rpcv2Cbor#StructureListMember" + } + }, + "smithy.protocoltests.rpcv2Cbor#StructureListMember": { + "type": "structure", + "members": { + "a": { + "target": "smithy.api#String" + }, + "b": { + "target": "smithy.api#String" + } + } + }, + "smithy.protocoltests.rpcv2Cbor#TestEnum": { + "type": "enum", + "members": { + "FOO": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": "FOO" + } + }, + "BAR": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": "BAR" + } + }, + "BAZ": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": "BAZ" + } + } + } + }, + "smithy.protocoltests.rpcv2Cbor#TestIntEnum": { + "type": "intEnum", + "members": { + "ONE": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": 1 + } + }, + "TWO": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": 2 + } + } + } + }, + "smithy.protocoltests.rpcv2Cbor#TestStringList": { + "type": "list", + "member": { + "target": "smithy.api#String" + } + }, + "smithy.protocoltests.rpcv2Cbor#TestStringMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.api#String" + } + }, + "smithy.protocoltests.shared#BlobList": { + "type": "list", + "member": { + "target": "smithy.api#Blob" + } + }, + "smithy.protocoltests.shared#BlobSet": { + "type": "list", + "member": { + "target": "smithy.api#Blob" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#BooleanList": { + "type": "list", + "member": { + "target": "smithy.api#Boolean" + } + }, + "smithy.protocoltests.shared#BooleanSet": { + "type": "list", + "member": { + "target": "smithy.api#Boolean" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#ByteList": { + "type": "list", + "member": { + "target": "smithy.api#Byte" + } + }, + "smithy.protocoltests.shared#ByteSet": { + "type": "list", + "member": { + "target": "smithy.api#Byte" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#DateTime": { + "type": "timestamp", + "traits": { + "smithy.api#timestampFormat": "date-time" + } + }, + "smithy.protocoltests.shared#DateTimeList": { + "type": "list", + "member": { + "target": "smithy.protocoltests.shared#DateTime" + } + }, + "smithy.protocoltests.shared#DateTimeSet": { + "type": "list", + "member": { + "target": "smithy.protocoltests.shared#DateTime" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#DoubleList": { + "type": "list", + "member": { + "target": "smithy.api#Double" + } + }, + "smithy.protocoltests.shared#EpochSeconds": { + "type": "timestamp", + "traits": { + "smithy.api#timestampFormat": "epoch-seconds" + } + }, + "smithy.protocoltests.shared#FloatList": { + "type": "list", + "member": { + "target": "smithy.api#Float" + } + }, + "smithy.protocoltests.shared#FooEnum": { + "type": "enum", + "members": { + "FOO": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": "Foo" + } + }, + "BAZ": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": "Baz" + } + }, + "BAR": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": "Bar" + } + }, + "ONE": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": "1" + } + }, + "ZERO": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": "0" + } + } + } + }, + "smithy.protocoltests.shared#FooEnumList": { + "type": "list", + "member": { + "target": "smithy.protocoltests.shared#FooEnum" + } + }, + "smithy.protocoltests.shared#FooEnumMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.protocoltests.shared#FooEnum" + } + }, + "smithy.protocoltests.shared#FooEnumSet": { + "type": "list", + "member": { + "target": "smithy.protocoltests.shared#FooEnum" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#FooUnion": { + "type": "union", + "members": { + "string": { + "target": "smithy.api#String" + }, + "integer": { + "target": "smithy.api#Integer" + } + } + }, + "smithy.protocoltests.shared#GreetingList": { + "type": "list", + "member": { + "target": "smithy.protocoltests.shared#GreetingStruct" + } + }, + "smithy.protocoltests.shared#GreetingStruct": { + "type": "structure", + "members": { + "hi": { + "target": "smithy.api#String" + } + } + }, + "smithy.protocoltests.shared#HttpDate": { + "type": "timestamp", + "traits": { + "smithy.api#timestampFormat": "http-date" + } + }, + "smithy.protocoltests.shared#HttpDateSet": { + "type": "list", + "member": { + "target": "smithy.protocoltests.shared#HttpDate" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#IntegerEnum": { + "type": "intEnum", + "members": { + "A": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": 1 + } + }, + "B": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": 2 + } + }, + "C": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#enumValue": 3 + } + } + } + }, + "smithy.protocoltests.shared#IntegerEnumList": { + "type": "list", + "member": { + "target": "smithy.protocoltests.shared#IntegerEnum" + } + }, + "smithy.protocoltests.shared#IntegerEnumMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.protocoltests.shared#IntegerEnum" + } + }, + "smithy.protocoltests.shared#IntegerEnumSet": { + "type": "list", + "member": { + "target": "smithy.protocoltests.shared#IntegerEnum" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#IntegerList": { + "type": "list", + "member": { + "target": "smithy.api#Integer" + } + }, + "smithy.protocoltests.shared#IntegerSet": { + "type": "list", + "member": { + "target": "smithy.api#Integer" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#JpegBlob": { + "type": "blob", + "traits": { + "smithy.api#mediaType": "image/jpeg" + } + }, + "smithy.protocoltests.shared#ListSet": { + "type": "list", + "member": { + "target": "smithy.protocoltests.shared#StringList" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#LongList": { + "type": "list", + "member": { + "target": "smithy.api#Long" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#LongSet": { + "type": "list", + "member": { + "target": "smithy.api#Long" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#NestedStringList": { + "type": "list", + "member": { + "target": "smithy.protocoltests.shared#StringList" + }, + "traits": { + "smithy.api#documentation": "A list of lists of strings." + } + }, + "smithy.protocoltests.shared#ShortList": { + "type": "list", + "member": { + "target": "smithy.api#Short" + } + }, + "smithy.protocoltests.shared#ShortSet": { + "type": "list", + "member": { + "target": "smithy.api#Short" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#SparseStringList": { + "type": "list", + "member": { + "target": "smithy.api#String" + }, + "traits": { + "smithy.api#sparse": {} + } + }, + "smithy.protocoltests.shared#SparseStringMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.api#String" + }, + "traits": { + "smithy.api#sparse": {} + } + }, + "smithy.protocoltests.shared#StringList": { + "type": "list", + "member": { + "target": "smithy.api#String" + } + }, + "smithy.protocoltests.shared#StringListMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.protocoltests.shared#StringList" + } + }, + "smithy.protocoltests.shared#StringMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.api#String" + } + }, + "smithy.protocoltests.shared#StringSet": { + "type": "list", + "member": { + "target": "smithy.api#String" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#StructureSet": { + "type": "list", + "member": { + "target": "smithy.protocoltests.shared#GreetingStruct" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#TextPlainBlob": { + "type": "blob", + "traits": { + "smithy.api#mediaType": "text/plain" + } + }, + "smithy.protocoltests.shared#TimestampList": { + "type": "list", + "member": { + "target": "smithy.api#Timestamp" + } + }, + "smithy.protocoltests.shared#TimestampSet": { + "type": "list", + "member": { + "target": "smithy.api#Timestamp" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, + "smithy.protocoltests.shared#UnionSet": { + "type": "list", + "member": { + "target": "smithy.protocoltests.shared#FooUnion" + }, + "traits": { + "smithy.api#uniqueItems": {} + } + }, "smithy.ruby.tests#Operation": { "type": "operation", "input": { @@ -26,6 +3351,588 @@ "target": "smithy.ruby.tests#Structure" } } + }, + "smithy.test#AppliesTo": { + "type": "enum", + "members": { + "CLIENT": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The test only applies to client implementations.", + "smithy.api#enumValue": "client" + } + }, + "SERVER": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The test only applies to server implementations.", + "smithy.api#enumValue": "server" + } + } + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.test#HttpMalformedRequestDefinition": { + "type": "structure", + "members": { + "method": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The HTTP request method.", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#required": {} + } + }, + "uri": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The request-target of the HTTP request, not including\nthe query string (for example, \"/foo/bar\").", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#required": {} + } + }, + "host": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The host / endpoint provided to the client, not including the path\nor scheme (for example, \"example.com\")." + } + }, + "queryParams": { + "target": "smithy.test#StringList", + "traits": { + "smithy.api#documentation": "A list of the serialized query string parameters to include in the request.\n\nEach element in the list is a query string key value pair\nthat starts with the query string parameter name optionally\nfollowed by \"=\", optionally followed by the query string\nparameter value. For example, \"foo=bar\", \"foo=\", and \"foo\"\nare all valid values. The query string parameter name and\nthe value MUST appear in the format in which it is expected\nto be sent over the wire; if a key or value needs to be\npercent-encoded, then it MUST appear percent-encoded in this list." + } + }, + "headers": { + "target": "smithy.test#StringMap", + "traits": { + "smithy.api#documentation": "Defines a map of HTTP headers to include in the request" + } + }, + "body": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The HTTP message body to include in the request" + } + }, + "bodyMediaType": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The media type of the `body`.\n\nThis is used to help test runners to parse and validate the expected\ndata against generated data." + } + } + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.test#HttpMalformedRequestTestCase": { + "type": "structure", + "members": { + "id": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The identifier of the test case. This identifier can be used by\nprotocol test implementations to filter out unsupported test\ncases by ID, to generate test case names, etc. The provided `id`\nMUST match Smithy's `identifier` ABNF. No two `httpMalformedRequestTests`\ntest cases can share the same ID.", + "smithy.api#pattern": "^[A-Za-z_][A-Za-z0-9_]+$", + "smithy.api#required": {} + } + }, + "protocol": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the protocol to test.", + "smithy.api#idRef": { + "selector": "[trait|protocolDefinition]", + "failWhenMissing": true + }, + "smithy.api#required": {} + } + }, + "request": { + "target": "smithy.test#HttpMalformedRequestDefinition", + "traits": { + "smithy.api#documentation": "The malformed request to send.", + "smithy.api#required": {} + } + }, + "response": { + "target": "smithy.test#HttpMalformedResponseDefinition", + "traits": { + "smithy.api#documentation": "The expected response.", + "smithy.api#required": {} + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A description of the test and what is being asserted." + } + }, + "tags": { + "target": "smithy.test#NonEmptyStringList", + "traits": { + "smithy.api#documentation": "Applies a list of tags to the test." + } + }, + "testParameters": { + "target": "smithy.test#HttpMalformedRequestTestParametersDefinition", + "traits": { + "smithy.api#documentation": "An optional set of test parameters for parameterized testing." + } + } + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.test#HttpMalformedRequestTestParametersDefinition": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.test#StringList" + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.test#HttpMalformedResponseBodyAssertion": { + "type": "union", + "members": { + "contents": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Defines the expected serialized response body, which will be matched\nexactly." + } + }, + "messageRegex": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A regex to evaluate against the `message` field in the body. For\nresponses that may have some variance from platform to platform,\nsuch as those that include messages from a parser." + } + } + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.test#HttpMalformedResponseBodyDefinition": { + "type": "structure", + "members": { + "assertion": { + "target": "smithy.test#HttpMalformedResponseBodyAssertion", + "traits": { + "smithy.api#documentation": "The assertion to execute against the response body.", + "smithy.api#required": {} + } + }, + "mediaType": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The media type of the response body.\n\nThis is used to help test runners to parse and evaluate\n`contents' and `messageRegex` in the assertion", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.test#HttpMalformedResponseDefinition": { + "type": "structure", + "members": { + "headers": { + "target": "smithy.test#StringMap", + "traits": { + "smithy.api#documentation": "Defines a map of expected HTTP headers.\n\nHeaders that are not listed in this map are ignored." + } + }, + "code": { + "target": "smithy.api#Integer", + "traits": { + "smithy.api#documentation": "Defines the HTTP response code.", + "smithy.api#range": { + "min": 100, + "max": 599 + }, + "smithy.api#required": {} + } + }, + "body": { + "target": "smithy.test#HttpMalformedResponseBodyDefinition", + "traits": { + "smithy.api#documentation": "The expected response body." + } + } + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.test#HttpRequestTestCase": { + "type": "structure", + "members": { + "id": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The identifier of the test case. This identifier can be used by\nprotocol test implementations to filter out unsupported test\ncases by ID, to generate test case names, etc. The provided `id`\nMUST match Smithy's `identifier` ABNF. No two `httpRequestTests`\ntest cases can share the same ID.", + "smithy.api#pattern": "^[A-Za-z_][A-Za-z0-9_]+$", + "smithy.api#required": {} + } + }, + "protocol": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The name of the protocol to test.", + "smithy.api#idRef": { + "selector": "[trait|protocolDefinition]", + "failWhenMissing": true + }, + "smithy.api#required": {} + } + }, + "method": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected serialized HTTP request method.", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#required": {} + } + }, + "uri": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The request-target of the HTTP request, not including\nthe query string (for example, \"/foo/bar\").", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#required": {} + } + }, + "host": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The host / endpoint provided to the client, not including the path\nor scheme (for example, \"example.com\")." + } + }, + "resolvedHost": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The host / endpoint that the client should send to, not including\nthe path or scheme (for example, \"prefix.example.com\").\n\nThis can differ from the host provided to the client if the `hostPrefix`\nmember of the `endpoint` trait is set, for instance." + } + }, + "authScheme": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The optional authentication scheme shape ID to assume. It's\npossible that specific authentication schemes might influence\nthe serialization logic of an HTTP request.", + "smithy.api#idRef": { + "selector": "[trait|authDefinition]", + "failWhenMissing": true + } + } + }, + "queryParams": { + "target": "smithy.test#StringList", + "traits": { + "smithy.api#documentation": "A list of the expected serialized query string parameters.\n\nEach element in the list is a query string key value pair\nthat starts with the query string parameter name optionally\nfollowed by \"=\", optionally followed by the query string\nparameter value. For example, \"foo=bar\", \"foo=\", and \"foo\"\nare all valid values. The query string parameter name and\nthe value MUST appear in the format in which it is expected\nto be sent over the wire; if a key or value needs to be\npercent-encoded, then it MUST appear percent-encoded in this list.\n\nA serialized HTTP request is not in compliance with the protocol\nif any query string parameter defined in `queryParams` is not\ndefined in the request or if the value of a query string parameter\nin the request differs from the expected value.\n\n`queryParams` applies no constraints on additional query parameters." + } + }, + "forbidQueryParams": { + "target": "smithy.test#StringList", + "traits": { + "smithy.api#documentation": "A list of query string parameter names that must not appear in the\nserialized HTTP request.\n\nEach value MUST appear in the format in which it is sent over the\nwire; if a key needs to be percent-encoded, then it MUST appear\npercent-encoded in this list." + } + }, + "requireQueryParams": { + "target": "smithy.test#StringList", + "traits": { + "smithy.api#documentation": "A list of query string parameter names that MUST appear in the\nserialized request URI, but no assertion is made on the value.\n\nEach value MUST appear in the format in which it is sent over the\nwire; if a key needs to be percent-encoded, then it MUST appear\npercent-encoded in this list." + } + }, + "headers": { + "target": "smithy.test#StringMap", + "traits": { + "smithy.api#documentation": "Defines a map of expected HTTP headers.\n\nHeaders that are not listed in this map are ignored unless they are\nexplicitly forbidden through `forbidHeaders`." + } + }, + "forbidHeaders": { + "target": "smithy.test#StringList", + "traits": { + "smithy.api#documentation": "A list of header field names that must not appear in the serialized\nHTTP request." + } + }, + "requireHeaders": { + "target": "smithy.test#StringList", + "traits": { + "smithy.api#documentation": "A list of header field names that must appear in the serialized\nHTTP message, but no assertion is made on the value.\n\nHeaders listed in `headers` do not need to appear in this list." + } + }, + "body": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected HTTP message body.\n\nIf no request body is defined, then no assertions are made about\nthe body of the message." + } + }, + "bodyMediaType": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The media type of the `body`.\n\nThis is used to help test runners to parse and validate the expected\ndata against generated data." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the input parameters used to generated the HTTP request.\n\nThese parameters MUST be compatible with the input of the operation." + } + }, + "vendorParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines vendor-specific parameters that are used to influence the\nrequest. For example, some vendors might utilize environment\nvariables, configuration files on disk, or other means to influence\nthe serialization formats used by clients or servers.\n\nIf a `vendorParamsShape` is set, these parameters MUST be compatible\nwith that shape's definition." + } + }, + "vendorParamsShape": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A shape to be used to validate the `vendorParams` member contents.\n\nIf set, the parameters in `vendorParams` MUST be compatible with this\nshape's definition.", + "smithy.api#idRef": { + "failWhenMissing": true + } + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A description of the test and what is being asserted." + } + }, + "tags": { + "target": "smithy.test#NonEmptyStringList", + "traits": { + "smithy.api#documentation": "Applies a list of tags to the test." + } + }, + "appliesTo": { + "target": "smithy.test#AppliesTo", + "traits": { + "smithy.api#documentation": "Indicates that the test case is only to be implemented by \"client\" or\n\"server\" implementations. This property is useful for identifying and\ntesting edge cases of clients and servers that are impossible or\nundesirable to test in *both* client and server implementations." + } + } + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.test#HttpResponseTestCase": { + "type": "structure", + "members": { + "id": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The identifier of the test case. This identifier can be used by\nprotocol test implementations to filter out unsupported test\ncases by ID, to generate test case names, etc. The provided `id`\nMUST match Smithy's `identifier` ABNF. No two `httpResponseTests`\ntest cases can share the same ID.", + "smithy.api#pattern": "^[A-Za-z_][A-Za-z0-9_]+$", + "smithy.api#required": {} + } + }, + "protocol": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The shape ID of the protocol to test.", + "smithy.api#idRef": { + "selector": "[trait|protocolDefinition]", + "failWhenMissing": true + }, + "smithy.api#required": {} + } + }, + "code": { + "target": "smithy.api#Integer", + "traits": { + "smithy.api#documentation": "Defines the HTTP response code.", + "smithy.api#range": { + "min": 100, + "max": 599 + }, + "smithy.api#required": {} + } + }, + "authScheme": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The optional authentication scheme shape ID to assume. It's possible\nthat specific authentication schemes might influence the serialization\nlogic of an HTTP response.", + "smithy.api#idRef": { + "selector": "[trait|authDefinition]", + "failWhenMissing": true + } + } + }, + "headers": { + "target": "smithy.test#StringMap", + "traits": { + "smithy.api#documentation": "A map of expected HTTP headers. Each key represents a header field\nname and each value represents the expected header value. An HTTP\nresponse is not in compliance with the protocol if any listed header\nis missing from the serialized response or if the expected header\nvalue differs from the serialized response value.\n\n`headers` applies no constraints on additional headers." + } + }, + "forbidHeaders": { + "target": "smithy.test#StringList", + "traits": { + "smithy.api#documentation": "A list of header field names that must not appear." + } + }, + "requireHeaders": { + "target": "smithy.test#StringList", + "traits": { + "smithy.api#documentation": "A list of header field names that must appear in the serialized\nHTTP message, but no assertion is made on the value.\n\nHeaders listed in `headers` map do not need to appear in this list." + } + }, + "body": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Defines the HTTP message body.\n\nIf no response body is defined, then no assertions are made about\nthe body of the message." + } + }, + "bodyMediaType": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The media type of the `body`.\n\nThis is used to help test runners to parse and validate the expected\ndata against generated data. Binary media type formats require that\nthe contents of `body` are base64 encoded." + } + }, + "params": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines the output parameters deserialized from the HTTP response.\n\nThese parameters MUST be compatible with the output of the operation." + } + }, + "vendorParams": { + "target": "smithy.api#Document", + "traits": { + "smithy.api#documentation": "Defines vendor-specific parameters that are used to influence the\nresponse. For example, some vendors might utilize environment\nvariables, configuration files on disk, or other means to influence\nthe serialization formats used by clients or servers.\n\nIf a `vendorParamsShape` is set, these parameters MUST be compatible\nwith that shape's definition." + } + }, + "vendorParamsShape": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A shape to be used to validate the `vendorParams` member contents.\n\nIf set, the parameters in `vendorParams` MUST be compatible with this\nshape's definition.", + "smithy.api#idRef": { + "failWhenMissing": true + } + } + }, + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A description of the test and what is being asserted." + } + }, + "tags": { + "target": "smithy.test#NonEmptyStringList", + "traits": { + "smithy.api#documentation": "Applies a list of tags to the test." + } + }, + "appliesTo": { + "target": "smithy.test#AppliesTo", + "traits": { + "smithy.api#documentation": "Indicates that the test case is only to be implemented by \"client\" or\n\"server\" implementations. This property is useful for identifying and\ntesting edge cases of clients and servers that are impossible or\nundesirable to test in *both* client and server implementations." + } + } + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.test#NonEmptyString": { + "type": "string", + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.test#NonEmptyStringList": { + "type": "list", + "member": { + "target": "smithy.test#NonEmptyString" + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.test#StringList": { + "type": "list", + "member": { + "target": "smithy.api#String" + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.test#StringMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.api#String" + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.test#httpMalformedRequestTests": { + "type": "list", + "member": { + "target": "smithy.test#HttpMalformedRequestTestCase" + }, + "traits": { + "smithy.api#documentation": "Define how a malformed HTTP request is rejected by a server given a specific protocol", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#trait": { + "selector": "operation" + }, + "smithy.api#unstable": {} + } + }, + "smithy.test#httpRequestTests": { + "type": "list", + "member": { + "target": "smithy.test#HttpRequestTestCase" + }, + "traits": { + "smithy.api#documentation": "Define how an HTTP request is serialized given a specific protocol,\nauthentication scheme, and set of input parameters.", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#trait": { + "selector": "operation" + } + } + }, + "smithy.test#httpResponseTests": { + "type": "list", + "member": { + "target": "smithy.test#HttpResponseTestCase" + }, + "traits": { + "smithy.api#documentation": "Define how an HTTP response is serialized given a specific protocol,\nauthentication scheme, and set of output or error parameters.", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#trait": { + "selector": ":test(operation, structure[trait|error])" + } + } } } } diff --git a/gems/smithy/spec/fixtures/service_index/model.json b/gems/smithy/spec/fixtures/service_index/model.json index 38670a411..d002a3606 100644 --- a/gems/smithy/spec/fixtures/service_index/model.json +++ b/gems/smithy/spec/fixtures/service_index/model.json @@ -1,6 +1,53 @@ { "smithy": "2.0", "shapes": { + "smithy.protocols#StringList": { + "type": "list", + "member": { + "target": "smithy.api#String" + }, + "traits": { + "smithy.api#documentation": "A list of String shapes.", + "smithy.api#private": {} + } + }, + "smithy.protocols#rpcv2Cbor": { + "type": "structure", + "members": { + "http": { + "target": "smithy.protocols#StringList", + "traits": { + "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions." + } + }, + "eventStreamHttp": { + "target": "smithy.protocols#StringList", + "traits": { + "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions\nthat are required when using event streams." + } + } + }, + "traits": { + "smithy.api#documentation": "An RPC-based protocol that serializes CBOR payloads.", + "smithy.api#protocolDefinition": { + "traits": [ + "smithy.api#cors", + "smithy.api#endpoint", + "smithy.api#hostLabel", + "smithy.api#httpError" + ] + }, + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#traitValidators": { + "rpcv2Cbor.NoDocuments": { + "selector": "service ~> member :test(> document)", + "message": "This protocol does not support document types" + } + } + } + }, "smithy.ruby.tests#ClientError": { "type": "structure", "members": { diff --git a/gems/smithy/spec/fixtures/shapes/model.json b/gems/smithy/spec/fixtures/shapes/model.json index 2f7119c92..91b588170 100644 --- a/gems/smithy/spec/fixtures/shapes/model.json +++ b/gems/smithy/spec/fixtures/shapes/model.json @@ -1,6 +1,53 @@ { "smithy": "2.0", "shapes": { + "smithy.protocols#StringList": { + "type": "list", + "member": { + "target": "smithy.api#String" + }, + "traits": { + "smithy.api#documentation": "A list of String shapes.", + "smithy.api#private": {} + } + }, + "smithy.protocols#rpcv2Cbor": { + "type": "structure", + "members": { + "http": { + "target": "smithy.protocols#StringList", + "traits": { + "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions." + } + }, + "eventStreamHttp": { + "target": "smithy.protocols#StringList", + "traits": { + "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions\nthat are required when using event streams." + } + } + }, + "traits": { + "smithy.api#documentation": "An RPC-based protocol that serializes CBOR payloads.", + "smithy.api#protocolDefinition": { + "traits": [ + "smithy.api#cors", + "smithy.api#endpoint", + "smithy.api#hostLabel", + "smithy.api#httpError" + ] + }, + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#traitValidators": { + "rpcv2Cbor.NoDocuments": { + "selector": "service ~> member :test(> document)", + "message": "This protocol does not support document types" + } + } + } + }, "smithy.ruby.tests#BigDecimal": { "type": "bigDecimal", "traits": { diff --git a/gems/smithy/spec/fixtures/syntax_examples/model.json b/gems/smithy/spec/fixtures/syntax_examples/model.json index 47c136deb..fb43bba1a 100644 --- a/gems/smithy/spec/fixtures/syntax_examples/model.json +++ b/gems/smithy/spec/fixtures/syntax_examples/model.json @@ -1,6 +1,53 @@ { "smithy": "2.0", "shapes": { + "smithy.protocols#StringList": { + "type": "list", + "member": { + "target": "smithy.api#String" + }, + "traits": { + "smithy.api#documentation": "A list of String shapes.", + "smithy.api#private": {} + } + }, + "smithy.protocols#rpcv2Cbor": { + "type": "structure", + "members": { + "http": { + "target": "smithy.protocols#StringList", + "traits": { + "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions." + } + }, + "eventStreamHttp": { + "target": "smithy.protocols#StringList", + "traits": { + "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions\nthat are required when using event streams." + } + } + }, + "traits": { + "smithy.api#documentation": "An RPC-based protocol that serializes CBOR payloads.", + "smithy.api#protocolDefinition": { + "traits": [ + "smithy.api#cors", + "smithy.api#endpoint", + "smithy.api#hostLabel", + "smithy.api#httpError" + ] + }, + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#traitValidators": { + "rpcv2Cbor.NoDocuments": { + "selector": "service ~> member :test(> document)", + "message": "This protocol does not support document types" + } + } + } + }, "smithy.ruby.tests#ComplexList": { "type": "list", "member": { diff --git a/gems/smithy/spec/fixtures/waiters/model.json b/gems/smithy/spec/fixtures/waiters/model.json new file mode 100644 index 000000000..a915b9ece --- /dev/null +++ b/gems/smithy/spec/fixtures/waiters/model.json @@ -0,0 +1,606 @@ +{ + "smithy": "2.0", + "shapes": { + "smithy.ruby.tests#BooleanArray": { + "type": "list", + "member": { + "target": "smithy.api#Boolean" + } + }, + "smithy.ruby.tests#Child": { + "type": "structure", + "members": { + "grandchildren": { + "target": "smithy.ruby.tests#GrandchildArray" + } + } + }, + "smithy.ruby.tests#ChildArray": { + "type": "list", + "member": { + "target": "smithy.ruby.tests#Child" + } + }, + "smithy.ruby.tests#DataMap": { + "type": "map", + "key": { + "target": "smithy.api#String" + }, + "value": { + "target": "smithy.api#String" + } + }, + "smithy.ruby.tests#GetWidget": { + "type": "operation", + "input": { + "target": "smithy.ruby.tests#WidgetInput" + }, + "output": { + "target": "smithy.ruby.tests#WidgetOutput" + }, + "errors": [ + { + "target": "smithy.ruby.tests#MyError" + } + ], + "traits": { + "smithy.api#http": { + "uri": "/widget", + "method": "POST" + }, + "smithy.waiters#waitable": { + "SuccessTrueMatcher": { + "documentation": "Acceptor matches on successful request", + "acceptors": [ + { + "state": "success", + "matcher": { + "success": true + } + } + ] + }, + "SuccessFalseMatcher": { + "documentation": "Acceptor matches on unsuccessful request", + "acceptors": [ + { + "state": "success", + "matcher": { + "success": false + } + } + ] + }, + "ErrorTypeMatcher": { + "documentation": "Acceptor matches on receipt of specified error", + "acceptors": [ + { + "state": "success", + "matcher": { + "errorType": "MyError" + } + } + ] + }, + "OutputStringPropertyMatcher": { + "documentation": "Acceptor matches on output payload property", + "acceptors": [ + { + "state": "success", + "matcher": { + "output": { + "path": "stringProperty", + "expected": "payload property contents", + "comparator": "stringEquals" + } + } + } + ] + }, + "OutputStringArrayAllPropertyMatcher": { + "documentation": "Acceptor matches on output payload property", + "acceptors": [ + { + "state": "success", + "matcher": { + "output": { + "path": "stringArrayProperty", + "expected": "payload property contents", + "comparator": "allStringEquals" + } + } + } + ] + }, + "OutputStringArrayAnyPropertyMatcher": { + "documentation": "Acceptor matches on output payload property", + "acceptors": [ + { + "state": "success", + "matcher": { + "output": { + "path": "stringArrayProperty", + "expected": "payload property contents", + "comparator": "anyStringEquals" + } + } + } + ] + }, + "OutputBooleanPropertyMatcher": { + "documentation": "Acceptor matches on output payload property", + "acceptors": [ + { + "state": "success", + "matcher": { + "output": { + "path": "booleanProperty", + "expected": "false", + "comparator": "booleanEquals" + } + } + } + ] + }, + "InputOutputPropertyMatcher": { + "documentation": "Acceptor matches on input property equaling output property", + "acceptors": [ + { + "state": "success", + "matcher": { + "inputOutput": { + "path": "input.stringProperty == output.stringProperty", + "expected": "true", + "comparator": "booleanEquals" + } + } + } + ] + }, + "FlattenMatcher": { + "documentation": "Matches when any grandchild has name 'expected name'", + "acceptors": [ + { + "state": "success", + "matcher": { + "output": { + "path": "children[].grandchildren[].name", + "expected": "expected name", + "comparator": "anyStringEquals" + } + } + } + ] + }, + "FlattenLengthMatcher": { + "documentation": "Matches when there are 6 grandchildren total", + "acceptors": [ + { + "state": "success", + "matcher": { + "output": { + "path": "length(children[].grandchildren[]) == `6`", + "expected": "true", + "comparator": "booleanEquals" + } + } + } + ] + }, + "FlattenFilterMatcher": { + "documentation": "Matches when exactly one child has 3 grandchildren", + "acceptors": [ + { + "state": "success", + "matcher": { + "output": { + "path": "length(children[?length(grandchildren) == `3`]) == `1`", + "expected": "true", + "comparator": "booleanEquals" + } + } + } + ] + }, + "LengthFlattenFilterMatcher": { + "documentation": "Matches when exactly 3 grandchildren have numbers above 4", + "acceptors": [ + { + "state": "success", + "matcher": { + "output": { + "path": "length((children[].grandchildren[])[?number > `4`]) == `3`", + "expected": "true", + "comparator": "booleanEquals" + } + } + } + ] + }, + "ProjectionMatcher": { + "documentation": "Matches when dataMap values are all `abc`", + "acceptors": [ + { + "state": "success", + "matcher": { + "output": { + "path": "dataMap.*", + "expected": "abc", + "comparator": "allStringEquals" + } + } + } + ] + }, + "ContainsFieldMatcher": { + "documentation": "Matches when any value of dataMap is the same as stringProperty", + "acceptors": [ + { + "state": "success", + "matcher": { + "output": { + "path": "contains(dataMap.*, stringProperty)", + "expected": "true", + "comparator": "booleanEquals" + } + } + } + ] + }, + "AndInequalityMatcher": { + "documentation": "Matches when there are three elements in dataMap but not three in stringArrayProperty", + "acceptors": [ + { + "state": "success", + "matcher": { + "output": { + "path": "length(dataMap) == `3` && length(stringArrayProperty) != `3`", + "expected": "true", + "comparator": "booleanEquals" + } + } + } + ] + } + } + } + }, + "smithy.ruby.tests#Grandchild": { + "type": "structure", + "members": { + "name": { + "target": "smithy.api#String" + }, + "number": { + "target": "smithy.api#Integer" + } + } + }, + "smithy.ruby.tests#GrandchildArray": { + "type": "list", + "member": { + "target": "smithy.ruby.tests#Grandchild" + } + }, + "smithy.ruby.tests#MyError": { + "type": "structure", + "members": { + "message": { + "target": "smithy.api#String" + } + }, + "traits": { + "smithy.api#error": "client" + } + }, + "smithy.ruby.tests#StringArray": { + "type": "list", + "member": { + "target": "smithy.api#String" + } + }, + "smithy.ruby.tests#Waiters": { + "type": "service", + "version": "2022-11-30", + "operations": [ + { + "target": "smithy.ruby.tests#GetWidget" + } + ] + }, + "smithy.ruby.tests#WidgetInput": { + "type": "structure", + "members": { + "stringProperty": { + "target": "smithy.api#String" + } + } + }, + "smithy.ruby.tests#WidgetOutput": { + "type": "structure", + "members": { + "stringProperty": { + "target": "smithy.api#String" + }, + "stringArrayProperty": { + "target": "smithy.ruby.tests#StringArray" + }, + "booleanProperty": { + "target": "smithy.api#Boolean" + }, + "booleanArrayProperty": { + "target": "smithy.ruby.tests#BooleanArray" + }, + "children": { + "target": "smithy.ruby.tests#ChildArray" + }, + "dataMap": { + "target": "smithy.ruby.tests#DataMap" + } + } + }, + "smithy.waiters#Acceptor": { + "type": "structure", + "members": { + "state": { + "target": "smithy.waiters#AcceptorState", + "traits": { + "smithy.api#documentation": "The state the acceptor transitions to when matched.", + "smithy.api#required": {} + } + }, + "matcher": { + "target": "smithy.waiters#Matcher", + "traits": { + "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", + "smithy.api#private": {} + } + }, + "smithy.waiters#AcceptorState": { + "type": "enum", + "members": { + "SUCCESS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", + "smithy.api#enumValue": "success" + } + }, + "FAILURE": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", + "smithy.api#enumValue": "failure" + } + }, + "RETRY": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", + "smithy.api#enumValue": "retry" + } + } + }, + "traits": { + "smithy.api#documentation": "The transition state of a waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Acceptors": { + "type": "list", + "member": { + "target": "smithy.waiters#Acceptor" + }, + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#Matcher": { + "type": "union", + "members": { + "output": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." + } + }, + "inputOutput": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." + } + }, + "errorType": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." + } + }, + "success": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyString": { + "type": "string", + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyStringList": { + "type": "list", + "member": { + "target": "smithy.waiters#NonEmptyString" + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.waiters#PathComparator": { + "type": "enum", + "members": { + "STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", + "smithy.api#enumValue": "stringEquals" + } + }, + "BOOLEAN_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", + "smithy.api#enumValue": "booleanEquals" + } + }, + "ALL_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if all values in the list matches the expected string.", + "smithy.api#enumValue": "allStringEquals" + } + }, + "ANY_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if any value in the list matches the expected string.", + "smithy.api#enumValue": "anyStringEquals" + } + } + }, + "traits": { + "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", + "smithy.api#private": {} + } + }, + "smithy.waiters#PathMatcher": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", + "smithy.api#required": {} + } + }, + "expected": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected return value of the expression.", + "smithy.api#required": {} + } + }, + "comparator": { + "target": "smithy.waiters#PathComparator", + "traits": { + "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Waiter": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." + } + }, + "acceptors": { + "target": "smithy.waiters#Acceptors", + "traits": { + "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", + "smithy.api#required": {} + } + }, + "minDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 2, + "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." + } + }, + "maxDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 120, + "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." + } + }, + "deprecated": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." + } + }, + "tags": { + "target": "smithy.waiters#NonEmptyStringList", + "traits": { + "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines an individual operation waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#WaiterDelay": { + "type": "integer", + "traits": { + "smithy.api#range": { + "min": 1 + } + } + }, + "smithy.waiters#WaiterName": { + "type": "string", + "traits": { + "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" + } + }, + "smithy.waiters#waitable": { + "type": "map", + "key": { + "target": "smithy.waiters#WaiterName" + }, + "value": { + "target": "smithy.waiters#Waiter" + }, + "traits": { + "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#trait": { + "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" + } + } + } + } +} diff --git a/gems/smithy/spec/fixtures/waiters/model.smithy b/gems/smithy/spec/fixtures/waiters/model.smithy new file mode 100644 index 000000000..98dccb69a --- /dev/null +++ b/gems/smithy/spec/fixtures/waiters/model.smithy @@ -0,0 +1,284 @@ +$version: "2" + +namespace smithy.ruby.tests + +use smithy.waiters#waitable + +// A service which has a GET operation with waiters defined upon it. +// The acceptor in each waiter serves as subject for unit testing, +// to ensure that the logic in code-generated acceptors works as +// expected. +service Waiters { + version: "2022-11-30", + operations: [GetWidget] +} + +@http(uri: "/widget", method: "POST") +@waitable( + SuccessTrueMatcher: { + documentation: "Acceptor matches on successful request" + acceptors: [ + { + state: "success" + matcher: { + success: true + } + } + ] + } + SuccessFalseMatcher: { + documentation: "Acceptor matches on unsuccessful request" + acceptors: [ + { + state: "success" + matcher: { + success: false + } + } + ] + } + ErrorTypeMatcher: { + documentation: "Acceptor matches on receipt of specified error" + acceptors: [ + { + state: "success" + matcher: { + errorType: "MyError" + } + } + ] + } + OutputStringPropertyMatcher: { + documentation: "Acceptor matches on output payload property" + acceptors: [ + { + state: "success" + matcher: { + output: { + path: "stringProperty" + expected: "payload property contents" + comparator: "stringEquals" + } + } + } + ] + } + OutputStringArrayAllPropertyMatcher: { + documentation: "Acceptor matches on output payload property" + acceptors: [ + { + state: "success" + matcher: { + output: { + path: "stringArrayProperty" + expected: "payload property contents" + comparator: "allStringEquals" + } + } + } + ] + } + OutputStringArrayAnyPropertyMatcher: { + documentation: "Acceptor matches on output payload property" + acceptors: [ + { + state: "success" + matcher: { + output: { + path: "stringArrayProperty" + expected: "payload property contents" + comparator: "anyStringEquals" + } + } + } + ] + } + OutputBooleanPropertyMatcher: { + documentation: "Acceptor matches on output payload property" + acceptors: [ + { + state: "success" + matcher: { + output: { + path: "booleanProperty" + expected: "false" + comparator: "booleanEquals" + } + } + } + ] + } + InputOutputPropertyMatcher: { + documentation: "Acceptor matches on input property equaling output property" + acceptors: [ + { + state: "success" + matcher: { + inputOutput: { + path: "input.stringProperty == output.stringProperty" + expected: "true" + comparator: "booleanEquals" + } + } + } + ] + } + FlattenMatcher: { + documentation: "Matches when any grandchild has name 'expected name'" + acceptors: [ + { + state: "success" + matcher: { + output: { + path: "children[].grandchildren[].name" + expected: "expected name" + comparator: "anyStringEquals" + } + } + } + ] + } + FlattenLengthMatcher: { + documentation: "Matches when there are 6 grandchildren total" + acceptors: [ + { + state: "success" + matcher: { + output: { + path: "length(children[].grandchildren[]) == `6`" + expected: "true" + comparator: "booleanEquals" + } + } + } + ] + } + FlattenFilterMatcher: { + documentation: "Matches when exactly one child has 3 grandchildren" + acceptors: [ + { + state: "success" + matcher: { + output: { + path: "length(children[?length(grandchildren) == `3`]) == `1`" + expected: "true" + comparator: "booleanEquals" + } + } + } + ] + } + LengthFlattenFilterMatcher: { + documentation: "Matches when exactly 3 grandchildren have numbers above 4" + acceptors: [ + { + state: "success" + matcher: { + output: { + path: "length((children[].grandchildren[])[?number > `4`]) == `3`" + expected: "true" + comparator: "booleanEquals" + } + } + } + ] + } + ProjectionMatcher: { + documentation: "Matches when dataMap values are all `abc`" + acceptors: [ + { + state: "success" + matcher: { + output: { + path: "dataMap.*" + expected: "abc" + comparator: "allStringEquals" + } + } + } + ] + } + ContainsFieldMatcher: { + documentation: "Matches when any value of dataMap is the same as stringProperty" + acceptors: [ + { + state: "success" + matcher: { + output: { + path: "contains(dataMap.*, stringProperty)" + expected: "true" + comparator: "booleanEquals" + } + } + } + ] + } + AndInequalityMatcher: { + documentation: "Matches when there are three elements in dataMap but not three in stringArrayProperty" + acceptors: [ + { + state: "success" + matcher: { + output: { + path: "length(dataMap) == `3` && length(stringArrayProperty) != `3`" + expected: "true" + comparator: "booleanEquals" + } + } + } + ] + } +) +operation GetWidget { + input: WidgetInput, + output: WidgetOutput + errors: [MyError] +} + +structure WidgetInput { + stringProperty: String +} + +structure WidgetOutput { + stringProperty: String + stringArrayProperty: StringArray + booleanProperty: Boolean + booleanArrayProperty: BooleanArray + children: ChildArray + dataMap: DataMap +} + +structure Child { + grandchildren: GrandchildArray +} + +structure Grandchild { + name: String + number: Integer +} + +list StringArray{ + member: String +} + +list BooleanArray{ + member: Boolean +} + +list ChildArray { + member: Child +} + +list GrandchildArray { + member: Grandchild +} + +map DataMap { + key: String + value: String +} + +@error("client") +structure MyError { + message: String +} diff --git a/gems/smithy/spec/fixtures/waiters/smithy-build.json b/gems/smithy/spec/fixtures/waiters/smithy-build.json new file mode 100644 index 000000000..7cb8c3841 --- /dev/null +++ b/gems/smithy/spec/fixtures/waiters/smithy-build.json @@ -0,0 +1,8 @@ +{ + "version": "1.0", + "maven": { + "dependencies": [ + "software.amazon.smithy:smithy-waiters:1.56.0" + ] + } +} \ No newline at end of file diff --git a/gems/smithy/spec/fixtures/weather/model.json b/gems/smithy/spec/fixtures/weather/model.json index adb421790..5d1cb8412 100644 --- a/gems/smithy/spec/fixtures/weather/model.json +++ b/gems/smithy/spec/fixtures/weather/model.json @@ -290,6 +290,269 @@ "pageSize": "pageSize" } } + }, + "smithy.waiters#Acceptor": { + "type": "structure", + "members": { + "state": { + "target": "smithy.waiters#AcceptorState", + "traits": { + "smithy.api#documentation": "The state the acceptor transitions to when matched.", + "smithy.api#required": {} + } + }, + "matcher": { + "target": "smithy.waiters#Matcher", + "traits": { + "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", + "smithy.api#private": {} + } + }, + "smithy.waiters#AcceptorState": { + "type": "enum", + "members": { + "SUCCESS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", + "smithy.api#enumValue": "success" + } + }, + "FAILURE": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", + "smithy.api#enumValue": "failure" + } + }, + "RETRY": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", + "smithy.api#enumValue": "retry" + } + } + }, + "traits": { + "smithy.api#documentation": "The transition state of a waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Acceptors": { + "type": "list", + "member": { + "target": "smithy.waiters#Acceptor" + }, + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#Matcher": { + "type": "union", + "members": { + "output": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." + } + }, + "inputOutput": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." + } + }, + "errorType": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." + } + }, + "success": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyString": { + "type": "string", + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyStringList": { + "type": "list", + "member": { + "target": "smithy.waiters#NonEmptyString" + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.waiters#PathComparator": { + "type": "enum", + "members": { + "STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", + "smithy.api#enumValue": "stringEquals" + } + }, + "BOOLEAN_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", + "smithy.api#enumValue": "booleanEquals" + } + }, + "ALL_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if all values in the list matches the expected string.", + "smithy.api#enumValue": "allStringEquals" + } + }, + "ANY_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if any value in the list matches the expected string.", + "smithy.api#enumValue": "anyStringEquals" + } + } + }, + "traits": { + "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", + "smithy.api#private": {} + } + }, + "smithy.waiters#PathMatcher": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", + "smithy.api#required": {} + } + }, + "expected": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected return value of the expression.", + "smithy.api#required": {} + } + }, + "comparator": { + "target": "smithy.waiters#PathComparator", + "traits": { + "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Waiter": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." + } + }, + "acceptors": { + "target": "smithy.waiters#Acceptors", + "traits": { + "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", + "smithy.api#required": {} + } + }, + "minDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 2, + "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." + } + }, + "maxDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 120, + "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." + } + }, + "deprecated": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." + } + }, + "tags": { + "target": "smithy.waiters#NonEmptyStringList", + "traits": { + "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines an individual operation waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#WaiterDelay": { + "type": "integer", + "traits": { + "smithy.api#range": { + "min": 1 + } + } + }, + "smithy.waiters#WaiterName": { + "type": "string", + "traits": { + "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" + } + }, + "smithy.waiters#waitable": { + "type": "map", + "key": { + "target": "smithy.waiters#WaiterName" + }, + "value": { + "target": "smithy.waiters#Waiter" + }, + "traits": { + "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#trait": { + "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" + } + } } } } diff --git a/gems/smithy/spec/fixtures/weld_protocol/model.json b/gems/smithy/spec/fixtures/weld_protocol/model.json index faf1eb9a0..2539fe02d 100644 --- a/gems/smithy/spec/fixtures/weld_protocol/model.json +++ b/gems/smithy/spec/fixtures/weld_protocol/model.json @@ -14,6 +14,269 @@ "smithy.api#protocolDefinition": {}, "smithy.api#trait": {} } + }, + "smithy.waiters#Acceptor": { + "type": "structure", + "members": { + "state": { + "target": "smithy.waiters#AcceptorState", + "traits": { + "smithy.api#documentation": "The state the acceptor transitions to when matched.", + "smithy.api#required": {} + } + }, + "matcher": { + "target": "smithy.waiters#Matcher", + "traits": { + "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", + "smithy.api#private": {} + } + }, + "smithy.waiters#AcceptorState": { + "type": "enum", + "members": { + "SUCCESS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", + "smithy.api#enumValue": "success" + } + }, + "FAILURE": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", + "smithy.api#enumValue": "failure" + } + }, + "RETRY": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", + "smithy.api#enumValue": "retry" + } + } + }, + "traits": { + "smithy.api#documentation": "The transition state of a waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Acceptors": { + "type": "list", + "member": { + "target": "smithy.waiters#Acceptor" + }, + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#Matcher": { + "type": "union", + "members": { + "output": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." + } + }, + "inputOutput": { + "target": "smithy.waiters#PathMatcher", + "traits": { + "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." + } + }, + "errorType": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." + } + }, + "success": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyString": { + "type": "string", + "traits": { + "smithy.api#length": { + "min": 1 + }, + "smithy.api#private": {} + } + }, + "smithy.waiters#NonEmptyStringList": { + "type": "list", + "member": { + "target": "smithy.waiters#NonEmptyString" + }, + "traits": { + "smithy.api#private": {} + } + }, + "smithy.waiters#PathComparator": { + "type": "enum", + "members": { + "STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", + "smithy.api#enumValue": "stringEquals" + } + }, + "BOOLEAN_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", + "smithy.api#enumValue": "booleanEquals" + } + }, + "ALL_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if all values in the list matches the expected string.", + "smithy.api#enumValue": "allStringEquals" + } + }, + "ANY_STRING_EQUALS": { + "target": "smithy.api#Unit", + "traits": { + "smithy.api#documentation": "Matches if any value in the list matches the expected string.", + "smithy.api#enumValue": "anyStringEquals" + } + } + }, + "traits": { + "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", + "smithy.api#private": {} + } + }, + "smithy.waiters#PathMatcher": { + "type": "structure", + "members": { + "path": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", + "smithy.api#required": {} + } + }, + "expected": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "The expected return value of the expression.", + "smithy.api#required": {} + } + }, + "comparator": { + "target": "smithy.waiters#PathComparator", + "traits": { + "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", + "smithy.api#required": {} + } + } + }, + "traits": { + "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", + "smithy.api#private": {} + } + }, + "smithy.waiters#Waiter": { + "type": "structure", + "members": { + "documentation": { + "target": "smithy.api#String", + "traits": { + "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." + } + }, + "acceptors": { + "target": "smithy.waiters#Acceptors", + "traits": { + "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", + "smithy.api#required": {} + } + }, + "minDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 2, + "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." + } + }, + "maxDelay": { + "target": "smithy.waiters#WaiterDelay", + "traits": { + "smithy.api#default": 120, + "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." + } + }, + "deprecated": { + "target": "smithy.api#Boolean", + "traits": { + "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." + } + }, + "tags": { + "target": "smithy.waiters#NonEmptyStringList", + "traits": { + "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." + } + } + }, + "traits": { + "smithy.api#documentation": "Defines an individual operation waiter.", + "smithy.api#private": {} + } + }, + "smithy.waiters#WaiterDelay": { + "type": "integer", + "traits": { + "smithy.api#range": { + "min": 1 + } + } + }, + "smithy.waiters#WaiterName": { + "type": "string", + "traits": { + "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" + } + }, + "smithy.waiters#waitable": { + "type": "map", + "key": { + "target": "smithy.waiters#WaiterName" + }, + "value": { + "target": "smithy.waiters#Waiter" + }, + "traits": { + "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", + "smithy.api#length": { + "min": 1 + }, + "smithy.api#trait": { + "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" + } + } } } } diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb new file mode 100644 index 000000000..e95254a11 --- /dev/null +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require_relative '../../spec_helper' + +describe 'Client: Waiters' do + ['generated client gem'].each do |context| + context context do + include_examples context, 'Waiters' + + it 'generates waiters' do + assert true + end + end + end +end \ No newline at end of file diff --git a/projections/weather/lib/weather/waiters.rb b/projections/weather/lib/weather/waiters.rb index 7131dfb1e..9baa9cf0f 100644 --- a/projections/weather/lib/weather/waiters.rb +++ b/projections/weather/lib/weather/waiters.rb @@ -14,7 +14,7 @@ def initialize(options = {}) min_delay: options[:min_delay] || 2, max_delay: options[:max_delay] || 120, poller: Poller.new( - operation_name: get_city, + operation_name: :get_city, acceptors: [{ "state" => "success", "matcher" => { @@ -39,7 +39,7 @@ def initialize(options = {}) min_delay: options[:min_delay] || 2, max_delay: options[:max_delay] || 120, poller: Poller.new( - operation_name: get_city, + operation_name: :get_city, acceptors: [{ "state" => "success", "matcher" => { @@ -64,7 +64,7 @@ def initialize(options = {}) min_delay: options[:min_delay] || 2, max_delay: options[:max_delay] || 120, poller: Poller.new( - operation_name: get_forecast, + operation_name: :get_forecast, acceptors: [ { "state" => "failure", From c6a9395182c09afda335714790f3b47ad9f7a392 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 28 Apr 2025 12:49:48 -0700 Subject: [PATCH 07/48] Small fixes --- gems/smithy-client/lib/smithy-client/waiters.rb | 5 +++++ .../lib/smithy-client/waiters/errors.rb | 6 +++--- .../lib/smithy-client/waiters/poller.rb | 9 +++++---- .../lib/smithy-client/waiters/waiter.rb | 15 +++++++++++++-- gems/smithy/lib/smithy/plan.rb | 1 + .../lib/smithy/templates/client/waiters.erb | 6 ++++-- projections/shapes/lib/shapes/waiters.rb | 2 ++ projections/weather/lib/weather/waiters.rb | 14 ++++++++------ 8 files changed, 41 insertions(+), 17 deletions(-) create mode 100644 gems/smithy-client/lib/smithy-client/waiters.rb diff --git a/gems/smithy-client/lib/smithy-client/waiters.rb b/gems/smithy-client/lib/smithy-client/waiters.rb new file mode 100644 index 000000000..fec16853d --- /dev/null +++ b/gems/smithy-client/lib/smithy-client/waiters.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +require_relative 'waiters/errors' +require_relative 'waiters/poller' +require_relative 'waiters/waiter' \ No newline at end of file diff --git a/gems/smithy-client/lib/smithy-client/waiters/errors.rb b/gems/smithy-client/lib/smithy-client/waiters/errors.rb index caf1a4c5e..4027b5ae2 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/errors.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/errors.rb @@ -20,10 +20,10 @@ def initialize(response) end class MaxWaitTimeExceededError < WaiterFailed - MSG = "stopped waiting after maximum wait time was exceeded" + MSG = "stopped waiting after maximum wait time of %s seconds was exceeded" - def initialize - super(MSG) + def initialize(max_wait_time) + super(MSG % [max_wait_time]) end end diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index d8c20cf27..2081d89b1 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -4,13 +4,14 @@ module Smithy module Client module Waiters class Poller - def initialize(operation_name, acceptors) - @operation_name = operation_name - @acceptors = acceptors + def initialize(options = {}) + @operation_name = options[:operation_name] + @acceptors = options[:acceptors] end def call(client, params) resp = client.send(@operation_name, params) + puts resp status = evaluate_acceptors(resp) [resp, status] end @@ -31,7 +32,7 @@ def evaluate_acceptors(resp) def acceptor_matches?(matcher, resp) matcher_type = matcher.keys[0] - send("matches_#{matcher_type}?") + send("matches_#{matcher_type}?", matcher_type, resp) end def matches_output?(path_matcher, resp) diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index 6fcf30780..5bd1742d9 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -5,7 +5,8 @@ module Client module Waiters class Waiter def initialize(options = {}) - @remaining_time = options[:max_wait_time] + @max_wait_time = options[:max_wait_time] + @remaining_time = @max_wait_time @min_delay = options[:min_delay] @max_delay = options[:max_delay] @poller = options[:poller] @@ -21,6 +22,7 @@ def poll(client, params) attempts = 0 loop do resp, status = @poller.call(client, params) + attempts += 1 case status when :retry @@ -29,7 +31,7 @@ def poll(client, params) when :error then return Errors::UnexpectedError.new(resp) end - return Errors::MaxWaitTimeExceededError.new if @remaining_time == 0 + return Errors::MaxWaitTimeExceededError.new(@max_wait_time) if @remaining_time == 0 delay = delay(attempts) @remaining_time -= delay @@ -39,9 +41,18 @@ def poll(client, params) def delay(attempts) attempt_ceiling = (Math.log(@max_delay / @min_delay) / Math.log(2)) + 1 + puts "attempt_ceiling #{attempt_ceiling}" delay = attempts > attempt_ceiling ? @max_delay : @min_delay * 2 ** (attempts - 1) + puts @max_delay + puts @min_delay + puts attempts - 1 + puts 2 ** (attempts - 1) + puts @min_delay * 2 ** (attempts - 1) + puts "delay #{delay}" delay = rand(@min_delay..delay) + puts "delay after rand #{delay}" delay = @remaining_time if @remaining_time - delay <= @min_delay + puts "delay if #{delay}" delay end end diff --git a/gems/smithy/lib/smithy/plan.rb b/gems/smithy/lib/smithy/plan.rb index a3b22d7c9..cdf43fac0 100644 --- a/gems/smithy/lib/smithy/plan.rb +++ b/gems/smithy/lib/smithy/plan.rb @@ -66,6 +66,7 @@ def initialize(model, type, options = {}) def find_service(shapes) service = shapes.select { |_, shape| shape['type'] == 'service' } + puts service raise 'Multiple service shapes found' if service.size > 1 raise 'No service shape found' if service.empty? diff --git a/gems/smithy/lib/smithy/templates/client/waiters.erb b/gems/smithy/lib/smithy/templates/client/waiters.erb index b5fa7ac47..a0fe3297c 100644 --- a/gems/smithy/lib/smithy/templates/client/waiters.erb +++ b/gems/smithy/lib/smithy/templates/client/waiters.erb @@ -2,6 +2,8 @@ # This is generated code! +require 'smithy-client/waiters' + module <%= module_name %> # @api private module Waiters @@ -10,11 +12,11 @@ module <%= module_name %> class <%= waiter.name %> def initialize(options = {}) @client = options[:client] - @waiter = Waiter.new( + @waiter = Smithy::Client::Waiters::Waiter.new( max_wait_time: options[:max_wait_time], min_delay: options[:min_delay] || <%= waiter.min_delay %>, max_delay: options[:max_delay] || <%= waiter.max_delay %>, - poller: Poller.new( + poller: Smithy::Client::Waiters::Poller.new( operation_name: :<%= waiter.operation_name %>, <%= waiter.acceptors %> ) diff --git a/projections/shapes/lib/shapes/waiters.rb b/projections/shapes/lib/shapes/waiters.rb index 58a5d6c79..1f257c14c 100644 --- a/projections/shapes/lib/shapes/waiters.rb +++ b/projections/shapes/lib/shapes/waiters.rb @@ -2,6 +2,8 @@ # This is generated code! +require 'smithy-client/waiters' + module ShapeService # @api private module Waiters diff --git a/projections/weather/lib/weather/waiters.rb b/projections/weather/lib/weather/waiters.rb index 9baa9cf0f..587b21816 100644 --- a/projections/weather/lib/weather/waiters.rb +++ b/projections/weather/lib/weather/waiters.rb @@ -2,6 +2,8 @@ # This is generated code! +require 'smithy-client/waiters' + module Weather # @api private module Waiters @@ -9,11 +11,11 @@ module Waiters class CityDeleted def initialize(options = {}) @client = options[:client] - @waiter = Waiter.new( + @waiter = Smithy::Client::Waiters::Waiter.new( max_wait_time: options[:max_wait_time], min_delay: options[:min_delay] || 2, max_delay: options[:max_delay] || 120, - poller: Poller.new( + poller: Smithy::Client::Waiters::Poller.new( operation_name: :get_city, acceptors: [{ "state" => "success", @@ -34,11 +36,11 @@ def wait(params = {}) class CityExists def initialize(options = {}) @client = options[:client] - @waiter = Waiter.new( + @waiter = Smithy::Client::Waiters::Waiter.new( max_wait_time: options[:max_wait_time], min_delay: options[:min_delay] || 2, max_delay: options[:max_delay] || 120, - poller: Poller.new( + poller: Smithy::Client::Waiters::Poller.new( operation_name: :get_city, acceptors: [{ "state" => "success", @@ -59,11 +61,11 @@ def wait(params = {}) class ForecastExists def initialize(options = {}) @client = options[:client] - @waiter = Waiter.new( + @waiter = Smithy::Client::Waiters::Waiter.new( max_wait_time: options[:max_wait_time], min_delay: options[:min_delay] || 2, max_delay: options[:max_delay] || 120, - poller: Poller.new( + poller: Smithy::Client::Waiters::Poller.new( operation_name: :get_forecast, acceptors: [ { From 8f4856ef6111233901e11423526521f1de077df4 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 28 Apr 2025 14:13:13 -0700 Subject: [PATCH 08/48] Dynamically create waiters --- .../lib/smithy-client/waiters/waiter.rb | 5 ++ projections/weather/lib/weather/client.rb | 55 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index 5bd1742d9..0dc230352 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -10,12 +10,17 @@ def initialize(options = {}) @min_delay = options[:min_delay] @max_delay = options[:max_delay] @poller = options[:poller] + @client = options[:client] # custom waiter approach end def wait(client, params) poll(client, params) end + def wait_custom(params) + poll(@client, params) + end + private def poll(client, params) diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index 16ab95a20..5c106f857 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -232,6 +232,14 @@ def wait_until(waiter_name, params = {}, options = {}) w.wait(params) end + def wait_until_custom(waiter_name, params = {}, options = {}) + operation_name, waiter_config = find_waiter(waiter_name) + puts operation_name.class + poller = poller_custom(operation_name, waiter_config["acceptors"]) + waiter = waiter_custom(waiter_config, options, poller) + waiter.wait_custom(params) + end + private def build_input(operation_name, params) @@ -257,6 +265,53 @@ def waiter(waiter_name, options = {}) end end + def find_waiter(waiter_name) + operations = config.service.operations + operations.each do |operation_name, operation| + if (trait = waitable_trait(operation)) + trait.each do |name, waiter| + if underscore(name) == waiter_name.to_s + return [operation_name, waiter] + end + end + end + end + nil + end + + def waitable_trait(operation) + if operation.traits && !operation.traits['smithy.waiters#waitable'].nil? + operation.traits['smithy.waiters#waitable'] + end + + end + + def underscore(input) + input.gsub(/::/, '/') + .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') + .gsub(/([a-z\d])([A-Z])/,'\1_\2') + .tr("-", "_") + .downcase + end + + def poller_custom(operation_name, acceptors) + Smithy::Client::Waiters::Poller.new( + operation_name: operation_name.to_sym, + acceptors: acceptors + ) + end + + def waiter_custom(waiter_config, options, poller) + Smithy::Client::Waiters::Waiter.new( + max_wait_time: options[:max_wait_time], + min_delay: options[:min_delay] || waiter_config[:min_delay] || 2, + max_delay: options[:max_delay] || waiter_config[:max_delay] || 120, + poller: poller, + client: self + ) + end + + def waiters { city_deleted: Waiters::CityDeleted, From 4b0a05de30c174ef5497d7ed4fef42ce414a8123 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 28 Apr 2025 14:22:26 -0700 Subject: [PATCH 09/48] Add dynamic waiter to code gen --- .../lib/smithy/templates/client/client.erb | 52 +++++++++++++++++++ projections/shapes/lib/shapes/client.rb | 52 +++++++++++++++++++ projections/weather/lib/weather/client.rb | 19 +++---- 3 files changed, 112 insertions(+), 11 deletions(-) diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index fc9056db7..3aadb212b 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -43,6 +43,13 @@ module <%= module_name %> end <% end -%> + def wait_until_custom(waiter_name, params = {}, options = {}) + operation_name, waiter_config = find_waiter(waiter_name) + poller = poller_custom(operation_name, waiter_config["acceptors"]) + waiter = waiter_custom(waiter_config, options, poller) + waiter.wait_custom(params) + end + private def build_input(operation_name, params) @@ -75,6 +82,51 @@ module <%= module_name %> end <% end -%> + def find_waiter(waiter_name) + operations = config.service.operations + operations.each do |operation_name, operation| + if (trait = waitable_trait(operation)) + trait.each do |name, waiter| + if underscore(name) == waiter_name.to_s + return [operation_name, waiter] + end + end + end + end + nil + end + + def waitable_trait(operation) + if operation.traits && !operation.traits['smithy.waiters#waitable'].nil? + operation.traits['smithy.waiters#waitable'] + end + end + + def underscore(input) + input.gsub(/::/, '/') + .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') + .gsub(/([a-z\d])([A-Z])/,'\1_\2') + .tr("-", "_") + .downcase + end + + def poller_custom(operation_name, acceptors) + Smithy::Client::Waiters::Poller.new( + operation_name: operation_name.to_sym, + acceptors: acceptors + ) + end + + def waiter_custom(waiter_config, options, poller) + Smithy::Client::Waiters::Waiter.new( + max_wait_time: options[:max_wait_time], + min_delay: options[:min_delay] || waiter_config[:min_delay] || 2, + max_delay: options[:max_delay] || waiter_config[:max_delay] || 120, + poller: poller, + client: self + ) + end + class << self # @api private attr_reader :identifier diff --git a/projections/shapes/lib/shapes/client.rb b/projections/shapes/lib/shapes/client.rb index a52335dc6..4e7d692f4 100644 --- a/projections/shapes/lib/shapes/client.rb +++ b/projections/shapes/lib/shapes/client.rb @@ -229,6 +229,13 @@ def operation(params = {}, options = {}) input.send_request(options) end + def wait_until_custom(waiter_name, params = {}, options = {}) + operation_name, waiter_config = find_waiter(waiter_name) + poller = poller_custom(operation_name, waiter_config["acceptors"]) + waiter = waiter_custom(waiter_config, options, poller) + waiter.wait_custom(params) + end + private def build_input(operation_name, params) @@ -245,6 +252,51 @@ def build_input(operation_name, params) Smithy::Client::Input.new(handlers: handlers, context: context) end + def find_waiter(waiter_name) + operations = config.service.operations + operations.each do |operation_name, operation| + if (trait = waitable_trait(operation)) + trait.each do |name, waiter| + if underscore(name) == waiter_name.to_s + return [operation_name, waiter] + end + end + end + end + nil + end + + def waitable_trait(operation) + if operation.traits && !operation.traits['smithy.waiters#waitable'].nil? + operation.traits['smithy.waiters#waitable'] + end + end + + def underscore(input) + input.gsub(/::/, '/') + .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') + .gsub(/([a-z\d])([A-Z])/,'\1_\2') + .tr("-", "_") + .downcase + end + + def poller_custom(operation_name, acceptors) + Smithy::Client::Waiters::Poller.new( + operation_name: operation_name.to_sym, + acceptors: acceptors + ) + end + + def waiter_custom(waiter_config, options, poller) + Smithy::Client::Waiters::Waiter.new( + max_wait_time: options[:max_wait_time], + min_delay: options[:min_delay] || waiter_config[:min_delay] || 2, + max_delay: options[:max_delay] || waiter_config[:max_delay] || 120, + poller: poller, + client: self + ) + end + class << self # @api private attr_reader :identifier diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index 5c106f857..4b8bddef5 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -234,7 +234,6 @@ def wait_until(waiter_name, params = {}, options = {}) def wait_until_custom(waiter_name, params = {}, options = {}) operation_name, waiter_config = find_waiter(waiter_name) - puts operation_name.class poller = poller_custom(operation_name, waiter_config["acceptors"]) waiter = waiter_custom(waiter_config, options, poller) waiter.wait_custom(params) @@ -265,6 +264,14 @@ def waiter(waiter_name, options = {}) end end + def waiters + { + city_deleted: Waiters::CityDeleted, + city_exists: Waiters::CityExists, + forecast_exists: Waiters::ForecastExists + } + end + def find_waiter(waiter_name) operations = config.service.operations operations.each do |operation_name, operation| @@ -283,7 +290,6 @@ def waitable_trait(operation) if operation.traits && !operation.traits['smithy.waiters#waitable'].nil? operation.traits['smithy.waiters#waitable'] end - end def underscore(input) @@ -311,15 +317,6 @@ def waiter_custom(waiter_config, options, poller) ) end - - def waiters - { - city_deleted: Waiters::CityDeleted, - city_exists: Waiters::CityExists, - forecast_exists: Waiters::ForecastExists - } - end - class << self # @api private attr_reader :identifier From 3dd5e64da102bc2d157a921263eba231071bfabf Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 28 Apr 2025 15:08:30 -0700 Subject: [PATCH 10/48] Debug test failure --- gems/smithy-client/lib/smithy-client/waiters/poller.rb | 2 +- gems/smithy-client/lib/smithy-client/waiters/waiter.rb | 6 ------ projections/weather/lib/weather/client.rb | 1 + 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index 2081d89b1..006e56eb0 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -11,7 +11,6 @@ def initialize(options = {}) def call(client, params) resp = client.send(@operation_name, params) - puts resp status = evaluate_acceptors(resp) [resp, status] end @@ -55,6 +54,7 @@ def matches_inputOutput?(path_matcher, resp) end def matches_success?(path_matcher, resp) + puts "resp is #{resp}" if path_matcher['success'] resp.error.nil? else diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index 0dc230352..08459e021 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -46,13 +46,7 @@ def poll(client, params) def delay(attempts) attempt_ceiling = (Math.log(@max_delay / @min_delay) / Math.log(2)) + 1 - puts "attempt_ceiling #{attempt_ceiling}" delay = attempts > attempt_ceiling ? @max_delay : @min_delay * 2 ** (attempts - 1) - puts @max_delay - puts @min_delay - puts attempts - 1 - puts 2 ** (attempts - 1) - puts @min_delay * 2 ** (attempts - 1) puts "delay #{delay}" delay = rand(@min_delay..delay) puts "delay after rand #{delay}" diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index 4b8bddef5..56d3b1161 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -236,6 +236,7 @@ def wait_until_custom(waiter_name, params = {}, options = {}) operation_name, waiter_config = find_waiter(waiter_name) poller = poller_custom(operation_name, waiter_config["acceptors"]) waiter = waiter_custom(waiter_config, options, poller) + puts waiter.inspect waiter.wait_custom(params) end From 970f2368c2068ac3e5da729c2124bcbf2963d98d Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 29 Apr 2025 09:08:18 -0700 Subject: [PATCH 11/48] Revert fixture model changes --- .../spec/fixtures/auth/auth_trait/model.json | 263 -- .../auth/http_api_key_auth/model.json | 263 -- .../fixtures/auth/http_basic_auth/model.json | 263 -- .../fixtures/auth/http_bearer_auth/model.json | 263 -- .../fixtures/auth/http_digest_auth/model.json | 263 -- .../fixtures/auth/no_auth_trait/model.json | 263 -- gems/smithy/spec/fixtures/errors/model.json | 400 -- .../spec/fixtures/examples_trait/model.json | 400 -- .../fixtures/mixins/apply-list/model.json | 400 -- .../spec/fixtures/mixins/apply-map/model.json | 400 -- .../mixins/apply-structure/model.json | 400 -- .../fixtures/mixins/apply-union/model.json | 400 -- .../spec/fixtures/mixins/composed/model.json | 400 -- .../fixtures/mixins/local-traits/model.json | 400 -- .../fixtures/mixins/member-order/model.json | 400 -- .../spec/fixtures/mixins/multiple/model.json | 400 -- .../fixtures/mixins/operations/model.json | 400 -- .../spec/fixtures/mixins/redefine/model.json | 400 -- .../mixins/replace-redefine/model.json | 400 -- .../spec/fixtures/mixins/resources/model.json | 400 -- .../spec/fixtures/mixins/services/model.json | 400 -- .../mixins/trait-inheritance/model.json | 400 -- .../fixtures/mixins/trait-order/model.json | 400 -- .../fixtures/mixins/trait-override/model.json | 400 -- .../fixtures/mixins/type-agnostic/model.json | 400 -- .../spec/fixtures/mixins/vanilla/model.json | 400 -- .../spec/fixtures/multi_service/model.json | 400 -- .../spec/fixtures/no_protocol/model.json | 400 -- .../spec/fixtures/no_service/model.json | 403 +- .../spec/fixtures/one_service/model.json | 400 -- .../smithy/spec/fixtures/recursive/model.json | 3907 ----------------- .../spec/fixtures/service_index/model.json | 47 - gems/smithy/spec/fixtures/shapes/model.json | 47 - .../spec/fixtures/syntax_examples/model.json | 47 - gems/smithy/spec/fixtures/weather/model.json | 263 -- .../spec/fixtures/weld_protocol/model.json | 263 -- 36 files changed, 1 insertion(+), 15754 deletions(-) diff --git a/gems/smithy/spec/fixtures/auth/auth_trait/model.json b/gems/smithy/spec/fixtures/auth/auth_trait/model.json index db88a755d..8c0af79fa 100644 --- a/gems/smithy/spec/fixtures/auth/auth_trait/model.json +++ b/gems/smithy/spec/fixtures/auth/auth_trait/model.json @@ -59,269 +59,6 @@ "smithy.api#httpBearerAuth": {}, "smithy.api#httpDigestAuth": {} } - }, - "smithy.waiters#Acceptor": { - "type": "structure", - "members": { - "state": { - "target": "smithy.waiters#AcceptorState", - "traits": { - "smithy.api#documentation": "The state the acceptor transitions to when matched.", - "smithy.api#required": {} - } - }, - "matcher": { - "target": "smithy.waiters#Matcher", - "traits": { - "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", - "smithy.api#private": {} - } - }, - "smithy.waiters#AcceptorState": { - "type": "enum", - "members": { - "SUCCESS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", - "smithy.api#enumValue": "success" - } - }, - "FAILURE": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", - "smithy.api#enumValue": "failure" - } - }, - "RETRY": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", - "smithy.api#enumValue": "retry" - } - } - }, - "traits": { - "smithy.api#documentation": "The transition state of a waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Acceptors": { - "type": "list", - "member": { - "target": "smithy.waiters#Acceptor" - }, - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#Matcher": { - "type": "union", - "members": { - "output": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." - } - }, - "inputOutput": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." - } - }, - "errorType": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." - } - }, - "success": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyString": { - "type": "string", - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyStringList": { - "type": "list", - "member": { - "target": "smithy.waiters#NonEmptyString" - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.waiters#PathComparator": { - "type": "enum", - "members": { - "STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", - "smithy.api#enumValue": "stringEquals" - } - }, - "BOOLEAN_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", - "smithy.api#enumValue": "booleanEquals" - } - }, - "ALL_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if all values in the list matches the expected string.", - "smithy.api#enumValue": "allStringEquals" - } - }, - "ANY_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if any value in the list matches the expected string.", - "smithy.api#enumValue": "anyStringEquals" - } - } - }, - "traits": { - "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", - "smithy.api#private": {} - } - }, - "smithy.waiters#PathMatcher": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", - "smithy.api#required": {} - } - }, - "expected": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected return value of the expression.", - "smithy.api#required": {} - } - }, - "comparator": { - "target": "smithy.waiters#PathComparator", - "traits": { - "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Waiter": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." - } - }, - "acceptors": { - "target": "smithy.waiters#Acceptors", - "traits": { - "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", - "smithy.api#required": {} - } - }, - "minDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 2, - "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." - } - }, - "maxDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 120, - "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." - } - }, - "deprecated": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." - } - }, - "tags": { - "target": "smithy.waiters#NonEmptyStringList", - "traits": { - "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines an individual operation waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#WaiterDelay": { - "type": "integer", - "traits": { - "smithy.api#range": { - "min": 1 - } - } - }, - "smithy.waiters#WaiterName": { - "type": "string", - "traits": { - "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" - } - }, - "smithy.waiters#waitable": { - "type": "map", - "key": { - "target": "smithy.waiters#WaiterName" - }, - "value": { - "target": "smithy.waiters#Waiter" - }, - "traits": { - "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#trait": { - "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" - } - } } } } diff --git a/gems/smithy/spec/fixtures/auth/http_api_key_auth/model.json b/gems/smithy/spec/fixtures/auth/http_api_key_auth/model.json index 4a6c9278c..33a8a7043 100644 --- a/gems/smithy/spec/fixtures/auth/http_api_key_auth/model.json +++ b/gems/smithy/spec/fixtures/auth/http_api_key_auth/model.json @@ -9,269 +9,6 @@ "in": "header" } } - }, - "smithy.waiters#Acceptor": { - "type": "structure", - "members": { - "state": { - "target": "smithy.waiters#AcceptorState", - "traits": { - "smithy.api#documentation": "The state the acceptor transitions to when matched.", - "smithy.api#required": {} - } - }, - "matcher": { - "target": "smithy.waiters#Matcher", - "traits": { - "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", - "smithy.api#private": {} - } - }, - "smithy.waiters#AcceptorState": { - "type": "enum", - "members": { - "SUCCESS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", - "smithy.api#enumValue": "success" - } - }, - "FAILURE": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", - "smithy.api#enumValue": "failure" - } - }, - "RETRY": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", - "smithy.api#enumValue": "retry" - } - } - }, - "traits": { - "smithy.api#documentation": "The transition state of a waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Acceptors": { - "type": "list", - "member": { - "target": "smithy.waiters#Acceptor" - }, - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#Matcher": { - "type": "union", - "members": { - "output": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." - } - }, - "inputOutput": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." - } - }, - "errorType": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." - } - }, - "success": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyString": { - "type": "string", - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyStringList": { - "type": "list", - "member": { - "target": "smithy.waiters#NonEmptyString" - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.waiters#PathComparator": { - "type": "enum", - "members": { - "STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", - "smithy.api#enumValue": "stringEquals" - } - }, - "BOOLEAN_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", - "smithy.api#enumValue": "booleanEquals" - } - }, - "ALL_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if all values in the list matches the expected string.", - "smithy.api#enumValue": "allStringEquals" - } - }, - "ANY_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if any value in the list matches the expected string.", - "smithy.api#enumValue": "anyStringEquals" - } - } - }, - "traits": { - "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", - "smithy.api#private": {} - } - }, - "smithy.waiters#PathMatcher": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", - "smithy.api#required": {} - } - }, - "expected": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected return value of the expression.", - "smithy.api#required": {} - } - }, - "comparator": { - "target": "smithy.waiters#PathComparator", - "traits": { - "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Waiter": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." - } - }, - "acceptors": { - "target": "smithy.waiters#Acceptors", - "traits": { - "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", - "smithy.api#required": {} - } - }, - "minDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 2, - "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." - } - }, - "maxDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 120, - "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." - } - }, - "deprecated": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." - } - }, - "tags": { - "target": "smithy.waiters#NonEmptyStringList", - "traits": { - "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines an individual operation waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#WaiterDelay": { - "type": "integer", - "traits": { - "smithy.api#range": { - "min": 1 - } - } - }, - "smithy.waiters#WaiterName": { - "type": "string", - "traits": { - "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" - } - }, - "smithy.waiters#waitable": { - "type": "map", - "key": { - "target": "smithy.waiters#WaiterName" - }, - "value": { - "target": "smithy.waiters#Waiter" - }, - "traits": { - "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#trait": { - "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" - } - } } } } diff --git a/gems/smithy/spec/fixtures/auth/http_basic_auth/model.json b/gems/smithy/spec/fixtures/auth/http_basic_auth/model.json index 19c418f2e..7cd1ac5b5 100644 --- a/gems/smithy/spec/fixtures/auth/http_basic_auth/model.json +++ b/gems/smithy/spec/fixtures/auth/http_basic_auth/model.json @@ -6,269 +6,6 @@ "traits": { "smithy.api#httpBasicAuth": {} } - }, - "smithy.waiters#Acceptor": { - "type": "structure", - "members": { - "state": { - "target": "smithy.waiters#AcceptorState", - "traits": { - "smithy.api#documentation": "The state the acceptor transitions to when matched.", - "smithy.api#required": {} - } - }, - "matcher": { - "target": "smithy.waiters#Matcher", - "traits": { - "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", - "smithy.api#private": {} - } - }, - "smithy.waiters#AcceptorState": { - "type": "enum", - "members": { - "SUCCESS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", - "smithy.api#enumValue": "success" - } - }, - "FAILURE": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", - "smithy.api#enumValue": "failure" - } - }, - "RETRY": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", - "smithy.api#enumValue": "retry" - } - } - }, - "traits": { - "smithy.api#documentation": "The transition state of a waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Acceptors": { - "type": "list", - "member": { - "target": "smithy.waiters#Acceptor" - }, - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#Matcher": { - "type": "union", - "members": { - "output": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." - } - }, - "inputOutput": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." - } - }, - "errorType": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." - } - }, - "success": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyString": { - "type": "string", - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyStringList": { - "type": "list", - "member": { - "target": "smithy.waiters#NonEmptyString" - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.waiters#PathComparator": { - "type": "enum", - "members": { - "STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", - "smithy.api#enumValue": "stringEquals" - } - }, - "BOOLEAN_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", - "smithy.api#enumValue": "booleanEquals" - } - }, - "ALL_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if all values in the list matches the expected string.", - "smithy.api#enumValue": "allStringEquals" - } - }, - "ANY_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if any value in the list matches the expected string.", - "smithy.api#enumValue": "anyStringEquals" - } - } - }, - "traits": { - "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", - "smithy.api#private": {} - } - }, - "smithy.waiters#PathMatcher": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", - "smithy.api#required": {} - } - }, - "expected": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected return value of the expression.", - "smithy.api#required": {} - } - }, - "comparator": { - "target": "smithy.waiters#PathComparator", - "traits": { - "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Waiter": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." - } - }, - "acceptors": { - "target": "smithy.waiters#Acceptors", - "traits": { - "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", - "smithy.api#required": {} - } - }, - "minDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 2, - "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." - } - }, - "maxDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 120, - "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." - } - }, - "deprecated": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." - } - }, - "tags": { - "target": "smithy.waiters#NonEmptyStringList", - "traits": { - "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines an individual operation waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#WaiterDelay": { - "type": "integer", - "traits": { - "smithy.api#range": { - "min": 1 - } - } - }, - "smithy.waiters#WaiterName": { - "type": "string", - "traits": { - "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" - } - }, - "smithy.waiters#waitable": { - "type": "map", - "key": { - "target": "smithy.waiters#WaiterName" - }, - "value": { - "target": "smithy.waiters#Waiter" - }, - "traits": { - "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#trait": { - "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" - } - } } } } diff --git a/gems/smithy/spec/fixtures/auth/http_bearer_auth/model.json b/gems/smithy/spec/fixtures/auth/http_bearer_auth/model.json index 4b3d56969..f5d48b8cc 100644 --- a/gems/smithy/spec/fixtures/auth/http_bearer_auth/model.json +++ b/gems/smithy/spec/fixtures/auth/http_bearer_auth/model.json @@ -6,269 +6,6 @@ "traits": { "smithy.api#httpBearerAuth": {} } - }, - "smithy.waiters#Acceptor": { - "type": "structure", - "members": { - "state": { - "target": "smithy.waiters#AcceptorState", - "traits": { - "smithy.api#documentation": "The state the acceptor transitions to when matched.", - "smithy.api#required": {} - } - }, - "matcher": { - "target": "smithy.waiters#Matcher", - "traits": { - "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", - "smithy.api#private": {} - } - }, - "smithy.waiters#AcceptorState": { - "type": "enum", - "members": { - "SUCCESS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", - "smithy.api#enumValue": "success" - } - }, - "FAILURE": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", - "smithy.api#enumValue": "failure" - } - }, - "RETRY": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", - "smithy.api#enumValue": "retry" - } - } - }, - "traits": { - "smithy.api#documentation": "The transition state of a waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Acceptors": { - "type": "list", - "member": { - "target": "smithy.waiters#Acceptor" - }, - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#Matcher": { - "type": "union", - "members": { - "output": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." - } - }, - "inputOutput": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." - } - }, - "errorType": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." - } - }, - "success": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyString": { - "type": "string", - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyStringList": { - "type": "list", - "member": { - "target": "smithy.waiters#NonEmptyString" - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.waiters#PathComparator": { - "type": "enum", - "members": { - "STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", - "smithy.api#enumValue": "stringEquals" - } - }, - "BOOLEAN_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", - "smithy.api#enumValue": "booleanEquals" - } - }, - "ALL_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if all values in the list matches the expected string.", - "smithy.api#enumValue": "allStringEquals" - } - }, - "ANY_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if any value in the list matches the expected string.", - "smithy.api#enumValue": "anyStringEquals" - } - } - }, - "traits": { - "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", - "smithy.api#private": {} - } - }, - "smithy.waiters#PathMatcher": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", - "smithy.api#required": {} - } - }, - "expected": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected return value of the expression.", - "smithy.api#required": {} - } - }, - "comparator": { - "target": "smithy.waiters#PathComparator", - "traits": { - "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Waiter": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." - } - }, - "acceptors": { - "target": "smithy.waiters#Acceptors", - "traits": { - "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", - "smithy.api#required": {} - } - }, - "minDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 2, - "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." - } - }, - "maxDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 120, - "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." - } - }, - "deprecated": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." - } - }, - "tags": { - "target": "smithy.waiters#NonEmptyStringList", - "traits": { - "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines an individual operation waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#WaiterDelay": { - "type": "integer", - "traits": { - "smithy.api#range": { - "min": 1 - } - } - }, - "smithy.waiters#WaiterName": { - "type": "string", - "traits": { - "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" - } - }, - "smithy.waiters#waitable": { - "type": "map", - "key": { - "target": "smithy.waiters#WaiterName" - }, - "value": { - "target": "smithy.waiters#Waiter" - }, - "traits": { - "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#trait": { - "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" - } - } } } } diff --git a/gems/smithy/spec/fixtures/auth/http_digest_auth/model.json b/gems/smithy/spec/fixtures/auth/http_digest_auth/model.json index 2ac58ef65..ca3b44225 100644 --- a/gems/smithy/spec/fixtures/auth/http_digest_auth/model.json +++ b/gems/smithy/spec/fixtures/auth/http_digest_auth/model.json @@ -6,269 +6,6 @@ "traits": { "smithy.api#httpDigestAuth": {} } - }, - "smithy.waiters#Acceptor": { - "type": "structure", - "members": { - "state": { - "target": "smithy.waiters#AcceptorState", - "traits": { - "smithy.api#documentation": "The state the acceptor transitions to when matched.", - "smithy.api#required": {} - } - }, - "matcher": { - "target": "smithy.waiters#Matcher", - "traits": { - "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", - "smithy.api#private": {} - } - }, - "smithy.waiters#AcceptorState": { - "type": "enum", - "members": { - "SUCCESS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", - "smithy.api#enumValue": "success" - } - }, - "FAILURE": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", - "smithy.api#enumValue": "failure" - } - }, - "RETRY": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", - "smithy.api#enumValue": "retry" - } - } - }, - "traits": { - "smithy.api#documentation": "The transition state of a waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Acceptors": { - "type": "list", - "member": { - "target": "smithy.waiters#Acceptor" - }, - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#Matcher": { - "type": "union", - "members": { - "output": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." - } - }, - "inputOutput": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." - } - }, - "errorType": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." - } - }, - "success": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyString": { - "type": "string", - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyStringList": { - "type": "list", - "member": { - "target": "smithy.waiters#NonEmptyString" - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.waiters#PathComparator": { - "type": "enum", - "members": { - "STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", - "smithy.api#enumValue": "stringEquals" - } - }, - "BOOLEAN_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", - "smithy.api#enumValue": "booleanEquals" - } - }, - "ALL_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if all values in the list matches the expected string.", - "smithy.api#enumValue": "allStringEquals" - } - }, - "ANY_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if any value in the list matches the expected string.", - "smithy.api#enumValue": "anyStringEquals" - } - } - }, - "traits": { - "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", - "smithy.api#private": {} - } - }, - "smithy.waiters#PathMatcher": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", - "smithy.api#required": {} - } - }, - "expected": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected return value of the expression.", - "smithy.api#required": {} - } - }, - "comparator": { - "target": "smithy.waiters#PathComparator", - "traits": { - "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Waiter": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." - } - }, - "acceptors": { - "target": "smithy.waiters#Acceptors", - "traits": { - "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", - "smithy.api#required": {} - } - }, - "minDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 2, - "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." - } - }, - "maxDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 120, - "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." - } - }, - "deprecated": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." - } - }, - "tags": { - "target": "smithy.waiters#NonEmptyStringList", - "traits": { - "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines an individual operation waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#WaiterDelay": { - "type": "integer", - "traits": { - "smithy.api#range": { - "min": 1 - } - } - }, - "smithy.waiters#WaiterName": { - "type": "string", - "traits": { - "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" - } - }, - "smithy.waiters#waitable": { - "type": "map", - "key": { - "target": "smithy.waiters#WaiterName" - }, - "value": { - "target": "smithy.waiters#Waiter" - }, - "traits": { - "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#trait": { - "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" - } - } } } } diff --git a/gems/smithy/spec/fixtures/auth/no_auth_trait/model.json b/gems/smithy/spec/fixtures/auth/no_auth_trait/model.json index cbbf2e25e..f74113c77 100644 --- a/gems/smithy/spec/fixtures/auth/no_auth_trait/model.json +++ b/gems/smithy/spec/fixtures/auth/no_auth_trait/model.json @@ -40,269 +40,6 @@ "smithy.api#httpBearerAuth": {}, "smithy.api#httpDigestAuth": {} } - }, - "smithy.waiters#Acceptor": { - "type": "structure", - "members": { - "state": { - "target": "smithy.waiters#AcceptorState", - "traits": { - "smithy.api#documentation": "The state the acceptor transitions to when matched.", - "smithy.api#required": {} - } - }, - "matcher": { - "target": "smithy.waiters#Matcher", - "traits": { - "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", - "smithy.api#private": {} - } - }, - "smithy.waiters#AcceptorState": { - "type": "enum", - "members": { - "SUCCESS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", - "smithy.api#enumValue": "success" - } - }, - "FAILURE": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", - "smithy.api#enumValue": "failure" - } - }, - "RETRY": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", - "smithy.api#enumValue": "retry" - } - } - }, - "traits": { - "smithy.api#documentation": "The transition state of a waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Acceptors": { - "type": "list", - "member": { - "target": "smithy.waiters#Acceptor" - }, - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#Matcher": { - "type": "union", - "members": { - "output": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." - } - }, - "inputOutput": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." - } - }, - "errorType": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." - } - }, - "success": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyString": { - "type": "string", - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyStringList": { - "type": "list", - "member": { - "target": "smithy.waiters#NonEmptyString" - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.waiters#PathComparator": { - "type": "enum", - "members": { - "STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", - "smithy.api#enumValue": "stringEquals" - } - }, - "BOOLEAN_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", - "smithy.api#enumValue": "booleanEquals" - } - }, - "ALL_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if all values in the list matches the expected string.", - "smithy.api#enumValue": "allStringEquals" - } - }, - "ANY_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if any value in the list matches the expected string.", - "smithy.api#enumValue": "anyStringEquals" - } - } - }, - "traits": { - "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", - "smithy.api#private": {} - } - }, - "smithy.waiters#PathMatcher": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", - "smithy.api#required": {} - } - }, - "expected": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected return value of the expression.", - "smithy.api#required": {} - } - }, - "comparator": { - "target": "smithy.waiters#PathComparator", - "traits": { - "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Waiter": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." - } - }, - "acceptors": { - "target": "smithy.waiters#Acceptors", - "traits": { - "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", - "smithy.api#required": {} - } - }, - "minDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 2, - "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." - } - }, - "maxDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 120, - "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." - } - }, - "deprecated": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." - } - }, - "tags": { - "target": "smithy.waiters#NonEmptyStringList", - "traits": { - "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines an individual operation waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#WaiterDelay": { - "type": "integer", - "traits": { - "smithy.api#range": { - "min": 1 - } - } - }, - "smithy.waiters#WaiterName": { - "type": "string", - "traits": { - "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" - } - }, - "smithy.waiters#waitable": { - "type": "map", - "key": { - "target": "smithy.waiters#WaiterName" - }, - "value": { - "target": "smithy.waiters#Waiter" - }, - "traits": { - "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#trait": { - "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" - } - } } } } diff --git a/gems/smithy/spec/fixtures/errors/model.json b/gems/smithy/spec/fixtures/errors/model.json index 15885913b..92ca9db43 100644 --- a/gems/smithy/spec/fixtures/errors/model.json +++ b/gems/smithy/spec/fixtures/errors/model.json @@ -118,406 +118,6 @@ "target": "smithy.api#String" } } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/examples_trait/model.json b/gems/smithy/spec/fixtures/examples_trait/model.json index 82b30edd0..6991c174d 100644 --- a/gems/smithy/spec/fixtures/examples_trait/model.json +++ b/gems/smithy/spec/fixtures/examples_trait/model.json @@ -139,406 +139,6 @@ "target": "smithy.api#String" } } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/apply-list/model.json b/gems/smithy/spec/fixtures/mixins/apply-list/model.json index 8073d77e1..ee9a4f1ee 100644 --- a/gems/smithy/spec/fixtures/mixins/apply-list/model.json +++ b/gems/smithy/spec/fixtures/mixins/apply-list/model.json @@ -26,406 +26,6 @@ "traits": { "smithy.api#mixin": {} } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/apply-map/model.json b/gems/smithy/spec/fixtures/mixins/apply-map/model.json index 62c6c06d6..cdda857fd 100644 --- a/gems/smithy/spec/fixtures/mixins/apply-map/model.json +++ b/gems/smithy/spec/fixtures/mixins/apply-map/model.json @@ -38,406 +38,6 @@ "traits": { "smithy.api#mixin": {} } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/apply-structure/model.json b/gems/smithy/spec/fixtures/mixins/apply-structure/model.json index a2bf46593..5ece222c8 100644 --- a/gems/smithy/spec/fixtures/mixins/apply-structure/model.json +++ b/gems/smithy/spec/fixtures/mixins/apply-structure/model.json @@ -29,406 +29,6 @@ "traits": { "smithy.api#documentation": "Specific docs" } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/apply-union/model.json b/gems/smithy/spec/fixtures/mixins/apply-union/model.json index 1e2fdcb86..6bc886eae 100644 --- a/gems/smithy/spec/fixtures/mixins/apply-union/model.json +++ b/gems/smithy/spec/fixtures/mixins/apply-union/model.json @@ -29,406 +29,6 @@ "traits": { "smithy.api#documentation": "Specific docs" } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/composed/model.json b/gems/smithy/spec/fixtures/mixins/composed/model.json index a17329d51..f6b2d1d79 100644 --- a/gems/smithy/spec/fixtures/mixins/composed/model.json +++ b/gems/smithy/spec/fixtures/mixins/composed/model.json @@ -40,406 +40,6 @@ "traits": { "smithy.api#mixin": {} } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/local-traits/model.json b/gems/smithy/spec/fixtures/mixins/local-traits/model.json index 332ad9b16..c46d937e4 100644 --- a/gems/smithy/spec/fixtures/mixins/local-traits/model.json +++ b/gems/smithy/spec/fixtures/mixins/local-traits/model.json @@ -25,406 +25,6 @@ } ], "members": {} - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/member-order/model.json b/gems/smithy/spec/fixtures/mixins/member-order/model.json index 359a034a9..290b16e84 100644 --- a/gems/smithy/spec/fixtures/mixins/member-order/model.json +++ b/gems/smithy/spec/fixtures/mixins/member-order/model.json @@ -41,406 +41,6 @@ "traits": { "smithy.api#mixin": {} } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/multiple/model.json b/gems/smithy/spec/fixtures/mixins/multiple/model.json index 9a9993db2..d8b0cdca3 100644 --- a/gems/smithy/spec/fixtures/mixins/multiple/model.json +++ b/gems/smithy/spec/fixtures/mixins/multiple/model.json @@ -41,406 +41,6 @@ "traits": { "smithy.api#mixin": {} } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/operations/model.json b/gems/smithy/spec/fixtures/mixins/operations/model.json index dcd5dece4..d083d9185 100644 --- a/gems/smithy/spec/fixtures/mixins/operations/model.json +++ b/gems/smithy/spec/fixtures/mixins/operations/model.json @@ -72,406 +72,6 @@ "traits": { "smithy.api#error": "client" } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/redefine/model.json b/gems/smithy/spec/fixtures/mixins/redefine/model.json index 33674c412..4fbb9f0f1 100644 --- a/gems/smithy/spec/fixtures/mixins/redefine/model.json +++ b/gems/smithy/spec/fixtures/mixins/redefine/model.json @@ -46,406 +46,6 @@ "traits": { "smithy.api#required": {} } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/replace-redefine/model.json b/gems/smithy/spec/fixtures/mixins/replace-redefine/model.json index a2bf46593..5ece222c8 100644 --- a/gems/smithy/spec/fixtures/mixins/replace-redefine/model.json +++ b/gems/smithy/spec/fixtures/mixins/replace-redefine/model.json @@ -29,406 +29,6 @@ "traits": { "smithy.api#documentation": "Specific docs" } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/resources/model.json b/gems/smithy/spec/fixtures/mixins/resources/model.json index 14b2734ab..6dc2eff59 100644 --- a/gems/smithy/spec/fixtures/mixins/resources/model.json +++ b/gems/smithy/spec/fixtures/mixins/resources/model.json @@ -15,406 +15,6 @@ "smithy.api#internal": {}, "smithy.api#mixin": {} } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/services/model.json b/gems/smithy/spec/fixtures/mixins/services/model.json index 8ef324b82..7e8a95df9 100644 --- a/gems/smithy/spec/fixtures/mixins/services/model.json +++ b/gems/smithy/spec/fixtures/mixins/services/model.json @@ -90,406 +90,6 @@ "output": { "target": "smithy.api#Unit" } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/trait-inheritance/model.json b/gems/smithy/spec/fixtures/mixins/trait-inheritance/model.json index 03e2fb6fd..25dc4982c 100644 --- a/gems/smithy/spec/fixtures/mixins/trait-inheritance/model.json +++ b/gems/smithy/spec/fixtures/mixins/trait-inheritance/model.json @@ -24,406 +24,6 @@ } ], "members": {} - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/trait-order/model.json b/gems/smithy/spec/fixtures/mixins/trait-order/model.json index a65191e3f..d4a8490e7 100644 --- a/gems/smithy/spec/fixtures/mixins/trait-order/model.json +++ b/gems/smithy/spec/fixtures/mixins/trait-order/model.json @@ -84,406 +84,6 @@ "traits": { "smithy.api#trait": {} } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/trait-override/model.json b/gems/smithy/spec/fixtures/mixins/trait-override/model.json index 24ae903a0..60d84694c 100644 --- a/gems/smithy/spec/fixtures/mixins/trait-override/model.json +++ b/gems/smithy/spec/fixtures/mixins/trait-override/model.json @@ -30,406 +30,6 @@ "replaced-tags" ] } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/type-agnostic/model.json b/gems/smithy/spec/fixtures/mixins/type-agnostic/model.json index 8c48c18b5..6e9a4d7c1 100644 --- a/gems/smithy/spec/fixtures/mixins/type-agnostic/model.json +++ b/gems/smithy/spec/fixtures/mixins/type-agnostic/model.json @@ -21,406 +21,6 @@ "max": 32 } } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/mixins/vanilla/model.json b/gems/smithy/spec/fixtures/mixins/vanilla/model.json index a73ec41fb..d76eda5d8 100644 --- a/gems/smithy/spec/fixtures/mixins/vanilla/model.json +++ b/gems/smithy/spec/fixtures/mixins/vanilla/model.json @@ -24,406 +24,6 @@ "traits": { "smithy.api#mixin": {} } - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/multi_service/model.json b/gems/smithy/spec/fixtures/multi_service/model.json index f8572e6db..b427e9ff6 100644 --- a/gems/smithy/spec/fixtures/multi_service/model.json +++ b/gems/smithy/spec/fixtures/multi_service/model.json @@ -6,406 +6,6 @@ }, "smithy.ruby.tests#Service2": { "type": "service" - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/no_protocol/model.json b/gems/smithy/spec/fixtures/no_protocol/model.json index 3dcfd96ad..6803eb6e8 100644 --- a/gems/smithy/spec/fixtures/no_protocol/model.json +++ b/gems/smithy/spec/fixtures/no_protocol/model.json @@ -3,406 +3,6 @@ "shapes": { "smithy.ruby.tests#NoProtocolService": { "type": "service" - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/no_service/model.json b/gems/smithy/spec/fixtures/no_service/model.json index 30e9b269d..46240d48a 100644 --- a/gems/smithy/spec/fixtures/no_service/model.json +++ b/gems/smithy/spec/fixtures/no_service/model.json @@ -1,405 +1,4 @@ { "smithy": "2.0", - "shapes": { - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - } - } + "shapes": {} } diff --git a/gems/smithy/spec/fixtures/one_service/model.json b/gems/smithy/spec/fixtures/one_service/model.json index 08cb62164..37aa2f545 100644 --- a/gems/smithy/spec/fixtures/one_service/model.json +++ b/gems/smithy/spec/fixtures/one_service/model.json @@ -3,406 +3,6 @@ "shapes": { "smithy.ruby.tests#Service1": { "type": "service" - }, - "smithy.rules#ClientContextParamDefinition": { - "type": "structure", - "members": { - "type": { - "target": "smithy.rules#ShapeType", - "traits": { - "smithy.api#documentation": "The Smithy shape type that should be used to generate a client configurable for the rule-set parameter.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation string to be generated with the client parameter." - } - } - }, - "traits": { - "smithy.api#documentation": "A client context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointExpectation": { - "type": "structure", - "members": { - "url": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected endpoint URL to be resolved for this test case." - } - }, - "headers": { - "target": "smithy.rules#EndpointHeaders", - "traits": { - "smithy.api#documentation": "The transport headers to be set for this test case." - } - }, - "properties": { - "target": "smithy.rules#Properties", - "traits": { - "smithy.api#documentation": "The properties for the endpoint for this test case." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of an expected endpoint to be resolved for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaderValue": { - "type": "list", - "member": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A transport header value." - } - }, - "traits": { - "smithy.api#documentation": "A list of transport header values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointHeaders": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The transport header name." - } - }, - "value": { - "target": "smithy.rules#EndpointHeaderValue", - "traits": { - "smithy.api#documentation": "The transport header values." - } - }, - "traits": { - "smithy.api#documentation": "A map of header names to list of values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTest": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation describing the test case." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines rule-set parameters and values to use for testing rules-engine." - } - }, - "operationInputs": { - "target": "smithy.rules#OperationInputs", - "traits": { - "smithy.api#documentation": "Defines a set of service operation configurations used for testing the rules-engine." - } - }, - "expect": { - "target": "smithy.rules#EndpointTestExpectation", - "traits": { - "smithy.api#documentation": "The expected outcome of the test case.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes an endpoint test case for validation of an endpoint rule-set.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestExpectation": { - "type": "union", - "members": { - "error": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an error." - } - }, - "endpoint": { - "target": "smithy.rules#EndpointExpectation", - "traits": { - "smithy.api#documentation": "A test case expectation resulting in an endpoint." - } - } - }, - "traits": { - "smithy.api#documentation": "An endpoint rule-set test expectation describing an expected endpoint or error.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#EndpointTestList": { - "type": "list", - "member": { - "target": "smithy.rules#EndpointTest" - }, - "traits": { - "smithy.api#documentation": "A list of endpoint rule-set tests.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationContextParamDefinition": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "a JMESPath expression to select element(s) from the operation input to bind to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "An operation context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInput": { - "type": "structure", - "members": { - "operationName": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the service operation targeted by the test.", - "smithy.api#required": {} - } - }, - "operationParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generate the operation request.\nThese parameters MUST be compatible with the input of the operation." - } - }, - "builtInParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of rule-set built-ins and their corresponding values to be set." - } - }, - "clientParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the set of client configuration parameters to be set." - } - } - }, - "traits": { - "smithy.api#documentation": "A description of a service operation and input used to verify an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#OperationInputs": { - "type": "list", - "member": { - "target": "smithy.rules#OperationInput", - "traits": { - "smithy.api#documentation": "The service operation configuration to be used for testing the rules-engine." - } - }, - "traits": { - "smithy.api#documentation": "A list of operation input descriptions for an endpoint rule-set test case.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#Properties": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The property name." - } - }, - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The property value." - } - }, - "traits": { - "smithy.api#documentation": "A map of strings to document values.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#ShapeType": { - "type": "enum", - "members": { - "STRING": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy string shape type.", - "smithy.api#enumValue": "string" - } - }, - "BOOLEAN": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Indicates a Smithy boolean shape type.", - "smithy.api#enumValue": "boolean" - } - } - }, - "traits": { - "smithy.api#documentation": "An enum representing supported Smithy shape types.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#StaticContextParamDefinition": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "The value to set the associated rule-set parameter to.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "A static context parameter definition.", - "smithy.api#private": {}, - "smithy.api#unstable": {} - } - }, - "smithy.rules#clientContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#ClientContextParamDefinition", - "traits": { - "smithy.api#documentation": "The client parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Defines one or more named rule-set parameters to be generated as configurable client parameters.\nThe type specified for the client parameter MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#contextParam": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Binds the targeted member of an operation's input structure to the named rule-set parameter.\nThe type of the shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation -[input]-> structure > member" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointRuleSet": { - "type": "document", - "traits": { - "smithy.api#documentation": "Defines an endpoint rule-set used to resolve the client's transport endpoint.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#endpointTests": { - "type": "structure", - "members": { - "version": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The endpoint tests schema version.", - "smithy.api#required": {} - } - }, - "testCases": { - "target": "smithy.rules#EndpointTestList", - "traits": { - "smithy.api#documentation": "List of endpoint test cases." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines endpoint test-cases for validating a client's endpoint rule-set.", - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#operationContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#OperationContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to elements contained in the operation's input structure.\nThe type of the shapes targeted by the trait MUST match the parameter types defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.rules#staticContextParams": { - "type": "map", - "key": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The rule-set parameter name." - } - }, - "value": { - "target": "smithy.rules#StaticContextParamDefinition", - "traits": { - "smithy.api#documentation": "The static parameter definition." - } - }, - "traits": { - "smithy.api#documentation": "Binds one or more named rule-set parameters to the defined static value for the targeted operation.\nThe type of the targeted shape targeted by the trait MUST match the parameter type defined in the rule-set.", - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } } } } diff --git a/gems/smithy/spec/fixtures/recursive/model.json b/gems/smithy/spec/fixtures/recursive/model.json index 90a3dd8d0..b56b8f3fb 100644 --- a/gems/smithy/spec/fixtures/recursive/model.json +++ b/gems/smithy/spec/fixtures/recursive/model.json @@ -1,3331 +1,6 @@ { "smithy": "2.0", - "metadata": { - "validators": [ - { - "configuration": { - "selector": "operation :not(< service)" - }, - "id": "UnboundTestOperation", - "message": "This operation in the Smithy protocol tests is not bound to a service.", - "name": "EmitEachSelector", - "namespaces": [ - "smithy.protocoltests.rpcv2Cbor" - ], - "severity": "WARNING" - } - ] - }, "shapes": { - "smithy.framework#ValidationException": { - "type": "structure", - "members": { - "message": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A summary of the validation failure.", - "smithy.api#required": {} - } - }, - "fieldList": { - "target": "smithy.framework#ValidationExceptionFieldList", - "traits": { - "smithy.api#documentation": "A list of specific failures encountered while validating the input.\nA member can appear in this list more than once if it failed to satisfy multiple constraints." - } - } - }, - "traits": { - "smithy.api#documentation": "A standard error for input validation failures.\nThis should be thrown by services when a member of the input structure\nfalls outside of the modeled or documented constraints.", - "smithy.api#error": "client" - } - }, - "smithy.framework#ValidationExceptionField": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A JSONPointer expression to the structure member whose value failed to satisfy the modeled constraints.", - "smithy.api#required": {} - } - }, - "message": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A detailed description of the validation failure.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Describes one specific validation failure for an input member." - } - }, - "smithy.framework#ValidationExceptionFieldList": { - "type": "list", - "member": { - "target": "smithy.framework#ValidationExceptionField" - } - }, - "smithy.protocols#StringList": { - "type": "list", - "member": { - "target": "smithy.api#String" - }, - "traits": { - "smithy.api#documentation": "A list of String shapes.", - "smithy.api#private": {} - } - }, - "smithy.protocols#rpcv2Cbor": { - "type": "structure", - "members": { - "http": { - "target": "smithy.protocols#StringList", - "traits": { - "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions." - } - }, - "eventStreamHttp": { - "target": "smithy.protocols#StringList", - "traits": { - "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions\nthat are required when using event streams." - } - } - }, - "traits": { - "smithy.api#documentation": "An RPC-based protocol that serializes CBOR payloads.", - "smithy.api#protocolDefinition": { - "traits": [ - "smithy.api#cors", - "smithy.api#endpoint", - "smithy.api#hostLabel", - "smithy.api#httpError" - ] - }, - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#traitValidators": { - "rpcv2Cbor.NoDocuments": { - "selector": "service ~> member :test(> document)", - "message": "This protocol does not support document types" - } - } - } - }, - "smithy.protocoltests.rpcv2Cbor#ClientOptionalDefaults": { - "type": "structure", - "members": { - "member": { - "target": "smithy.api#Integer", - "traits": { - "smithy.api#clientOptional": {}, - "smithy.api#default": 0 - } - } - } - }, - "smithy.protocoltests.rpcv2Cbor#ComplexError": { - "type": "structure", - "members": { - "TopLevel": { - "target": "smithy.api#String" - }, - "Nested": { - "target": "smithy.protocoltests.rpcv2Cbor#ComplexNestedErrorData" - } - }, - "traits": { - "smithy.api#documentation": "This error is thrown when a request is invalid.", - "smithy.api#error": "client", - "smithy.test#httpResponseTests": [ - { - "id": "RpcV2CborComplexError", - "documentation": "Parses a complex error with no message member", - "protocol": "smithy.protocols#rpcv2Cbor", - "params": { - "TopLevel": "Top level", - "Nested": { - "Foo": "bar" - } - }, - "code": 400, - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "body": "v2ZfX3R5cGV4K3NtaXRoeS5wcm90b2NvbHRlc3RzLnJwY3YyQ2JvciNDb21wbGV4RXJyb3JoVG9wTGV2ZWxpVG9wIGxldmVsZk5lc3RlZL9jRm9vY2Jhcv//", - "bodyMediaType": "application/cbor" - }, - { - "id": "RpcV2CborEmptyComplexError", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 400, - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "body": "v2ZfX3R5cGV4K3NtaXRoeS5wcm90b2NvbHRlc3RzLnJwY3YyQ2JvciNDb21wbGV4RXJyb3L/", - "bodyMediaType": "application/cbor" - } - ] - } - }, - "smithy.protocoltests.rpcv2Cbor#ComplexNestedErrorData": { - "type": "structure", - "members": { - "Foo": { - "target": "smithy.api#String" - } - } - }, - "smithy.protocoltests.rpcv2Cbor#Defaults": { - "type": "structure", - "mixins": [ - { - "target": "smithy.protocoltests.rpcv2Cbor#DefaultsMixin" - } - ], - "members": {} - }, - "smithy.protocoltests.rpcv2Cbor#DefaultsMixin": { - "type": "structure", - "members": { - "defaultString": { - "target": "smithy.api#String", - "traits": { - "smithy.api#default": "hi" - } - }, - "defaultBoolean": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#default": true - } - }, - "defaultList": { - "target": "smithy.protocoltests.rpcv2Cbor#TestStringList", - "traits": { - "smithy.api#default": [] - } - }, - "defaultTimestamp": { - "target": "smithy.api#Timestamp", - "traits": { - "smithy.api#default": 0 - } - }, - "defaultBlob": { - "target": "smithy.api#Blob", - "traits": { - "smithy.api#default": "YWJj" - } - }, - "defaultByte": { - "target": "smithy.api#Byte", - "traits": { - "smithy.api#default": 1 - } - }, - "defaultShort": { - "target": "smithy.api#Short", - "traits": { - "smithy.api#default": 1 - } - }, - "defaultInteger": { - "target": "smithy.api#Integer", - "traits": { - "smithy.api#default": 10 - } - }, - "defaultLong": { - "target": "smithy.api#Long", - "traits": { - "smithy.api#default": 100 - } - }, - "defaultFloat": { - "target": "smithy.api#Float", - "traits": { - "smithy.api#default": 1.0 - } - }, - "defaultDouble": { - "target": "smithy.api#Double", - "traits": { - "smithy.api#default": 1.0 - } - }, - "defaultMap": { - "target": "smithy.protocoltests.rpcv2Cbor#TestStringMap", - "traits": { - "smithy.api#default": {} - } - }, - "defaultEnum": { - "target": "smithy.protocoltests.rpcv2Cbor#TestEnum", - "traits": { - "smithy.api#default": "FOO" - } - }, - "defaultIntEnum": { - "target": "smithy.protocoltests.rpcv2Cbor#TestIntEnum", - "traits": { - "smithy.api#default": 1 - } - }, - "emptyString": { - "target": "smithy.api#String", - "traits": { - "smithy.api#default": "" - } - }, - "falseBoolean": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#default": false - } - }, - "emptyBlob": { - "target": "smithy.api#Blob", - "traits": { - "smithy.api#default": "" - } - }, - "zeroByte": { - "target": "smithy.api#Byte", - "traits": { - "smithy.api#default": 0 - } - }, - "zeroShort": { - "target": "smithy.api#Short", - "traits": { - "smithy.api#default": 0 - } - }, - "zeroInteger": { - "target": "smithy.api#Integer", - "traits": { - "smithy.api#default": 0 - } - }, - "zeroLong": { - "target": "smithy.api#Long", - "traits": { - "smithy.api#default": 0 - } - }, - "zeroFloat": { - "target": "smithy.api#Float", - "traits": { - "smithy.api#default": 0.0 - } - }, - "zeroDouble": { - "target": "smithy.api#Double", - "traits": { - "smithy.api#default": 0.0 - } - } - }, - "traits": { - "smithy.api#mixin": {} - } - }, - "smithy.protocoltests.rpcv2Cbor#DenseBooleanMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.api#Boolean" - } - }, - "smithy.protocoltests.rpcv2Cbor#DenseNumberMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.api#Integer" - } - }, - "smithy.protocoltests.rpcv2Cbor#DenseSetMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.protocoltests.shared#StringSet" - } - }, - "smithy.protocoltests.rpcv2Cbor#DenseStringMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.api#String" - } - }, - "smithy.protocoltests.rpcv2Cbor#DenseStructMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.protocoltests.shared#GreetingStruct" - } - }, - "smithy.protocoltests.rpcv2Cbor#EmptyInputOutput": { - "type": "operation", - "input": { - "target": "smithy.protocoltests.rpcv2Cbor#EmptyStructure" - }, - "output": { - "target": "smithy.protocoltests.rpcv2Cbor#EmptyStructure" - }, - "traits": { - "smithy.test#httpRequestTests": [ - { - "id": "empty_input", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "When Input structure is empty we write CBOR equivalent of {}", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "forbidHeaders": [ - "X-Amz-Target" - ], - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/EmptyInputOutput", - "bodyMediaType": "application/cbor", - "body": "v/8=" - }, - { - "id": "empty_input_no_body", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "When Input structure is empty the server should accept an empty body", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Accept": "application/cbor", - "Content-Type": "application/cbor" - }, - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/EmptyInputOutput", - "bodyMediaType": "application/cbor", - "body": "", - "appliesTo": "server" - }, - { - "id": "empty_input_no_body_has_accept", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "When input structure, is empty the server should accept an empty body\neven if the Accept header is set.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Accept": "application/cbor", - "Content-Type": "application/cbor" - }, - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/EmptyInputOutput", - "bodyMediaType": "application/cbor", - "body": "", - "appliesTo": "server" - } - ], - "smithy.test#httpResponseTests": [ - { - "id": "empty_output", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "When output structure is empty we write CBOR equivalent of {}", - "body": "v/8=", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "code": 200 - }, - { - "id": "empty_output_no_body", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "When output structure is empty the client should accept an empty body", - "body": "", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "code": 200, - "appliesTo": "client" - } - ] - } - }, - "smithy.protocoltests.rpcv2Cbor#EmptyStructure": { - "type": "structure", - "members": {} - }, - "smithy.protocoltests.rpcv2Cbor#Float16": { - "type": "operation", - "input": { - "target": "smithy.api#Unit" - }, - "output": { - "target": "smithy.protocoltests.rpcv2Cbor#Float16Output" - }, - "traits": { - "smithy.api#tags": [ - "client-only" - ], - "smithy.test#httpResponseTests": [ - { - "id": "RpcV2CborFloat16Inf", - "documentation": "Ensures that clients can correctly parse float16 +Inf.", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "oWV2YWx1Zfl8AA==", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "value": "Infinity" - }, - "bodyMediaType": "application/cbor", - "appliesTo": "client" - }, - { - "id": "RpcV2CborFloat16NegInf", - "documentation": "Ensures that clients can correctly parse float16 -Inf.", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "oWV2YWx1Zfn8AA==", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "value": "-Infinity" - }, - "bodyMediaType": "application/cbor", - "appliesTo": "client" - }, - { - "id": "RpcV2CborFloat16LSBNaN", - "documentation": "Ensures that clients can correctly parse float16 NaN with high LSB.", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "oWV2YWx1Zfl8AQ==", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "value": "NaN" - }, - "bodyMediaType": "application/cbor", - "appliesTo": "client" - }, - { - "id": "RpcV2CborFloat16MSBNaN", - "documentation": "Ensures that clients can correctly parse float16 NaN with high MSB.", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "oWV2YWx1Zfl+AA==", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "value": "NaN" - }, - "bodyMediaType": "application/cbor", - "appliesTo": "client" - }, - { - "id": "RpcV2CborFloat16Subnormal", - "documentation": "Ensures that clients can correctly parse a subnormal float16.", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "oWV2YWx1ZfkAUA==", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "value": 4.76837158203125E-6 - }, - "bodyMediaType": "application/cbor", - "appliesTo": "client" - } - ] - } - }, - "smithy.protocoltests.rpcv2Cbor#Float16Output": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#Double" - } - } - }, - "smithy.protocoltests.rpcv2Cbor#FractionalSeconds": { - "type": "operation", - "input": { - "target": "smithy.api#Unit" - }, - "output": { - "target": "smithy.protocoltests.rpcv2Cbor#FractionalSecondsOutput" - }, - "traits": { - "smithy.api#tags": [ - "client-only" - ], - "smithy.test#httpResponseTests": [ - { - "id": "RpcV2CborDateTimeWithFractionalSeconds", - "documentation": "Ensures that clients can correctly parse timestamps with fractional seconds", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "v2hkYXRldGltZcH7Qcw32zgPvnf/", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "datetime": 9.46845296123E8 - }, - "bodyMediaType": "application/cbor", - "appliesTo": "client" - } - ] - } - }, - "smithy.protocoltests.rpcv2Cbor#FractionalSecondsOutput": { - "type": "structure", - "members": { - "datetime": { - "target": "smithy.protocoltests.shared#DateTime" - } - } - }, - "smithy.protocoltests.rpcv2Cbor#GreetingWithErrors": { - "type": "operation", - "input": { - "target": "smithy.api#Unit" - }, - "output": { - "target": "smithy.protocoltests.rpcv2Cbor#GreetingWithErrorsOutput" - }, - "errors": [ - { - "target": "smithy.protocoltests.rpcv2Cbor#ComplexError" - }, - { - "target": "smithy.protocoltests.rpcv2Cbor#InvalidGreeting" - } - ], - "traits": { - "smithy.api#documentation": "This operation has three possible return values:\n\n1. A successful response in the form of GreetingWithErrorsOutput\n2. An InvalidGreeting error.\n3. A ComplexError error.\n\nImplementations must be able to successfully take a response and\nproperly deserialize successful and error responses.", - "smithy.api#idempotent": {} - } - }, - "smithy.protocoltests.rpcv2Cbor#GreetingWithErrorsOutput": { - "type": "structure", - "members": { - "greeting": { - "target": "smithy.api#String" - } - } - }, - "smithy.protocoltests.rpcv2Cbor#InvalidGreeting": { - "type": "structure", - "members": { - "Message": { - "target": "smithy.api#String" - } - }, - "traits": { - "smithy.api#documentation": "This error is thrown when an invalid greeting value is provided.", - "smithy.api#error": "client", - "smithy.test#httpResponseTests": [ - { - "id": "RpcV2CborInvalidGreetingError", - "documentation": "Parses simple RpcV2 Cbor errors", - "protocol": "smithy.protocols#rpcv2Cbor", - "params": { - "Message": "Hi" - }, - "code": 400, - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "body": "v2ZfX3R5cGV4LnNtaXRoeS5wcm90b2NvbHRlc3RzLnJwY3YyQ2JvciNJbnZhbGlkR3JlZXRpbmdnTWVzc2FnZWJIaf8=", - "bodyMediaType": "application/cbor" - } - ] - } - }, - "smithy.protocoltests.rpcv2Cbor#NoInputOutput": { - "type": "operation", - "input": { - "target": "smithy.api#Unit" - }, - "output": { - "target": "smithy.api#Unit" - }, - "traits": { - "smithy.test#httpRequestTests": [ - { - "id": "no_input", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Body is empty and no Content-Type header if no input", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Accept": "application/cbor" - }, - "forbidHeaders": [ - "Content-Type", - "X-Amz-Target" - ], - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/NoInputOutput", - "body": "" - }, - { - "id": "NoInputServerAllowsEmptyCbor", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Servers should accept CBOR empty struct if no input.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Accept": "application/cbor", - "Content-Type": "application/cbor" - }, - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/NoInputOutput", - "body": "v/8=", - "appliesTo": "server" - }, - { - "id": "NoInputServerAllowsEmptyBody", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Servers should accept an empty body if there is no input. Additionally,\nthey should not raise an error if the `Accept` header is set.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Accept": "application/cbor", - "Content-Type": "application/cbor" - }, - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/NoInputOutput", - "body": "", - "appliesTo": "server" - } - ], - "smithy.test#httpResponseTests": [ - { - "id": "no_output", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "A `Content-Type` header should not be set if the response body is empty.", - "body": "", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor" - }, - "forbidHeaders": [ - "Content-Type" - ], - "code": 200 - }, - { - "id": "NoOutputClientAllowsEmptyCbor", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Clients should accept a CBOR empty struct if there is no output.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "code": 200, - "bodyMediaType": "application/cbor", - "body": "v/8=", - "appliesTo": "client" - }, - { - "id": "NoOutputClientAllowsEmptyBody", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Clients should accept an empty body if there is no output and\nshould not raise an error if the `Content-Type` header is set.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "code": 200, - "bodyMediaType": "application/cbor", - "body": "", - "appliesTo": "client" - } - ] - } - }, - "smithy.protocoltests.rpcv2Cbor#OperationWithDefaults": { - "type": "operation", - "input": { - "target": "smithy.protocoltests.rpcv2Cbor#OperationWithDefaultsInput" - }, - "output": { - "target": "smithy.protocoltests.rpcv2Cbor#OperationWithDefaultsOutput" - }, - "errors": [ - { - "target": "smithy.framework#ValidationException" - } - ], - "traits": { - "smithy.test#httpRequestTests": [ - { - "id": "RpcV2CborClientPopulatesDefaultValuesInInput", - "documentation": "Client populates default values in input.", - "protocol": "smithy.protocols#rpcv2Cbor", - "appliesTo": "client", - "tags": [ - "defaults" - ], - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/OperationWithDefaults", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "bodyMediaType": "application/cbor", - "body": "v2hkZWZhdWx0c79tZGVmYXVsdFN0cmluZ2JoaW5kZWZhdWx0Qm9vbGVhbvVrZGVmYXVsdExpc3Sf/3BkZWZhdWx0VGltZXN0YW1wwQBrZGVmYXVsdEJsb2JDYWJja2RlZmF1bHRCeXRlAWxkZWZhdWx0U2hvcnQBbmRlZmF1bHRJbnRlZ2VyCmtkZWZhdWx0TG9uZxhkbGRlZmF1bHRGbG9hdPo/gAAAbWRlZmF1bHREb3VibGX6P4AAAGpkZWZhdWx0TWFwv/9rZGVmYXVsdEVudW1jRk9PbmRlZmF1bHRJbnRFbnVtAWtlbXB0eVN0cmluZ2BsZmFsc2VCb29sZWFu9GllbXB0eUJsb2JAaHplcm9CeXRlAGl6ZXJvU2hvcnQAa3plcm9JbnRlZ2VyAGh6ZXJvTG9uZwBpemVyb0Zsb2F0+gAAAABqemVyb0RvdWJsZfoAAAAA//8", - "params": { - "defaults": {} - } - }, - { - "id": "RpcV2CborClientSkipsTopLevelDefaultValuesInInput", - "documentation": "Client skips top level default values in input.", - "appliesTo": "client", - "tags": [ - "defaults" - ], - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/OperationWithDefaults", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "body": "v/8=", - "params": {} - }, - { - "id": "RpcV2CborClientUsesExplicitlyProvidedMemberValuesOverDefaults", - "documentation": "Client uses explicitly provided member values over defaults", - "appliesTo": "client", - "tags": [ - "defaults" - ], - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/OperationWithDefaults", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "body": "v2hkZWZhdWx0c7dtZGVmYXVsdFN0cmluZ2NieWVuZGVmYXVsdEJvb2xlYW71a2RlZmF1bHRMaXN0gWFhcGRlZmF1bHRUaW1lc3RhbXDB+z/wAAAAAAAAa2RlZmF1bHRCbG9iQmhpa2RlZmF1bHRCeXRlAmxkZWZhdWx0U2hvcnQCbmRlZmF1bHRJbnRlZ2VyFGtkZWZhdWx0TG9uZxjIbGRlZmF1bHRGbG9hdPpAAAAAbWRlZmF1bHREb3VibGX7QAAAAAAAAABqZGVmYXVsdE1hcKFkbmFtZWRKYWNra2RlZmF1bHRFbnVtY0JBUm5kZWZhdWx0SW50RW51bQJrZW1wdHlTdHJpbmdjZm9vbGZhbHNlQm9vbGVhbvVpZW1wdHlCbG9iQmhpaHplcm9CeXRlAWl6ZXJvU2hvcnQBa3plcm9JbnRlZ2VyAWh6ZXJvTG9uZwFpemVyb0Zsb2F0+j+AAABqemVyb0RvdWJsZfs/8AAAAAAAAP8=", - "params": { - "defaults": { - "defaultString": "bye", - "defaultBoolean": true, - "defaultList": [ - "a" - ], - "defaultTimestamp": 1, - "defaultBlob": "hi", - "defaultByte": 2, - "defaultShort": 2, - "defaultInteger": 20, - "defaultLong": 200, - "defaultFloat": 2.0, - "defaultDouble": 2.0, - "defaultMap": { - "name": "Jack" - }, - "defaultEnum": "BAR", - "defaultIntEnum": 2, - "emptyString": "foo", - "falseBoolean": true, - "emptyBlob": "hi", - "zeroByte": 1, - "zeroShort": 1, - "zeroInteger": 1, - "zeroLong": 1, - "zeroFloat": 1.0, - "zeroDouble": 1.0 - } - } - }, - { - "id": "RpcV2CborServerPopulatesDefaultsWhenMissingInRequestBody", - "documentation": "Server populates default values when missing in request body.", - "appliesTo": "server", - "tags": [ - "defaults" - ], - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/OperationWithDefaults", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "body": "v2hkZWZhdWx0c6D/", - "params": { - "defaults": { - "defaultString": "hi", - "defaultBoolean": true, - "defaultList": [], - "defaultTimestamp": 0, - "defaultBlob": "abc", - "defaultByte": 1, - "defaultShort": 1, - "defaultInteger": 10, - "defaultLong": 100, - "defaultFloat": 1.0, - "defaultDouble": 1.0, - "defaultMap": {}, - "defaultEnum": "FOO", - "defaultIntEnum": 1, - "emptyString": "", - "falseBoolean": false, - "emptyBlob": "", - "zeroByte": 0, - "zeroShort": 0, - "zeroInteger": 0, - "zeroLong": 0, - "zeroFloat": 0.0, - "zeroDouble": 0.0 - }, - "topLevelDefault": "hi", - "otherTopLevelDefault": 0 - } - }, - { - "id": "RpcV2CborClientUsesExplicitlyProvidedValuesInTopLevel", - "documentation": "Any time a value is provided for a member in the top level of input, it is used, regardless of if its the default.", - "appliesTo": "client", - "tags": [ - "defaults" - ], - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/OperationWithDefaults", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "body": "v290b3BMZXZlbERlZmF1bHRiaGl0b3RoZXJUb3BMZXZlbERlZmF1bHQA/w==", - "params": { - "topLevelDefault": "hi", - "otherTopLevelDefault": 0 - } - }, - { - "id": "RpcV2CborClientIgnoresNonTopLevelDefaultsOnMembersWithClientOptional", - "documentation": "Typically, non top-level members would have defaults filled in, but if they have the clientOptional trait, the defaults should be ignored.", - "appliesTo": "client", - "tags": [ - "defaults" - ], - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/OperationWithDefaults", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "body": "v3ZjbGllbnRPcHRpb25hbERlZmF1bHRzoP8=", - "params": { - "clientOptionalDefaults": {} - } - } - ], - "smithy.test#httpResponseTests": [ - { - "id": "RpcV2CborClientPopulatesDefaultsValuesWhenMissingInResponse", - "documentation": "Client populates default values when missing in response.", - "appliesTo": "client", - "tags": [ - "defaults" - ], - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "body": "v/8=", - "params": { - "defaultString": "hi", - "defaultBoolean": true, - "defaultList": [], - "defaultTimestamp": 0, - "defaultBlob": "abc", - "defaultByte": 1, - "defaultShort": 1, - "defaultInteger": 10, - "defaultLong": 100, - "defaultFloat": 1.0, - "defaultDouble": 1.0, - "defaultMap": {}, - "defaultEnum": "FOO", - "defaultIntEnum": 1, - "emptyString": "", - "falseBoolean": false, - "emptyBlob": "", - "zeroByte": 0, - "zeroShort": 0, - "zeroInteger": 0, - "zeroLong": 0, - "zeroFloat": 0.0, - "zeroDouble": 0.0 - } - }, - { - "id": "RpcV2CborClientIgnoresDefaultValuesIfMemberValuesArePresentInResponse", - "documentation": "Client ignores default values if member values are present in the response.", - "appliesTo": "client", - "tags": [ - "defaults" - ], - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "body": "v21kZWZhdWx0U3RyaW5nY2J5ZW5kZWZhdWx0Qm9vbGVhbvRrZGVmYXVsdExpc3SBYWFwZGVmYXVsdFRpbWVzdGFtcMH7QAAAAAAAAABrZGVmYXVsdEJsb2JCaGlrZGVmYXVsdEJ5dGUCbGRlZmF1bHRTaG9ydAJuZGVmYXVsdEludGVnZXIUa2RlZmF1bHRMb25nGMhsZGVmYXVsdEZsb2F0+kAAAABtZGVmYXVsdERvdWJsZftAAAAAAAAAAGpkZWZhdWx0TWFwoWRuYW1lZEphY2trZGVmYXVsdEVudW1jQkFSbmRlZmF1bHRJbnRFbnVtAmtlbXB0eVN0cmluZ2Nmb29sZmFsc2VCb29sZWFu9WllbXB0eUJsb2JCaGloemVyb0J5dGUBaXplcm9TaG9ydAFremVyb0ludGVnZXIBaHplcm9Mb25nAWl6ZXJvRmxvYXT6P4AAAGp6ZXJvRG91Ymxl+z/wAAAAAAAA/w==", - "params": { - "defaultString": "bye", - "defaultBoolean": false, - "defaultList": [ - "a" - ], - "defaultTimestamp": 2, - "defaultBlob": "hi", - "defaultByte": 2, - "defaultShort": 2, - "defaultInteger": 20, - "defaultLong": 200, - "defaultFloat": 2.0, - "defaultDouble": 2.0, - "defaultMap": { - "name": "Jack" - }, - "defaultEnum": "BAR", - "defaultIntEnum": 2, - "emptyString": "foo", - "falseBoolean": true, - "emptyBlob": "hi", - "zeroByte": 1, - "zeroShort": 1, - "zeroInteger": 1, - "zeroLong": 1, - "zeroFloat": 1.0, - "zeroDouble": 1.0 - } - }, - { - "id": "RpcV2CborServerPopulatesDefaultsInResponseWhenMissingInParams", - "documentation": "Server populates default values in response when missing in params.", - "appliesTo": "server", - "tags": [ - "defaults" - ], - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "body": "v21kZWZhdWx0U3RyaW5nYmhpbmRlZmF1bHRCb29sZWFu9WtkZWZhdWx0TGlzdIBwZGVmYXVsdFRpbWVzdGFtcMH7AAAAAAAAAABrZGVmYXVsdEJsb2JDYWJja2RlZmF1bHRCeXRlAWxkZWZhdWx0U2hvcnQBbmRlZmF1bHRJbnRlZ2VyCmtkZWZhdWx0TG9uZxhkbGRlZmF1bHRGbG9hdPo/gAAAbWRlZmF1bHREb3VibGX7P/AAAAAAAABqZGVmYXVsdE1hcKBrZGVmYXVsdEVudW1jRk9PbmRlZmF1bHRJbnRFbnVtAWtlbXB0eVN0cmluZ2BsZmFsc2VCb29sZWFu9GllbXB0eUJsb2JAaHplcm9CeXRlAGl6ZXJvU2hvcnQAa3plcm9JbnRlZ2VyAGh6ZXJvTG9uZwBpemVyb0Zsb2F0+gAAAABqemVyb0RvdWJsZfsAAAAAAAAAAP8=", - "params": {} - } - ] - } - }, - "smithy.protocoltests.rpcv2Cbor#OperationWithDefaultsInput": { - "type": "structure", - "members": { - "defaults": { - "target": "smithy.protocoltests.rpcv2Cbor#Defaults" - }, - "clientOptionalDefaults": { - "target": "smithy.protocoltests.rpcv2Cbor#ClientOptionalDefaults" - }, - "topLevelDefault": { - "target": "smithy.api#String", - "traits": { - "smithy.api#default": "hi" - } - }, - "otherTopLevelDefault": { - "target": "smithy.api#Integer", - "traits": { - "smithy.api#default": 0 - } - } - }, - "traits": { - "smithy.api#input": {} - } - }, - "smithy.protocoltests.rpcv2Cbor#OperationWithDefaultsOutput": { - "type": "structure", - "mixins": [ - { - "target": "smithy.protocoltests.rpcv2Cbor#DefaultsMixin" - } - ], - "members": {}, - "traits": { - "smithy.api#output": {} - } - }, - "smithy.protocoltests.rpcv2Cbor#OptionalInputOutput": { - "type": "operation", - "input": { - "target": "smithy.protocoltests.rpcv2Cbor#SimpleStructure" - }, - "output": { - "target": "smithy.protocoltests.rpcv2Cbor#SimpleStructure" - }, - "traits": { - "smithy.test#httpRequestTests": [ - { - "id": "optional_input", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "When input is empty we write CBOR equivalent of {}", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "forbidHeaders": [ - "X-Amz-Target" - ], - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/OptionalInputOutput", - "bodyMediaType": "application/cbor", - "body": "v/8=" - } - ], - "smithy.test#httpResponseTests": [ - { - "id": "optional_output", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "When output is empty we write CBOR equivalent of {}", - "body": "v/8=", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "code": 200 - } - ] - } - }, - "smithy.protocoltests.rpcv2Cbor#RecursiveShapes": { - "type": "operation", - "input": { - "target": "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutput" - }, - "output": { - "target": "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutput" - }, - "traits": { - "smithy.test#httpRequestTests": [ - { - "id": "RpcV2CborRecursiveShapes", - "documentation": "Serializes recursive structures", - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/RecursiveShapes", - "body": "v2ZuZXN0ZWS/Y2Zvb2RGb28xZm5lc3RlZL9jYmFyZEJhcjFvcmVjdXJzaXZlTWVtYmVyv2Nmb29kRm9vMmZuZXN0ZWS/Y2JhcmRCYXIy//////8=", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "nested": { - "foo": "Foo1", - "nested": { - "bar": "Bar1", - "recursiveMember": { - "foo": "Foo2", - "nested": { - "bar": "Bar2" - } - } - } - } - } - } - ], - "smithy.test#httpResponseTests": [ - { - "id": "RpcV2CborRecursiveShapes", - "documentation": "Serializes recursive structures", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "v2ZuZXN0ZWS/Y2Zvb2RGb28xZm5lc3RlZL9jYmFyZEJhcjFvcmVjdXJzaXZlTWVtYmVyv2Nmb29kRm9vMmZuZXN0ZWS/Y2JhcmRCYXIy//////8=", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "nested": { - "foo": "Foo1", - "nested": { - "bar": "Bar1", - "recursiveMember": { - "foo": "Foo2", - "nested": { - "bar": "Bar2" - } - } - } - } - } - }, - { - "id": "RpcV2CborRecursiveShapesUsingDefiniteLength", - "documentation": "Deserializes recursive structures encoded using a map with definite length", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "oWZuZXN0ZWSiY2Zvb2RGb28xZm5lc3RlZKJjYmFyZEJhcjFvcmVjdXJzaXZlTWVtYmVyomNmb29kRm9vMmZuZXN0ZWShY2JhcmRCYXIy", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "nested": { - "foo": "Foo1", - "nested": { - "bar": "Bar1", - "recursiveMember": { - "foo": "Foo2", - "nested": { - "bar": "Bar2" - } - } - } - } - }, - "appliesTo": "client" - } - ] - } - }, - "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutput": { - "type": "structure", - "members": { - "nested": { - "target": "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutputNested1" - } - } - }, - "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutputNested1": { - "type": "structure", - "members": { - "foo": { - "target": "smithy.api#String" - }, - "nested": { - "target": "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutputNested2" - } - } - }, - "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutputNested2": { - "type": "structure", - "members": { - "bar": { - "target": "smithy.api#String" - }, - "recursiveMember": { - "target": "smithy.protocoltests.rpcv2Cbor#RecursiveShapesInputOutputNested1" - } - } - }, - "smithy.protocoltests.rpcv2Cbor#RpcV2CborDenseMaps": { - "type": "operation", - "input": { - "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborDenseMapsInputOutput" - }, - "output": { - "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborDenseMapsInputOutput" - }, - "errors": [ - { - "target": "smithy.framework#ValidationException" - } - ], - "traits": { - "smithy.api#documentation": "The example tests basic map serialization.", - "smithy.test#httpRequestTests": [ - { - "id": "RpcV2CborMaps", - "documentation": "Serializes maps", - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/RpcV2CborDenseMaps", - "body": "oW5kZW5zZVN0cnVjdE1hcKJjZm9voWJoaWV0aGVyZWNiYXqhYmhpY2J5ZQ==", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "denseStructMap": { - "foo": { - "hi": "there" - }, - "baz": { - "hi": "bye" - } - } - } - }, - { - "id": "RpcV2CborSerializesZeroValuesInMaps", - "documentation": "Ensure that 0 and false are sent over the wire in all maps and lists", - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/RpcV2CborDenseMaps", - "body": "om5kZW5zZU51bWJlck1hcKFheABvZGVuc2VCb29sZWFuTWFwoWF49A==", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "denseNumberMap": { - "x": 0 - }, - "denseBooleanMap": { - "x": false - } - } - }, - { - "id": "RpcV2CborSerializesDenseSetMap", - "documentation": "A request that contains a dense map of sets.", - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/RpcV2CborDenseMaps", - "body": "oWtkZW5zZVNldE1hcKJheIBheYJhYWFi", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "denseSetMap": { - "x": [], - "y": [ - "a", - "b" - ] - } - } - } - ], - "smithy.test#httpResponseTests": [ - { - "id": "RpcV2CborMaps", - "documentation": "Deserializes maps", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "oW5kZW5zZVN0cnVjdE1hcKJjZm9voWJoaWV0aGVyZWNiYXqhYmhpY2J5ZQ==", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "denseStructMap": { - "foo": { - "hi": "there" - }, - "baz": { - "hi": "bye" - } - } - } - }, - { - "id": "RpcV2CborDeserializesZeroValuesInMaps", - "documentation": "Ensure that 0 and false are sent over the wire in all maps and lists", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "om5kZW5zZU51bWJlck1hcKFheABvZGVuc2VCb29sZWFuTWFwoWF49A==", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "denseNumberMap": { - "x": 0 - }, - "denseBooleanMap": { - "x": false - } - } - }, - { - "id": "RpcV2CborDeserializesDenseSetMap", - "documentation": "A response that contains a dense map of sets", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "oWtkZW5zZVNldE1hcKJheIBheYJhYWFi", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "denseSetMap": { - "x": [], - "y": [ - "a", - "b" - ] - } - } - }, - { - "id": "RpcV2CborDeserializesDenseSetMapAndSkipsNull", - "documentation": "Clients SHOULD tolerate seeing a null value in a dense map, and they SHOULD\ndrop the null key-value pair.", - "protocol": "smithy.protocols#rpcv2Cbor", - "appliesTo": "client", - "code": 200, - "body": "oWtkZW5zZVNldE1hcKNheIBheYJhYWFiYXr2", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "denseSetMap": { - "x": [], - "y": [ - "a", - "b" - ] - } - } - } - ] - } - }, - "smithy.protocoltests.rpcv2Cbor#RpcV2CborDenseMapsInputOutput": { - "type": "structure", - "members": { - "denseStructMap": { - "target": "smithy.protocoltests.rpcv2Cbor#DenseStructMap" - }, - "denseNumberMap": { - "target": "smithy.protocoltests.rpcv2Cbor#DenseNumberMap" - }, - "denseBooleanMap": { - "target": "smithy.protocoltests.rpcv2Cbor#DenseBooleanMap" - }, - "denseStringMap": { - "target": "smithy.protocoltests.rpcv2Cbor#DenseStringMap" - }, - "denseSetMap": { - "target": "smithy.protocoltests.rpcv2Cbor#DenseSetMap" - } - } - }, - "smithy.protocoltests.rpcv2Cbor#RpcV2CborListInputOutput": { - "type": "structure", - "members": { - "stringList": { - "target": "smithy.protocoltests.shared#StringList" - }, - "stringSet": { - "target": "smithy.protocoltests.shared#StringSet" - }, - "integerList": { - "target": "smithy.protocoltests.shared#IntegerList" - }, - "booleanList": { - "target": "smithy.protocoltests.shared#BooleanList" - }, - "timestampList": { - "target": "smithy.protocoltests.shared#TimestampList" - }, - "enumList": { - "target": "smithy.protocoltests.shared#FooEnumList" - }, - "intEnumList": { - "target": "smithy.protocoltests.shared#IntegerEnumList" - }, - "nestedStringList": { - "target": "smithy.protocoltests.shared#NestedStringList" - }, - "structureList": { - "target": "smithy.protocoltests.rpcv2Cbor#StructureList" - }, - "blobList": { - "target": "smithy.protocoltests.shared#BlobList" - } - } - }, - "smithy.protocoltests.rpcv2Cbor#RpcV2CborLists": { - "type": "operation", - "input": { - "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborListInputOutput" - }, - "output": { - "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborListInputOutput" - }, - "errors": [ - { - "target": "smithy.framework#ValidationException" - } - ], - "traits": { - "smithy.api#documentation": "This test case serializes JSON lists for the following cases for both\ninput and output:\n\n1. Normal lists.\n2. Normal sets.\n3. Lists of lists.\n4. Lists of structures.", - "smithy.api#idempotent": {}, - "smithy.test#httpRequestTests": [ - { - "id": "RpcV2CborLists", - "documentation": "Serializes RpcV2 Cbor lists", - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/RpcV2CborLists", - "body": "v2pzdHJpbmdMaXN0gmNmb29jYmFyaXN0cmluZ1NldIJjZm9vY2JhcmtpbnRlZ2VyTGlzdIIBAmtib29sZWFuTGlzdIL19G10aW1lc3RhbXBMaXN0gsH7QdTX+/OAAADB+0HU1/vzgAAAaGVudW1MaXN0gmNGb29hMGtpbnRFbnVtTGlzdIIBAnBuZXN0ZWRTdHJpbmdMaXN0goJjZm9vY2JhcoJjYmF6Y3F1eG1zdHJ1Y3R1cmVMaXN0gqJhYWExYWJhMqJhYWEzYWJhNGhibG9iTGlzdIJDZm9vQ2Jhcv8=", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "stringList": [ - "foo", - "bar" - ], - "stringSet": [ - "foo", - "bar" - ], - "integerList": [ - 1, - 2 - ], - "booleanList": [ - true, - false - ], - "timestampList": [ - 1398796238, - 1398796238 - ], - "enumList": [ - "Foo", - "0" - ], - "intEnumList": [ - 1, - 2 - ], - "nestedStringList": [ - [ - "foo", - "bar" - ], - [ - "baz", - "qux" - ] - ], - "structureList": [ - { - "a": "1", - "b": "2" - }, - { - "a": "3", - "b": "4" - } - ], - "blobList": [ - "foo", - "bar" - ] - } - }, - { - "id": "RpcV2CborListsEmpty", - "documentation": "Serializes empty JSON lists", - "tags": [ - "client-indefinite" - ], - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/RpcV2CborLists", - "body": "v2pzdHJpbmdMaXN0n///", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "stringList": [] - } - }, - { - "id": "RpcV2CborListsEmptyUsingDefiniteLength", - "documentation": "Serializes empty JSON definite length lists", - "tags": [ - "client-definite" - ], - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/RpcV2CborLists", - "body": "oWpzdHJpbmdMaXN0gA==", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "stringList": [] - } - }, - { - "id": "RpcV2CborIndefiniteStringInsideIndefiniteList", - "documentation": "Can deserialize indefinite length text strings inside an indefinite length list", - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/RpcV2CborLists", - "body": "v2pzdHJpbmdMaXN0n394HUFuIGV4YW1wbGUgaW5kZWZpbml0ZSBzdHJpbmcsdyB3aGljaCB3aWxsIGJlIGNodW5rZWQsbiBvbiBlYWNoIGNvbW1h/394NUFub3RoZXIgZXhhbXBsZSBpbmRlZmluaXRlIHN0cmluZyB3aXRoIG9ubHkgb25lIGNodW5r/3ZUaGlzIGlzIGEgcGxhaW4gc3RyaW5n//8=", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "stringList": [ - "An example indefinite string, which will be chunked, on each comma", - "Another example indefinite string with only one chunk", - "This is a plain string" - ] - }, - "appliesTo": "server" - }, - { - "id": "RpcV2CborIndefiniteStringInsideDefiniteList", - "documentation": "Can deserialize indefinite length text strings inside a definite length list", - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/RpcV2CborLists", - "body": "oWpzdHJpbmdMaXN0g394HUFuIGV4YW1wbGUgaW5kZWZpbml0ZSBzdHJpbmcsdyB3aGljaCB3aWxsIGJlIGNodW5rZWQsbiBvbiBlYWNoIGNvbW1h/394NUFub3RoZXIgZXhhbXBsZSBpbmRlZmluaXRlIHN0cmluZyB3aXRoIG9ubHkgb25lIGNodW5r/3ZUaGlzIGlzIGEgcGxhaW4gc3RyaW5n", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "stringList": [ - "An example indefinite string, which will be chunked, on each comma", - "Another example indefinite string with only one chunk", - "This is a plain string" - ] - }, - "appliesTo": "server" - } - ], - "smithy.test#httpResponseTests": [ - { - "id": "RpcV2CborLists", - "documentation": "Serializes RpcV2 Cbor lists", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "v2pzdHJpbmdMaXN0n2Nmb29jYmFy/2lzdHJpbmdTZXSfY2Zvb2NiYXL/a2ludGVnZXJMaXN0nwEC/2tib29sZWFuTGlzdJ/19P9tdGltZXN0YW1wTGlzdJ/B+0HU1/vzgAAAwftB1Nf784AAAP9oZW51bUxpc3SfY0Zvb2Ew/2tpbnRFbnVtTGlzdJ8BAv9wbmVzdGVkU3RyaW5nTGlzdJ+fY2Zvb2NiYXL/n2NiYXpjcXV4//9tc3RydWN0dXJlTGlzdJ+/YWFhMWFiYTL/v2FhYTNhYmE0//9oYmxvYkxpc3SfQ2Zvb0NiYXL//w==", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "stringList": [ - "foo", - "bar" - ], - "stringSet": [ - "foo", - "bar" - ], - "integerList": [ - 1, - 2 - ], - "booleanList": [ - true, - false - ], - "timestampList": [ - 1398796238, - 1398796238 - ], - "enumList": [ - "Foo", - "0" - ], - "intEnumList": [ - 1, - 2 - ], - "nestedStringList": [ - [ - "foo", - "bar" - ], - [ - "baz", - "qux" - ] - ], - "structureList": [ - { - "a": "1", - "b": "2" - }, - { - "a": "3", - "b": "4" - } - ], - "blobList": [ - "foo", - "bar" - ] - } - }, - { - "id": "RpcV2CborListsEmpty", - "documentation": "Serializes empty RpcV2 Cbor lists", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "v2pzdHJpbmdMaXN0n///", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "stringList": [] - } - }, - { - "id": "RpcV2CborIndefiniteStringInsideIndefiniteListCanDeserialize", - "documentation": "Can deserialize indefinite length text strings inside an indefinite length list", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "v2pzdHJpbmdMaXN0n394HUFuIGV4YW1wbGUgaW5kZWZpbml0ZSBzdHJpbmcsdyB3aGljaCB3aWxsIGJlIGNodW5rZWQsbiBvbiBlYWNoIGNvbW1h/394NUFub3RoZXIgZXhhbXBsZSBpbmRlZmluaXRlIHN0cmluZyB3aXRoIG9ubHkgb25lIGNodW5r/3ZUaGlzIGlzIGEgcGxhaW4gc3RyaW5n//8=", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "stringList": [ - "An example indefinite string, which will be chunked, on each comma", - "Another example indefinite string with only one chunk", - "This is a plain string" - ] - }, - "appliesTo": "client" - }, - { - "id": "RpcV2CborIndefiniteStringInsideDefiniteListCanDeserialize", - "documentation": "Can deserialize indefinite length text strings inside a definite length list", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "oWpzdHJpbmdMaXN0g394HUFuIGV4YW1wbGUgaW5kZWZpbml0ZSBzdHJpbmcsdyB3aGljaCB3aWxsIGJlIGNodW5rZWQsbiBvbiBlYWNoIGNvbW1h/394NUFub3RoZXIgZXhhbXBsZSBpbmRlZmluaXRlIHN0cmluZyB3aXRoIG9ubHkgb25lIGNodW5r/3ZUaGlzIGlzIGEgcGxhaW4gc3RyaW5n", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "stringList": [ - "An example indefinite string, which will be chunked, on each comma", - "Another example indefinite string with only one chunk", - "This is a plain string" - ] - }, - "appliesTo": "client" - } - ] - } - }, - "smithy.protocoltests.rpcv2Cbor#RpcV2CborSparseMaps": { - "type": "operation", - "input": { - "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborSparseMapsInputOutput" - }, - "output": { - "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborSparseMapsInputOutput" - }, - "errors": [ - { - "target": "smithy.framework#ValidationException" - } - ], - "traits": { - "smithy.test#httpRequestTests": [ - { - "id": "RpcV2CborSparseMaps", - "documentation": "Serializes sparse maps", - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/RpcV2CborSparseMaps", - "body": "v29zcGFyc2VTdHJ1Y3RNYXC/Y2Zvb79iaGlldGhlcmX/Y2Jher9iaGljYnll////", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "sparseStructMap": { - "foo": { - "hi": "there" - }, - "baz": { - "hi": "bye" - } - } - } - }, - { - "id": "RpcV2CborSerializesNullMapValues", - "documentation": "Serializes null map values in sparse maps", - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/RpcV2CborSparseMaps", - "body": "v3BzcGFyc2VCb29sZWFuTWFwv2F49v9vc3BhcnNlTnVtYmVyTWFwv2F49v9vc3BhcnNlU3RyaW5nTWFwv2F49v9vc3BhcnNlU3RydWN0TWFwv2F49v//", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "sparseBooleanMap": { - "x": null - }, - "sparseNumberMap": { - "x": null - }, - "sparseStringMap": { - "x": null - }, - "sparseStructMap": { - "x": null - } - } - }, - { - "id": "RpcV2CborSerializesSparseSetMap", - "documentation": "A request that contains a sparse map of sets", - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/RpcV2CborSparseMaps", - "body": "v2xzcGFyc2VTZXRNYXC/YXif/2F5n2FhYWL///8=", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "sparseSetMap": { - "x": [], - "y": [ - "a", - "b" - ] - } - } - }, - { - "id": "RpcV2CborSerializesSparseSetMapAndRetainsNull", - "documentation": "A request that contains a sparse map of sets.", - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/RpcV2CborSparseMaps", - "body": "v2xzcGFyc2VTZXRNYXC/YXif/2F5n2FhYWL/YXr2//8=", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "sparseSetMap": { - "x": [], - "y": [ - "a", - "b" - ], - "z": null - } - } - }, - { - "id": "RpcV2CborSerializesZeroValuesInSparseMaps", - "documentation": "Ensure that 0 and false are sent over the wire in all maps and lists", - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/RpcV2CborSparseMaps", - "body": "v29zcGFyc2VOdW1iZXJNYXC/YXgA/3BzcGFyc2VCb29sZWFuTWFwv2F49P//", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "sparseNumberMap": { - "x": 0 - }, - "sparseBooleanMap": { - "x": false - } - } - } - ], - "smithy.test#httpResponseTests": [ - { - "id": "RpcV2CborSparseJsonMaps", - "documentation": "Deserializes sparse maps", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "v29zcGFyc2VTdHJ1Y3RNYXC/Y2Zvb79iaGlldGhlcmX/Y2Jher9iaGljYnll////", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "sparseStructMap": { - "foo": { - "hi": "there" - }, - "baz": { - "hi": "bye" - } - } - } - }, - { - "id": "RpcV2CborDeserializesNullMapValues", - "documentation": "Deserializes null map values", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "v3BzcGFyc2VCb29sZWFuTWFwv2F49v9vc3BhcnNlTnVtYmVyTWFwv2F49v9vc3BhcnNlU3RyaW5nTWFwv2F49v9vc3BhcnNlU3RydWN0TWFwv2F49v//", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "sparseBooleanMap": { - "x": null - }, - "sparseNumberMap": { - "x": null - }, - "sparseStringMap": { - "x": null - }, - "sparseStructMap": { - "x": null - } - } - }, - { - "id": "RpcV2CborDeserializesSparseSetMap", - "documentation": "A response that contains a sparse map of sets", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "v2xzcGFyc2VTZXRNYXC/YXmfYWFhYv9heJ////8=", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "sparseSetMap": { - "x": [], - "y": [ - "a", - "b" - ] - } - } - }, - { - "id": "RpcV2CborDeserializesSparseSetMapAndRetainsNull", - "documentation": "A response that contains a sparse map of sets with a null", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "v2xzcGFyc2VTZXRNYXC/YXif/2F5n2FhYWL/YXr2//8=", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "sparseSetMap": { - "x": [], - "y": [ - "a", - "b" - ], - "z": null - } - } - }, - { - "id": "RpcV2CborDeserializesZeroValuesInSparseMaps", - "documentation": "Ensure that 0 and false are sent over the wire in all maps and lists", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "v29zcGFyc2VOdW1iZXJNYXC/YXgA/3BzcGFyc2VCb29sZWFuTWFwv2F49P//", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "sparseNumberMap": { - "x": 0 - }, - "sparseBooleanMap": { - "x": false - } - } - } - ] - } - }, - "smithy.protocoltests.rpcv2Cbor#RpcV2CborSparseMapsInputOutput": { - "type": "structure", - "members": { - "sparseStructMap": { - "target": "smithy.protocoltests.rpcv2Cbor#SparseStructMap" - }, - "sparseNumberMap": { - "target": "smithy.protocoltests.rpcv2Cbor#SparseNumberMap" - }, - "sparseBooleanMap": { - "target": "smithy.protocoltests.rpcv2Cbor#SparseBooleanMap" - }, - "sparseStringMap": { - "target": "smithy.protocoltests.shared#SparseStringMap" - }, - "sparseSetMap": { - "target": "smithy.protocoltests.rpcv2Cbor#SparseSetMap" - } - } - }, - "smithy.protocoltests.rpcv2Cbor#RpcV2Protocol": { - "type": "service", - "version": "2020-07-14", - "operations": [ - { - "target": "smithy.protocoltests.rpcv2Cbor#EmptyInputOutput" - }, - { - "target": "smithy.protocoltests.rpcv2Cbor#Float16" - }, - { - "target": "smithy.protocoltests.rpcv2Cbor#FractionalSeconds" - }, - { - "target": "smithy.protocoltests.rpcv2Cbor#GreetingWithErrors" - }, - { - "target": "smithy.protocoltests.rpcv2Cbor#NoInputOutput" - }, - { - "target": "smithy.protocoltests.rpcv2Cbor#OperationWithDefaults" - }, - { - "target": "smithy.protocoltests.rpcv2Cbor#OptionalInputOutput" - }, - { - "target": "smithy.protocoltests.rpcv2Cbor#RecursiveShapes" - }, - { - "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborDenseMaps" - }, - { - "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborLists" - }, - { - "target": "smithy.protocoltests.rpcv2Cbor#RpcV2CborSparseMaps" - }, - { - "target": "smithy.protocoltests.rpcv2Cbor#SimpleScalarProperties" - }, - { - "target": "smithy.protocoltests.rpcv2Cbor#SparseNullsOperation" - } - ], - "traits": { - "smithy.api#title": "RpcV2 Protocol Service", - "smithy.protocols#rpcv2Cbor": {} - } - }, - "smithy.protocoltests.rpcv2Cbor#SimpleScalarProperties": { - "type": "operation", - "input": { - "target": "smithy.protocoltests.rpcv2Cbor#SimpleScalarStructure" - }, - "output": { - "target": "smithy.protocoltests.rpcv2Cbor#SimpleScalarStructure" - }, - "traits": { - "smithy.test#httpRequestTests": [ - { - "id": "RpcV2CborSimpleScalarProperties", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Serializes simple scalar properties", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", - "body": "v2lieXRlVmFsdWUFa2RvdWJsZVZhbHVl+z/+OVgQYk3TcWZhbHNlQm9vbGVhblZhbHVl9GpmbG9hdFZhbHVl+kD0AABsaW50ZWdlclZhbHVlGQEAaWxvbmdWYWx1ZRkmkWpzaG9ydFZhbHVlGSaqa3N0cmluZ1ZhbHVlZnNpbXBsZXB0cnVlQm9vbGVhblZhbHVl9WlibG9iVmFsdWVDZm9v/w==", - "params": { - "byteValue": 5, - "doubleValue": 1.889, - "falseBooleanValue": false, - "floatValue": 7.625, - "integerValue": 256, - "longValue": 9873, - "shortValue": 9898, - "stringValue": "simple", - "trueBooleanValue": true, - "blobValue": "foo" - } - }, - { - "id": "RpcV2CborSimpleScalarPropertiesUsingIndefiniteLength", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "The server should be capable of deserializing simple scalar properties\nencoded using a map with a definite length. The server should also be able to parse\na key encoded using an indefinite length string.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", - "body": "qmlieXRlVmFsdWUFf2Zkb3VibGVlVmFsdWX/+z/+OVgQYk3Tf2VmYWxzZWdCb29sZWFuZVZhbHVl//RqZmxvYXRWYWx1ZfpA9AAAbGludGVnZXJWYWx1ZRkBAGlsb25nVmFsdWUZJpFqc2hvcnRWYWx1ZRkmqn9mc3RyaW5nZVZhbHVl/2ZzaW1wbGVwdHJ1ZUJvb2xlYW5WYWx1ZfVpYmxvYlZhbHVlQ2Zvbw==", - "params": { - "byteValue": 5, - "doubleValue": 1.889, - "falseBooleanValue": false, - "floatValue": 7.625, - "integerValue": 256, - "longValue": 9873, - "shortValue": 9898, - "stringValue": "simple", - "trueBooleanValue": true, - "blobValue": "foo" - }, - "appliesTo": "server" - }, - { - "id": "RpcV2CborClientDoesntSerializeNullStructureValues", - "documentation": "RpcV2 Cbor should not serialize null structure values", - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", - "body": "v/8=", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": { - "stringValue": null - }, - "appliesTo": "client" - }, - { - "id": "RpcV2CborServerDoesntDeSerializeNullStructureValues", - "documentation": "RpcV2 Cbor should not deserialize null structure values", - "protocol": "smithy.protocols#rpcv2Cbor", - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", - "body": "v2tzdHJpbmdWYWx1Zfb/", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "params": {}, - "appliesTo": "server" - }, - { - "id": "RpcV2CborSupportsNaNFloatInputs", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Supports handling NaN float values.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", - "body": "v2tkb3VibGVWYWx1Zft/+AAAAAAAAGpmbG9hdFZhbHVl+n/AAAD/", - "params": { - "doubleValue": "NaN", - "floatValue": "NaN" - } - }, - { - "id": "RpcV2CborSupportsInfinityFloatInputs", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Supports handling Infinity float values.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", - "body": "v2tkb3VibGVWYWx1Zft/8AAAAAAAAGpmbG9hdFZhbHVl+n+AAAD/", - "params": { - "doubleValue": "Infinity", - "floatValue": "Infinity" - } - }, - { - "id": "RpcV2CborSupportsNegativeInfinityFloatInputs", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Supports handling Infinity float values.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", - "body": "v2tkb3VibGVWYWx1Zfv/8AAAAAAAAGpmbG9hdFZhbHVl+v+AAAD/", - "params": { - "doubleValue": "-Infinity", - "floatValue": "-Infinity" - } - }, - { - "id": "RpcV2CborIndefiniteLengthStringsCanBeDeserialized", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "The server should be capable of deserializing indefinite length text strings.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", - "body": "oWtzdHJpbmdWYWx1ZX94HUFuIGV4YW1wbGUgaW5kZWZpbml0ZSBzdHJpbmcscSBjaHVua2VkIG9uIGNvbW1h/w==", - "params": { - "stringValue": "An example indefinite string, chunked on comma" - }, - "appliesTo": "server" - }, - { - "id": "RpcV2CborIndefiniteLengthByteStringsCanBeDeserialized", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "The server should be capable of deserializing indefinite length byte strings.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", - "body": "oWlibG9iVmFsdWVfWCJBbiBleGFtcGxlIGluZGVmaW5pdGUtYnl0ZSBzdHJpbmcsUSBjaHVua2VkIG9uIGNvbW1h/w==", - "params": { - "blobValue": "An example indefinite-byte string, chunked on comma" - }, - "appliesTo": "server" - }, - { - "id": "RpcV2CborSupportsUpcastingData", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Supports upcasting from a smaller byte representation of the same data type.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", - "body": "v2tkb3VibGVWYWx1Zfk+AGpmbG9hdFZhbHVl+UegbGludGVnZXJWYWx1ZRg4aWxvbmdWYWx1ZRkBAGpzaG9ydFZhbHVlCv8=", - "params": { - "doubleValue": 1.5, - "floatValue": 7.625, - "integerValue": 56, - "longValue": 256, - "shortValue": 10 - }, - "appliesTo": "server" - }, - { - "id": "RpcV2CborExtraFieldsInTheBodyShouldBeSkippedByServers", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "The server should skip over additional fields that are not part of the structure. This allows a\nclient generated against a newer Smithy model to be able to communicate with a server that is\ngenerated against an older Smithy model.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", - "body": "v2lieXRlVmFsdWUFa2RvdWJsZVZhbHVl+z/+OVgQYk3TcWZhbHNlQm9vbGVhblZhbHVl9GpmbG9hdFZhbHVl+kD0AABrZXh0cmFPYmplY3S/c2luZGVmaW5pdGVMZW5ndGhNYXC/a3dpdGhBbkFycmF5nwECA///cWRlZmluaXRlTGVuZ3RoTWFwo3J3aXRoQURlZmluaXRlQXJyYXmDAQIDeB1hbmRTb21lSW5kZWZpbml0ZUxlbmd0aFN0cmluZ3gfdGhhdCBoYXMsIGJlZW4gY2h1bmtlZCBvbiBjb21tYWxub3JtYWxTdHJpbmdjZm9vanNob3J0VmFsdWUZJw9uc29tZU90aGVyRmllbGR2dGhpcyBzaG91bGQgYmUgc2tpcHBlZP9saW50ZWdlclZhbHVlGQEAaWxvbmdWYWx1ZRkmkWpzaG9ydFZhbHVlGSaqa3N0cmluZ1ZhbHVlZnNpbXBsZXB0cnVlQm9vbGVhblZhbHVl9WlibG9iVmFsdWVDZm9v/w==", - "params": { - "byteValue": 5, - "doubleValue": 1.889, - "falseBooleanValue": false, - "floatValue": 7.625, - "integerValue": 256, - "longValue": 9873, - "shortValue": 9898, - "stringValue": "simple", - "trueBooleanValue": true, - "blobValue": "foo" - }, - "appliesTo": "server" - }, - { - "id": "RpcV2CborServersShouldHandleNoAcceptHeader", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Servers should tolerate requests without an Accept header set.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "method": "POST", - "bodyMediaType": "application/cbor", - "uri": "/service/RpcV2Protocol/operation/SimpleScalarProperties", - "body": "v2lieXRlVmFsdWUFa2RvdWJsZVZhbHVl+z/+OVgQYk3TcWZhbHNlQm9vbGVhblZhbHVl9GpmbG9hdFZhbHVl+kD0AABsaW50ZWdlclZhbHVlGQEAaWxvbmdWYWx1ZRkmkWpzaG9ydFZhbHVlGSaqa3N0cmluZ1ZhbHVlZnNpbXBsZXB0cnVlQm9vbGVhblZhbHVl9WlibG9iVmFsdWVDZm9v/w==", - "params": { - "byteValue": 5, - "doubleValue": 1.889, - "falseBooleanValue": false, - "floatValue": 7.625, - "integerValue": 256, - "longValue": 9873, - "shortValue": 9898, - "stringValue": "simple", - "trueBooleanValue": true, - "blobValue": "foo" - }, - "appliesTo": "server" - } - ], - "smithy.test#httpResponseTests": [ - { - "id": "RpcV2CborSimpleScalarProperties", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Serializes simple scalar properties", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "bodyMediaType": "application/cbor", - "body": "v3B0cnVlQm9vbGVhblZhbHVl9XFmYWxzZUJvb2xlYW5WYWx1ZfRpYnl0ZVZhbHVlBWtkb3VibGVWYWx1Zfs//jlYEGJN02pmbG9hdFZhbHVl+kD0AABsaW50ZWdlclZhbHVlGQEAanNob3J0VmFsdWUZJqprc3RyaW5nVmFsdWVmc2ltcGxlaWJsb2JWYWx1ZUNmb2//", - "code": 200, - "params": { - "trueBooleanValue": true, - "falseBooleanValue": false, - "byteValue": 5, - "doubleValue": 1.889, - "floatValue": 7.625, - "integerValue": 256, - "shortValue": 9898, - "stringValue": "simple", - "blobValue": "foo" - } - }, - { - "id": "RpcV2CborSimpleScalarPropertiesUsingDefiniteLength", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Deserializes simple scalar properties encoded using a map with definite length", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "bodyMediaType": "application/cbor", - "body": "qXB0cnVlQm9vbGVhblZhbHVl9XFmYWxzZUJvb2xlYW5WYWx1ZfRpYnl0ZVZhbHVlBWtkb3VibGVWYWx1Zfs//jlYEGJN02pmbG9hdFZhbHVl+kD0AABsaW50ZWdlclZhbHVlGQEAanNob3J0VmFsdWUZJqprc3RyaW5nVmFsdWVmc2ltcGxlaWJsb2JWYWx1ZUNmb28=", - "code": 200, - "params": { - "trueBooleanValue": true, - "falseBooleanValue": false, - "byteValue": 5, - "doubleValue": 1.889, - "floatValue": 7.625, - "integerValue": 256, - "shortValue": 9898, - "stringValue": "simple", - "blobValue": "foo" - }, - "appliesTo": "client" - }, - { - "id": "RpcV2CborClientDoesntDeserializeNullStructureValues", - "documentation": "RpcV2 Cbor should not deserialize null structure values", - "protocol": "smithy.protocols#rpcv2Cbor", - "body": "v2tzdHJpbmdWYWx1Zfb/", - "code": 200, - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": {}, - "appliesTo": "client" - }, - { - "id": "RpcV2CborServerDoesntSerializeNullStructureValues", - "documentation": "RpcV2 Cbor should not serialize null structure values", - "protocol": "smithy.protocols#rpcv2Cbor", - "body": "v/8=", - "code": 200, - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "stringValue": null - }, - "appliesTo": "server" - }, - { - "id": "RpcV2CborSupportsNaNFloatOutputs", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Supports handling NaN float values.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "code": 200, - "bodyMediaType": "application/cbor", - "body": "v2tkb3VibGVWYWx1Zft/+AAAAAAAAGpmbG9hdFZhbHVl+n/AAAD/", - "params": { - "doubleValue": "NaN", - "floatValue": "NaN" - } - }, - { - "id": "RpcV2CborSupportsInfinityFloatOutputs", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Supports handling Infinity float values.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "code": 200, - "bodyMediaType": "application/cbor", - "body": "v2tkb3VibGVWYWx1Zft/8AAAAAAAAGpmbG9hdFZhbHVl+n+AAAD/", - "params": { - "doubleValue": "Infinity", - "floatValue": "Infinity" - } - }, - { - "id": "RpcV2CborSupportsNegativeInfinityFloatOutputs", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Supports handling Negative Infinity float values.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "code": 200, - "bodyMediaType": "application/cbor", - "body": "v2tkb3VibGVWYWx1Zfv/8AAAAAAAAGpmbG9hdFZhbHVl+v+AAAD/", - "params": { - "doubleValue": "-Infinity", - "floatValue": "-Infinity" - } - }, - { - "id": "RpcV2CborSupportsUpcastingDataOnDeserialize", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "Supports upcasting from a smaller byte representation of the same data type.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "code": 200, - "bodyMediaType": "application/cbor", - "body": "v2tkb3VibGVWYWx1Zfk+AGpmbG9hdFZhbHVl+UegbGludGVnZXJWYWx1ZRg4aWxvbmdWYWx1ZRkBAGpzaG9ydFZhbHVlCv8=", - "params": { - "doubleValue": 1.5, - "floatValue": 7.625, - "integerValue": 56, - "longValue": 256, - "shortValue": 10 - }, - "appliesTo": "client" - }, - { - "id": "RpcV2CborExtraFieldsInTheBodyShouldBeSkippedByClients", - "protocol": "smithy.protocols#rpcv2Cbor", - "documentation": "The client should skip over additional fields that are not part of the structure. This allows a\nclient generated against an older Smithy model to be able to communicate with a server that is\ngenerated against a newer Smithy model.", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "code": 200, - "bodyMediaType": "application/cbor", - "body": "v2lieXRlVmFsdWUFa2RvdWJsZVZhbHVl+z/+OVgQYk3TcWZhbHNlQm9vbGVhblZhbHVl9GpmbG9hdFZhbHVl+kD0AABrZXh0cmFPYmplY3S/c2luZGVmaW5pdGVMZW5ndGhNYXC/a3dpdGhBbkFycmF5nwECA///cWRlZmluaXRlTGVuZ3RoTWFwo3J3aXRoQURlZmluaXRlQXJyYXmDAQIDeB1hbmRTb21lSW5kZWZpbml0ZUxlbmd0aFN0cmluZ3gfdGhhdCBoYXMsIGJlZW4gY2h1bmtlZCBvbiBjb21tYWxub3JtYWxTdHJpbmdjZm9vanNob3J0VmFsdWUZJw9uc29tZU90aGVyRmllbGR2dGhpcyBzaG91bGQgYmUgc2tpcHBlZP9saW50ZWdlclZhbHVlGQEAaWxvbmdWYWx1ZRkmkWpzaG9ydFZhbHVlGSaqa3N0cmluZ1ZhbHVlZnNpbXBsZXB0cnVlQm9vbGVhblZhbHVl9WlibG9iVmFsdWVDZm9v/w==", - "params": { - "byteValue": 5, - "doubleValue": 1.889, - "falseBooleanValue": false, - "floatValue": 7.625, - "integerValue": 256, - "longValue": 9873, - "shortValue": 9898, - "stringValue": "simple", - "trueBooleanValue": true, - "blobValue": "foo" - }, - "appliesTo": "client" - } - ] - } - }, - "smithy.protocoltests.rpcv2Cbor#SimpleScalarStructure": { - "type": "structure", - "members": { - "trueBooleanValue": { - "target": "smithy.api#Boolean" - }, - "falseBooleanValue": { - "target": "smithy.api#Boolean" - }, - "byteValue": { - "target": "smithy.api#Byte" - }, - "doubleValue": { - "target": "smithy.api#Double" - }, - "floatValue": { - "target": "smithy.api#Float" - }, - "integerValue": { - "target": "smithy.api#Integer" - }, - "longValue": { - "target": "smithy.api#Long" - }, - "shortValue": { - "target": "smithy.api#Short" - }, - "stringValue": { - "target": "smithy.api#String" - }, - "blobValue": { - "target": "smithy.api#Blob" - } - } - }, - "smithy.protocoltests.rpcv2Cbor#SimpleStructure": { - "type": "structure", - "members": { - "value": { - "target": "smithy.api#String" - } - } - }, - "smithy.protocoltests.rpcv2Cbor#SparseBooleanMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.api#Boolean" - }, - "traits": { - "smithy.api#sparse": {} - } - }, - "smithy.protocoltests.rpcv2Cbor#SparseNullsOperation": { - "type": "operation", - "input": { - "target": "smithy.protocoltests.rpcv2Cbor#SparseNullsOperationInputOutput" - }, - "output": { - "target": "smithy.protocoltests.rpcv2Cbor#SparseNullsOperationInputOutput" - }, - "traits": { - "smithy.test#httpRequestTests": [ - { - "id": "RpcV2CborSparseMapsSerializeNullValues", - "documentation": "Serializes null values in maps", - "protocol": "smithy.protocols#rpcv2Cbor", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "body": "v29zcGFyc2VTdHJpbmdNYXC/Y2Zvb/b//w==", - "params": { - "sparseStringMap": { - "foo": null - } - }, - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/SparseNullsOperation" - }, - { - "id": "RpcV2CborSparseListsSerializeNull", - "documentation": "Serializes null values in lists", - "protocol": "smithy.protocols#rpcv2Cbor", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor", - "Accept": "application/cbor" - }, - "requireHeaders": [ - "Content-Length" - ], - "body": "v3BzcGFyc2VTdHJpbmdMaXN0n/b//w==", - "params": { - "sparseStringList": [ - null - ] - }, - "method": "POST", - "uri": "/service/RpcV2Protocol/operation/SparseNullsOperation" - } - ], - "smithy.test#httpResponseTests": [ - { - "id": "RpcV2CborSparseMapsDeserializeNullValues", - "documentation": "Deserializes null values in maps", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "v29zcGFyc2VTdHJpbmdNYXC/Y2Zvb/b//w==", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "sparseStringMap": { - "foo": null - } - } - }, - { - "id": "RpcV2CborSparseListsDeserializeNull", - "documentation": "Deserializes null values in lists", - "protocol": "smithy.protocols#rpcv2Cbor", - "code": 200, - "body": "v3BzcGFyc2VTdHJpbmdMaXN0n/b//w==", - "bodyMediaType": "application/cbor", - "headers": { - "smithy-protocol": "rpc-v2-cbor", - "Content-Type": "application/cbor" - }, - "params": { - "sparseStringList": [ - null - ] - } - } - ] - } - }, - "smithy.protocoltests.rpcv2Cbor#SparseNullsOperationInputOutput": { - "type": "structure", - "members": { - "sparseStringList": { - "target": "smithy.protocoltests.shared#SparseStringList" - }, - "sparseStringMap": { - "target": "smithy.protocoltests.shared#SparseStringMap" - } - } - }, - "smithy.protocoltests.rpcv2Cbor#SparseNumberMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.api#Integer" - }, - "traits": { - "smithy.api#sparse": {} - } - }, - "smithy.protocoltests.rpcv2Cbor#SparseSetMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.protocoltests.shared#StringSet" - }, - "traits": { - "smithy.api#sparse": {} - } - }, - "smithy.protocoltests.rpcv2Cbor#SparseStructMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.protocoltests.shared#GreetingStruct" - }, - "traits": { - "smithy.api#sparse": {} - } - }, - "smithy.protocoltests.rpcv2Cbor#StructureList": { - "type": "list", - "member": { - "target": "smithy.protocoltests.rpcv2Cbor#StructureListMember" - } - }, - "smithy.protocoltests.rpcv2Cbor#StructureListMember": { - "type": "structure", - "members": { - "a": { - "target": "smithy.api#String" - }, - "b": { - "target": "smithy.api#String" - } - } - }, - "smithy.protocoltests.rpcv2Cbor#TestEnum": { - "type": "enum", - "members": { - "FOO": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#enumValue": "FOO" - } - }, - "BAR": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#enumValue": "BAR" - } - }, - "BAZ": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#enumValue": "BAZ" - } - } - } - }, - "smithy.protocoltests.rpcv2Cbor#TestIntEnum": { - "type": "intEnum", - "members": { - "ONE": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#enumValue": 1 - } - }, - "TWO": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#enumValue": 2 - } - } - } - }, - "smithy.protocoltests.rpcv2Cbor#TestStringList": { - "type": "list", - "member": { - "target": "smithy.api#String" - } - }, - "smithy.protocoltests.rpcv2Cbor#TestStringMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.api#String" - } - }, - "smithy.protocoltests.shared#BlobList": { - "type": "list", - "member": { - "target": "smithy.api#Blob" - } - }, - "smithy.protocoltests.shared#BlobSet": { - "type": "list", - "member": { - "target": "smithy.api#Blob" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#BooleanList": { - "type": "list", - "member": { - "target": "smithy.api#Boolean" - } - }, - "smithy.protocoltests.shared#BooleanSet": { - "type": "list", - "member": { - "target": "smithy.api#Boolean" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#ByteList": { - "type": "list", - "member": { - "target": "smithy.api#Byte" - } - }, - "smithy.protocoltests.shared#ByteSet": { - "type": "list", - "member": { - "target": "smithy.api#Byte" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#DateTime": { - "type": "timestamp", - "traits": { - "smithy.api#timestampFormat": "date-time" - } - }, - "smithy.protocoltests.shared#DateTimeList": { - "type": "list", - "member": { - "target": "smithy.protocoltests.shared#DateTime" - } - }, - "smithy.protocoltests.shared#DateTimeSet": { - "type": "list", - "member": { - "target": "smithy.protocoltests.shared#DateTime" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#DoubleList": { - "type": "list", - "member": { - "target": "smithy.api#Double" - } - }, - "smithy.protocoltests.shared#EpochSeconds": { - "type": "timestamp", - "traits": { - "smithy.api#timestampFormat": "epoch-seconds" - } - }, - "smithy.protocoltests.shared#FloatList": { - "type": "list", - "member": { - "target": "smithy.api#Float" - } - }, - "smithy.protocoltests.shared#FooEnum": { - "type": "enum", - "members": { - "FOO": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#enumValue": "Foo" - } - }, - "BAZ": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#enumValue": "Baz" - } - }, - "BAR": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#enumValue": "Bar" - } - }, - "ONE": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#enumValue": "1" - } - }, - "ZERO": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#enumValue": "0" - } - } - } - }, - "smithy.protocoltests.shared#FooEnumList": { - "type": "list", - "member": { - "target": "smithy.protocoltests.shared#FooEnum" - } - }, - "smithy.protocoltests.shared#FooEnumMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.protocoltests.shared#FooEnum" - } - }, - "smithy.protocoltests.shared#FooEnumSet": { - "type": "list", - "member": { - "target": "smithy.protocoltests.shared#FooEnum" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#FooUnion": { - "type": "union", - "members": { - "string": { - "target": "smithy.api#String" - }, - "integer": { - "target": "smithy.api#Integer" - } - } - }, - "smithy.protocoltests.shared#GreetingList": { - "type": "list", - "member": { - "target": "smithy.protocoltests.shared#GreetingStruct" - } - }, - "smithy.protocoltests.shared#GreetingStruct": { - "type": "structure", - "members": { - "hi": { - "target": "smithy.api#String" - } - } - }, - "smithy.protocoltests.shared#HttpDate": { - "type": "timestamp", - "traits": { - "smithy.api#timestampFormat": "http-date" - } - }, - "smithy.protocoltests.shared#HttpDateSet": { - "type": "list", - "member": { - "target": "smithy.protocoltests.shared#HttpDate" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#IntegerEnum": { - "type": "intEnum", - "members": { - "A": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#enumValue": 1 - } - }, - "B": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#enumValue": 2 - } - }, - "C": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#enumValue": 3 - } - } - } - }, - "smithy.protocoltests.shared#IntegerEnumList": { - "type": "list", - "member": { - "target": "smithy.protocoltests.shared#IntegerEnum" - } - }, - "smithy.protocoltests.shared#IntegerEnumMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.protocoltests.shared#IntegerEnum" - } - }, - "smithy.protocoltests.shared#IntegerEnumSet": { - "type": "list", - "member": { - "target": "smithy.protocoltests.shared#IntegerEnum" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#IntegerList": { - "type": "list", - "member": { - "target": "smithy.api#Integer" - } - }, - "smithy.protocoltests.shared#IntegerSet": { - "type": "list", - "member": { - "target": "smithy.api#Integer" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#JpegBlob": { - "type": "blob", - "traits": { - "smithy.api#mediaType": "image/jpeg" - } - }, - "smithy.protocoltests.shared#ListSet": { - "type": "list", - "member": { - "target": "smithy.protocoltests.shared#StringList" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#LongList": { - "type": "list", - "member": { - "target": "smithy.api#Long" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#LongSet": { - "type": "list", - "member": { - "target": "smithy.api#Long" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#NestedStringList": { - "type": "list", - "member": { - "target": "smithy.protocoltests.shared#StringList" - }, - "traits": { - "smithy.api#documentation": "A list of lists of strings." - } - }, - "smithy.protocoltests.shared#ShortList": { - "type": "list", - "member": { - "target": "smithy.api#Short" - } - }, - "smithy.protocoltests.shared#ShortSet": { - "type": "list", - "member": { - "target": "smithy.api#Short" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#SparseStringList": { - "type": "list", - "member": { - "target": "smithy.api#String" - }, - "traits": { - "smithy.api#sparse": {} - } - }, - "smithy.protocoltests.shared#SparseStringMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.api#String" - }, - "traits": { - "smithy.api#sparse": {} - } - }, - "smithy.protocoltests.shared#StringList": { - "type": "list", - "member": { - "target": "smithy.api#String" - } - }, - "smithy.protocoltests.shared#StringListMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.protocoltests.shared#StringList" - } - }, - "smithy.protocoltests.shared#StringMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.api#String" - } - }, - "smithy.protocoltests.shared#StringSet": { - "type": "list", - "member": { - "target": "smithy.api#String" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#StructureSet": { - "type": "list", - "member": { - "target": "smithy.protocoltests.shared#GreetingStruct" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#TextPlainBlob": { - "type": "blob", - "traits": { - "smithy.api#mediaType": "text/plain" - } - }, - "smithy.protocoltests.shared#TimestampList": { - "type": "list", - "member": { - "target": "smithy.api#Timestamp" - } - }, - "smithy.protocoltests.shared#TimestampSet": { - "type": "list", - "member": { - "target": "smithy.api#Timestamp" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, - "smithy.protocoltests.shared#UnionSet": { - "type": "list", - "member": { - "target": "smithy.protocoltests.shared#FooUnion" - }, - "traits": { - "smithy.api#uniqueItems": {} - } - }, "smithy.ruby.tests#Operation": { "type": "operation", "input": { @@ -3351,588 +26,6 @@ "target": "smithy.ruby.tests#Structure" } } - }, - "smithy.test#AppliesTo": { - "type": "enum", - "members": { - "CLIENT": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The test only applies to client implementations.", - "smithy.api#enumValue": "client" - } - }, - "SERVER": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The test only applies to server implementations.", - "smithy.api#enumValue": "server" - } - } - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.test#HttpMalformedRequestDefinition": { - "type": "structure", - "members": { - "method": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The HTTP request method.", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#required": {} - } - }, - "uri": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The request-target of the HTTP request, not including\nthe query string (for example, \"/foo/bar\").", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#required": {} - } - }, - "host": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The host / endpoint provided to the client, not including the path\nor scheme (for example, \"example.com\")." - } - }, - "queryParams": { - "target": "smithy.test#StringList", - "traits": { - "smithy.api#documentation": "A list of the serialized query string parameters to include in the request.\n\nEach element in the list is a query string key value pair\nthat starts with the query string parameter name optionally\nfollowed by \"=\", optionally followed by the query string\nparameter value. For example, \"foo=bar\", \"foo=\", and \"foo\"\nare all valid values. The query string parameter name and\nthe value MUST appear in the format in which it is expected\nto be sent over the wire; if a key or value needs to be\npercent-encoded, then it MUST appear percent-encoded in this list." - } - }, - "headers": { - "target": "smithy.test#StringMap", - "traits": { - "smithy.api#documentation": "Defines a map of HTTP headers to include in the request" - } - }, - "body": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The HTTP message body to include in the request" - } - }, - "bodyMediaType": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The media type of the `body`.\n\nThis is used to help test runners to parse and validate the expected\ndata against generated data." - } - } - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.test#HttpMalformedRequestTestCase": { - "type": "structure", - "members": { - "id": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The identifier of the test case. This identifier can be used by\nprotocol test implementations to filter out unsupported test\ncases by ID, to generate test case names, etc. The provided `id`\nMUST match Smithy's `identifier` ABNF. No two `httpMalformedRequestTests`\ntest cases can share the same ID.", - "smithy.api#pattern": "^[A-Za-z_][A-Za-z0-9_]+$", - "smithy.api#required": {} - } - }, - "protocol": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the protocol to test.", - "smithy.api#idRef": { - "selector": "[trait|protocolDefinition]", - "failWhenMissing": true - }, - "smithy.api#required": {} - } - }, - "request": { - "target": "smithy.test#HttpMalformedRequestDefinition", - "traits": { - "smithy.api#documentation": "The malformed request to send.", - "smithy.api#required": {} - } - }, - "response": { - "target": "smithy.test#HttpMalformedResponseDefinition", - "traits": { - "smithy.api#documentation": "The expected response.", - "smithy.api#required": {} - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A description of the test and what is being asserted." - } - }, - "tags": { - "target": "smithy.test#NonEmptyStringList", - "traits": { - "smithy.api#documentation": "Applies a list of tags to the test." - } - }, - "testParameters": { - "target": "smithy.test#HttpMalformedRequestTestParametersDefinition", - "traits": { - "smithy.api#documentation": "An optional set of test parameters for parameterized testing." - } - } - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.test#HttpMalformedRequestTestParametersDefinition": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.test#StringList" - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.test#HttpMalformedResponseBodyAssertion": { - "type": "union", - "members": { - "contents": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Defines the expected serialized response body, which will be matched\nexactly." - } - }, - "messageRegex": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A regex to evaluate against the `message` field in the body. For\nresponses that may have some variance from platform to platform,\nsuch as those that include messages from a parser." - } - } - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.test#HttpMalformedResponseBodyDefinition": { - "type": "structure", - "members": { - "assertion": { - "target": "smithy.test#HttpMalformedResponseBodyAssertion", - "traits": { - "smithy.api#documentation": "The assertion to execute against the response body.", - "smithy.api#required": {} - } - }, - "mediaType": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The media type of the response body.\n\nThis is used to help test runners to parse and evaluate\n`contents' and `messageRegex` in the assertion", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.test#HttpMalformedResponseDefinition": { - "type": "structure", - "members": { - "headers": { - "target": "smithy.test#StringMap", - "traits": { - "smithy.api#documentation": "Defines a map of expected HTTP headers.\n\nHeaders that are not listed in this map are ignored." - } - }, - "code": { - "target": "smithy.api#Integer", - "traits": { - "smithy.api#documentation": "Defines the HTTP response code.", - "smithy.api#range": { - "min": 100, - "max": 599 - }, - "smithy.api#required": {} - } - }, - "body": { - "target": "smithy.test#HttpMalformedResponseBodyDefinition", - "traits": { - "smithy.api#documentation": "The expected response body." - } - } - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.test#HttpRequestTestCase": { - "type": "structure", - "members": { - "id": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The identifier of the test case. This identifier can be used by\nprotocol test implementations to filter out unsupported test\ncases by ID, to generate test case names, etc. The provided `id`\nMUST match Smithy's `identifier` ABNF. No two `httpRequestTests`\ntest cases can share the same ID.", - "smithy.api#pattern": "^[A-Za-z_][A-Za-z0-9_]+$", - "smithy.api#required": {} - } - }, - "protocol": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The name of the protocol to test.", - "smithy.api#idRef": { - "selector": "[trait|protocolDefinition]", - "failWhenMissing": true - }, - "smithy.api#required": {} - } - }, - "method": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected serialized HTTP request method.", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#required": {} - } - }, - "uri": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The request-target of the HTTP request, not including\nthe query string (for example, \"/foo/bar\").", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#required": {} - } - }, - "host": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The host / endpoint provided to the client, not including the path\nor scheme (for example, \"example.com\")." - } - }, - "resolvedHost": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The host / endpoint that the client should send to, not including\nthe path or scheme (for example, \"prefix.example.com\").\n\nThis can differ from the host provided to the client if the `hostPrefix`\nmember of the `endpoint` trait is set, for instance." - } - }, - "authScheme": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The optional authentication scheme shape ID to assume. It's\npossible that specific authentication schemes might influence\nthe serialization logic of an HTTP request.", - "smithy.api#idRef": { - "selector": "[trait|authDefinition]", - "failWhenMissing": true - } - } - }, - "queryParams": { - "target": "smithy.test#StringList", - "traits": { - "smithy.api#documentation": "A list of the expected serialized query string parameters.\n\nEach element in the list is a query string key value pair\nthat starts with the query string parameter name optionally\nfollowed by \"=\", optionally followed by the query string\nparameter value. For example, \"foo=bar\", \"foo=\", and \"foo\"\nare all valid values. The query string parameter name and\nthe value MUST appear in the format in which it is expected\nto be sent over the wire; if a key or value needs to be\npercent-encoded, then it MUST appear percent-encoded in this list.\n\nA serialized HTTP request is not in compliance with the protocol\nif any query string parameter defined in `queryParams` is not\ndefined in the request or if the value of a query string parameter\nin the request differs from the expected value.\n\n`queryParams` applies no constraints on additional query parameters." - } - }, - "forbidQueryParams": { - "target": "smithy.test#StringList", - "traits": { - "smithy.api#documentation": "A list of query string parameter names that must not appear in the\nserialized HTTP request.\n\nEach value MUST appear in the format in which it is sent over the\nwire; if a key needs to be percent-encoded, then it MUST appear\npercent-encoded in this list." - } - }, - "requireQueryParams": { - "target": "smithy.test#StringList", - "traits": { - "smithy.api#documentation": "A list of query string parameter names that MUST appear in the\nserialized request URI, but no assertion is made on the value.\n\nEach value MUST appear in the format in which it is sent over the\nwire; if a key needs to be percent-encoded, then it MUST appear\npercent-encoded in this list." - } - }, - "headers": { - "target": "smithy.test#StringMap", - "traits": { - "smithy.api#documentation": "Defines a map of expected HTTP headers.\n\nHeaders that are not listed in this map are ignored unless they are\nexplicitly forbidden through `forbidHeaders`." - } - }, - "forbidHeaders": { - "target": "smithy.test#StringList", - "traits": { - "smithy.api#documentation": "A list of header field names that must not appear in the serialized\nHTTP request." - } - }, - "requireHeaders": { - "target": "smithy.test#StringList", - "traits": { - "smithy.api#documentation": "A list of header field names that must appear in the serialized\nHTTP message, but no assertion is made on the value.\n\nHeaders listed in `headers` do not need to appear in this list." - } - }, - "body": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected HTTP message body.\n\nIf no request body is defined, then no assertions are made about\nthe body of the message." - } - }, - "bodyMediaType": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The media type of the `body`.\n\nThis is used to help test runners to parse and validate the expected\ndata against generated data." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the input parameters used to generated the HTTP request.\n\nThese parameters MUST be compatible with the input of the operation." - } - }, - "vendorParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines vendor-specific parameters that are used to influence the\nrequest. For example, some vendors might utilize environment\nvariables, configuration files on disk, or other means to influence\nthe serialization formats used by clients or servers.\n\nIf a `vendorParamsShape` is set, these parameters MUST be compatible\nwith that shape's definition." - } - }, - "vendorParamsShape": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A shape to be used to validate the `vendorParams` member contents.\n\nIf set, the parameters in `vendorParams` MUST be compatible with this\nshape's definition.", - "smithy.api#idRef": { - "failWhenMissing": true - } - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A description of the test and what is being asserted." - } - }, - "tags": { - "target": "smithy.test#NonEmptyStringList", - "traits": { - "smithy.api#documentation": "Applies a list of tags to the test." - } - }, - "appliesTo": { - "target": "smithy.test#AppliesTo", - "traits": { - "smithy.api#documentation": "Indicates that the test case is only to be implemented by \"client\" or\n\"server\" implementations. This property is useful for identifying and\ntesting edge cases of clients and servers that are impossible or\nundesirable to test in *both* client and server implementations." - } - } - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.test#HttpResponseTestCase": { - "type": "structure", - "members": { - "id": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The identifier of the test case. This identifier can be used by\nprotocol test implementations to filter out unsupported test\ncases by ID, to generate test case names, etc. The provided `id`\nMUST match Smithy's `identifier` ABNF. No two `httpResponseTests`\ntest cases can share the same ID.", - "smithy.api#pattern": "^[A-Za-z_][A-Za-z0-9_]+$", - "smithy.api#required": {} - } - }, - "protocol": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The shape ID of the protocol to test.", - "smithy.api#idRef": { - "selector": "[trait|protocolDefinition]", - "failWhenMissing": true - }, - "smithy.api#required": {} - } - }, - "code": { - "target": "smithy.api#Integer", - "traits": { - "smithy.api#documentation": "Defines the HTTP response code.", - "smithy.api#range": { - "min": 100, - "max": 599 - }, - "smithy.api#required": {} - } - }, - "authScheme": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The optional authentication scheme shape ID to assume. It's possible\nthat specific authentication schemes might influence the serialization\nlogic of an HTTP response.", - "smithy.api#idRef": { - "selector": "[trait|authDefinition]", - "failWhenMissing": true - } - } - }, - "headers": { - "target": "smithy.test#StringMap", - "traits": { - "smithy.api#documentation": "A map of expected HTTP headers. Each key represents a header field\nname and each value represents the expected header value. An HTTP\nresponse is not in compliance with the protocol if any listed header\nis missing from the serialized response or if the expected header\nvalue differs from the serialized response value.\n\n`headers` applies no constraints on additional headers." - } - }, - "forbidHeaders": { - "target": "smithy.test#StringList", - "traits": { - "smithy.api#documentation": "A list of header field names that must not appear." - } - }, - "requireHeaders": { - "target": "smithy.test#StringList", - "traits": { - "smithy.api#documentation": "A list of header field names that must appear in the serialized\nHTTP message, but no assertion is made on the value.\n\nHeaders listed in `headers` map do not need to appear in this list." - } - }, - "body": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Defines the HTTP message body.\n\nIf no response body is defined, then no assertions are made about\nthe body of the message." - } - }, - "bodyMediaType": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The media type of the `body`.\n\nThis is used to help test runners to parse and validate the expected\ndata against generated data. Binary media type formats require that\nthe contents of `body` are base64 encoded." - } - }, - "params": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines the output parameters deserialized from the HTTP response.\n\nThese parameters MUST be compatible with the output of the operation." - } - }, - "vendorParams": { - "target": "smithy.api#Document", - "traits": { - "smithy.api#documentation": "Defines vendor-specific parameters that are used to influence the\nresponse. For example, some vendors might utilize environment\nvariables, configuration files on disk, or other means to influence\nthe serialization formats used by clients or servers.\n\nIf a `vendorParamsShape` is set, these parameters MUST be compatible\nwith that shape's definition." - } - }, - "vendorParamsShape": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A shape to be used to validate the `vendorParams` member contents.\n\nIf set, the parameters in `vendorParams` MUST be compatible with this\nshape's definition.", - "smithy.api#idRef": { - "failWhenMissing": true - } - } - }, - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A description of the test and what is being asserted." - } - }, - "tags": { - "target": "smithy.test#NonEmptyStringList", - "traits": { - "smithy.api#documentation": "Applies a list of tags to the test." - } - }, - "appliesTo": { - "target": "smithy.test#AppliesTo", - "traits": { - "smithy.api#documentation": "Indicates that the test case is only to be implemented by \"client\" or\n\"server\" implementations. This property is useful for identifying and\ntesting edge cases of clients and servers that are impossible or\nundesirable to test in *both* client and server implementations." - } - } - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.test#NonEmptyString": { - "type": "string", - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.test#NonEmptyStringList": { - "type": "list", - "member": { - "target": "smithy.test#NonEmptyString" - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.test#StringList": { - "type": "list", - "member": { - "target": "smithy.api#String" - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.test#StringMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.api#String" - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.test#httpMalformedRequestTests": { - "type": "list", - "member": { - "target": "smithy.test#HttpMalformedRequestTestCase" - }, - "traits": { - "smithy.api#documentation": "Define how a malformed HTTP request is rejected by a server given a specific protocol", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#trait": { - "selector": "operation" - }, - "smithy.api#unstable": {} - } - }, - "smithy.test#httpRequestTests": { - "type": "list", - "member": { - "target": "smithy.test#HttpRequestTestCase" - }, - "traits": { - "smithy.api#documentation": "Define how an HTTP request is serialized given a specific protocol,\nauthentication scheme, and set of input parameters.", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#trait": { - "selector": "operation" - } - } - }, - "smithy.test#httpResponseTests": { - "type": "list", - "member": { - "target": "smithy.test#HttpResponseTestCase" - }, - "traits": { - "smithy.api#documentation": "Define how an HTTP response is serialized given a specific protocol,\nauthentication scheme, and set of output or error parameters.", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#trait": { - "selector": ":test(operation, structure[trait|error])" - } - } } } } diff --git a/gems/smithy/spec/fixtures/service_index/model.json b/gems/smithy/spec/fixtures/service_index/model.json index d002a3606..38670a411 100644 --- a/gems/smithy/spec/fixtures/service_index/model.json +++ b/gems/smithy/spec/fixtures/service_index/model.json @@ -1,53 +1,6 @@ { "smithy": "2.0", "shapes": { - "smithy.protocols#StringList": { - "type": "list", - "member": { - "target": "smithy.api#String" - }, - "traits": { - "smithy.api#documentation": "A list of String shapes.", - "smithy.api#private": {} - } - }, - "smithy.protocols#rpcv2Cbor": { - "type": "structure", - "members": { - "http": { - "target": "smithy.protocols#StringList", - "traits": { - "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions." - } - }, - "eventStreamHttp": { - "target": "smithy.protocols#StringList", - "traits": { - "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions\nthat are required when using event streams." - } - } - }, - "traits": { - "smithy.api#documentation": "An RPC-based protocol that serializes CBOR payloads.", - "smithy.api#protocolDefinition": { - "traits": [ - "smithy.api#cors", - "smithy.api#endpoint", - "smithy.api#hostLabel", - "smithy.api#httpError" - ] - }, - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#traitValidators": { - "rpcv2Cbor.NoDocuments": { - "selector": "service ~> member :test(> document)", - "message": "This protocol does not support document types" - } - } - } - }, "smithy.ruby.tests#ClientError": { "type": "structure", "members": { diff --git a/gems/smithy/spec/fixtures/shapes/model.json b/gems/smithy/spec/fixtures/shapes/model.json index 91b588170..2f7119c92 100644 --- a/gems/smithy/spec/fixtures/shapes/model.json +++ b/gems/smithy/spec/fixtures/shapes/model.json @@ -1,53 +1,6 @@ { "smithy": "2.0", "shapes": { - "smithy.protocols#StringList": { - "type": "list", - "member": { - "target": "smithy.api#String" - }, - "traits": { - "smithy.api#documentation": "A list of String shapes.", - "smithy.api#private": {} - } - }, - "smithy.protocols#rpcv2Cbor": { - "type": "structure", - "members": { - "http": { - "target": "smithy.protocols#StringList", - "traits": { - "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions." - } - }, - "eventStreamHttp": { - "target": "smithy.protocols#StringList", - "traits": { - "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions\nthat are required when using event streams." - } - } - }, - "traits": { - "smithy.api#documentation": "An RPC-based protocol that serializes CBOR payloads.", - "smithy.api#protocolDefinition": { - "traits": [ - "smithy.api#cors", - "smithy.api#endpoint", - "smithy.api#hostLabel", - "smithy.api#httpError" - ] - }, - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#traitValidators": { - "rpcv2Cbor.NoDocuments": { - "selector": "service ~> member :test(> document)", - "message": "This protocol does not support document types" - } - } - } - }, "smithy.ruby.tests#BigDecimal": { "type": "bigDecimal", "traits": { diff --git a/gems/smithy/spec/fixtures/syntax_examples/model.json b/gems/smithy/spec/fixtures/syntax_examples/model.json index fb43bba1a..47c136deb 100644 --- a/gems/smithy/spec/fixtures/syntax_examples/model.json +++ b/gems/smithy/spec/fixtures/syntax_examples/model.json @@ -1,53 +1,6 @@ { "smithy": "2.0", "shapes": { - "smithy.protocols#StringList": { - "type": "list", - "member": { - "target": "smithy.api#String" - }, - "traits": { - "smithy.api#documentation": "A list of String shapes.", - "smithy.api#private": {} - } - }, - "smithy.protocols#rpcv2Cbor": { - "type": "structure", - "members": { - "http": { - "target": "smithy.protocols#StringList", - "traits": { - "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions." - } - }, - "eventStreamHttp": { - "target": "smithy.protocols#StringList", - "traits": { - "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions\nthat are required when using event streams." - } - } - }, - "traits": { - "smithy.api#documentation": "An RPC-based protocol that serializes CBOR payloads.", - "smithy.api#protocolDefinition": { - "traits": [ - "smithy.api#cors", - "smithy.api#endpoint", - "smithy.api#hostLabel", - "smithy.api#httpError" - ] - }, - "smithy.api#trait": { - "selector": "service" - }, - "smithy.api#traitValidators": { - "rpcv2Cbor.NoDocuments": { - "selector": "service ~> member :test(> document)", - "message": "This protocol does not support document types" - } - } - } - }, "smithy.ruby.tests#ComplexList": { "type": "list", "member": { diff --git a/gems/smithy/spec/fixtures/weather/model.json b/gems/smithy/spec/fixtures/weather/model.json index 5d1cb8412..adb421790 100644 --- a/gems/smithy/spec/fixtures/weather/model.json +++ b/gems/smithy/spec/fixtures/weather/model.json @@ -290,269 +290,6 @@ "pageSize": "pageSize" } } - }, - "smithy.waiters#Acceptor": { - "type": "structure", - "members": { - "state": { - "target": "smithy.waiters#AcceptorState", - "traits": { - "smithy.api#documentation": "The state the acceptor transitions to when matched.", - "smithy.api#required": {} - } - }, - "matcher": { - "target": "smithy.waiters#Matcher", - "traits": { - "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", - "smithy.api#private": {} - } - }, - "smithy.waiters#AcceptorState": { - "type": "enum", - "members": { - "SUCCESS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", - "smithy.api#enumValue": "success" - } - }, - "FAILURE": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", - "smithy.api#enumValue": "failure" - } - }, - "RETRY": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", - "smithy.api#enumValue": "retry" - } - } - }, - "traits": { - "smithy.api#documentation": "The transition state of a waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Acceptors": { - "type": "list", - "member": { - "target": "smithy.waiters#Acceptor" - }, - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#Matcher": { - "type": "union", - "members": { - "output": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." - } - }, - "inputOutput": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." - } - }, - "errorType": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." - } - }, - "success": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyString": { - "type": "string", - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyStringList": { - "type": "list", - "member": { - "target": "smithy.waiters#NonEmptyString" - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.waiters#PathComparator": { - "type": "enum", - "members": { - "STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", - "smithy.api#enumValue": "stringEquals" - } - }, - "BOOLEAN_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", - "smithy.api#enumValue": "booleanEquals" - } - }, - "ALL_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if all values in the list matches the expected string.", - "smithy.api#enumValue": "allStringEquals" - } - }, - "ANY_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if any value in the list matches the expected string.", - "smithy.api#enumValue": "anyStringEquals" - } - } - }, - "traits": { - "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", - "smithy.api#private": {} - } - }, - "smithy.waiters#PathMatcher": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", - "smithy.api#required": {} - } - }, - "expected": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected return value of the expression.", - "smithy.api#required": {} - } - }, - "comparator": { - "target": "smithy.waiters#PathComparator", - "traits": { - "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Waiter": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." - } - }, - "acceptors": { - "target": "smithy.waiters#Acceptors", - "traits": { - "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", - "smithy.api#required": {} - } - }, - "minDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 2, - "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." - } - }, - "maxDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 120, - "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." - } - }, - "deprecated": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." - } - }, - "tags": { - "target": "smithy.waiters#NonEmptyStringList", - "traits": { - "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines an individual operation waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#WaiterDelay": { - "type": "integer", - "traits": { - "smithy.api#range": { - "min": 1 - } - } - }, - "smithy.waiters#WaiterName": { - "type": "string", - "traits": { - "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" - } - }, - "smithy.waiters#waitable": { - "type": "map", - "key": { - "target": "smithy.waiters#WaiterName" - }, - "value": { - "target": "smithy.waiters#Waiter" - }, - "traits": { - "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#trait": { - "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" - } - } } } } diff --git a/gems/smithy/spec/fixtures/weld_protocol/model.json b/gems/smithy/spec/fixtures/weld_protocol/model.json index 2539fe02d..faf1eb9a0 100644 --- a/gems/smithy/spec/fixtures/weld_protocol/model.json +++ b/gems/smithy/spec/fixtures/weld_protocol/model.json @@ -14,269 +14,6 @@ "smithy.api#protocolDefinition": {}, "smithy.api#trait": {} } - }, - "smithy.waiters#Acceptor": { - "type": "structure", - "members": { - "state": { - "target": "smithy.waiters#AcceptorState", - "traits": { - "smithy.api#documentation": "The state the acceptor transitions to when matched.", - "smithy.api#required": {} - } - }, - "matcher": { - "target": "smithy.waiters#Matcher", - "traits": { - "smithy.api#documentation": "The matcher used to test if the resource is in a given state.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Represents an acceptor in a waiter's state machine.", - "smithy.api#private": {} - } - }, - "smithy.waiters#AcceptorState": { - "type": "enum", - "members": { - "SUCCESS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", - "smithy.api#enumValue": "success" - } - }, - "FAILURE": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", - "smithy.api#enumValue": "failure" - } - }, - "RETRY": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", - "smithy.api#enumValue": "retry" - } - } - }, - "traits": { - "smithy.api#documentation": "The transition state of a waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Acceptors": { - "type": "list", - "member": { - "target": "smithy.waiters#Acceptor" - }, - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#Matcher": { - "type": "union", - "members": { - "output": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on the successful output of an operation using a\nJMESPath expression." - } - }, - "inputOutput": { - "target": "smithy.waiters#PathMatcher", - "traits": { - "smithy.api#documentation": "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." - } - }, - "errorType": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." - } - }, - "success": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how an acceptor determines if it matches the current state of\na resource.", - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyString": { - "type": "string", - "traits": { - "smithy.api#length": { - "min": 1 - }, - "smithy.api#private": {} - } - }, - "smithy.waiters#NonEmptyStringList": { - "type": "list", - "member": { - "target": "smithy.waiters#NonEmptyString" - }, - "traits": { - "smithy.api#private": {} - } - }, - "smithy.waiters#PathComparator": { - "type": "enum", - "members": { - "STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a string that is equal to the expected string.", - "smithy.api#enumValue": "stringEquals" - } - }, - "BOOLEAN_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", - "smithy.api#enumValue": "booleanEquals" - } - }, - "ALL_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if all values in the list matches the expected string.", - "smithy.api#enumValue": "allStringEquals" - } - }, - "ANY_STRING_EQUALS": { - "target": "smithy.api#Unit", - "traits": { - "smithy.api#documentation": "Matches if any value in the list matches the expected string.", - "smithy.api#enumValue": "anyStringEquals" - } - } - }, - "traits": { - "smithy.api#documentation": "Defines a comparison to perform in a PathMatcher.", - "smithy.api#private": {} - } - }, - "smithy.waiters#PathMatcher": { - "type": "structure", - "members": { - "path": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "A JMESPath expression applied to the input or output of an operation.", - "smithy.api#required": {} - } - }, - "expected": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "The expected return value of the expression.", - "smithy.api#required": {} - } - }, - "comparator": { - "target": "smithy.waiters#PathComparator", - "traits": { - "smithy.api#documentation": "The comparator used to compare the result of the expression with the\nexpected value.", - "smithy.api#required": {} - } - } - }, - "traits": { - "smithy.api#documentation": "Defines how to test the result of a JMESPath expression against\nan expected value.", - "smithy.api#private": {} - } - }, - "smithy.waiters#Waiter": { - "type": "structure", - "members": { - "documentation": { - "target": "smithy.api#String", - "traits": { - "smithy.api#documentation": "Documentation about the waiter. Can use CommonMark." - } - }, - "acceptors": { - "target": "smithy.waiters#Acceptors", - "traits": { - "smithy.api#documentation": "An ordered array of acceptors to check after executing an operation.", - "smithy.api#required": {} - } - }, - "minDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 2, - "smithy.api#documentation": "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." - } - }, - "maxDelay": { - "target": "smithy.waiters#WaiterDelay", - "traits": { - "smithy.api#default": 120, - "smithy.api#documentation": "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." - } - }, - "deprecated": { - "target": "smithy.api#Boolean", - "traits": { - "smithy.api#documentation": "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." - } - }, - "tags": { - "target": "smithy.waiters#NonEmptyStringList", - "traits": { - "smithy.api#documentation": "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." - } - } - }, - "traits": { - "smithy.api#documentation": "Defines an individual operation waiter.", - "smithy.api#private": {} - } - }, - "smithy.waiters#WaiterDelay": { - "type": "integer", - "traits": { - "smithy.api#range": { - "min": 1 - } - } - }, - "smithy.waiters#WaiterName": { - "type": "string", - "traits": { - "smithy.api#pattern": "^[A-Z]+[A-Za-z0-9]*$" - } - }, - "smithy.waiters#waitable": { - "type": "map", - "key": { - "target": "smithy.waiters#WaiterName" - }, - "value": { - "target": "smithy.waiters#Waiter" - }, - "traits": { - "smithy.api#documentation": "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", - "smithy.api#length": { - "min": 1 - }, - "smithy.api#trait": { - "selector": "operation :not(-[input, output]-> structure > member > union[trait|streaming])" - } - } } } } From c588576e6c52cc089bd66e13ed41040a8631e53f Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 29 Apr 2025 15:16:12 -0700 Subject: [PATCH 12/48] Start adding tests --- .../lib/smithy-client/waiters/errors.rb | 64 +++++----- .../lib/smithy-client/waiters/poller.rb | 67 ++++++----- .../lib/smithy-client/waiters/waiter.rb | 8 +- gems/smithy/lib/smithy/plan.rb | 1 - .../lib/smithy/templates/client/client.erb | 10 +- gems/smithy/lib/smithy/util/underscore.rb | 8 ++ .../{waiters => wait_service}/model.json | 66 ++++++++++- .../{waiters => wait_service}/model.smithy | 39 ++++++- .../smithy-build.json | 0 .../spec/interfaces/client/waiters_spec.rb | 110 +++++++++++++++++- projections/shapes/lib/shapes/client.rb | 10 +- projections/weather/lib/weather/client.rb | 11 +- 12 files changed, 298 insertions(+), 96 deletions(-) rename gems/smithy/spec/fixtures/{waiters => wait_service}/model.json (92%) rename gems/smithy/spec/fixtures/{waiters => wait_service}/model.smithy (90%) rename gems/smithy/spec/fixtures/{waiters => wait_service}/smithy-build.json (100%) diff --git a/gems/smithy-client/lib/smithy-client/waiters/errors.rb b/gems/smithy-client/lib/smithy-client/waiters/errors.rb index 4027b5ae2..281cc3677 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/errors.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/errors.rb @@ -2,49 +2,51 @@ module Smithy module Client - module Errors + module Waiters + module Errors - # Raised when a waiter detects a condition where the waiter can never - # succeed. - class WaiterFailed < StandardError; end + # Raised when a waiter detects a condition where the waiter can never + # succeed. + class WaiterFailed < StandardError; end - class FailureStateError < WaiterFailed - MSG = "stopped waiting, encountered a failure state" + class FailureStateError < WaiterFailed + MSG = "stopped waiting, encountered a failure state" - def initialize(response) - @response = response - super(MSG) - end + def initialize(response) + @response = response + super(MSG) + end - attr_reader :response - end + attr_reader :response + end - class MaxWaitTimeExceededError < WaiterFailed - MSG = "stopped waiting after maximum wait time of %s seconds was exceeded" + class MaxWaitTimeExceededError < WaiterFailed + MSG = "stopped waiting after maximum wait time of %s seconds was exceeded" - def initialize(max_wait_time) - super(MSG % [max_wait_time]) + def initialize(max_wait_time) + super(MSG % [max_wait_time]) + end end - end - class UnexpectedError < WaiterFailed - MSG = "stopped waiting due to an unexpected error: %s" + class UnexpectedError < WaiterFailed + MSG = "stopped waiting due to an unexpected error: %s" - def initialize(error) - @error = error - super(MSG % [error.message]) - end + def initialize(error) + @error = error + super(MSG % [error.message]) + end - attr_reader :error - end + attr_reader :error + end - # Raised when attempting to get a waiter by name and the waiter has not - # been defined. - class NoSuchWaiterError < ArgumentError - MSG = "no such waiter" + # Raised when attempting to get a waiter by name and the waiter has not + # been defined. + class NoSuchWaiterError < ArgumentError + MSG = "no such waiter" - def initialize - super(MSG) + def initialize + super(MSG) + end end end end diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index 006e56eb0..f7662c6c8 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -10,63 +10,76 @@ def initialize(options = {}) end def call(client, params) - resp = client.send(@operation_name, params) - status = evaluate_acceptors(resp) - [resp, status] + @input = params + begin + resp = client.send(@operation_name, params) + rescue StandardError => e + error = e + end + resp_or_error = resp || error + status = evaluate_acceptors(resp, error) + puts "status is #{status}" + [resp_or_error, status] end - def evaluate_acceptors(resp) + def evaluate_acceptors(resp, error) @acceptors.each do |acceptor| - return acceptor['state'] if acceptor_matches?(acceptor['matcher'], resp) + return acceptor['state'] if acceptor_matches?(acceptor['matcher'], resp, error) end # If none of the acceptors match and an error was encountered, # transition to failure state. Otherwise, transition to retry state. - if resp.error? + if error 'error' else 'retry' end end - def acceptor_matches?(matcher, resp) + def acceptor_matches?(matcher, resp, error) matcher_type = matcher.keys[0] - send("matches_#{matcher_type}?", matcher_type, resp) + send("matches_#{matcher_type}?", matcher[matcher_type], resp, error) end - def matches_output?(path_matcher, resp) - return false if resp.error || resp.data.nil? + def matches_output?(path_matcher, resp, error) + return false unless error.nil? - actual = JMESPath.search(path_matcher['path'], resp.data) - is_equal?(actual, expected, path_matcher['comparator']) + actual = JMESPath.search(Smithy::Util::Underscore.underscore_jmespath(path_matcher['path']), resp) + is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) end - def matches_inputOutput?(path_matcher, resp) - return false if resp.error + def matches_inputOutput?(path_matcher, resp, error) + puts "Matches input output?" + return false unless error.nil? && @input data = { - input: input, ### Where do we get this? - output: resp.data + input: @input, ### Where do we get this? + output: resp } - actual = JMESPath.search(path_matcher['path'], data) - is_equal?(actual, expected, path_matcher['comparator']) + puts "resp is #{resp}" + puts "error is #{error}" + puts "data is #{data}" + puts "path_matcher is #{path_matcher}" + + actual = JMESPath.search(Smithy::Util::Underscore.underscore_jmespath(path_matcher['path']), data) + + is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) end - def matches_success?(path_matcher, resp) - puts "resp is #{resp}" - if path_matcher['success'] - resp.error.nil? + def matches_success?(path_matcher, resp, error) + if path_matcher == true + !resp.nil? else - resp.error? + !error.nil? end end - def matches_errorType?(path_matcher, resp) - return false unless resp.error + def matches_errorType?(path_matcher, resp, error) + return false unless resp.nil? - error = path_matcher['errorType'].split('#').last.split('#').first - error == resp.error + err = path_matcher.split('#').last.split('#').first + error.class.to_s.include?(err) end def is_equal?(actual, expected, comparator) diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index 08459e021..8f997f62b 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -29,14 +29,14 @@ def poll(client, params) resp, status = @poller.call(client, params) attempts += 1 - case status + case status.to_sym when :retry when :success then return resp - when :failure then return Errors::FailureStateError.new(resp) - when :error then return Errors::UnexpectedError.new(resp) + when :failure then raise Errors::FailureStateError.new(resp) + when :error then raise Errors::UnexpectedError.new(resp) end - return Errors::MaxWaitTimeExceededError.new(@max_wait_time) if @remaining_time == 0 + raise Errors::MaxWaitTimeExceededError.new(@max_wait_time) if @remaining_time == 0 delay = delay(attempts) @remaining_time -= delay diff --git a/gems/smithy/lib/smithy/plan.rb b/gems/smithy/lib/smithy/plan.rb index cdf43fac0..a3b22d7c9 100644 --- a/gems/smithy/lib/smithy/plan.rb +++ b/gems/smithy/lib/smithy/plan.rb @@ -66,7 +66,6 @@ def initialize(model, type, options = {}) def find_service(shapes) service = shapes.select { |_, shape| shape['type'] == 'service' } - puts service raise 'Multiple service shapes found' if service.size > 1 raise 'No service shape found' if service.empty? diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index 3aadb212b..8b1e0e5a3 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -87,7 +87,7 @@ module <%= module_name %> operations.each do |operation_name, operation| if (trait = waitable_trait(operation)) trait.each do |name, waiter| - if underscore(name) == waiter_name.to_s + if Smithy::Util::Underscore.underscore(name) == waiter_name.to_s return [operation_name, waiter] end end @@ -102,14 +102,6 @@ module <%= module_name %> end end - def underscore(input) - input.gsub(/::/, '/') - .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') - .gsub(/([a-z\d])([A-Z])/,'\1_\2') - .tr("-", "_") - .downcase - end - def poller_custom(operation_name, acceptors) Smithy::Client::Waiters::Poller.new( operation_name: operation_name.to_sym, diff --git a/gems/smithy/lib/smithy/util/underscore.rb b/gems/smithy/lib/smithy/util/underscore.rb index 8e735c679..c14fe2804 100644 --- a/gems/smithy/lib/smithy/util/underscore.rb +++ b/gems/smithy/lib/smithy/util/underscore.rb @@ -12,6 +12,14 @@ def underscore_jmespath(expression) .gsub(' or ', '||') .gsub(/(? Date: Wed, 30 Apr 2025 11:07:52 -0700 Subject: [PATCH 13/48] Add more unit tests --- .../lib/smithy-client/waiters/poller.rb | 23 +- .../lib/smithy-client/waiters/waiter.rb | 4 +- .../spec/fixtures/wait_service/model.json | 103 +++- .../spec/fixtures/wait_service/model.smithy | 95 +++- .../spec/interfaces/client/waiters_spec.rb | 506 ++++++++++++++---- smithy-build.json | 5 - 6 files changed, 601 insertions(+), 135 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index f7662c6c8..5bbcf26db 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -18,7 +18,7 @@ def call(client, params) end resp_or_error = resp || error status = evaluate_acceptors(resp, error) - puts "status is #{status}" + # puts "status is #{status}" [resp_or_error, status] end @@ -44,12 +44,17 @@ def acceptor_matches?(matcher, resp, error) def matches_output?(path_matcher, resp, error) return false unless error.nil? + # puts "Path matcher is #{path_matcher}" + # puts "Resp is #{resp}" + actual = JMESPath.search(Smithy::Util::Underscore.underscore_jmespath(path_matcher['path']), resp) - is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) + equal = is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) + # puts "Actual #{actual} and Expected #{path_matcher['expected']} Equal? #{equal}" + equal end def matches_inputOutput?(path_matcher, resp, error) - puts "Matches input output?" + # puts "Matches input output?" return false unless error.nil? && @input data = { @@ -57,14 +62,16 @@ def matches_inputOutput?(path_matcher, resp, error) output: resp } - puts "resp is #{resp}" - puts "error is #{error}" - puts "data is #{data}" - puts "path_matcher is #{path_matcher}" + # puts "resp is #{resp}" + # puts "error is #{error}" + # puts "data is #{data}" + # puts "path_matcher is #{path_matcher}" actual = JMESPath.search(Smithy::Util::Underscore.underscore_jmespath(path_matcher['path']), data) - is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) + equal = is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) + # puts "Actual #{actual} and Expected #{path_matcher['expected']} Equal? #{equal}" + equal end def matches_success?(path_matcher, resp, error) diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index 8f997f62b..35672f831 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -47,11 +47,9 @@ def poll(client, params) def delay(attempts) attempt_ceiling = (Math.log(@max_delay / @min_delay) / Math.log(2)) + 1 delay = attempts > attempt_ceiling ? @max_delay : @min_delay * 2 ** (attempts - 1) - puts "delay #{delay}" delay = rand(@min_delay..delay) - puts "delay after rand #{delay}" delay = @remaining_time if @remaining_time - delay <= @min_delay - puts "delay if #{delay}" + puts "delay for #{delay} seconds" delay end end diff --git a/gems/smithy/spec/fixtures/wait_service/model.json b/gems/smithy/spec/fixtures/wait_service/model.json index 2a920f0b2..31aec57b6 100644 --- a/gems/smithy/spec/fixtures/wait_service/model.json +++ b/gems/smithy/spec/fixtures/wait_service/model.json @@ -52,7 +52,7 @@ "method": "POST" }, "smithy.waiters#waitable": { - "MultipleAcceptorsMatcher": { + "AcceptorOrderSuccessMatcher": { "documentation": "Matcher with multiple acceptors", "acceptors": [ { @@ -62,9 +62,26 @@ } }, { - "state": "retry", + "state": "failure", "matcher": { - "errorType": "MyError" + "errorType": "WidgetDoesNotExist" + } + } + ] + }, + "AcceptorOrderFailureMatcher": { + "documentation": "Matcher with multiple acceptors", + "acceptors": [ + { + "state": "failure", + "matcher": { + "errorType": "WidgetDoesNotExist" + } + }, + { + "state": "success", + "matcher": { + "errorType": "WidgetDoesNotExist" } } ] @@ -140,13 +157,28 @@ "matcher": { "output": { "path": "stringProperty", - "expected": "payload property contents", + "expected": "expected string", "comparator": "stringEquals" } } } ] }, + "OutputBooleanPropertyMatcher": { + "documentation": "Acceptor matches on output payload property", + "acceptors": [ + { + "state": "success", + "matcher": { + "output": { + "path": "booleanProperty", + "expected": "false", + "comparator": "booleanEquals" + } + } + } + ] + }, "OutputStringArrayAllPropertyMatcher": { "documentation": "Acceptor matches on output payload property", "acceptors": [ @@ -155,7 +187,7 @@ "matcher": { "output": { "path": "stringArrayProperty", - "expected": "payload property contents", + "expected": "expected string", "comparator": "allStringEquals" } } @@ -170,29 +202,29 @@ "matcher": { "output": { "path": "stringArrayProperty", - "expected": "payload property contents", + "expected": "expected string", "comparator": "anyStringEquals" } } } ] }, - "OutputBooleanPropertyMatcher": { - "documentation": "Acceptor matches on output payload property", + "InputOutputStringPropertyMatcher": { + "documentation": "Acceptor matches on string property of input and output", "acceptors": [ { "state": "success", "matcher": { - "output": { - "path": "booleanProperty", - "expected": "false", - "comparator": "booleanEquals" + "inputOutput": { + "path": "input.stringProperty", + "expected": "output.stringProperty", + "comparator": "stringEquals" } } } ] }, - "InputOutputPropertyMatcher": { + "InputOutputBooleanPropertyMatcher": { "documentation": "Acceptor matches on input property equaling output property", "acceptors": [ { @@ -207,6 +239,36 @@ } ] }, + "InputOutputStringArrayAllPropertyMatcher": { + "documentation": "Acceptor matches on string array property of input and output", + "acceptors": [ + { + "state": "success", + "matcher": { + "inputOutput": { + "path": "input.stringArrayProperty", + "expected": "output.stringArrayProperty", + "comparator": "allStringEquals" + } + } + } + ] + }, + "InputOutputStringArrayAnyPropertyMatcher": { + "documentation": "Acceptor matches on string array property of input and output", + "acceptors": [ + { + "state": "success", + "matcher": { + "inputOutput": { + "path": "input.stringArrayProperty", + "expected": "output.stringArrayProperty", + "comparator": "anyStringEquals" + } + } + } + ] + }, "FlattenMatcher": { "documentation": "Matches when any grandchild has name 'expected name'", "acceptors": [ @@ -377,6 +439,21 @@ "members": { "stringProperty": { "target": "smithy.api#String" + }, + "stringArrayProperty": { + "target": "smithy.ruby.tests#StringArray" + }, + "booleanProperty": { + "target": "smithy.api#Boolean" + }, + "booleanArrayProperty": { + "target": "smithy.ruby.tests#BooleanArray" + }, + "children": { + "target": "smithy.ruby.tests#ChildArray" + }, + "dataMap": { + "target": "smithy.ruby.tests#DataMap" } } }, diff --git a/gems/smithy/spec/fixtures/wait_service/model.smithy b/gems/smithy/spec/fixtures/wait_service/model.smithy index a886b0558..81a4c7bc1 100644 --- a/gems/smithy/spec/fixtures/wait_service/model.smithy +++ b/gems/smithy/spec/fixtures/wait_service/model.smithy @@ -56,13 +56,28 @@ service WaitService { matcher: { output: { path: "stringProperty" - expected: "payload property contents" + expected: "expected string" comparator: "stringEquals" } } } ] } + OutputBooleanPropertyMatcher: { + documentation: "Acceptor matches on output payload property" + acceptors: [ + { + state: "success" + matcher: { + output: { + path: "booleanProperty" + expected: "false" + comparator: "booleanEquals" + } + } + } + ] + } OutputStringArrayAllPropertyMatcher: { documentation: "Acceptor matches on output payload property" acceptors: [ @@ -71,7 +86,7 @@ service WaitService { matcher: { output: { path: "stringArrayProperty" - expected: "payload property contents" + expected: "expected string" comparator: "allStringEquals" } } @@ -86,29 +101,29 @@ service WaitService { matcher: { output: { path: "stringArrayProperty" - expected: "payload property contents" + expected: "expected string" comparator: "anyStringEquals" } } } ] } - OutputBooleanPropertyMatcher: { - documentation: "Acceptor matches on output payload property" + InputOutputStringPropertyMatcher: { + documentation: "Acceptor matches on string property of input and output" acceptors: [ { state: "success" matcher: { - output: { - path: "booleanProperty" - expected: "false" - comparator: "booleanEquals" + inputOutput: { + path: "input.stringProperty" + expected: "output.stringProperty" + comparator: "stringEquals" } } } ] } - InputOutputPropertyMatcher: { + InputOutputBooleanPropertyMatcher: { documentation: "Acceptor matches on input property equaling output property" acceptors: [ { @@ -123,6 +138,36 @@ service WaitService { } ] } + InputOutputStringArrayAllPropertyMatcher: { + documentation: "Acceptor matches on string array property of input and output" + acceptors: [ + { + state: "success" + matcher: { + inputOutput: { + path: "input.stringArrayProperty" + expected: "output.stringArrayProperty" + comparator: "allStringEquals" + } + } + } + ] + } + InputOutputStringArrayAnyPropertyMatcher: { + documentation: "Acceptor matches on string array property of input and output" + acceptors: [ + { + state: "success" + matcher: { + inputOutput: { + path: "input.stringArrayProperty" + expected: "output.stringArrayProperty" + comparator: "anyStringEquals" + } + } + } + ] + } FlattenMatcher: { documentation: "Matches when any grandchild has name 'expected name'" acceptors: [ @@ -237,7 +282,7 @@ operation GetWidget { @http(uri: "/delete-widget", method: "POST") @waitable( - MultipleAcceptorsMatcher: { + AcceptorOrderSuccessMatcher: { documentation: "Matcher with multiple acceptors" acceptors: [ { @@ -245,11 +290,28 @@ operation GetWidget { matcher: { errorType: "WidgetDoesNotExist" } - }, + } { - state: "retry" + state: "failure" matcher: { - errorType: "MyError" + errorType: "WidgetDoesNotExist" + } + } + ] + } + AcceptorOrderFailureMatcher: { + documentation: "Matcher with multiple acceptors" + acceptors: [ + { + state: "failure" + matcher: { + errorType: "WidgetDoesNotExist" + } + } + { + state: "success" + matcher: { + errorType: "WidgetDoesNotExist" } } ] @@ -263,6 +325,11 @@ operation DeleteWidget { structure WidgetInput { stringProperty: String + stringArrayProperty: StringArray + booleanProperty: Boolean + booleanArrayProperty: BooleanArray + children: ChildArray + dataMap: DataMap } structure WidgetOutput { diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index f079511ce..bc047289a 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -3,118 +3,440 @@ require_relative '../../spec_helper' describe 'Client: Waiters' do + let(:input) { { string_property: 'input_string' } } let(:client) { Wait_Service::Client.new(stub_responses: true) } + let(:waiter) { Smithy::Client::Waiters::Waiter } + let(:my_error) { Wait_Service::Errors::MyError.new({}, message: 'my error message') } + let(:widget_does_not_exist_error) { + Wait_Service::Errors::WidgetDoesNotExist.new({}, message: 'widget does not exist message') + } + let(:unexpected_error) { Smithy::Client::Waiters::Errors::UnexpectedError } + let(:failure_state_error) { Smithy::Client::Waiters::Errors::FailureStateError } + let(:max_wait_time_exceeded_error) { Smithy::Client::Waiters::Errors::MaxWaitTimeExceededError } ['generated client gem'].each do |context| context context do include_context context, 'Wait_Service' - it 'generates waiters' do - input = { string_property: 'prop' } - output = { - string_property: 'string', - string_array_property: ['string'], - boolean_property: true, - boolean_array_property: [true], - children: [ - { - grandchildren: [ - { - string_property: 'string', - boolean_property: true, - } - ] - } - ], - dataMap: { key: 'key', value: 'value' }, - } - expect(client).to receive(:get_widget).and_return(output) - client.wait_until(:success_true_matcher, input, max_wait_time: 60) - end + describe 'code generated waiters' do + context 'success matcher' do + it 'waits successfully when set to true' do + output = {} + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:success_true_matcher, input, max_wait_time: 60) + }.to_not raise_error + end - it 'generates waiters again' do - input = { string_property: 'prop' } - expect(client).to receive(:get_widget).and_raise(Wait_Service::Errors::MyError.new({}, message: 'Error message')) - # client.wait_until(:success_true_matcher, input, max_wait_time: 60) + it 'waits successfully when set to false' do + expect(client).to receive(:get_widget).and_raise(StandardError) + expect { + client.wait_until(:success_false_matcher, input, max_wait_time: 60) + }.to_not raise_error + end - expect { - client.wait_until(:success_true_matcher, input, max_wait_time: 60) - }.to raise_error(Smithy::Client::Waiters::Errors::UnexpectedError) - end + it 'retries until successful' do + output = {} + 3.times do + expect(client).to receive(:get_widget).and_return(output) + expect_any_instance_of(waiter).to receive(:delay).and_call_original + end + expect(client).to receive(:get_widget).and_raise(StandardError) + expect { + client.wait_until(:success_false_matcher, input, max_wait_time: 60) + }.to_not raise_error + end - it 'generates waiters again again' do - input = { string_property: 'prop' } - expect(client).to receive(:get_widget).and_raise(Wait_Service::Errors::MyError.new({}, message: 'Error message')) - # client.wait_until(:success_true_matcher, input, max_wait_time: 60) + it 'fails when set to true and unexpected error is encountered' do + expect(client).to receive(:get_widget).and_raise(StandardError) + expect { + client.wait_until(:success_true_matcher, input, max_wait_time: 60) + }.to raise_error(unexpected_error) + end - expect { - client.wait_until(:success_false_matcher, input, max_wait_time: 60) - }.not_to raise_error - end + it 'fails when max wait time is exceeded' do + output = {} + 5.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:success_false_matcher, input, max_wait_time: 10) + }.to raise_error(max_wait_time_exceeded_error) + end + end - it 'generates waiters again again again' do - input = { string_property: 'prop' } - expect(client).to receive(:get_widget).and_raise(Wait_Service::Errors::MyError.new({}, message: 'Error message')) - # client.wait_until(:success_true_matcher, input, max_wait_time: 60) + context 'error type matcher' do + it 'waits successfully when error matches' do + expect(client).to receive(:get_widget).and_raise(my_error) + expect { + client.wait_until(:error_type_matcher, input, max_wait_time: 60) + }.to_not raise_error + end - expect { - client.wait_until(:error_type_matcher, input, max_wait_time: 60) - }.not_to raise_error - end + it 'retries until successful' do + output = {} + 3.times do + expect(client).to receive(:get_widget).and_return(output) + expect_any_instance_of(waiter).to receive(:delay).and_call_original + end + expect(client).to receive(:get_widget).and_raise(my_error) + expect { + client.wait_until(:error_type_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when error does not match' do + expect(client).to receive(:get_widget).and_raise(StandardError) + expect { + client.wait_until(:error_type_matcher, input, max_wait_time: 60) + }.to raise_error(unexpected_error) + end + + it 'fails when max wait time is exceeded' do + output = {} + 5.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:error_type_matcher, input, max_wait_time: 10) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'output matcher' do + context 'string equals comparator' do + it 'waits successfully' do + output = { string_property: 'expected string' } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'retries until successful' do + output_expected = { string_property: 'expected string' } + output_unexpected = { string_property: 'unexpected string' } + 3.times do + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect_any_instance_of(waiter).to receive(:delay).and_call_original + end + expect(client).to receive(:get_widget).and_return(output_expected) + expect { + client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + end + + context 'boolean equals comparator' do + it 'waits successfully' do + output = { boolean_property: false } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'retries until successful' do + output_expected = { boolean_property: false } + output_unexpected = { boolean_property: true } + 3.times do + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect_any_instance_of(waiter).to receive(:delay).and_call_original + end + expect(client).to receive(:get_widget).and_return(output_expected) + expect { + client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + end + + context 'all string equals comparator' do + it 'waits successfully' do + output = { + string_array_property: [ + 'expected string', + 'expected string', + 'expected string' + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'retries until successful' do + output_expected = { + string_array_property: [ + 'expected string', + 'expected string', + 'expected string' + ] + } + output_unexpected = { + string_array_property: [ + 'expected string', + 'unexpected string', + 'unexpected string' + ] + } + 3.times do + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect_any_instance_of(waiter).to receive(:delay).and_call_original + end + expect(client).to receive(:get_widget).and_return(output_expected) + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + end + + context 'any string equals comparator' do + it 'waits successfully' do + output = { + string_array_property: [ + 'some other string', + 'another string', + 'expected string', + 'yet another string' + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end - it 'generates waiters again again again again' do - input = { string_property: 'prop' } - expect(client).to receive(:delete_widget).twice.and_raise(Wait_Service::Errors::MyError.new({}, message: 'Error message')) - expect(client).to receive(:delete_widget).once.and_raise(Wait_Service::Errors::WidgetDoesNotExist.new({}, message: 'Widget does not exist')) - expect { - client.wait_until(:multiple_acceptors_matcher, input, max_wait_time: 60) - }.not_to raise_error + it 'retries until successful' do + output_expected = { + string_array_property: [ + 'some other string', + 'another string', + 'expected string', + 'yet another string' + ] + } + output_unexpected = { + string_array_property: [ + 'some other string', + 'another string', + 'unexpected string', + 'yet another string' + ] + } + 3.times do + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect_any_instance_of(waiter).to receive(:delay).and_call_original + end + expect(client).to receive(:get_widget).and_return(output_expected) + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + end + end + + context 'input output matcher' do + # it 'waits successfully for string equals comparator' do + # output = { string_property: 'input_string' } + # expect(client).to receive(:get_widget).and_return(output) + # expect { + # client.wait_until(:input_output_string_property_matcher, input, max_wait_time: 60) + # }.to_not raise_error + # end + + it 'waits successfully for boolean equals comparator' do + output = { string_property: 'input_string' } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:input_output_boolean_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + # it 'waits successfully for all string equals comparator' do + # input = :input + # input['string_array_property'] = [ + # 'expected string', + # 'expected string', + # 'expected string' + # ] + # output = { + # string_array_property: [ + # 'expected string', + # 'expected string', + # 'expected string' + # ] + # } + # expect(client).to receive(:get_widget).and_return(output) + # expect { + # client.wait_until(:input_output_string_array_all_property_matcher, input, max_wait_time: 60) + # }.to_not raise_error + # end + # + # it 'waits successfully for any string equals comparator' do + # input = :input + # input['string_array_property'] = [ + # 'expected string', + # ] + # output = { + # string_array_property: [ + # 'some other string', + # 'another string', + # 'expected string', + # 'yet another string' + # ] + # } + # expect(client).to receive(:get_widget).and_return(output) + # expect { + # client.wait_until(:input_output_string_array_any_property_matcher, input, max_wait_time: 60) + # }.to_not raise_error + # end + end + + it 'checks acceptors in order' do + expect(client).to receive(:delete_widget).and_raise(widget_does_not_exist_error) + expect { + client.wait_until(:acceptor_order_success_matcher, input, max_wait_time: 60) + }.to_not raise_error + + expect(client).to receive(:delete_widget).and_raise(widget_does_not_exist_error) + expect { + client.wait_until(:acceptor_order_failure_matcher, input, max_wait_time: 60) + }.to raise_error(failure_state_error) + end end - it 'matches output' do - input = { string_property: 'prop' } - output = { - string_property: 'payload property contents', - string_array_property: ['string'], - boolean_property: true, - boolean_array_property: [true], - children: [ - { - grandchildren: [ - { - string_property: 'string', - boolean_property: true, - } + describe 'runtime generated waiters' do + context 'success matcher' do + it 'waits successfully when set to true' do + output = {} + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until_custom(:success_true_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'waits successfully when set to false' do + expect(client).to receive(:get_widget).and_raise(StandardError) + expect { + client.wait_until_custom(:success_false_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + end + + + context 'error type matcher' do + it 'waits successfully when error matches' do + expect(client).to receive(:get_widget).and_raise(my_error) + expect { + client.wait_until_custom(:error_type_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + end + + context 'output matcher' do + it 'waits successfully for string equals comparator' do + output = { string_property: 'expected string' } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until_custom(:output_string_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'waits successfully for boolean equals comparator' do + output = { boolean_property: false } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until_custom(:output_boolean_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'waits successfully for all string equals comparator' do + output = { + string_array_property: [ + 'expected string', + 'expected string', + 'expected string' ] } - ], - dataMap: { key: 'key', value: 'value' }, - } - expect(client).to receive(:get_widget).and_return(output) - client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) - end + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until_custom(:output_string_array_all_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end - it 'matches inputoutput' do - input = { string_property: 'prop' } - output = { - string_property: 'prop', - string_array_property: ['string'], - boolean_property: true, - boolean_array_property: [true], - children: [ - { - grandchildren: [ - { - string_property: 'string', - boolean_property: true, - } + it 'waits successfully for any string equals comparator' do + output = { + string_array_property: [ + 'some other string', + 'another string', + 'expected string', + 'yet another string' ] } - ], - dataMap: { key: 'key', value: 'value' }, - } - expect(client).to receive(:get_widget).and_return(output) - client.wait_until(:input_output_property_matcher, input, max_wait_time: 60) + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until_custom(:output_string_array_any_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + end + + context 'input output matcher' do + # it 'waits successfully for string equals comparator' do + # output = { string_property: 'input_string' } + # expect(client).to receive(:get_widget).and_return(output) + # expect { + # client.wait_until_custom(:input_output_string_property_matcher, input, max_wait_time: 60) + # }.to_not raise_error + # end + + it 'waits successfully for boolean equals comparator' do + output = { string_property: 'input_string' } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until_custom(:input_output_boolean_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + # it 'waits successfully for all string equals comparator' do + # input = :input + # input['string_array_property'] = [ + # 'expected string', + # 'expected string', + # 'expected string' + # ] + # output = { + # string_array_property: [ + # 'expected string', + # 'expected string', + # 'expected string' + # ] + # } + # expect(client).to receive(:get_widget).and_return(output) + # expect { + # client.wait_until_custom(:input_output_string_array_all_property_matcher, input, max_wait_time: 60) + # }.to_not raise_error + # end + # + # it 'waits successfully for any string equals comparator' do + # input = :input + # input['string_array_property'] = [ + # 'expected string', + # ] + # output = { + # string_array_property: [ + # 'some other string', + # 'another string', + # 'expected string', + # 'yet another string' + # ] + # } + # expect(client).to receive(:get_widget).and_return(output) + # expect { + # client.wait_until_custom(:input_output_string_array_any_property_matcher, input, max_wait_time: 60) + # }.to_not raise_error + # end + end end end end diff --git a/smithy-build.json b/smithy-build.json index a1f229862..cbfbe5d22 100644 --- a/smithy-build.json +++ b/smithy-build.json @@ -1,10 +1,5 @@ { "version": "1.0", - "maven": { - "dependencies": [ - "software.amazon.smithy:smithy-waiters:1.56.0" - ] - }, "projections": { "weather": { "plugins": { From ff32042ba419e57d1db924fb0a43aa5b13292583 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 30 Apr 2025 15:04:24 -0700 Subject: [PATCH 14/48] Add more unit tests --- .../lib/smithy-client/waiters/poller.rb | 4 +- .../lib/smithy-client/waiters/waiter.rb | 12 +- .../lib/smithy/templates/client/client.erb | 4 +- .../spec/interfaces/client/waiters_spec.rb | 774 ++++++++++++++---- 4 files changed, 652 insertions(+), 142 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index 5bbcf26db..5c86a166c 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -96,14 +96,14 @@ def is_equal?(actual, expected, comparator) when 'booleanEquals' return actual.to_s == expected when 'allStringEquals' - return false if actual.empty? + return false if actual.nil? || actual.empty? actual.each do |value| return false if value != expected end return true when 'anyStringEquals' - return false if actual.empty? + return false if actual.nil? || actual.empty? actual.each do |value| return true if value == expected diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index 35672f831..09f9111b7 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -5,10 +5,21 @@ module Client module Waiters class Waiter def initialize(options = {}) + unless options[:max_wait_time].is_a?(Integer) + raise ArgumentError, 'Waiter must be initialized with `:max_wait_time`' + end + @max_wait_time = options[:max_wait_time] @remaining_time = @max_wait_time @min_delay = options[:min_delay] @max_delay = options[:max_delay] + if @max_delay < 1 + raise ArgumentError, '`:max_delay` must be greater than 0' + end + if @min_delay < 1 || @min_delay > @max_delay + raise ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`' + end + @poller = options[:poller] @client = options[:client] # custom waiter approach end @@ -49,7 +60,6 @@ def delay(attempts) delay = attempts > attempt_ceiling ? @max_delay : @min_delay * 2 ** (attempts - 1) delay = rand(@min_delay..delay) delay = @remaining_time if @remaining_time - delay <= @min_delay - puts "delay for #{delay} seconds" delay end end diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index 8b1e0e5a3..99151a3c0 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -71,7 +71,7 @@ module <%= module_name %> if waiter_class waiter_class.new(options.merge(client: self)) else - raise Errors::NoSuchWaiterError + raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new end end @@ -93,7 +93,7 @@ module <%= module_name %> end end end - nil + raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new end def waitable_trait(operation) diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index bc047289a..8fd4aab66 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -13,6 +13,7 @@ let(:unexpected_error) { Smithy::Client::Waiters::Errors::UnexpectedError } let(:failure_state_error) { Smithy::Client::Waiters::Errors::FailureStateError } let(:max_wait_time_exceeded_error) { Smithy::Client::Waiters::Errors::MaxWaitTimeExceededError } + let(:no_such_waiter_error) { Smithy::Client::Waiters::Errors::NoSuchWaiterError } ['generated client gem'].each do |context| context context do @@ -20,7 +21,7 @@ describe 'code generated waiters' do context 'success matcher' do - it 'waits successfully when set to true' do + it 'waits successfully when set to true and receives successful response' do output = {} expect(client).to receive(:get_widget).and_return(output) expect { @@ -28,18 +29,17 @@ }.to_not raise_error end - it 'waits successfully when set to false' do + it 'waits successfully when set to false and error is encountered' do expect(client).to receive(:get_widget).and_raise(StandardError) expect { client.wait_until(:success_false_matcher, input, max_wait_time: 60) }.to_not raise_error end - it 'retries until successful' do + it 'retries and succeeds when match' do output = {} - 3.times do + 2.times do expect(client).to receive(:get_widget).and_return(output) - expect_any_instance_of(waiter).to receive(:delay).and_call_original end expect(client).to receive(:get_widget).and_raise(StandardError) expect { @@ -60,7 +60,7 @@ allow(client).to receive(:get_widget).and_return(output) end expect { - client.wait_until(:success_false_matcher, input, max_wait_time: 10) + client.wait_until(:success_false_matcher, input, max_wait_time: 2) }.to raise_error(max_wait_time_exceeded_error) end end @@ -73,9 +73,9 @@ }.to_not raise_error end - it 'retries until successful' do + it 'retries and succeeds when match' do output = {} - 3.times do + 2.times do expect(client).to receive(:get_widget).and_return(output) expect_any_instance_of(waiter).to receive(:delay).and_call_original end @@ -98,14 +98,14 @@ allow(client).to receive(:get_widget).and_return(output) end expect { - client.wait_until(:error_type_matcher, input, max_wait_time: 10) + client.wait_until(:error_type_matcher, input, max_wait_time: 2) }.to raise_error(max_wait_time_exceeded_error) end end context 'output matcher' do context 'string equals comparator' do - it 'waits successfully' do + it 'waits successfully when output matches' do output = { string_property: 'expected string' } expect(client).to receive(:get_widget).and_return(output) expect { @@ -113,10 +113,10 @@ }.to_not raise_error end - it 'retries until successful' do + it 'retries and succeeds when match' do output_expected = { string_property: 'expected string' } output_unexpected = { string_property: 'unexpected string' } - 3.times do + 2.times do expect(client).to receive(:get_widget).and_return(output_unexpected) expect_any_instance_of(waiter).to receive(:delay).and_call_original end @@ -125,6 +125,26 @@ client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) }.to_not raise_error end + + it 'fails when output property does not match' do + output_unexpected = { string_property: 'unexpected string' } + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is null' do + output_unexpected = {} + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end end context 'boolean equals comparator' do @@ -136,10 +156,10 @@ }.to_not raise_error end - it 'retries until successful' do + it 'retries and succeeds when match' do output_expected = { boolean_property: false } output_unexpected = { boolean_property: true } - 3.times do + 2.times do expect(client).to receive(:get_widget).and_return(output_unexpected) expect_any_instance_of(waiter).to receive(:delay).and_call_original end @@ -148,6 +168,26 @@ client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) }.to_not raise_error end + + it 'fails when output property does not match' do + output_unexpected = { boolean_property: true } + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is null' do + output_unexpected = {} + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end end context 'all string equals comparator' do @@ -165,7 +205,7 @@ }.to_not raise_error end - it 'retries until successful' do + it 'retries and succeeds when match' do output_expected = { string_array_property: [ 'expected string', @@ -180,7 +220,7 @@ 'unexpected string' ] } - 3.times do + 2.times do expect(client).to receive(:get_widget).and_return(output_unexpected) expect_any_instance_of(waiter).to receive(:delay).and_call_original end @@ -189,6 +229,42 @@ client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) }.to_not raise_error end + + it 'fails when output property does not match' do + output_unexpected = { + string_array_property: [ + 'expected string', + 'unexpected string', + 'unexpected string' + ] + } + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is empty' do + output_unexpected = { string_array_property: [] } + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is null' do + output_unexpected = {} + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end end context 'any string equals comparator' do @@ -207,7 +283,7 @@ }.to_not raise_error end - it 'retries until successful' do + it 'retries and succeeds when match' do output_expected = { string_array_property: [ 'some other string', @@ -224,7 +300,7 @@ 'yet another string' ] } - 3.times do + 2.times do expect(client).to receive(:get_widget).and_return(output_unexpected) expect_any_instance_of(waiter).to receive(:delay).and_call_original end @@ -233,6 +309,458 @@ client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) }.to_not raise_error end + + it 'fails when output property does not match' do + output_unexpected = { + string_array_property: [ + 'some other string', + 'another string', + 'unexpected string', + 'yet another string' + ] + } + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is empty' do + output_unexpected = { string_array_property: [] } + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is null' do + output_unexpected = {} + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'flatten' do + it 'succeeds when match' do + output = { + children: [ + { + grandchildren: [ + { + name: 'expected name', + number: 1 + } + ] + }, + { + grandchildren: [ + { + name: 'unexpected name', + number: 1 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:flatten_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when no match' do + output = { + children: [ + { + grandchildren: [ + { + name: 'unexpected name', + number: 1 + } + ] + } + ] + } + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:flatten_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'flatten length' do + it 'succeeds when match' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 4 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 5 + }, + { + name: 'name', + number: 6 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:flatten_length_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when no match' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + } + ] + } + ] + } + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:flatten_length_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'flatten filter' do + it 'succeeds when match' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 4 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 5 + }, + { + name: 'name', + number: 6 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:flatten_filter_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when no match' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 4 + }, + { + name: 'name', + number: 5 + }, + { + name: 'name', + number: 6 + } + ] + } + ] + } + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:flatten_filter_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'length flatten filter' do + it 'succeeds when match' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 5 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 6 + }, + { + name: 'name', + number: 7 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when no match' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 3 + }, + { + name: 'name', + number: 4 + }, + { + name: 'name', + number: 5 + } + ] + } + ] + } + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'projection' do + it 'succeeds when match' do + output = { + data_map: { + 'key1' => 'abc', + 'key2' => 'abc', + 'key3' => 'abc', + } + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:projection_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when no match' do + output = { + data_map: { + 'key1' => 'abc', + 'key2' => 'def', + 'key3' => 'ghi', + } + } + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:projection_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'contains field' do + it 'succeeds when match' do + output = { + string_property: 'match', + data_map: { + 'key1' => 'not a match', + 'key2' => 'match', + 'key3' => 'not a match', + } + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:contains_field_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when no match' do + output = { + string_property: 'match', + data_map: { + 'key1' => 'not a match', + 'key2' => 'not a match', + 'key3' => 'not a match', + } + } + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:contains_field_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'and inequality' do + it 'succeeds when match' do + output = { + string_array_property: [ + 'some string', + 'another string' + ], + data_map: { + 'key1' => 'one', + 'key2' => 'two', + 'key3' => 'three', + } + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:and_inequality_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when no match' do + output = { + string_array_property: [ + 'some string', + 'another string', + 'yet another string' + ], + data_map: { + 'key1' => 'one', + 'key2' => 'two', + 'key3' => 'three', + } + } + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:and_inequality_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end end end @@ -304,138 +832,110 @@ client.wait_until(:acceptor_order_failure_matcher, input, max_wait_time: 60) }.to raise_error(failure_state_error) end - end - describe 'runtime generated waiters' do - context 'success matcher' do - it 'waits successfully when set to true' do - output = {} - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until_custom(:success_true_matcher, input, max_wait_time: 60) - }.to_not raise_error + it 'allows configuration of min and max delay' do + options = { + max_wait_time: 5, + min_delay: 3, + max_delay: 4 + } + output = {} + 2.times do + allow(client).to receive(:get_widget).and_return(output) end - - it 'waits successfully when set to false' do - expect(client).to receive(:get_widget).and_raise(StandardError) - expect { - client.wait_until_custom(:success_false_matcher, input, max_wait_time: 60) - }.to_not raise_error + expect_any_instance_of(waiter).to receive(:delay).and_wrap_original do |m, *args| + delay = m.call(*args) + expect(delay).to equal(5) + delay end + expect { + client.wait_until(:success_false_matcher, input, options) + }.to raise_error(max_wait_time_exceeded_error) end - - context 'error type matcher' do - it 'waits successfully when error matches' do - expect(client).to receive(:get_widget).and_raise(my_error) - expect { - client.wait_until_custom(:error_type_matcher, input, max_wait_time: 60) - }.to_not raise_error - end + it 'does not allow custom waiters' do + custom_waiter = { + 'CustomWaiterMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'success' => true + } + } + ] + } + } + client.config.service.operations[:delete_widget].traits['smithy.waiters#waitable'].merge!(custom_waiter) + expect { + client.wait_until(:custom_waiter_matcher, input, max_wait_time: 60) + }.to raise_error(no_such_waiter_error) end - context 'output matcher' do - it 'waits successfully for string equals comparator' do - output = { string_property: 'expected string' } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until_custom(:output_string_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'waits successfully for boolean equals comparator' do - output = { boolean_property: false } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until_custom(:output_boolean_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end + it 'raises and error for nonexistent waiters' do + expect { + client.wait_until(:nonexistent_waiter, input, max_wait_time: 60) + }.to raise_error(no_such_waiter_error) + end - it 'waits successfully for all string equals comparator' do - output = { - string_array_property: [ - 'expected string', - 'expected string', - 'expected string' - ] - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until_custom(:output_string_array_all_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end + it 'raises an error when max_wait_time is not provided' do + expect { + client.wait_until(:success_true_matcher, input) + }.to raise_error(ArgumentError, 'Waiter must be initialized with `:max_wait_time`') + end - it 'waits successfully for any string equals comparator' do - output = { - string_array_property: [ - 'some other string', - 'another string', - 'expected string', - 'yet another string' - ] - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until_custom(:output_string_array_any_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end + it 'raises an error when max_delay is less than 1' do + options = { + max_wait_time: 5, + max_delay: 0 + } + expect { + client.wait_until(:success_true_matcher, input, options) + }.to raise_error(ArgumentError, '`:max_delay` must be greater than 0') end - context 'input output matcher' do - # it 'waits successfully for string equals comparator' do - # output = { string_property: 'input_string' } - # expect(client).to receive(:get_widget).and_return(output) - # expect { - # client.wait_until_custom(:input_output_string_property_matcher, input, max_wait_time: 60) - # }.to_not raise_error - # end + it 'raises an error when min_delay is less than 1' do + options = { + max_wait_time: 5, + min_delay: 0 + } + expect { + client.wait_until(:success_true_matcher, input, options) + }.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') + end - it 'waits successfully for boolean equals comparator' do - output = { string_property: 'input_string' } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until_custom(:input_output_boolean_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end + it 'raises an error when max_delay is less than min_delay' do + options = { + max_wait_time: 5, + min_delay: 4, + max_delay: 2 + } + expect { + client.wait_until(:success_true_matcher, input, options) + }.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') + end + end - # it 'waits successfully for all string equals comparator' do - # input = :input - # input['string_array_property'] = [ - # 'expected string', - # 'expected string', - # 'expected string' - # ] - # output = { - # string_array_property: [ - # 'expected string', - # 'expected string', - # 'expected string' - # ] - # } - # expect(client).to receive(:get_widget).and_return(output) - # expect { - # client.wait_until_custom(:input_output_string_array_all_property_matcher, input, max_wait_time: 60) - # }.to_not raise_error - # end - # - # it 'waits successfully for any string equals comparator' do - # input = :input - # input['string_array_property'] = [ - # 'expected string', - # ] - # output = { - # string_array_property: [ - # 'some other string', - # 'another string', - # 'expected string', - # 'yet another string' - # ] - # } - # expect(client).to receive(:get_widget).and_return(output) - # expect { - # client.wait_until_custom(:input_output_string_array_any_property_matcher, input, max_wait_time: 60) - # }.to_not raise_error - # end + describe 'runtime generated waiters' do + it 'allows custom waiters' do + custom_waiter = { + 'CustomWaiterMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'success' => true + } + } + ] + } + } + client.config.service.operations[:delete_widget].traits['smithy.waiters#waitable'].merge!(custom_waiter) + output = {} + expect(client).to receive(:delete_widget).and_return(output) + expect { + client.wait_until_custom(:custom_waiter_matcher, input, max_wait_time: 60) + }.to_not raise_error end end end From 0c8cf8b2240db0820ae0f7092e2b24158e303de8 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 1 May 2025 09:56:24 -0700 Subject: [PATCH 15/48] Update test names --- .../spec/interfaces/client/waiters_spec.rb | 92 +++++++++---------- 1 file changed, 41 insertions(+), 51 deletions(-) diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index 8fd4aab66..2824e759a 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -15,13 +15,13 @@ let(:max_wait_time_exceeded_error) { Smithy::Client::Waiters::Errors::MaxWaitTimeExceededError } let(:no_such_waiter_error) { Smithy::Client::Waiters::Errors::NoSuchWaiterError } - ['generated client gem'].each do |context| + ['generated client gem', 'generated client from source code'].each do |context| context context do include_context context, 'Wait_Service' describe 'code generated waiters' do context 'success matcher' do - it 'waits successfully when set to true and receives successful response' do + it 'succeeds when success is set to true and successful response is received' do output = {} expect(client).to receive(:get_widget).and_return(output) expect { @@ -29,14 +29,14 @@ }.to_not raise_error end - it 'waits successfully when set to false and error is encountered' do + it 'succeeds when success is set to false and error is received' do expect(client).to receive(:get_widget).and_raise(StandardError) expect { client.wait_until(:success_false_matcher, input, max_wait_time: 60) }.to_not raise_error end - it 'retries and succeeds when match' do + it 'retries and succeeds when matched' do output = {} 2.times do expect(client).to receive(:get_widget).and_return(output) @@ -47,33 +47,23 @@ }.to_not raise_error end - it 'fails when set to true and unexpected error is encountered' do + it 'fails when success is set to true and unexpected error is received' do expect(client).to receive(:get_widget).and_raise(StandardError) expect { client.wait_until(:success_true_matcher, input, max_wait_time: 60) }.to raise_error(unexpected_error) end - - it 'fails when max wait time is exceeded' do - output = {} - 5.times do - allow(client).to receive(:get_widget).and_return(output) - end - expect { - client.wait_until(:success_false_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end end context 'error type matcher' do - it 'waits successfully when error matches' do + it 'succeeds when error matches' do expect(client).to receive(:get_widget).and_raise(my_error) expect { client.wait_until(:error_type_matcher, input, max_wait_time: 60) }.to_not raise_error end - it 'retries and succeeds when match' do + it 'retries and succeeds when matched' do output = {} 2.times do expect(client).to receive(:get_widget).and_return(output) @@ -91,21 +81,11 @@ client.wait_until(:error_type_matcher, input, max_wait_time: 60) }.to raise_error(unexpected_error) end - - it 'fails when max wait time is exceeded' do - output = {} - 5.times do - allow(client).to receive(:get_widget).and_return(output) - end - expect { - client.wait_until(:error_type_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end end context 'output matcher' do context 'string equals comparator' do - it 'waits successfully when output matches' do + it 'succeeds when output matches' do output = { string_property: 'expected string' } expect(client).to receive(:get_widget).and_return(output) expect { @@ -113,7 +93,7 @@ }.to_not raise_error end - it 'retries and succeeds when match' do + it 'retries and succeeds when matched' do output_expected = { string_property: 'expected string' } output_unexpected = { string_property: 'unexpected string' } 2.times do @@ -148,7 +128,7 @@ end context 'boolean equals comparator' do - it 'waits successfully' do + it 'succeeds when output matches' do output = { boolean_property: false } expect(client).to receive(:get_widget).and_return(output) expect { @@ -156,7 +136,7 @@ }.to_not raise_error end - it 'retries and succeeds when match' do + it 'retries and succeeds when matched' do output_expected = { boolean_property: false } output_unexpected = { boolean_property: true } 2.times do @@ -191,7 +171,7 @@ end context 'all string equals comparator' do - it 'waits successfully' do + it 'succeeds when output matches' do output = { string_array_property: [ 'expected string', @@ -205,7 +185,7 @@ }.to_not raise_error end - it 'retries and succeeds when match' do + it 'retries and succeeds when matched' do output_expected = { string_array_property: [ 'expected string', @@ -268,7 +248,7 @@ end context 'any string equals comparator' do - it 'waits successfully' do + it 'succeeds when output matches' do output = { string_array_property: [ 'some other string', @@ -283,7 +263,7 @@ }.to_not raise_error end - it 'retries and succeeds when match' do + it 'retries and succeeds when matched' do output_expected = { string_array_property: [ 'some other string', @@ -349,7 +329,7 @@ end context 'flatten' do - it 'succeeds when match' do + it 'succeeds when matched' do output = { children: [ { @@ -376,7 +356,7 @@ }.to_not raise_error end - it 'fails when no match' do + it 'fails when not matched' do output = { children: [ { @@ -399,7 +379,7 @@ end context 'flatten length' do - it 'succeeds when match' do + it 'succeeds when matched' do output = { children: [ { @@ -446,7 +426,7 @@ }.to_not raise_error end - it 'fails when no match' do + it 'fails when not matched' do output = { children: [ { @@ -469,7 +449,7 @@ end context 'flatten filter' do - it 'succeeds when match' do + it 'succeeds when matched' do output = { children: [ { @@ -516,7 +496,7 @@ }.to_not raise_error end - it 'fails when no match' do + it 'fails when not matched' do output = { children: [ { @@ -563,7 +543,7 @@ end context 'length flatten filter' do - it 'succeeds when match' do + it 'succeeds when matched' do output = { children: [ { @@ -610,7 +590,7 @@ }.to_not raise_error end - it 'fails when no match' do + it 'fails when not matched' do output = { children: [ { @@ -657,7 +637,7 @@ end context 'projection' do - it 'succeeds when match' do + it 'succeeds when matched' do output = { data_map: { 'key1' => 'abc', @@ -671,7 +651,7 @@ }.to_not raise_error end - it 'fails when no match' do + it 'fails when not matched' do output = { data_map: { 'key1' => 'abc', @@ -689,7 +669,7 @@ end context 'contains field' do - it 'succeeds when match' do + it 'succeeds when matched' do output = { string_property: 'match', data_map: { @@ -704,7 +684,7 @@ }.to_not raise_error end - it 'fails when no match' do + it 'fails when not matched' do output = { string_property: 'match', data_map: { @@ -723,7 +703,7 @@ end context 'and inequality' do - it 'succeeds when match' do + it 'succeeds when matched' do output = { string_array_property: [ 'some string', @@ -741,7 +721,7 @@ }.to_not raise_error end - it 'fails when no match' do + it 'fails when not matched' do output = { string_array_property: [ 'some string', @@ -773,7 +753,7 @@ # }.to_not raise_error # end - it 'waits successfully for boolean equals comparator' do + it 'succeeds for boolean equals comparator' do output = { string_property: 'input_string' } expect(client).to receive(:get_widget).and_return(output) expect { @@ -872,7 +852,17 @@ }.to raise_error(no_such_waiter_error) end - it 'raises and error for nonexistent waiters' do + it 'raises an error when max wait time is exceeded' do + output = {} + 5.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:success_false_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'raises an error for nonexistent waiters' do expect { client.wait_until(:nonexistent_waiter, input, max_wait_time: 60) }.to raise_error(no_such_waiter_error) From 63c6e6f5f297cc0d6f78ef64ec7f808520668f26 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 1 May 2025 11:20:46 -0700 Subject: [PATCH 16/48] Add underscore methods --- .../lib/smithy-client/waiters/poller.rb | 20 +++++++++++++++++-- .../lib/smithy/templates/client/client.erb | 10 +++++++++- gems/smithy/lib/smithy/util/underscore.rb | 8 -------- projections/shapes/lib/shapes/client.rb | 12 +++++++++-- projections/weather/lib/weather/client.rb | 14 ++++++++++--- 5 files changed, 48 insertions(+), 16 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index 5c86a166c..655f6d957 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -22,6 +22,8 @@ def call(client, params) [resp_or_error, status] end + private + def evaluate_acceptors(resp, error) @acceptors.each do |acceptor| return acceptor['state'] if acceptor_matches?(acceptor['matcher'], resp, error) @@ -47,7 +49,7 @@ def matches_output?(path_matcher, resp, error) # puts "Path matcher is #{path_matcher}" # puts "Resp is #{resp}" - actual = JMESPath.search(Smithy::Util::Underscore.underscore_jmespath(path_matcher['path']), resp) + actual = JMESPath.search(underscore_jmespath(path_matcher['path']), resp) equal = is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) # puts "Actual #{actual} and Expected #{path_matcher['expected']} Equal? #{equal}" equal @@ -67,7 +69,7 @@ def matches_inputOutput?(path_matcher, resp, error) # puts "data is #{data}" # puts "path_matcher is #{path_matcher}" - actual = JMESPath.search(Smithy::Util::Underscore.underscore_jmespath(path_matcher['path']), data) + actual = JMESPath.search(underscore_jmespath(path_matcher['path']), data) equal = is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) # puts "Actual #{actual} and Expected #{path_matcher['expected']} Equal? #{equal}" @@ -111,6 +113,20 @@ def is_equal?(actual, expected, comparator) return false end end + + def underscore(string) + string.gsub(/::/, '/') + .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') + .gsub(/([a-z\d])([A-Z])/,'\1_\2') + .tr("-", "_") + .downcase + end + + def underscore_jmespath(expression) + expression + .gsub(' or ', '||') + .gsub(/(? operations.each do |operation_name, operation| if (trait = waitable_trait(operation)) trait.each do |name, waiter| - if Smithy::Util::Underscore.underscore(name) == waiter_name.to_s + if underscore(name) == waiter_name.to_s return [operation_name, waiter] end end @@ -102,6 +102,14 @@ module <%= module_name %> end end + def underscore(string) + string.gsub(/::/, '/') + .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') + .gsub(/([a-z\d])([A-Z])/,'\1_\2') + .tr("-", "_") + .downcase + end + def poller_custom(operation_name, acceptors) Smithy::Client::Waiters::Poller.new( operation_name: operation_name.to_sym, diff --git a/gems/smithy/lib/smithy/util/underscore.rb b/gems/smithy/lib/smithy/util/underscore.rb index c14fe2804..8e735c679 100644 --- a/gems/smithy/lib/smithy/util/underscore.rb +++ b/gems/smithy/lib/smithy/util/underscore.rb @@ -12,14 +12,6 @@ def underscore_jmespath(expression) .gsub(' or ', '||') .gsub(/(? Date: Thu, 1 May 2025 12:37:12 -0700 Subject: [PATCH 17/48] Cleanup --- .../lib/smithy-client/waiters/poller.rb | 20 ++----------------- .../lib/smithy-client/waiters/waiter.rb | 3 ++- .../lib/smithy/templates/client/client.erb | 6 ++++++ projections/shapes/lib/shapes/client.rb | 6 ++++++ projections/weather/lib/weather/client.rb | 6 ++++++ 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index 655f6d957..a4bd117d0 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -18,7 +18,6 @@ def call(client, params) end resp_or_error = resp || error status = evaluate_acceptors(resp, error) - # puts "status is #{status}" [resp_or_error, status] end @@ -46,34 +45,19 @@ def acceptor_matches?(matcher, resp, error) def matches_output?(path_matcher, resp, error) return false unless error.nil? - # puts "Path matcher is #{path_matcher}" - # puts "Resp is #{resp}" - actual = JMESPath.search(underscore_jmespath(path_matcher['path']), resp) - equal = is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) - # puts "Actual #{actual} and Expected #{path_matcher['expected']} Equal? #{equal}" - equal + is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) end def matches_inputOutput?(path_matcher, resp, error) - # puts "Matches input output?" return false unless error.nil? && @input data = { input: @input, ### Where do we get this? output: resp } - - # puts "resp is #{resp}" - # puts "error is #{error}" - # puts "data is #{data}" - # puts "path_matcher is #{path_matcher}" - actual = JMESPath.search(underscore_jmespath(path_matcher['path']), data) - - equal = is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) - # puts "Actual #{actual} and Expected #{path_matcher['expected']} Equal? #{equal}" - equal + is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) end def matches_success?(path_matcher, resp, error) diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index 09f9111b7..4cc601196 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -21,13 +21,14 @@ def initialize(options = {}) end @poller = options[:poller] - @client = options[:client] # custom waiter approach + @client = options[:client] # runtime approach end def wait(client, params) poll(client, params) end + # Used for runtime approach def wait_custom(params) poll(@client, params) end diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index 2e509da78..ce3c38f71 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -43,6 +43,7 @@ module <%= module_name %> end <% end -%> + # runtime approach def wait_until_custom(waiter_name, params = {}, options = {}) operation_name, waiter_config = find_waiter(waiter_name) poller = poller_custom(operation_name, waiter_config["acceptors"]) @@ -82,6 +83,7 @@ module <%= module_name %> end <% end -%> + # runtime approach def find_waiter(waiter_name) operations = config.service.operations operations.each do |operation_name, operation| @@ -96,12 +98,14 @@ module <%= module_name %> raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new end + # runtime approach def waitable_trait(operation) if operation.traits && !operation.traits['smithy.waiters#waitable'].nil? operation.traits['smithy.waiters#waitable'] end end + # runtime approach def underscore(string) string.gsub(/::/, '/') .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') @@ -110,6 +114,7 @@ module <%= module_name %> .downcase end + # runtime approach def poller_custom(operation_name, acceptors) Smithy::Client::Waiters::Poller.new( operation_name: operation_name.to_sym, @@ -117,6 +122,7 @@ module <%= module_name %> ) end + # runtime approach def waiter_custom(waiter_config, options, poller) Smithy::Client::Waiters::Waiter.new( max_wait_time: options[:max_wait_time], diff --git a/projections/shapes/lib/shapes/client.rb b/projections/shapes/lib/shapes/client.rb index 35854afac..66d905582 100644 --- a/projections/shapes/lib/shapes/client.rb +++ b/projections/shapes/lib/shapes/client.rb @@ -229,6 +229,7 @@ def operation(params = {}, options = {}) input.send_request(options) end + # runtime approach def wait_until_custom(waiter_name, params = {}, options = {}) operation_name, waiter_config = find_waiter(waiter_name) poller = poller_custom(operation_name, waiter_config["acceptors"]) @@ -252,6 +253,7 @@ def build_input(operation_name, params) Smithy::Client::Input.new(handlers: handlers, context: context) end + # runtime approach def find_waiter(waiter_name) operations = config.service.operations operations.each do |operation_name, operation| @@ -266,12 +268,14 @@ def find_waiter(waiter_name) raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new end + # runtime approach def waitable_trait(operation) if operation.traits && !operation.traits['smithy.waiters#waitable'].nil? operation.traits['smithy.waiters#waitable'] end end + # runtime approach def underscore(string) string.gsub(/::/, '/') .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') @@ -280,6 +284,7 @@ def underscore(string) .downcase end + # runtime approach def poller_custom(operation_name, acceptors) Smithy::Client::Waiters::Poller.new( operation_name: operation_name.to_sym, @@ -287,6 +292,7 @@ def poller_custom(operation_name, acceptors) ) end + # runtime approach def waiter_custom(waiter_config, options, poller) Smithy::Client::Waiters::Waiter.new( max_wait_time: options[:max_wait_time], diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index b694ff2a3..a533d9656 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -232,6 +232,7 @@ def wait_until(waiter_name, params = {}, options = {}) w.wait(params) end + # runtime approach def wait_until_custom(waiter_name, params = {}, options = {}) operation_name, waiter_config = find_waiter(waiter_name) poller = poller_custom(operation_name, waiter_config["acceptors"]) @@ -272,6 +273,7 @@ def waiters } end + # runtime approach def find_waiter(waiter_name) operations = config.service.operations operations.each do |operation_name, operation| @@ -286,12 +288,14 @@ def find_waiter(waiter_name) raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new end + # runtime approach def waitable_trait(operation) if operation.traits && !operation.traits['smithy.waiters#waitable'].nil? operation.traits['smithy.waiters#waitable'] end end + # runtime approach def underscore(string) string.gsub(/::/, '/') .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') @@ -300,6 +304,7 @@ def underscore(string) .downcase end + # runtime approach def poller_custom(operation_name, acceptors) Smithy::Client::Waiters::Poller.new( operation_name: operation_name.to_sym, @@ -307,6 +312,7 @@ def poller_custom(operation_name, acceptors) ) end + # runtime approach def waiter_custom(waiter_config, options, poller) Smithy::Client::Waiters::Waiter.new( max_wait_time: options[:max_wait_time], From f28e3171cc3ce04a5d0207a11162d02d9cd4bcd5 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 2 May 2025 11:14:18 -0700 Subject: [PATCH 18/48] Remove runtime trait waiters --- .../lib/smithy-client/waiters/waiter.rb | 6 -- .../lib/smithy/templates/client/client.erb | 58 ------------------- .../spec/interfaces/client/waiters_spec.rb | 23 -------- projections/shapes/lib/shapes/client.rb | 58 ------------------- projections/weather/lib/weather/client.rb | 58 ------------------- 5 files changed, 203 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index 4cc601196..8bbf2bf33 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -21,18 +21,12 @@ def initialize(options = {}) end @poller = options[:poller] - @client = options[:client] # runtime approach end def wait(client, params) poll(client, params) end - # Used for runtime approach - def wait_custom(params) - poll(@client, params) - end - private def poll(client, params) diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index ce3c38f71..7eaadf93a 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -43,14 +43,6 @@ module <%= module_name %> end <% end -%> - # runtime approach - def wait_until_custom(waiter_name, params = {}, options = {}) - operation_name, waiter_config = find_waiter(waiter_name) - poller = poller_custom(operation_name, waiter_config["acceptors"]) - waiter = waiter_custom(waiter_config, options, poller) - waiter.wait_custom(params) - end - private def build_input(operation_name, params) @@ -83,56 +75,6 @@ module <%= module_name %> end <% end -%> - # runtime approach - def find_waiter(waiter_name) - operations = config.service.operations - operations.each do |operation_name, operation| - if (trait = waitable_trait(operation)) - trait.each do |name, waiter| - if underscore(name) == waiter_name.to_s - return [operation_name, waiter] - end - end - end - end - raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new - end - - # runtime approach - def waitable_trait(operation) - if operation.traits && !operation.traits['smithy.waiters#waitable'].nil? - operation.traits['smithy.waiters#waitable'] - end - end - - # runtime approach - def underscore(string) - string.gsub(/::/, '/') - .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') - .gsub(/([a-z\d])([A-Z])/,'\1_\2') - .tr("-", "_") - .downcase - end - - # runtime approach - def poller_custom(operation_name, acceptors) - Smithy::Client::Waiters::Poller.new( - operation_name: operation_name.to_sym, - acceptors: acceptors - ) - end - - # runtime approach - def waiter_custom(waiter_config, options, poller) - Smithy::Client::Waiters::Waiter.new( - max_wait_time: options[:max_wait_time], - min_delay: options[:min_delay] || waiter_config[:min_delay] || 2, - max_delay: options[:max_delay] || waiter_config[:max_delay] || 120, - poller: poller, - client: self - ) - end - class << self # @api private attr_reader :identifier diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index 2824e759a..fcff20bc9 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -905,29 +905,6 @@ }.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') end end - - describe 'runtime generated waiters' do - it 'allows custom waiters' do - custom_waiter = { - 'CustomWaiterMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'success' => true - } - } - ] - } - } - client.config.service.operations[:delete_widget].traits['smithy.waiters#waitable'].merge!(custom_waiter) - output = {} - expect(client).to receive(:delete_widget).and_return(output) - expect { - client.wait_until_custom(:custom_waiter_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - end end end end \ No newline at end of file diff --git a/projections/shapes/lib/shapes/client.rb b/projections/shapes/lib/shapes/client.rb index 66d905582..a52335dc6 100644 --- a/projections/shapes/lib/shapes/client.rb +++ b/projections/shapes/lib/shapes/client.rb @@ -229,14 +229,6 @@ def operation(params = {}, options = {}) input.send_request(options) end - # runtime approach - def wait_until_custom(waiter_name, params = {}, options = {}) - operation_name, waiter_config = find_waiter(waiter_name) - poller = poller_custom(operation_name, waiter_config["acceptors"]) - waiter = waiter_custom(waiter_config, options, poller) - waiter.wait_custom(params) - end - private def build_input(operation_name, params) @@ -253,56 +245,6 @@ def build_input(operation_name, params) Smithy::Client::Input.new(handlers: handlers, context: context) end - # runtime approach - def find_waiter(waiter_name) - operations = config.service.operations - operations.each do |operation_name, operation| - if (trait = waitable_trait(operation)) - trait.each do |name, waiter| - if underscore(name) == waiter_name.to_s - return [operation_name, waiter] - end - end - end - end - raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new - end - - # runtime approach - def waitable_trait(operation) - if operation.traits && !operation.traits['smithy.waiters#waitable'].nil? - operation.traits['smithy.waiters#waitable'] - end - end - - # runtime approach - def underscore(string) - string.gsub(/::/, '/') - .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') - .gsub(/([a-z\d])([A-Z])/,'\1_\2') - .tr("-", "_") - .downcase - end - - # runtime approach - def poller_custom(operation_name, acceptors) - Smithy::Client::Waiters::Poller.new( - operation_name: operation_name.to_sym, - acceptors: acceptors - ) - end - - # runtime approach - def waiter_custom(waiter_config, options, poller) - Smithy::Client::Waiters::Waiter.new( - max_wait_time: options[:max_wait_time], - min_delay: options[:min_delay] || waiter_config[:min_delay] || 2, - max_delay: options[:max_delay] || waiter_config[:max_delay] || 120, - poller: poller, - client: self - ) - end - class << self # @api private attr_reader :identifier diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index a533d9656..21859a5ae 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -232,14 +232,6 @@ def wait_until(waiter_name, params = {}, options = {}) w.wait(params) end - # runtime approach - def wait_until_custom(waiter_name, params = {}, options = {}) - operation_name, waiter_config = find_waiter(waiter_name) - poller = poller_custom(operation_name, waiter_config["acceptors"]) - waiter = waiter_custom(waiter_config, options, poller) - waiter.wait_custom(params) - end - private def build_input(operation_name, params) @@ -273,56 +265,6 @@ def waiters } end - # runtime approach - def find_waiter(waiter_name) - operations = config.service.operations - operations.each do |operation_name, operation| - if (trait = waitable_trait(operation)) - trait.each do |name, waiter| - if underscore(name) == waiter_name.to_s - return [operation_name, waiter] - end - end - end - end - raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new - end - - # runtime approach - def waitable_trait(operation) - if operation.traits && !operation.traits['smithy.waiters#waitable'].nil? - operation.traits['smithy.waiters#waitable'] - end - end - - # runtime approach - def underscore(string) - string.gsub(/::/, '/') - .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') - .gsub(/([a-z\d])([A-Z])/,'\1_\2') - .tr("-", "_") - .downcase - end - - # runtime approach - def poller_custom(operation_name, acceptors) - Smithy::Client::Waiters::Poller.new( - operation_name: operation_name.to_sym, - acceptors: acceptors - ) - end - - # runtime approach - def waiter_custom(waiter_config, options, poller) - Smithy::Client::Waiters::Waiter.new( - max_wait_time: options[:max_wait_time], - min_delay: options[:min_delay] || waiter_config[:min_delay] || 2, - max_delay: options[:max_delay] || waiter_config[:max_delay] || 120, - poller: poller, - client: self - ) - end - class << self # @api private attr_reader :identifier From 01aca71fba713d17c8d794719dd05ad1b9be0a63 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 2 May 2025 13:08:16 -0700 Subject: [PATCH 19/48] Add changes from review comments --- .../lib/smithy-client/waiters/errors.rb | 20 ++++++-------- .../lib/smithy-client/waiters/poller.rb | 16 ++++------- .../lib/smithy-client/waiters/waiter.rb | 27 ++++++++++++------- gems/smithy/lib/smithy/generators/client.rb | 2 +- .../lib/smithy/templates/client/client.erb | 11 ++++---- gems/smithy/lib/smithy/views/client/client.rb | 10 +++---- gems/smithy/lib/smithy/views/client/module.rb | 4 +-- .../smithy/lib/smithy/views/client/waiters.rb | 23 +++++++--------- .../spec/interfaces/client/waiters_spec.rb | 2 +- projections/shapes/lib/shapes.rb | 2 +- projections/shapes/lib/shapes/client.rb | 18 +++++++++++++ projections/weather/lib/weather.rb | 2 +- 12 files changed, 74 insertions(+), 63 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/errors.rb b/gems/smithy-client/lib/smithy-client/waiters/errors.rb index 281cc3677..c1172c95c 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/errors.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/errors.rb @@ -10,30 +10,27 @@ module Errors class WaiterFailed < StandardError; end class FailureStateError < WaiterFailed - MSG = "stopped waiting, encountered a failure state" - def initialize(response) + msg = "stopped waiting, encountered a failure state" @response = response - super(MSG) + super(msg) end attr_reader :response end class MaxWaitTimeExceededError < WaiterFailed - MSG = "stopped waiting after maximum wait time of %s seconds was exceeded" - def initialize(max_wait_time) - super(MSG % [max_wait_time]) + msg = "stopped waiting after maximum wait time of %s seconds was exceeded" + super(msg % [max_wait_time]) end end class UnexpectedError < WaiterFailed - MSG = "stopped waiting due to an unexpected error: %s" - def initialize(error) + msg = "stopped waiting due to an unexpected error: %s" @error = error - super(MSG % [error.message]) + super(msg % [error.message]) end attr_reader :error @@ -42,10 +39,9 @@ def initialize(error) # Raised when attempting to get a waiter by name and the waiter has not # been defined. class NoSuchWaiterError < ArgumentError - MSG = "no such waiter" - def initialize - super(MSG) + msg = "no such waiter" + super(msg) end end end diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index a4bd117d0..e6fbaadb1 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -16,9 +16,9 @@ def call(client, params) rescue StandardError => e error = e end - resp_or_error = resp || error + output_or_error = resp || error status = evaluate_acceptors(resp, error) - [resp_or_error, status] + [output_or_error, status] end private @@ -53,7 +53,7 @@ def matches_inputOutput?(path_matcher, resp, error) return false unless error.nil? && @input data = { - input: @input, ### Where do we get this? + input: @input, output: resp } actual = JMESPath.search(underscore_jmespath(path_matcher['path']), data) @@ -84,17 +84,11 @@ def is_equal?(actual, expected, comparator) when 'allStringEquals' return false if actual.nil? || actual.empty? - actual.each do |value| - return false if value != expected - end - return true + actual.all? { |value| value == expected } when 'anyStringEquals' return false if actual.nil? || actual.empty? - actual.each do |value| - return true if value == expected - end - return false + actual.any? { |value| value == expected } end end diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index 8bbf2bf33..abd7a60f0 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -6,20 +6,13 @@ module Waiters class Waiter def initialize(options = {}) unless options[:max_wait_time].is_a?(Integer) - raise ArgumentError, 'Waiter must be initialized with `:max_wait_time`' + raise ArgumentError, "expected `:max_wait_time` to be an integer, got: #{options[:max_wait_time]}" end @max_wait_time = options[:max_wait_time] @remaining_time = @max_wait_time - @min_delay = options[:min_delay] - @max_delay = options[:max_delay] - if @max_delay < 1 - raise ArgumentError, '`:max_delay` must be greater than 0' - end - if @min_delay < 1 || @min_delay > @max_delay - raise ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`' - end - + @max_delay = max_delay(options[:max_delay]) + @min_delay = min_delay(options[:min_delay]) @poller = options[:poller] end @@ -29,6 +22,20 @@ def wait(client, params) private + def max_delay(delay) + if delay < 1 + raise ArgumentError, '`:max_delay` must be greater than 0' + end + delay + end + + def min_delay(delay) + if delay < 1 || delay > @max_delay + raise ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`' + end + delay + end + def poll(client, params) attempts = 0 loop do diff --git a/gems/smithy/lib/smithy/generators/client.rb b/gems/smithy/lib/smithy/generators/client.rb index 6ffd5384f..05ea99aab 100644 --- a/gems/smithy/lib/smithy/generators/client.rb +++ b/gems/smithy/lib/smithy/generators/client.rb @@ -50,10 +50,10 @@ def source_files e.yield "lib/#{@gem_name}/endpoint_parameters.rb", Views::Client::EndpointParameters.new(@plan).render e.yield "lib/#{@gem_name}/endpoint_provider.rb", Views::Client::EndpointProvider.new(@plan).render e.yield "lib/#{@gem_name}/paginators.rb", Views::Client::Paginators.new(@plan).render - e.yield "lib/#{@gem_name}/waiters.rb", Views::Client::Waiters.new(@plan).render code_generated_plugins.each { |path, plugin| e.yield path, plugin.source } e.yield "lib/#{@gem_name}/types.rb", Views::Client::Types.new(@plan).render e.yield "lib/#{@gem_name}/schema.rb", Views::Client::Schema.new(@plan).render + e.yield "lib/#{@gem_name}/waiters.rb", Views::Client::Waiters.new(@plan).render e.yield "lib/#{@gem_name}/client.rb", Views::Client::Client.new(@plan, code_generated_plugins).render end end diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index 7eaadf93a..f26f9b2ef 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -36,13 +36,11 @@ module <%= module_name %> end <% end -%> -<% if waiters? -%> def wait_until(waiter_name, params = {}, options = {}) w = waiter(waiter_name, options) w.wait(params) end -<% end -%> private def build_input(operation_name, params) @@ -58,7 +56,7 @@ module <%= module_name %> context[:gem_version] = '<%= gem_version %>' Smithy::Client::Input.new(handlers: handlers, context: context) end -<% if waiters? %> + def waiter(waiter_name, options = {}) waiter_class = waiters[waiter_name] if waiter_class @@ -69,11 +67,14 @@ module <%= module_name %> end def waiters +<% if waiters? -%> <% waiters.each do |line| -%> - <%= line %> + <%= line %> <% end -%> - end +<% else -%> + {} <% end -%> + end class << self # @api private diff --git a/gems/smithy/lib/smithy/views/client/client.rb b/gems/smithy/lib/smithy/views/client/client.rb index 01b29d032..f912fc00c 100644 --- a/gems/smithy/lib/smithy/views/client/client.rb +++ b/gems/smithy/lib/smithy/views/client/client.rb @@ -62,14 +62,14 @@ def protocols def waiters waiters = Views::Client::Waiters.new(@plan).waiters - code = [' {'] + lines = ['{'] waiters.each_with_index do |waiter, i| - line = ' ' + waiter.name.underscore + ': Waiters::' + waiter.name + ',' + line = ' ' + waiter.name.underscore + ': Waiters::' + waiter.name + ',' line.chomp!(',') if i == waiters.length - 1 - code << line + lines << line end - code << ' }' - code + lines << '}' + lines end def waiters? diff --git a/gems/smithy/lib/smithy/views/client/module.rb b/gems/smithy/lib/smithy/views/client/module.rb index 10fdc2b20..d157b8c02 100644 --- a/gems/smithy/lib/smithy/views/client/module.rb +++ b/gems/smithy/lib/smithy/views/client/module.rb @@ -43,8 +43,8 @@ def relative_requires return %i[customizations types schema] if @plan.type == :schema # paginators must come before schemas - %w[types paginators waiters schema auth_parameters auth_resolver client customizations errors endpoint_parameters - endpoint_provider] + %w[types paginators schema auth_parameters auth_resolver client customizations errors endpoint_parameters + endpoint_provider waiters] end end end diff --git a/gems/smithy/lib/smithy/views/client/waiters.rb b/gems/smithy/lib/smithy/views/client/waiters.rb index 1888f5a5e..fc58eafd5 100644 --- a/gems/smithy/lib/smithy/views/client/waiters.rb +++ b/gems/smithy/lib/smithy/views/client/waiters.rb @@ -16,22 +16,18 @@ def module_name end def waiters - Model::ServiceIndex - .new(@model) - .operations_for(@plan.service) - .map do |operation_id, operation| - waiters_from_trait = waitable_trait(operation) - next if waiters_from_trait.empty? - + waiters = [] + operations = Model::ServiceIndex.new(@model).operations_for(@plan.service) + operations.each do |operation_id, operation| + waiters_from_trait = waitable_trait(operation) + unless waiters_from_trait.empty? operation_name = Model::Shape.name(operation_id).underscore - waiters_from_trait.map do |waiter_name, waiter| - Waiter.new(operation_name, waiter_name, waiter) + waiters << Waiter.new(operation_name, waiter_name, waiter) end end - .flatten - .compact - .sort_by(&:name) + end + waiters.sort_by(&:name) end private @@ -50,10 +46,9 @@ def initialize(operation, name, waiter) @min_delay = waiter['minDelay'] || 2 @max_delay = waiter['maxDelay'] || 120 @deprecated = waiter['deprecated'] - @tags = waiter['tags'] end - attr_reader :operation_name, :name, :documentation, :acceptors, :min_delay, :max_delay, :deprecated, :tags + attr_reader :operation_name, :name, :documentation, :acceptors, :min_delay, :max_delay, :deprecated def formatted_acceptors(acceptors) Util::HashFormatter.new( diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index fcff20bc9..88c9b5aed 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -871,7 +871,7 @@ it 'raises an error when max_wait_time is not provided' do expect { client.wait_until(:success_true_matcher, input) - }.to raise_error(ArgumentError, 'Waiter must be initialized with `:max_wait_time`') + }.to raise_error(ArgumentError, "expected `:max_wait_time` to be an integer, got: #{nil}") end it 'raises an error when max_delay is less than 1' do diff --git a/projections/shapes/lib/shapes.rb b/projections/shapes/lib/shapes.rb index ed3018b54..098f97605 100644 --- a/projections/shapes/lib/shapes.rb +++ b/projections/shapes/lib/shapes.rb @@ -11,7 +11,6 @@ module ShapeService require_relative 'shapes/types' require_relative 'shapes/paginators' -require_relative 'shapes/waiters' require_relative 'shapes/schema' require_relative 'shapes/auth_parameters' require_relative 'shapes/auth_resolver' @@ -20,3 +19,4 @@ module ShapeService require_relative 'shapes/errors' require_relative 'shapes/endpoint_parameters' require_relative 'shapes/endpoint_provider' +require_relative 'shapes/waiters' diff --git a/projections/shapes/lib/shapes/client.rb b/projections/shapes/lib/shapes/client.rb index a52335dc6..e3dee66e8 100644 --- a/projections/shapes/lib/shapes/client.rb +++ b/projections/shapes/lib/shapes/client.rb @@ -229,6 +229,11 @@ def operation(params = {}, options = {}) input.send_request(options) end + def wait_until(waiter_name, params = {}, options = {}) + w = waiter(waiter_name, options) + w.wait(params) + end + private def build_input(operation_name, params) @@ -245,6 +250,19 @@ def build_input(operation_name, params) Smithy::Client::Input.new(handlers: handlers, context: context) end + def waiter(waiter_name, options = {}) + waiter_class = waiters[waiter_name] + if waiter_class + waiter_class.new(options.merge(client: self)) + else + raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new + end + end + + def waiters + {} + end + class << self # @api private attr_reader :identifier diff --git a/projections/weather/lib/weather.rb b/projections/weather/lib/weather.rb index 885d64c36..88b665748 100644 --- a/projections/weather/lib/weather.rb +++ b/projections/weather/lib/weather.rb @@ -11,7 +11,6 @@ module Weather require_relative 'weather/types' require_relative 'weather/paginators' -require_relative 'weather/waiters' require_relative 'weather/schema' require_relative 'weather/auth_parameters' require_relative 'weather/auth_resolver' @@ -20,3 +19,4 @@ module Weather require_relative 'weather/errors' require_relative 'weather/endpoint_parameters' require_relative 'weather/endpoint_provider' +require_relative 'weather/waiters' From 3ff3ca14f9484ea269889ac5a0fcb9c3c30e1282 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 2 May 2025 13:53:52 -0700 Subject: [PATCH 20/48] Underscore paths during code generation --- .../lib/smithy-client/waiters/errors.rb | 14 ++---- .../lib/smithy-client/waiters/poller.rb | 46 +++++++------------ .../smithy/lib/smithy/views/client/waiters.rb | 8 ++++ model/weather.smithy | 8 ++-- projections/weather/lib/weather/client.rb | 2 +- projections/weather/lib/weather/schema.rb | 4 +- projections/weather/lib/weather/types.rb | 2 +- projections/weather/lib/weather/waiters.rb | 4 +- projections/weather/sig/weather/client.rbs | 2 +- projections/weather/sig/weather/types.rbs | 4 +- 10 files changed, 41 insertions(+), 53 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/errors.rb b/gems/smithy-client/lib/smithy-client/waiters/errors.rb index c1172c95c..8703092bd 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/errors.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/errors.rb @@ -10,13 +10,10 @@ module Errors class WaiterFailed < StandardError; end class FailureStateError < WaiterFailed - def initialize(response) - msg = "stopped waiting, encountered a failure state" - @response = response - super(msg) + def initialize(error) + msg = "stopped waiting, encountered a failure state: %s" + super(msg % [error]) end - - attr_reader :response end class MaxWaitTimeExceededError < WaiterFailed @@ -29,11 +26,8 @@ def initialize(max_wait_time) class UnexpectedError < WaiterFailed def initialize(error) msg = "stopped waiting due to an unexpected error: %s" - @error = error - super(msg % [error.message]) + super(msg % [error]) end - - attr_reader :error end # Raised when attempting to get a waiter by name and the waiter has not diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index e6fbaadb1..88948486c 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -12,20 +12,20 @@ def initialize(options = {}) def call(client, params) @input = params begin - resp = client.send(@operation_name, params) + output = client.send(@operation_name, params) rescue StandardError => e error = e end - output_or_error = resp || error - status = evaluate_acceptors(resp, error) + output_or_error = output || error + status = evaluate_acceptors(output, error) [output_or_error, status] end private - def evaluate_acceptors(resp, error) + def evaluate_acceptors(output, error) @acceptors.each do |acceptor| - return acceptor['state'] if acceptor_matches?(acceptor['matcher'], resp, error) + return acceptor['state'] if acceptor_matches?(acceptor['matcher'], output, error) end # If none of the acceptors match and an error was encountered, @@ -37,39 +37,39 @@ def evaluate_acceptors(resp, error) end end - def acceptor_matches?(matcher, resp, error) + def acceptor_matches?(matcher, output, error) matcher_type = matcher.keys[0] - send("matches_#{matcher_type}?", matcher[matcher_type], resp, error) + send("matches_#{matcher_type}?", matcher[matcher_type], output, error) end - def matches_output?(path_matcher, resp, error) + def matches_output?(path_matcher, output, error) return false unless error.nil? - actual = JMESPath.search(underscore_jmespath(path_matcher['path']), resp) + actual = JMESPath.search(path_matcher['path'], output) is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) end - def matches_inputOutput?(path_matcher, resp, error) + def matches_inputOutput?(path_matcher, output, error) return false unless error.nil? && @input data = { input: @input, - output: resp + output: output } - actual = JMESPath.search(underscore_jmespath(path_matcher['path']), data) + actual = JMESPath.search(path_matcher['path'], data) is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) end - def matches_success?(path_matcher, resp, error) + def matches_success?(path_matcher, output, error) if path_matcher == true - !resp.nil? + !output.nil? else !error.nil? end end - def matches_errorType?(path_matcher, resp, error) - return false unless resp.nil? + def matches_errorType?(path_matcher, output, error) + return false unless output.nil? err = path_matcher.split('#').last.split('#').first error.class.to_s.include?(err) @@ -91,20 +91,6 @@ def is_equal?(actual, expected, comparator) actual.any? { |value| value == expected } end end - - def underscore(string) - string.gsub(/::/, '/') - .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') - .gsub(/([a-z\d])([A-Z])/,'\1_\2') - .tr("-", "_") - .downcase - end - - def underscore_jmespath(expression) - expression - .gsub(' or ', '||') - .gsub(/(? # { # chance_of_rain: 1.0, - # status: "String" + # status_property: "String" # } def get_forecast(params = {}, options = {}) input = build_input(:get_forecast, params) diff --git a/projections/weather/lib/weather/schema.rb b/projections/weather/lib/weather/schema.rb index fd6f8467b..23fd61a19 100644 --- a/projections/weather/lib/weather/schema.rb +++ b/projections/weather/lib/weather/schema.rb @@ -44,7 +44,7 @@ module Schema GetForecastInput.type = Types::GetForecastInput GetForecastOutput.add_member(:chance_of_rain, 'chanceOfRain', Prelude::Float) - GetForecastOutput.add_member(:status, 'status', Prelude::String) + GetForecastOutput.add_member(:status_property, 'statusProperty', Prelude::String) GetForecastOutput.type = Types::GetForecastOutput ListCitiesInput.add_member(:next_token, 'nextToken', Prelude::String) @@ -83,7 +83,7 @@ module Schema operation.name = "GetForecast" operation.input = GetForecastInput operation.output = GetForecastOutput - operation.traits = {"smithy.api#readonly"=>{}, "smithy.waiters#waitable"=>{"ForecastExists"=>{"documentation"=>"Waits until forecast is created", "acceptors"=>[{"state"=>"failure", "matcher"=>{"output"=>{"path"=>"status", "comparator"=>"stringEquals", "expected"=>"failed"}}}, {"state"=>"success", "matcher"=>{"output"=>{"path"=>"status", "comparator"=>"stringEquals", "expected"=>"success"}}}]}}} + operation.traits = {"smithy.api#readonly"=>{}, "smithy.waiters#waitable"=>{"ForecastExists"=>{"documentation"=>"Waits until forecast is created", "acceptors"=>[{"state"=>"failure", "matcher"=>{"output"=>{"path"=>"statusProperty", "comparator"=>"stringEquals", "expected"=>"failed"}}}, {"state"=>"success", "matcher"=>{"output"=>{"path"=>"statusProperty", "comparator"=>"stringEquals", "expected"=>"success"}}}]}}} end) service.add_operation(:list_cities, OperationShape.new do |operation| operation.id = "example.weather#ListCities" diff --git a/projections/weather/lib/weather/types.rb b/projections/weather/lib/weather/types.rb index 5ebcaf981..8ee2246fe 100644 --- a/projections/weather/lib/weather/types.rb +++ b/projections/weather/lib/weather/types.rb @@ -53,7 +53,7 @@ module Types GetForecastOutput = Struct.new( :chance_of_rain, - :status, + :status_property, keyword_init: true ) do include Smithy::Schema::Structure diff --git a/projections/weather/lib/weather/waiters.rb b/projections/weather/lib/weather/waiters.rb index 587b21816..799547447 100644 --- a/projections/weather/lib/weather/waiters.rb +++ b/projections/weather/lib/weather/waiters.rb @@ -72,7 +72,7 @@ def initialize(options = {}) "state" => "failure", "matcher" => { "output" => { - "path" => "status", + "path" => "status_property", "comparator" => "stringEquals", "expected" => "failed" } @@ -82,7 +82,7 @@ def initialize(options = {}) "state" => "success", "matcher" => { "output" => { - "path" => "status", + "path" => "status_property", "comparator" => "stringEquals", "expected" => "success" } diff --git a/projections/weather/sig/weather/client.rbs b/projections/weather/sig/weather/client.rbs index 5a1a46f6e..6d8dc8c09 100644 --- a/projections/weather/sig/weather/client.rbs +++ b/projections/weather/sig/weather/client.rbs @@ -52,7 +52,7 @@ module Weather interface _GetForecastResponse include Smithy::Client::_Output[Types::GetForecastOutput] def chance_of_rain: () -> Float? - def status: () -> String? + def status_property: () -> String? end def get_forecast: ( ?city_id: String diff --git a/projections/weather/sig/weather/types.rbs b/projections/weather/sig/weather/types.rbs index 0e9eecee3..63e5f28df 100644 --- a/projections/weather/sig/weather/types.rbs +++ b/projections/weather/sig/weather/types.rbs @@ -78,12 +78,12 @@ module Weather def initialize: ( ?chance_of_rain: Float, - ?status: String, + ?status_property: String, ) -> void | (?Hash[Symbol, untyped]) -> void attr_accessor chance_of_rain: Float? - attr_accessor status: String? + attr_accessor status_property: String? end class ListCitiesInput From 6decd0600a3b4bb32c873747c76b32eaae60b681 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 2 May 2025 14:49:35 -0700 Subject: [PATCH 21/48] Add documentation and deprecated traits to generated waiters --- .../lib/smithy/templates/client/waiters.erb | 7 ++++ .../spec/fixtures/wait_service/model.json | 34 ++++++++++++++++++ .../spec/fixtures/wait_service/model.smithy | 35 +++++++++++++++++++ model/weather.smithy | 3 ++ projections/shapes/lib/shapes/waiters.rb | 1 + projections/weather/lib/weather/schema.rb | 2 +- projections/weather/lib/weather/waiters.rb | 15 ++++++-- 7 files changed, 94 insertions(+), 3 deletions(-) diff --git a/gems/smithy/lib/smithy/templates/client/waiters.erb b/gems/smithy/lib/smithy/templates/client/waiters.erb index a0fe3297c..636d62bc6 100644 --- a/gems/smithy/lib/smithy/templates/client/waiters.erb +++ b/gems/smithy/lib/smithy/templates/client/waiters.erb @@ -5,10 +5,17 @@ require 'smithy-client/waiters' module <%= module_name %> + # @api private module Waiters <% waiters.each do |waiter| -%> +<% if waiter.deprecated -%> + # @deprecated +<% end -%> # @api private + # + # <%= waiter.documentation %> + # class <%= waiter.name %> def initialize(options = {}) @client = options[:client] diff --git a/gems/smithy/spec/fixtures/wait_service/model.json b/gems/smithy/spec/fixtures/wait_service/model.json index 31aec57b6..9b6e57031 100644 --- a/gems/smithy/spec/fixtures/wait_service/model.json +++ b/gems/smithy/spec/fixtures/wait_service/model.json @@ -85,6 +85,40 @@ } } ] + }, + "FullyConfiguredMatcher": { + "documentation": "Fully configured waiter", + "acceptors": [ + { + "state": "retry", + "matcher": { + "errorType": "WidgetDoesNotExist" + } + }, + { + "state": "failure", + "matcher": { + "output": { + "path": "stringProperty", + "expected": "fail", + "comparator": "stringEquals" + } + } + }, + { + "state": "success", + "matcher": { + "success": true + } + } + ], + "minDelay": 5, + "maxDelay": 20, + "deprecated": true, + "tags": [ + "some", + "tags" + ] } } } diff --git a/gems/smithy/spec/fixtures/wait_service/model.smithy b/gems/smithy/spec/fixtures/wait_service/model.smithy index 81a4c7bc1..e30afe5f1 100644 --- a/gems/smithy/spec/fixtures/wait_service/model.smithy +++ b/gems/smithy/spec/fixtures/wait_service/model.smithy @@ -2,6 +2,7 @@ $version: "2" namespace smithy.ruby.tests +use smithy.tests.endpointrules.stringarray#EmptyStaticContextOperation use smithy.waiters#waitable // A service which has a GET operation with waiters defined upon it. @@ -316,6 +317,40 @@ operation GetWidget { } ] } + FullyConfiguredMatcher: { + documentation: "Fully configured waiter" + acceptors: [ + { + state: "retry" + matcher: { + errorType: "WidgetDoesNotExist" + } + } + { + state: "failure" + matcher: { + output: { + path: "stringProperty" + expected: "fail" + comparator: "stringEquals" + } + } + } + { + state: "success" + matcher: { + success: true + } + } + ] + minDelay: 5 + maxDelay: 20 + deprecated: true + tags: [ + "some" + "tags" + ] + } ) operation DeleteWidget { input: WidgetInput, diff --git a/model/weather.smithy b/model/weather.smithy index d8c6ae753..972d0bf01 100644 --- a/model/weather.smithy +++ b/model/weather.smithy @@ -174,6 +174,9 @@ operation GetCurrentTime { } } ] + minDelay: 5 + maxDelay: 20 + deprecated: true } ) operation GetForecast { diff --git a/projections/shapes/lib/shapes/waiters.rb b/projections/shapes/lib/shapes/waiters.rb index 1f257c14c..162af715f 100644 --- a/projections/shapes/lib/shapes/waiters.rb +++ b/projections/shapes/lib/shapes/waiters.rb @@ -5,6 +5,7 @@ require 'smithy-client/waiters' module ShapeService + # @api private module Waiters end diff --git a/projections/weather/lib/weather/schema.rb b/projections/weather/lib/weather/schema.rb index 23fd61a19..878fb7817 100644 --- a/projections/weather/lib/weather/schema.rb +++ b/projections/weather/lib/weather/schema.rb @@ -83,7 +83,7 @@ module Schema operation.name = "GetForecast" operation.input = GetForecastInput operation.output = GetForecastOutput - operation.traits = {"smithy.api#readonly"=>{}, "smithy.waiters#waitable"=>{"ForecastExists"=>{"documentation"=>"Waits until forecast is created", "acceptors"=>[{"state"=>"failure", "matcher"=>{"output"=>{"path"=>"statusProperty", "comparator"=>"stringEquals", "expected"=>"failed"}}}, {"state"=>"success", "matcher"=>{"output"=>{"path"=>"statusProperty", "comparator"=>"stringEquals", "expected"=>"success"}}}]}}} + operation.traits = {"smithy.api#readonly"=>{}, "smithy.waiters#waitable"=>{"ForecastExists"=>{"documentation"=>"Waits until forecast is created", "acceptors"=>[{"state"=>"failure", "matcher"=>{"output"=>{"path"=>"statusProperty", "comparator"=>"stringEquals", "expected"=>"failed"}}}, {"state"=>"success", "matcher"=>{"output"=>{"path"=>"statusProperty", "comparator"=>"stringEquals", "expected"=>"success"}}}], "minDelay"=>5, "maxDelay"=>20, "deprecated"=>true}}} end) service.add_operation(:list_cities, OperationShape.new do |operation| operation.id = "example.weather#ListCities" diff --git a/projections/weather/lib/weather/waiters.rb b/projections/weather/lib/weather/waiters.rb index 799547447..cb0d08af8 100644 --- a/projections/weather/lib/weather/waiters.rb +++ b/projections/weather/lib/weather/waiters.rb @@ -5,9 +5,13 @@ require 'smithy-client/waiters' module Weather + # @api private module Waiters # @api private + # + # Waits until city is deleted + # class CityDeleted def initialize(options = {}) @client = options[:client] @@ -33,6 +37,9 @@ def wait(params = {}) end # @api private + # + # Waits until city exists + # class CityExists def initialize(options = {}) @client = options[:client] @@ -57,14 +64,18 @@ def wait(params = {}) end end + # @deprecated # @api private + # + # Waits until forecast is created + # class ForecastExists def initialize(options = {}) @client = options[:client] @waiter = Smithy::Client::Waiters::Waiter.new( max_wait_time: options[:max_wait_time], - min_delay: options[:min_delay] || 2, - max_delay: options[:max_delay] || 120, + min_delay: options[:min_delay] || 5, + max_delay: options[:max_delay] || 20, poller: Smithy::Client::Waiters::Poller.new( operation_name: :get_forecast, acceptors: [ From 779fe1a5d0895959e71beb7f2bb6c97a4729edde Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 5 May 2025 11:09:23 -0700 Subject: [PATCH 22/48] Refactor unit tests --- .../lib/smithy-client/waiters/errors.rb | 6 +- .../spec/smithy-client/waiters_spec.rb | 1621 +++++++++++++++++ .../lib/smithy/templates/client/client.erb | 2 +- .../spec/fixtures/wait_service/model.json | 400 +--- .../spec/fixtures/wait_service/model.smithy | 349 +--- .../spec/interfaces/client/waiters_spec.rb | 923 +--------- projections/shapes/lib/shapes/client.rb | 2 +- projections/weather/lib/weather/client.rb | 2 +- 8 files changed, 1693 insertions(+), 1612 deletions(-) create mode 100644 gems/smithy-client/spec/smithy-client/waiters_spec.rb diff --git a/gems/smithy-client/lib/smithy-client/waiters/errors.rb b/gems/smithy-client/lib/smithy-client/waiters/errors.rb index 8703092bd..cb8c12c8c 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/errors.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/errors.rb @@ -33,9 +33,9 @@ def initialize(error) # Raised when attempting to get a waiter by name and the waiter has not # been defined. class NoSuchWaiterError < ArgumentError - def initialize - msg = "no such waiter" - super(msg) + def initialize(waiter_name, valid_waiters) + msg = "no such waiter: %s; valid waiter names are: %s" + super(msg % [waiter_name, valid_waiters]) end end end diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb new file mode 100644 index 000000000..78b042f02 --- /dev/null +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -0,0 +1,1621 @@ +# frozen_string_literal: true + +require_relative '../spec_helper' + +module Smithy + module Client + module Waiters + describe Waiters do + let(:shapes) do + { + "smithy.ruby.tests#BooleanArray" => { + "type" => "list", + "member" => { + "target" => "smithy.api#Boolean" + } + }, + "smithy.ruby.tests#Child" => { + "type" => "structure", + "members" => { + "grandchildren" => { + "target" => "smithy.ruby.tests#GrandchildArray" + } + } + }, + "smithy.ruby.tests#ChildArray" => { + "type" => "list", + "member" => { + "target" => "smithy.ruby.tests#Child" + } + }, + "smithy.ruby.tests#DataMap" => { + "type" => "map", + "key" => { + "target" => "smithy.api#String" + }, + "value" => { + "target" => "smithy.api#String" + } + }, + "smithy.ruby.tests#DeleteWidget" => { + "type" => "operation", + "input" => { + "target" => "smithy.ruby.tests#WidgetInput" + }, + "output" => { + "target" => "smithy.ruby.tests#DeletedWidgetOutput" + }, + "errors" => [ + { + "target" => "smithy.ruby.tests#MyError" + }, + { + "target" => "smithy.ruby.tests#WidgetDoesNotExistError" + } + ], + "traits" => { + "smithy.api#http" => { + "uri" => "/delete-widget", + "method" => "POST" + }, + "smithy.waiters#waitable" => { + "AcceptorOrderSuccessMatcher" => { + "documentation" => "Matcher with multiple acceptors", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "errorType" => "WidgetDoesNotExistError" + } + }, + { + "state" => "failure", + "matcher" => { + "errorType" => "WidgetDoesNotExistError" + } + } + ] + }, + "AcceptorOrderFailureMatcher" => { + "documentation" => "Matcher with multiple acceptors", + "acceptors" => [ + { + "state" => "failure", + "matcher" => { + "errorType" => "WidgetDoesNotExistError" + } + }, + { + "state" => "success", + "matcher" => { + "errorType" => "WidgetDoesNotExistError" + } + } + ] + }, + "FullyConfiguredMatcher" => { + "documentation" => "Fully configured waiter", + "acceptors" => [ + { + "state" => "retry", + "matcher" => { + "errorType" => "WidgetDoesNotExistError" + } + }, + { + "state" => "failure", + "matcher" => { + "output" => { + "path" => "stringProperty", + "expected" => "fail", + "comparator" => "stringEquals" + } + } + }, + { + "state" => "success", + "matcher" => { + "success" => true + } + } + ], + "minDelay" => 5, + "maxDelay" => 20, + "deprecated" => true, + "tags" => %w[some tags] + } + } + } + }, + "smithy.ruby.tests#DeletedWidgetOutput" => { + "type" => "structure", + "members" => { + "stringProperty" => { + "target" => "smithy.api#String" + } + } + }, + "smithy.ruby.tests#GetWidget" => { + "type" => "operation", + "input" => { + "target" => "smithy.ruby.tests#WidgetInput" + }, + "output" => { + "target" => "smithy.ruby.tests#WidgetOutput" + }, + "errors" => [ + { + "target" => "smithy.ruby.tests#MyError" + } + ], + "traits" => { + "smithy.api#http" => { + "uri" => "/widget", + "method" => "POST" + }, + "smithy.waiters#waitable" => { + "SuccessTrueMatcher" => { + "documentation" => "Acceptor matches on successful request", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "success" => true + } + } + ] + }, + "SuccessFalseMatcher" => { + "documentation" => "Acceptor matches on unsuccessful request", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "success" => false + } + } + ] + }, + "ErrorTypeMatcher" => { + "documentation" => "Acceptor matches on receipt of specified error", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "errorType" => "MyError" + } + } + ] + }, + "OutputStringPropertyMatcher" => { + "documentation" => "Acceptor matches on output payload property", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "output" => { + "path" => "stringProperty", + "expected" => "expected string", + "comparator" => "stringEquals" + } + } + } + ] + }, + "OutputBooleanPropertyMatcher" => { + "documentation" => "Acceptor matches on output payload property", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "output" => { + "path" => "booleanProperty", + "expected" => "false", + "comparator" => "booleanEquals" + } + } + } + ] + }, + "OutputStringArrayAllPropertyMatcher" => { + "documentation" => "Acceptor matches on output payload property", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "output" => { + "path" => "stringArrayProperty", + "expected" => "expected string", + "comparator" => "allStringEquals" + } + } + } + ] + }, + "OutputStringArrayAnyPropertyMatcher" => { + "documentation" => "Acceptor matches on output payload property", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "output" => { + "path" => "stringArrayProperty", + "expected" => "expected string", + "comparator" => "anyStringEquals" + } + } + } + ] + }, + "InputOutputStringPropertyMatcher" => { + "documentation" => "Acceptor matches on string property of input and output", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "inputOutput" => { + "path" => "input.stringProperty", + "expected" => "output.stringProperty", + "comparator" => "stringEquals" + } + } + } + ] + }, + "InputOutputBooleanPropertyMatcher" => { + "documentation" => "Acceptor matches on input property equaling output property", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "inputOutput" => { + "path" => "input.stringProperty == output.stringProperty", + "expected" => "true", + "comparator" => "booleanEquals" + } + } + } + ] + }, + "InputOutputStringArrayAllPropertyMatcher" => { + "documentation" => "Acceptor matches on string array property of input and output", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "inputOutput" => { + "path" => "input.stringArrayProperty", + "expected" => "output.stringArrayProperty", + "comparator" => "allStringEquals" + } + } + } + ] + }, + "InputOutputStringArrayAnyPropertyMatcher" => { + "documentation" => "Acceptor matches on string array property of input and output", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "inputOutput" => { + "path" => "input.stringArrayProperty", + "expected" => "output.stringArrayProperty", + "comparator" => "anyStringEquals" + } + } + } + ] + }, + "FlattenMatcher" => { + "documentation" => "Matches when any grandchild has name 'expected name'", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "output" => { + "path" => "children[].grandchildren[].name", + "expected" => "expected name", + "comparator" => "anyStringEquals" + } + } + } + ] + }, + "FlattenLengthMatcher" => { + "documentation" => "Matches when there are 6 grandchildren total", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "output" => { + "path" => "length(children[].grandchildren[]) == `6`", + "expected" => "true", + "comparator" => "booleanEquals" + } + } + } + ] + }, + "FlattenFilterMatcher" => { + "documentation" => "Matches when exactly one child has 3 grandchildren", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "output" => { + "path" => "length(children[?length(grandchildren) == `3`]) == `1`", + "expected" => "true", + "comparator" => "booleanEquals" + } + } + } + ] + }, + "LengthFlattenFilterMatcher" => { + "documentation" => "Matches when exactly 3 grandchildren have numbers above 4", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "output" => { + "path" => "length((children[].grandchildren[])[?number > `4`]) == `3`", + "expected" => "true", + "comparator" => "booleanEquals" + } + } + } + ] + }, + "ProjectionMatcher" => { + "documentation" => "Matches when dataMap values are all `abc`", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "output" => { + "path" => "dataMap.*", + "expected" => "abc", + "comparator" => "allStringEquals" + } + } + } + ] + }, + "ContainsFieldMatcher" => { + "documentation" => "Matches when any value of dataMap is the same as stringProperty", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "output" => { + "path" => "contains(dataMap.*, stringProperty)", + "expected" => "true", + "comparator" => "booleanEquals" + } + } + } + ] + }, + "AndInequalityMatcher" => { + "documentation" => "Matches when there are three elements in dataMap but not three in stringArrayProperty", + "acceptors" => [ + { + "state" => "success", + "matcher" => { + "output" => { + "path" => "length(dataMap) == `3` && length(stringArrayProperty) != `3`", + "expected" => "true", + "comparator" => "booleanEquals" + } + } + } + ] + } + } + } + }, + "smithy.ruby.tests#Grandchild" => { + "type" => "structure", + "members" => { + "name" => { + "target" => "smithy.api#String" + }, + "number" => { + "target" => "smithy.api#Integer" + } + } + }, + "smithy.ruby.tests#GrandchildArray" => { + "type" => "list", + "member" => { + "target" => "smithy.ruby.tests#Grandchild" + } + }, + "smithy.ruby.tests#MyError" => { + "type" => "structure", + "members" => { + "message" => { + "target" => "smithy.api#String" + } + }, + "traits" => { + "smithy.api#error" => "client" + } + }, + "smithy.ruby.tests#StringArray" => { + "type" => "list", + "member" => { + "target" => "smithy.api#String" + } + }, + "smithy.ruby.tests#WaitService" => { + "type" => "service", + "version" => "2022-11-30", + "operations" => [ + { + "target" => "smithy.ruby.tests#DeleteWidget" + }, + { + "target" => "smithy.ruby.tests#GetWidget" + } + ] + }, + "smithy.ruby.tests#WidgetDoesNotExistError" => { + "type" => "structure", + "members" => { + "message" => { + "target" => "smithy.api#String" + } + }, + "traits" => { + "smithy.api#error" => "client" + } + }, + "smithy.ruby.tests#WidgetInput" => { + "type" => "structure", + "members" => { + "stringProperty" => { + "target" => "smithy.api#String" + }, + "stringArrayProperty" => { + "target" => "smithy.ruby.tests#StringArray" + }, + "booleanProperty" => { + "target" => "smithy.api#Boolean" + }, + "booleanArrayProperty" => { + "target" => "smithy.ruby.tests#BooleanArray" + }, + "children" => { + "target" => "smithy.ruby.tests#ChildArray" + }, + "dataMap" => { + "target" => "smithy.ruby.tests#DataMap" + } + } + }, + "smithy.ruby.tests#WidgetOutput" => { + "type" => "structure", + "members" => { + "stringProperty" => { + "target" => "smithy.api#String" + }, + "stringArrayProperty" => { + "target" => "smithy.ruby.tests#StringArray" + }, + "booleanProperty" => { + "target" => "smithy.api#Boolean" + }, + "booleanArrayProperty" => { + "target" => "smithy.ruby.tests#BooleanArray" + }, + "children" => { + "target" => "smithy.ruby.tests#ChildArray" + }, + "dataMap" => { + "target" => "smithy.ruby.tests#DataMap" + } + } + }, + "smithy.waiters#Acceptor" => { + "type" => "structure", + "members" => { + "state" => { + "target" => "smithy.waiters#AcceptorState", + "traits" => { + "smithy.api#documentation" => "The state the acceptor transitions to when matched.", + "smithy.api#required" => {} + } + }, + "matcher" => { + "target" => "smithy.waiters#Matcher", + "traits" => { + "smithy.api#documentation" => "The matcher used to test if the resource is in a given state.", + "smithy.api#required" => {} + } + } + }, + "traits" => { + "smithy.api#documentation" => "Represents an acceptor in a waiter's state machine.", + "smithy.api#private" => {} + } + }, + "smithy.waiters#AcceptorState" => { + "type" => "enum", + "members" => { + "SUCCESS" => { + "target" => "smithy.api#Unit", + "traits" => { + "smithy.api#documentation" => "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", + "smithy.api#enumValue" => "success" + } + }, + "FAILURE" => { + "target" => "smithy.api#Unit", + "traits" => { + "smithy.api#documentation" => "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", + "smithy.api#enumValue" => "failure" + } + }, + "RETRY" => { + "target" => "smithy.api#Unit", + "traits" => { + "smithy.api#documentation" => "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", + "smithy.api#enumValue" => "retry" + } + } + }, + "traits" => { + "smithy.api#documentation" => "The transition state of a waiter.", + "smithy.api#private" => {} + } + }, + "smithy.waiters#Acceptors" => { + "type" => "list", + "member" => { + "target" => "smithy.waiters#Acceptor" + }, + "traits" => { + "smithy.api#length" => { + "min" => 1 + }, + "smithy.api#private" => {} + } + }, + "smithy.waiters#Matcher" => { + "type" => "union", + "members" => { + "output" => { + "target" => "smithy.waiters#PathMatcher", + "traits" => { + "smithy.api#documentation" => "Matches on the successful output of an operation using a\nJMESPath expression." + } + }, + "inputOutput" => { + "target" => "smithy.waiters#PathMatcher", + "traits" => { + "smithy.api#documentation" => "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." + } + }, + "errorType" => { + "target" => "smithy.api#String", + "traits" => { + "smithy.api#documentation" => "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." + } + }, + "success" => { + "target" => "smithy.api#Boolean", + "traits" => { + "smithy.api#documentation" => "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." + } + } + }, + "traits" => { + "smithy.api#documentation" => "Defines how an acceptor determines if it matches the current state of\na resource.", + "smithy.api#private" => {} + } + }, + "smithy.waiters#NonEmptyString" => { + "type" => "string", + "traits" => { + "smithy.api#length" => { + "min" => 1 + }, + "smithy.api#private" => {} + } + }, + "smithy.waiters#NonEmptyStringList" => { + "type" => "list", + "member" => { + "target" => "smithy.waiters#NonEmptyString" + }, + "traits" => { + "smithy.api#private" => {} + } + }, + "smithy.waiters#PathComparator" => { + "type" => "enum", + "members" => { + "STRING_EQUALS" => { + "target" => "smithy.api#Unit", + "traits" => { + "smithy.api#documentation" => "Matches if the return value is a string that is equal to the expected string.", + "smithy.api#enumValue" => "stringEquals" + } + }, + "BOOLEAN_EQUALS" => { + "target" => "smithy.api#Unit", + "traits" => { + "smithy.api#documentation" => "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", + "smithy.api#enumValue" => "booleanEquals" + } + }, + "ALL_STRING_EQUALS" => { + "target" => "smithy.api#Unit", + "traits" => { + "smithy.api#documentation" => "Matches if all values in the list matches the expected string.", + "smithy.api#enumValue" => "allStringEquals" + } + }, + "ANY_STRING_EQUALS" => { + "target" => "smithy.api#Unit", + "traits" => { + "smithy.api#documentation" => "Matches if any value in the list matches the expected string.", + "smithy.api#enumValue" => "anyStringEquals" + } + } + }, + "traits" => { + "smithy.api#documentation" => "Defines a comparison to perform in a PathMatcher.", + "smithy.api#private" => {} + } + }, + "smithy.waiters#PathMatcher" => { + "type" => "structure", + "members" => { + "path" => { + "target" => "smithy.api#String", + "traits" => { + "smithy.api#documentation" => "A JMESPath expression applied to the input or output of an operation.", + "smithy.api#required" => {} + } + }, + "expected" => { + "target" => "smithy.api#String", + "traits" => { + "smithy.api#documentation" => "The expected return value of the expression.", + "smithy.api#required" => {} + } + }, + "comparator" => { + "target" => "smithy.waiters#PathComparator", + "traits" => { + "smithy.api#documentation" => "The comparator used to compare the result of the expression with the\nexpected value.", + "smithy.api#required" => {} + } + } + }, + "traits" => { + "smithy.api#documentation" => "Defines how to test the result of a JMESPath expression against\nan expected value.", + "smithy.api#private" => {} + } + }, + "smithy.waiters#Waiter" => { + "type" => "structure", + "members" => { + "documentation" => { + "target" => "smithy.api#String", + "traits" => { + "smithy.api#documentation" => "Documentation about the waiter. Can use CommonMark." + } + }, + "acceptors" => { + "target" => "smithy.waiters#Acceptors", + "traits" => { + "smithy.api#documentation" => "An ordered array of acceptors to check after executing an operation.", + "smithy.api#required" => {} + } + }, + "minDelay" => { + "target" => "smithy.waiters#WaiterDelay", + "traits" => { + "smithy.api#default" => 2, + "smithy.api#documentation" => "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." + } + }, + "maxDelay" => { + "target" => "smithy.waiters#WaiterDelay", + "traits" => { + "smithy.api#default" => 120, + "smithy.api#documentation" => "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." + } + }, + "deprecated" => { + "target" => "smithy.api#Boolean", + "traits" => { + "smithy.api#documentation" => "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." + } + }, + "tags" => { + "target" => "smithy.waiters#NonEmptyStringList", + "traits" => { + "smithy.api#documentation" => "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." + } + } + }, + "traits" => { + "smithy.api#documentation" => "Defines an individual operation waiter.", + "smithy.api#private" => {} + } + }, + "smithy.waiters#WaiterDelay" => { + "type" => "integer", + "traits" => { + "smithy.api#range" => { + "min" => 1 + } + } + }, + "smithy.waiters#WaiterName" => { + "type" => "string", + "traits" => { + "smithy.api#pattern" => "^[A-Z]+[A-Za-z0-9]*$" + } + }, + "smithy.waiters#waitable" => { + "type" => "map", + "key" => { + "target" => "smithy.waiters#WaiterName" + }, + "value" => { + "target" => "smithy.waiters#Waiter" + }, + "traits" => { + "smithy.api#documentation" => "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", + "smithy.api#length" => { + "min" => 1 + }, + "smithy.api#trait" => { + "selector" => "operation :not(-[input, output]-> structure > member > union[trait|streaming])" + } + } + } + } + end + let(:sample_client) { ClientHelper.sample_client(shapes: shapes) } + let(:client_class) do + client_class = sample_client.const_get(:Client) + client_class.clear_plugins + client_class.add_plugin(sample_client::Plugins::Endpoint) + client_class.add_plugin(Smithy::Client::Plugins::StubResponses) + client_class + end + let(:client) { client_class.new(stub_responses: true) } + let(:input) { { string_property: 'input_string' } } + let(:waiter) { Waiter } + let(:my_error) { sample_client::Errors::MyError.new({}, message: 'my error message') } + let(:widget_does_not_exist_error) { + sample_client::Errors::WidgetDoesNotExistError.new({}, message: 'widget does not exist message') + } + let(:unexpected_error) { Errors::UnexpectedError } + let(:failure_state_error) { Errors::FailureStateError } + let(:max_wait_time_exceeded_error) { Errors::MaxWaitTimeExceededError } + let(:no_such_waiter_error) { Errors::NoSuchWaiterError } + + describe 'success matcher' do + it 'succeeds when success is set to true and successful response is received' do + output = {} + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:success_true_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'succeeds when success is set to false and error is received' do + expect(client).to receive(:get_widget).and_raise(StandardError) + expect { + client.wait_until(:success_false_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'retries and succeeds when matched' do + output = {} + 2.times do + expect(client).to receive(:get_widget).and_return(output) + end + expect(client).to receive(:get_widget).and_raise(StandardError) + expect { + client.wait_until(:success_false_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when success is set to true and unexpected error is received' do + expect(client).to receive(:get_widget).and_raise(StandardError) + expect { + client.wait_until(:success_true_matcher, input, max_wait_time: 60) + }.to raise_error(unexpected_error) + end + end + + describe 'error type matcher' do + it 'succeeds when error matches' do + expect(client).to receive(:get_widget).and_raise(my_error) + expect { + client.wait_until(:error_type_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'retries and succeeds when matched' do + output = {} + 2.times do + expect(client).to receive(:get_widget).and_return(output) + expect_any_instance_of(waiter).to receive(:delay).and_call_original + end + expect(client).to receive(:get_widget).and_raise(my_error) + expect { + client.wait_until(:error_type_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when error does not match' do + expect(client).to receive(:get_widget).and_raise(StandardError) + expect { + client.wait_until(:error_type_matcher, input, max_wait_time: 60) + }.to raise_error(unexpected_error) + end + end + + describe 'output matcher' do + context 'string equals comparator' do + it 'succeeds when output matches' do + output = { string_property: 'expected string' } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'retries and succeeds when matched' do + output_expected = { string_property: 'expected string' } + output_unexpected = { string_property: 'unexpected string' } + 2.times do + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect_any_instance_of(waiter).to receive(:delay).and_call_original + end + expect(client).to receive(:get_widget).and_return(output_expected) + expect { + client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when output property does not match' do + output_unexpected = { string_property: 'unexpected string' } + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is null' do + output_unexpected = {} + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'boolean equals comparator' do + it 'succeeds when output matches' do + output = { boolean_property: false } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'retries and succeeds when matched' do + output_expected = { boolean_property: false } + output_unexpected = { boolean_property: true } + 2.times do + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect_any_instance_of(waiter).to receive(:delay).and_call_original + end + expect(client).to receive(:get_widget).and_return(output_expected) + expect { + client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when output property does not match' do + output_unexpected = { boolean_property: true } + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is null' do + output_unexpected = {} + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'all string equals comparator' do + it 'succeeds when output matches' do + output = { + string_array_property: [ + 'expected string', + 'expected string', + 'expected string' + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'retries and succeeds when matched' do + output_expected = { + string_array_property: [ + 'expected string', + 'expected string', + 'expected string' + ] + } + output_unexpected = { + string_array_property: [ + 'expected string', + 'unexpected string', + 'unexpected string' + ] + } + 2.times do + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect_any_instance_of(waiter).to receive(:delay).and_call_original + end + expect(client).to receive(:get_widget).and_return(output_expected) + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when output property does not match' do + output_unexpected = { + string_array_property: [ + 'expected string', + 'unexpected string', + 'unexpected string' + ] + } + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is empty' do + output_unexpected = { string_array_property: [] } + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is null' do + output_unexpected = {} + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'any string equals comparator' do + it 'succeeds when output matches' do + output = { + string_array_property: [ + 'some other string', + 'another string', + 'expected string', + 'yet another string' + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'retries and succeeds when matched' do + output_expected = { + string_array_property: [ + 'some other string', + 'another string', + 'expected string', + 'yet another string' + ] + } + output_unexpected = { + string_array_property: [ + 'some other string', + 'another string', + 'unexpected string', + 'yet another string' + ] + } + 2.times do + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect_any_instance_of(waiter).to receive(:delay).and_call_original + end + expect(client).to receive(:get_widget).and_return(output_expected) + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when output property does not match' do + output_unexpected = { + string_array_property: [ + 'some other string', + 'another string', + 'unexpected string', + 'yet another string' + ] + } + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is empty' do + output_unexpected = { string_array_property: [] } + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is null' do + output_unexpected = {} + 2.times do + allow(client).to receive(:get_widget).and_return(output_unexpected) + end + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'flatten' do + it 'succeeds when matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'expected name', + number: 1 + } + ] + }, + { + grandchildren: [ + { + name: 'unexpected name', + number: 1 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:flatten_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when not matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'unexpected name', + number: 1 + } + ] + } + ] + } + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:flatten_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'flatten length' do + it 'succeeds when matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 4 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 5 + }, + { + name: 'name', + number: 6 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:flatten_length_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when not matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + } + ] + } + ] + } + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:flatten_length_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'flatten filter' do + it 'succeeds when matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 4 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 5 + }, + { + name: 'name', + number: 6 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:flatten_filter_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when not matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 4 + }, + { + name: 'name', + number: 5 + }, + { + name: 'name', + number: 6 + } + ] + } + ] + } + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:flatten_filter_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'length flatten filter' do + it 'succeeds when matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 5 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 6 + }, + { + name: 'name', + number: 7 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when not matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 3 + }, + { + name: 'name', + number: 4 + }, + { + name: 'name', + number: 5 + } + ] + } + ] + } + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'projection' do + it 'succeeds when matched' do + output = { + data_map: { + 'key1' => 'abc', + 'key2' => 'abc', + 'key3' => 'abc', + } + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:projection_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when not matched' do + output = { + data_map: { + 'key1' => 'abc', + 'key2' => 'def', + 'key3' => 'ghi', + } + } + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:projection_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'contains field' do + it 'succeeds when matched' do + output = { + string_property: 'match', + data_map: { + 'key1' => 'not a match', + 'key2' => 'match', + 'key3' => 'not a match', + } + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:contains_field_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when not matched' do + output = { + string_property: 'match', + data_map: { + 'key1' => 'not a match', + 'key2' => 'not a match', + 'key3' => 'not a match', + } + } + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:contains_field_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + + context 'and inequality' do + it 'succeeds when matched' do + output = { + string_array_property: [ + 'some string', + 'another string' + ], + data_map: { + 'key1' => 'one', + 'key2' => 'two', + 'key3' => 'three', + } + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:and_inequality_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when not matched' do + output = { + string_array_property: [ + 'some string', + 'another string', + 'yet another string' + ], + data_map: { + 'key1' => 'one', + 'key2' => 'two', + 'key3' => 'three', + } + } + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:and_inequality_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + end + end + + describe 'input output matcher' do + it 'succeeds for boolean equals comparator' do + output = { string_property: 'input_string' } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:input_output_boolean_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + end + + it 'checks acceptors in order' do + expect(client).to receive(:delete_widget).and_raise(widget_does_not_exist_error) + expect { + client.wait_until(:acceptor_order_success_matcher, input, max_wait_time: 60) + }.to_not raise_error + + expect(client).to receive(:delete_widget).and_raise(widget_does_not_exist_error) + expect { + client.wait_until(:acceptor_order_failure_matcher, input, max_wait_time: 60) + }.to raise_error(failure_state_error) + end + + it 'allows configuration of min and max delay' do + options = { + max_wait_time: 5, + min_delay: 3, + max_delay: 4 + } + output = {} + 2.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect_any_instance_of(waiter).to receive(:delay).and_wrap_original do |m, *args| + delay = m.call(*args) + expect(delay).to equal(5) + delay + end + expect { + client.wait_until(:success_false_matcher, input, options) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'raises an error when max wait time is exceeded' do + output = {} + 5.times do + allow(client).to receive(:get_widget).and_return(output) + end + expect { + client.wait_until(:success_false_matcher, input, max_wait_time: 2) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'raises an error when max_wait_time is not provided' do + expect { + client.wait_until(:success_true_matcher, input) + }.to raise_error(ArgumentError, "expected `:max_wait_time` to be an integer, got: #{nil}") + end + + it 'raises an error when max_delay is less than 1' do + options = { + max_wait_time: 5, + max_delay: 0 + } + expect { + client.wait_until(:success_true_matcher, input, options) + }.to raise_error(ArgumentError, '`:max_delay` must be greater than 0') + end + + it 'raises an error when min_delay is less than 1' do + options = { + max_wait_time: 5, + min_delay: 0 + } + expect { + client.wait_until(:success_true_matcher, input, options) + }.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') + end + + it 'raises an error when max_delay is less than min_delay' do + options = { + max_wait_time: 5, + min_delay: 4, + max_delay: 2 + } + expect { + client.wait_until(:success_true_matcher, input, options) + }.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') + end + end + end + end +end diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index f26f9b2ef..02fc2e562 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -62,7 +62,7 @@ module <%= module_name %> if waiter_class waiter_class.new(options.merge(client: self)) else - raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new + raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new(waiter_name, waiters.keys) end end diff --git a/gems/smithy/spec/fixtures/wait_service/model.json b/gems/smithy/spec/fixtures/wait_service/model.json index 9b6e57031..d298816dd 100644 --- a/gems/smithy/spec/fixtures/wait_service/model.json +++ b/gems/smithy/spec/fixtures/wait_service/model.json @@ -30,99 +30,6 @@ "target": "smithy.api#String" } }, - "smithy.ruby.tests#DeleteWidget": { - "type": "operation", - "input": { - "target": "smithy.ruby.tests#WidgetInput" - }, - "output": { - "target": "smithy.ruby.tests#DeletedWidgetOutput" - }, - "errors": [ - { - "target": "smithy.ruby.tests#MyError" - }, - { - "target": "smithy.ruby.tests#WidgetDoesNotExist" - } - ], - "traits": { - "smithy.api#http": { - "uri": "/delete-widget", - "method": "POST" - }, - "smithy.waiters#waitable": { - "AcceptorOrderSuccessMatcher": { - "documentation": "Matcher with multiple acceptors", - "acceptors": [ - { - "state": "success", - "matcher": { - "errorType": "WidgetDoesNotExist" - } - }, - { - "state": "failure", - "matcher": { - "errorType": "WidgetDoesNotExist" - } - } - ] - }, - "AcceptorOrderFailureMatcher": { - "documentation": "Matcher with multiple acceptors", - "acceptors": [ - { - "state": "failure", - "matcher": { - "errorType": "WidgetDoesNotExist" - } - }, - { - "state": "success", - "matcher": { - "errorType": "WidgetDoesNotExist" - } - } - ] - }, - "FullyConfiguredMatcher": { - "documentation": "Fully configured waiter", - "acceptors": [ - { - "state": "retry", - "matcher": { - "errorType": "WidgetDoesNotExist" - } - }, - { - "state": "failure", - "matcher": { - "output": { - "path": "stringProperty", - "expected": "fail", - "comparator": "stringEquals" - } - } - }, - { - "state": "success", - "matcher": { - "success": true - } - } - ], - "minDelay": 5, - "maxDelay": 20, - "deprecated": true, - "tags": [ - "some", - "tags" - ] - } - } - } - }, "smithy.ruby.tests#DeletedWidgetOutput": { "type": "structure", "members": { @@ -131,13 +38,13 @@ } } }, - "smithy.ruby.tests#GetWidget": { + "smithy.ruby.tests#GetOperation": { "type": "operation", "input": { - "target": "smithy.ruby.tests#WidgetInput" + "target": "smithy.ruby.tests#OperationInput" }, "output": { - "target": "smithy.ruby.tests#WidgetOutput" + "target": "smithy.ruby.tests#OperationOutput" }, "errors": [ { @@ -145,12 +52,8 @@ } ], "traits": { - "smithy.api#http": { - "uri": "/widget", - "method": "POST" - }, "smithy.waiters#waitable": { - "SuccessTrueMatcher": { + "SuccessMatcher": { "documentation": "Acceptor matches on successful request", "acceptors": [ { @@ -160,253 +63,6 @@ } } ] - }, - "SuccessFalseMatcher": { - "documentation": "Acceptor matches on unsuccessful request", - "acceptors": [ - { - "state": "success", - "matcher": { - "success": false - } - } - ] - }, - "ErrorTypeMatcher": { - "documentation": "Acceptor matches on receipt of specified error", - "acceptors": [ - { - "state": "success", - "matcher": { - "errorType": "MyError" - } - } - ] - }, - "OutputStringPropertyMatcher": { - "documentation": "Acceptor matches on output payload property", - "acceptors": [ - { - "state": "success", - "matcher": { - "output": { - "path": "stringProperty", - "expected": "expected string", - "comparator": "stringEquals" - } - } - } - ] - }, - "OutputBooleanPropertyMatcher": { - "documentation": "Acceptor matches on output payload property", - "acceptors": [ - { - "state": "success", - "matcher": { - "output": { - "path": "booleanProperty", - "expected": "false", - "comparator": "booleanEquals" - } - } - } - ] - }, - "OutputStringArrayAllPropertyMatcher": { - "documentation": "Acceptor matches on output payload property", - "acceptors": [ - { - "state": "success", - "matcher": { - "output": { - "path": "stringArrayProperty", - "expected": "expected string", - "comparator": "allStringEquals" - } - } - } - ] - }, - "OutputStringArrayAnyPropertyMatcher": { - "documentation": "Acceptor matches on output payload property", - "acceptors": [ - { - "state": "success", - "matcher": { - "output": { - "path": "stringArrayProperty", - "expected": "expected string", - "comparator": "anyStringEquals" - } - } - } - ] - }, - "InputOutputStringPropertyMatcher": { - "documentation": "Acceptor matches on string property of input and output", - "acceptors": [ - { - "state": "success", - "matcher": { - "inputOutput": { - "path": "input.stringProperty", - "expected": "output.stringProperty", - "comparator": "stringEquals" - } - } - } - ] - }, - "InputOutputBooleanPropertyMatcher": { - "documentation": "Acceptor matches on input property equaling output property", - "acceptors": [ - { - "state": "success", - "matcher": { - "inputOutput": { - "path": "input.stringProperty == output.stringProperty", - "expected": "true", - "comparator": "booleanEquals" - } - } - } - ] - }, - "InputOutputStringArrayAllPropertyMatcher": { - "documentation": "Acceptor matches on string array property of input and output", - "acceptors": [ - { - "state": "success", - "matcher": { - "inputOutput": { - "path": "input.stringArrayProperty", - "expected": "output.stringArrayProperty", - "comparator": "allStringEquals" - } - } - } - ] - }, - "InputOutputStringArrayAnyPropertyMatcher": { - "documentation": "Acceptor matches on string array property of input and output", - "acceptors": [ - { - "state": "success", - "matcher": { - "inputOutput": { - "path": "input.stringArrayProperty", - "expected": "output.stringArrayProperty", - "comparator": "anyStringEquals" - } - } - } - ] - }, - "FlattenMatcher": { - "documentation": "Matches when any grandchild has name 'expected name'", - "acceptors": [ - { - "state": "success", - "matcher": { - "output": { - "path": "children[].grandchildren[].name", - "expected": "expected name", - "comparator": "anyStringEquals" - } - } - } - ] - }, - "FlattenLengthMatcher": { - "documentation": "Matches when there are 6 grandchildren total", - "acceptors": [ - { - "state": "success", - "matcher": { - "output": { - "path": "length(children[].grandchildren[]) == `6`", - "expected": "true", - "comparator": "booleanEquals" - } - } - } - ] - }, - "FlattenFilterMatcher": { - "documentation": "Matches when exactly one child has 3 grandchildren", - "acceptors": [ - { - "state": "success", - "matcher": { - "output": { - "path": "length(children[?length(grandchildren) == `3`]) == `1`", - "expected": "true", - "comparator": "booleanEquals" - } - } - } - ] - }, - "LengthFlattenFilterMatcher": { - "documentation": "Matches when exactly 3 grandchildren have numbers above 4", - "acceptors": [ - { - "state": "success", - "matcher": { - "output": { - "path": "length((children[].grandchildren[])[?number > `4`]) == `3`", - "expected": "true", - "comparator": "booleanEquals" - } - } - } - ] - }, - "ProjectionMatcher": { - "documentation": "Matches when dataMap values are all `abc`", - "acceptors": [ - { - "state": "success", - "matcher": { - "output": { - "path": "dataMap.*", - "expected": "abc", - "comparator": "allStringEquals" - } - } - } - ] - }, - "ContainsFieldMatcher": { - "documentation": "Matches when any value of dataMap is the same as stringProperty", - "acceptors": [ - { - "state": "success", - "matcher": { - "output": { - "path": "contains(dataMap.*, stringProperty)", - "expected": "true", - "comparator": "booleanEquals" - } - } - } - ] - }, - "AndInequalityMatcher": { - "documentation": "Matches when there are three elements in dataMap but not three in stringArrayProperty", - "acceptors": [ - { - "state": "success", - "matcher": { - "output": { - "path": "length(dataMap) == `3` && length(stringArrayProperty) != `3`", - "expected": "true", - "comparator": "booleanEquals" - } - } - } - ] } } } @@ -439,36 +95,7 @@ "smithy.api#error": "client" } }, - "smithy.ruby.tests#StringArray": { - "type": "list", - "member": { - "target": "smithy.api#String" - } - }, - "smithy.ruby.tests#WaitService": { - "type": "service", - "version": "2022-11-30", - "operations": [ - { - "target": "smithy.ruby.tests#DeleteWidget" - }, - { - "target": "smithy.ruby.tests#GetWidget" - } - ] - }, - "smithy.ruby.tests#WidgetDoesNotExist": { - "type": "structure", - "members": { - "message": { - "target": "smithy.api#String" - } - }, - "traits": { - "smithy.api#error": "client" - } - }, - "smithy.ruby.tests#WidgetInput": { + "smithy.ruby.tests#OperationInput": { "type": "structure", "members": { "stringProperty": { @@ -491,7 +118,7 @@ } } }, - "smithy.ruby.tests#WidgetOutput": { + "smithy.ruby.tests#OperationOutput": { "type": "structure", "members": { "stringProperty": { @@ -514,6 +141,21 @@ } } }, + "smithy.ruby.tests#StringArray": { + "type": "list", + "member": { + "target": "smithy.api#String" + } + }, + "smithy.ruby.tests#WaitService": { + "type": "service", + "version": "2022-11-30", + "operations": [ + { + "target": "smithy.ruby.tests#GetOperation" + } + ] + }, "smithy.waiters#Acceptor": { "type": "structure", "members": { diff --git a/gems/smithy/spec/fixtures/wait_service/model.smithy b/gems/smithy/spec/fixtures/wait_service/model.smithy index e30afe5f1..be64a2523 100644 --- a/gems/smithy/spec/fixtures/wait_service/model.smithy +++ b/gems/smithy/spec/fixtures/wait_service/model.smithy @@ -2,21 +2,15 @@ $version: "2" namespace smithy.ruby.tests -use smithy.tests.endpointrules.stringarray#EmptyStaticContextOperation use smithy.waiters#waitable -// A service which has a GET operation with waiters defined upon it. -// The acceptor in each waiter serves as subject for unit testing, -// to ensure that the logic in code-generated acceptors works as -// expected. service WaitService { version: "2022-11-30", - operations: [GetWidget, DeleteWidget] + operations: [GetOperation] } -@http(uri: "/widget", method: "POST") @waitable( - SuccessTrueMatcher: { + SuccessMatcher: { documentation: "Acceptor matches on successful request" acceptors: [ { @@ -27,338 +21,14 @@ service WaitService { } ] } - SuccessFalseMatcher: { - documentation: "Acceptor matches on unsuccessful request" - acceptors: [ - { - state: "success" - matcher: { - success: false - } - } - ] - } - ErrorTypeMatcher: { - documentation: "Acceptor matches on receipt of specified error" - acceptors: [ - { - state: "success" - matcher: { - errorType: "MyError" - } - } - ] - } - OutputStringPropertyMatcher: { - documentation: "Acceptor matches on output payload property" - acceptors: [ - { - state: "success" - matcher: { - output: { - path: "stringProperty" - expected: "expected string" - comparator: "stringEquals" - } - } - } - ] - } - OutputBooleanPropertyMatcher: { - documentation: "Acceptor matches on output payload property" - acceptors: [ - { - state: "success" - matcher: { - output: { - path: "booleanProperty" - expected: "false" - comparator: "booleanEquals" - } - } - } - ] - } - OutputStringArrayAllPropertyMatcher: { - documentation: "Acceptor matches on output payload property" - acceptors: [ - { - state: "success" - matcher: { - output: { - path: "stringArrayProperty" - expected: "expected string" - comparator: "allStringEquals" - } - } - } - ] - } - OutputStringArrayAnyPropertyMatcher: { - documentation: "Acceptor matches on output payload property" - acceptors: [ - { - state: "success" - matcher: { - output: { - path: "stringArrayProperty" - expected: "expected string" - comparator: "anyStringEquals" - } - } - } - ] - } - InputOutputStringPropertyMatcher: { - documentation: "Acceptor matches on string property of input and output" - acceptors: [ - { - state: "success" - matcher: { - inputOutput: { - path: "input.stringProperty" - expected: "output.stringProperty" - comparator: "stringEquals" - } - } - } - ] - } - InputOutputBooleanPropertyMatcher: { - documentation: "Acceptor matches on input property equaling output property" - acceptors: [ - { - state: "success" - matcher: { - inputOutput: { - path: "input.stringProperty == output.stringProperty" - expected: "true" - comparator: "booleanEquals" - } - } - } - ] - } - InputOutputStringArrayAllPropertyMatcher: { - documentation: "Acceptor matches on string array property of input and output" - acceptors: [ - { - state: "success" - matcher: { - inputOutput: { - path: "input.stringArrayProperty" - expected: "output.stringArrayProperty" - comparator: "allStringEquals" - } - } - } - ] - } - InputOutputStringArrayAnyPropertyMatcher: { - documentation: "Acceptor matches on string array property of input and output" - acceptors: [ - { - state: "success" - matcher: { - inputOutput: { - path: "input.stringArrayProperty" - expected: "output.stringArrayProperty" - comparator: "anyStringEquals" - } - } - } - ] - } - FlattenMatcher: { - documentation: "Matches when any grandchild has name 'expected name'" - acceptors: [ - { - state: "success" - matcher: { - output: { - path: "children[].grandchildren[].name" - expected: "expected name" - comparator: "anyStringEquals" - } - } - } - ] - } - FlattenLengthMatcher: { - documentation: "Matches when there are 6 grandchildren total" - acceptors: [ - { - state: "success" - matcher: { - output: { - path: "length(children[].grandchildren[]) == `6`" - expected: "true" - comparator: "booleanEquals" - } - } - } - ] - } - FlattenFilterMatcher: { - documentation: "Matches when exactly one child has 3 grandchildren" - acceptors: [ - { - state: "success" - matcher: { - output: { - path: "length(children[?length(grandchildren) == `3`]) == `1`" - expected: "true" - comparator: "booleanEquals" - } - } - } - ] - } - LengthFlattenFilterMatcher: { - documentation: "Matches when exactly 3 grandchildren have numbers above 4" - acceptors: [ - { - state: "success" - matcher: { - output: { - path: "length((children[].grandchildren[])[?number > `4`]) == `3`" - expected: "true" - comparator: "booleanEquals" - } - } - } - ] - } - ProjectionMatcher: { - documentation: "Matches when dataMap values are all `abc`" - acceptors: [ - { - state: "success" - matcher: { - output: { - path: "dataMap.*" - expected: "abc" - comparator: "allStringEquals" - } - } - } - ] - } - ContainsFieldMatcher: { - documentation: "Matches when any value of dataMap is the same as stringProperty" - acceptors: [ - { - state: "success" - matcher: { - output: { - path: "contains(dataMap.*, stringProperty)" - expected: "true" - comparator: "booleanEquals" - } - } - } - ] - } - AndInequalityMatcher: { - documentation: "Matches when there are three elements in dataMap but not three in stringArrayProperty" - acceptors: [ - { - state: "success" - matcher: { - output: { - path: "length(dataMap) == `3` && length(stringArrayProperty) != `3`" - expected: "true" - comparator: "booleanEquals" - } - } - } - ] - } ) -operation GetWidget { - input: WidgetInput, - output: WidgetOutput +operation GetOperation { + input: OperationInput, + output: OperationOutput errors: [MyError] } -@http(uri: "/delete-widget", method: "POST") -@waitable( - AcceptorOrderSuccessMatcher: { - documentation: "Matcher with multiple acceptors" - acceptors: [ - { - state: "success" - matcher: { - errorType: "WidgetDoesNotExist" - } - } - { - state: "failure" - matcher: { - errorType: "WidgetDoesNotExist" - } - } - ] - } - AcceptorOrderFailureMatcher: { - documentation: "Matcher with multiple acceptors" - acceptors: [ - { - state: "failure" - matcher: { - errorType: "WidgetDoesNotExist" - } - } - { - state: "success" - matcher: { - errorType: "WidgetDoesNotExist" - } - } - ] - } - FullyConfiguredMatcher: { - documentation: "Fully configured waiter" - acceptors: [ - { - state: "retry" - matcher: { - errorType: "WidgetDoesNotExist" - } - } - { - state: "failure" - matcher: { - output: { - path: "stringProperty" - expected: "fail" - comparator: "stringEquals" - } - } - } - { - state: "success" - matcher: { - success: true - } - } - ] - minDelay: 5 - maxDelay: 20 - deprecated: true - tags: [ - "some" - "tags" - ] - } -) -operation DeleteWidget { - input: WidgetInput, - output: DeletedWidgetOutput - errors: [MyError, WidgetDoesNotExist] -} - -structure WidgetInput { +structure OperationInput { stringProperty: String stringArrayProperty: StringArray booleanProperty: Boolean @@ -367,7 +37,7 @@ structure WidgetInput { dataMap: DataMap } -structure WidgetOutput { +structure OperationOutput { stringProperty: String stringArrayProperty: StringArray booleanProperty: Boolean @@ -414,8 +84,3 @@ map DataMap { structure MyError { message: String } - -@error("client") -structure WidgetDoesNotExist { - message: String -} diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index 88c9b5aed..bd9c38356 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -5,905 +5,58 @@ describe 'Client: Waiters' do let(:input) { { string_property: 'input_string' } } let(:client) { Wait_Service::Client.new(stub_responses: true) } - let(:waiter) { Smithy::Client::Waiters::Waiter } - let(:my_error) { Wait_Service::Errors::MyError.new({}, message: 'my error message') } - let(:widget_does_not_exist_error) { - Wait_Service::Errors::WidgetDoesNotExist.new({}, message: 'widget does not exist message') - } let(:unexpected_error) { Smithy::Client::Waiters::Errors::UnexpectedError } - let(:failure_state_error) { Smithy::Client::Waiters::Errors::FailureStateError } - let(:max_wait_time_exceeded_error) { Smithy::Client::Waiters::Errors::MaxWaitTimeExceededError } let(:no_such_waiter_error) { Smithy::Client::Waiters::Errors::NoSuchWaiterError } ['generated client gem', 'generated client from source code'].each do |context| context context do include_context context, 'Wait_Service' - describe 'code generated waiters' do - context 'success matcher' do - it 'succeeds when success is set to true and successful response is received' do - output = {} - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:success_true_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'succeeds when success is set to false and error is received' do - expect(client).to receive(:get_widget).and_raise(StandardError) - expect { - client.wait_until(:success_false_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'retries and succeeds when matched' do - output = {} - 2.times do - expect(client).to receive(:get_widget).and_return(output) - end - expect(client).to receive(:get_widget).and_raise(StandardError) - expect { - client.wait_until(:success_false_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'fails when success is set to true and unexpected error is received' do - expect(client).to receive(:get_widget).and_raise(StandardError) - expect { - client.wait_until(:success_true_matcher, input, max_wait_time: 60) - }.to raise_error(unexpected_error) - end - end - - context 'error type matcher' do - it 'succeeds when error matches' do - expect(client).to receive(:get_widget).and_raise(my_error) - expect { - client.wait_until(:error_type_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'retries and succeeds when matched' do - output = {} - 2.times do - expect(client).to receive(:get_widget).and_return(output) - expect_any_instance_of(waiter).to receive(:delay).and_call_original - end - expect(client).to receive(:get_widget).and_raise(my_error) - expect { - client.wait_until(:error_type_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'fails when error does not match' do - expect(client).to receive(:get_widget).and_raise(StandardError) - expect { - client.wait_until(:error_type_matcher, input, max_wait_time: 60) - }.to raise_error(unexpected_error) - end - end - - context 'output matcher' do - context 'string equals comparator' do - it 'succeeds when output matches' do - output = { string_property: 'expected string' } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'retries and succeeds when matched' do - output_expected = { string_property: 'expected string' } - output_unexpected = { string_property: 'unexpected string' } - 2.times do - expect(client).to receive(:get_widget).and_return(output_unexpected) - expect_any_instance_of(waiter).to receive(:delay).and_call_original - end - expect(client).to receive(:get_widget).and_return(output_expected) - expect { - client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'fails when output property does not match' do - output_unexpected = { string_property: 'unexpected string' } - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) - end - expect { - client.wait_until(:output_string_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - - it 'fails when output property is null' do - output_unexpected = {} - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) - end - expect { - client.wait_until(:output_string_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - end - - context 'boolean equals comparator' do - it 'succeeds when output matches' do - output = { boolean_property: false } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'retries and succeeds when matched' do - output_expected = { boolean_property: false } - output_unexpected = { boolean_property: true } - 2.times do - expect(client).to receive(:get_widget).and_return(output_unexpected) - expect_any_instance_of(waiter).to receive(:delay).and_call_original - end - expect(client).to receive(:get_widget).and_return(output_expected) - expect { - client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'fails when output property does not match' do - output_unexpected = { boolean_property: true } - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) - end - expect { - client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - - it 'fails when output property is null' do - output_unexpected = {} - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) - end - expect { - client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - end - - context 'all string equals comparator' do - it 'succeeds when output matches' do - output = { - string_array_property: [ - 'expected string', - 'expected string', - 'expected string' - ] - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'retries and succeeds when matched' do - output_expected = { - string_array_property: [ - 'expected string', - 'expected string', - 'expected string' - ] - } - output_unexpected = { - string_array_property: [ - 'expected string', - 'unexpected string', - 'unexpected string' - ] - } - 2.times do - expect(client).to receive(:get_widget).and_return(output_unexpected) - expect_any_instance_of(waiter).to receive(:delay).and_call_original - end - expect(client).to receive(:get_widget).and_return(output_expected) - expect { - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'fails when output property does not match' do - output_unexpected = { - string_array_property: [ - 'expected string', - 'unexpected string', - 'unexpected string' - ] - } - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) - end - expect { - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - - it 'fails when output property is empty' do - output_unexpected = { string_array_property: [] } - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) - end - expect { - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - - it 'fails when output property is null' do - output_unexpected = {} - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) - end - expect { - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - end - - context 'any string equals comparator' do - it 'succeeds when output matches' do - output = { - string_array_property: [ - 'some other string', - 'another string', - 'expected string', - 'yet another string' - ] - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'retries and succeeds when matched' do - output_expected = { - string_array_property: [ - 'some other string', - 'another string', - 'expected string', - 'yet another string' - ] - } - output_unexpected = { - string_array_property: [ - 'some other string', - 'another string', - 'unexpected string', - 'yet another string' - ] - } - 2.times do - expect(client).to receive(:get_widget).and_return(output_unexpected) - expect_any_instance_of(waiter).to receive(:delay).and_call_original - end - expect(client).to receive(:get_widget).and_return(output_expected) - expect { - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'fails when output property does not match' do - output_unexpected = { - string_array_property: [ - 'some other string', - 'another string', - 'unexpected string', - 'yet another string' - ] - } - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) - end - expect { - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - - it 'fails when output property is empty' do - output_unexpected = { string_array_property: [] } - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) - end - expect { - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - - it 'fails when output property is null' do - output_unexpected = {} - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) - end - expect { - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - end - - context 'flatten' do - it 'succeeds when matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'expected name', - number: 1 - } - ] - }, - { - grandchildren: [ - { - name: 'unexpected name', - number: 1 - } - ] - } - ] - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:flatten_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'fails when not matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'unexpected name', - number: 1 - } - ] - } - ] - } - 2.times do - allow(client).to receive(:get_widget).and_return(output) - end - expect { - client.wait_until(:flatten_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - end - - context 'flatten length' do - it 'succeeds when matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 4 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 5 - }, - { - name: 'name', - number: 6 - } - ] - } - ] - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:flatten_length_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'fails when not matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - } - ] - } - ] - } - 2.times do - allow(client).to receive(:get_widget).and_return(output) - end - expect { - client.wait_until(:flatten_length_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - end - - context 'flatten filter' do - it 'succeeds when matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 4 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 5 - }, - { - name: 'name', - number: 6 - } - ] - } - ] - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:flatten_filter_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'fails when not matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 4 - }, - { - name: 'name', - number: 5 - }, - { - name: 'name', - number: 6 - } - ] - } - ] - } - 2.times do - allow(client).to receive(:get_widget).and_return(output) - end - expect { - client.wait_until(:flatten_filter_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - end - - context 'length flatten filter' do - it 'succeeds when matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 5 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 6 - }, - { - name: 'name', - number: 7 - } - ] - } - ] - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'fails when not matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 3 - }, - { - name: 'name', - number: 4 - }, - { - name: 'name', - number: 5 - } - ] - } - ] - } - 2.times do - allow(client).to receive(:get_widget).and_return(output) - end - expect { - client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - end - - context 'projection' do - it 'succeeds when matched' do - output = { - data_map: { - 'key1' => 'abc', - 'key2' => 'abc', - 'key3' => 'abc', - } - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:projection_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - it 'fails when not matched' do - output = { - data_map: { - 'key1' => 'abc', - 'key2' => 'def', - 'key3' => 'ghi', - } - } - 2.times do - allow(client).to receive(:get_widget).and_return(output) - end - expect { - client.wait_until(:projection_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - end + it 'returns when successful' do + output = {} + expect(client).to receive(:get_operation).and_return(output) + expect { + client.wait_until(:success_matcher, input, max_wait_time: 60) + }.to_not raise_error + end - context 'contains field' do - it 'succeeds when matched' do - output = { - string_property: 'match', - data_map: { - 'key1' => 'not a match', - 'key2' => 'match', - 'key3' => 'not a match', - } - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:contains_field_matcher, input, max_wait_time: 60) - }.to_not raise_error - end + it 'returns output when successful' do + output = { string_property: 'success' } + expect(client).to receive(:get_operation).and_return(output) + resp = client.wait_until(:success_matcher, input, max_wait_time: 60) + expect(resp[:string_property]).to eq('success') + end - it 'fails when not matched' do - output = { - string_property: 'match', - data_map: { - 'key1' => 'not a match', - 'key2' => 'not a match', - 'key3' => 'not a match', - } - } - 2.times do - allow(client).to receive(:get_widget).and_return(output) - end - expect { - client.wait_until(:contains_field_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - end + it 'raises an error when unsuccessful' do + expect(client).to receive(:get_operation).and_raise(StandardError) + expect { + client.wait_until(:success_matcher, input, max_wait_time: 60) + }.to raise_error(unexpected_error) + end - context 'and inequality' do - it 'succeeds when matched' do - output = { - string_array_property: [ - 'some string', - 'another string' - ], - data_map: { - 'key1' => 'one', - 'key2' => 'two', - 'key3' => 'three', - } - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:and_inequality_matcher, input, max_wait_time: 60) - }.to_not raise_error - end + it 'raises an error for nonexistent waiters' do + expect { + client.wait_until(:nonexistent_waiter, input, max_wait_time: 60) + }.to raise_error(no_such_waiter_error) + end - it 'fails when not matched' do - output = { - string_array_property: [ - 'some string', - 'another string', - 'yet another string' - ], - data_map: { - 'key1' => 'one', - 'key2' => 'two', - 'key3' => 'three', + it 'does not allow custom waiters' do + custom_waiter = { + 'CustomWaiterMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'success' => false } } - 2.times do - allow(client).to receive(:get_widget).and_return(output) - end - expect { - client.wait_until(:and_inequality_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - end - end - - context 'input output matcher' do - # it 'waits successfully for string equals comparator' do - # output = { string_property: 'input_string' } - # expect(client).to receive(:get_widget).and_return(output) - # expect { - # client.wait_until(:input_output_string_property_matcher, input, max_wait_time: 60) - # }.to_not raise_error - # end - - it 'succeeds for boolean equals comparator' do - output = { string_property: 'input_string' } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:input_output_boolean_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - - # it 'waits successfully for all string equals comparator' do - # input = :input - # input['string_array_property'] = [ - # 'expected string', - # 'expected string', - # 'expected string' - # ] - # output = { - # string_array_property: [ - # 'expected string', - # 'expected string', - # 'expected string' - # ] - # } - # expect(client).to receive(:get_widget).and_return(output) - # expect { - # client.wait_until(:input_output_string_array_all_property_matcher, input, max_wait_time: 60) - # }.to_not raise_error - # end - # - # it 'waits successfully for any string equals comparator' do - # input = :input - # input['string_array_property'] = [ - # 'expected string', - # ] - # output = { - # string_array_property: [ - # 'some other string', - # 'another string', - # 'expected string', - # 'yet another string' - # ] - # } - # expect(client).to receive(:get_widget).and_return(output) - # expect { - # client.wait_until(:input_output_string_array_any_property_matcher, input, max_wait_time: 60) - # }.to_not raise_error - # end - end - - it 'checks acceptors in order' do - expect(client).to receive(:delete_widget).and_raise(widget_does_not_exist_error) - expect { - client.wait_until(:acceptor_order_success_matcher, input, max_wait_time: 60) - }.to_not raise_error - - expect(client).to receive(:delete_widget).and_raise(widget_does_not_exist_error) - expect { - client.wait_until(:acceptor_order_failure_matcher, input, max_wait_time: 60) - }.to raise_error(failure_state_error) - end - - it 'allows configuration of min and max delay' do - options = { - max_wait_time: 5, - min_delay: 3, - max_delay: 4 - } - output = {} - 2.times do - allow(client).to receive(:get_widget).and_return(output) - end - expect_any_instance_of(waiter).to receive(:delay).and_wrap_original do |m, *args| - delay = m.call(*args) - expect(delay).to equal(5) - delay - end - expect { - client.wait_until(:success_false_matcher, input, options) - }.to raise_error(max_wait_time_exceeded_error) - end - - it 'does not allow custom waiters' do - custom_waiter = { - 'CustomWaiterMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'success' => true - } - } - ] - } - } - client.config.service.operations[:delete_widget].traits['smithy.waiters#waitable'].merge!(custom_waiter) - expect { - client.wait_until(:custom_waiter_matcher, input, max_wait_time: 60) - }.to raise_error(no_such_waiter_error) - end - - it 'raises an error when max wait time is exceeded' do - output = {} - 5.times do - allow(client).to receive(:get_widget).and_return(output) - end - expect { - client.wait_until(:success_false_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - - it 'raises an error for nonexistent waiters' do - expect { - client.wait_until(:nonexistent_waiter, input, max_wait_time: 60) - }.to raise_error(no_such_waiter_error) - end - - it 'raises an error when max_wait_time is not provided' do - expect { - client.wait_until(:success_true_matcher, input) - }.to raise_error(ArgumentError, "expected `:max_wait_time` to be an integer, got: #{nil}") - end - - it 'raises an error when max_delay is less than 1' do - options = { - max_wait_time: 5, - max_delay: 0 - } - expect { - client.wait_until(:success_true_matcher, input, options) - }.to raise_error(ArgumentError, '`:max_delay` must be greater than 0') - end - - it 'raises an error when min_delay is less than 1' do - options = { - max_wait_time: 5, - min_delay: 0 - } - expect { - client.wait_until(:success_true_matcher, input, options) - }.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') - end - - it 'raises an error when max_delay is less than min_delay' do - options = { - max_wait_time: 5, - min_delay: 4, - max_delay: 2 + ] } - expect { - client.wait_until(:success_true_matcher, input, options) - }.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') - end + } + client.config.service.operations[:get_operation].traits['smithy.waiters#waitable'].merge!(custom_waiter) + expect { + client.wait_until(:custom_waiter_matcher, input, max_wait_time: 60) + }.to raise_error(no_such_waiter_error) end end end diff --git a/projections/shapes/lib/shapes/client.rb b/projections/shapes/lib/shapes/client.rb index e3dee66e8..37683095b 100644 --- a/projections/shapes/lib/shapes/client.rb +++ b/projections/shapes/lib/shapes/client.rb @@ -255,7 +255,7 @@ def waiter(waiter_name, options = {}) if waiter_class waiter_class.new(options.merge(client: self)) else - raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new + raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new(waiter_name, waiters.keys) end end diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index 15d97827e..472644eef 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -253,7 +253,7 @@ def waiter(waiter_name, options = {}) if waiter_class waiter_class.new(options.merge(client: self)) else - raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new + raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new(waiter_name, waiters.keys) end end From e8e5f2bc3296cc3b8c52d9aab768781a69ce52c2 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 5 May 2025 13:05:56 -0700 Subject: [PATCH 23/48] Add more tests --- .../lib/smithy-client/waiters/waiter.rb | 8 +- .../spec/smithy-client/waiters_spec.rb | 1428 +++++++++-------- 2 files changed, 738 insertions(+), 698 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index abd7a60f0..952b8f2ba 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -39,14 +39,14 @@ def min_delay(delay) def poll(client, params) attempts = 0 loop do - resp, status = @poller.call(client, params) + output_or_error, status = @poller.call(client, params) attempts += 1 case status.to_sym when :retry - when :success then return resp - when :failure then raise Errors::FailureStateError.new(resp) - when :error then raise Errors::UnexpectedError.new(resp) + when :success then return output_or_error + when :failure then raise Errors::FailureStateError.new(output_or_error) + when :error then raise Errors::UnexpectedError.new(output_or_error) end raise Errors::MaxWaitTimeExceededError.new(@max_wait_time) if @remaining_time == 0 diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index 78b042f02..70b22c5ed 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -794,6 +794,7 @@ module Waiters let(:client) { client_class.new(stub_responses: true) } let(:input) { { string_property: 'input_string' } } let(:waiter) { Waiter } + let(:poller) { Poller } let(:my_error) { sample_client::Errors::MyError.new({}, message: 'my error message') } let(:widget_does_not_exist_error) { sample_client::Errors::WidgetDoesNotExistError.new({}, message: 'widget does not exist message') @@ -803,817 +804,856 @@ module Waiters let(:max_wait_time_exceeded_error) { Errors::MaxWaitTimeExceededError } let(:no_such_waiter_error) { Errors::NoSuchWaiterError } - describe 'success matcher' do - it 'succeeds when success is set to true and successful response is received' do - output = {} - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:success_true_matcher, input, max_wait_time: 60) - }.to_not raise_error - end + describe 'waiter' do + before(:each) { client } - it 'succeeds when success is set to false and error is received' do - expect(client).to receive(:get_widget).and_raise(StandardError) - expect { - client.wait_until(:success_false_matcher, input, max_wait_time: 60) - }.to_not raise_error - end + describe '#poll' do + it 'delays when status is retry' do + output = { string_property: 'expected' } + expect_any_instance_of(poller).to receive(:call).and_return([{}, :retry], [output, :success]) + expect_any_instance_of(waiter).to receive(:delay).and_return(0) + expect(client.wait_until(:success_true_matcher, input, max_wait_time: 60)).to eq(output) + end - it 'retries and succeeds when matched' do - output = {} - 2.times do - expect(client).to receive(:get_widget).and_return(output) + it 'returns output when status is success' do + output = { string_property: 'expected' } + expect_any_instance_of(poller).to receive(:call).and_return([output, :success]) + expect(client.wait_until(:success_true_matcher, input, max_wait_time: 60)).to eq(output) end - expect(client).to receive(:get_widget).and_raise(StandardError) - expect { - client.wait_until(:success_false_matcher, input, max_wait_time: 60) - }.to_not raise_error - end - it 'fails when success is set to true and unexpected error is received' do - expect(client).to receive(:get_widget).and_raise(StandardError) - expect { - client.wait_until(:success_true_matcher, input, max_wait_time: 60) - }.to raise_error(unexpected_error) - end - end + it 'raises a failure state error when status is failure' do + expect_any_instance_of(poller).to receive(:call).and_return([my_error, :failure]) + expect { + client.wait_until(:success_false_matcher, input, max_wait_time: 60) + }.to raise_error(failure_state_error) + end - describe 'error type matcher' do - it 'succeeds when error matches' do - expect(client).to receive(:get_widget).and_raise(my_error) - expect { - client.wait_until(:error_type_matcher, input, max_wait_time: 60) - }.to_not raise_error - end + it 'raises an unexpected error when status is error' do + expect_any_instance_of(poller).to receive(:call).and_return([StandardError, :error]) + expect { + client.wait_until(:success_false_matcher, input, max_wait_time: 60) + }.to raise_error(unexpected_error) + end - it 'retries and succeeds when matched' do - output = {} - 2.times do - expect(client).to receive(:get_widget).and_return(output) - expect_any_instance_of(waiter).to receive(:delay).and_call_original + it 'raises a max wait time exceeded error when there is no more remaining time' do + expect_any_instance_of(poller).to receive(:call).and_return([{}, :retry], [{}, :retry]) + expect_any_instance_of(waiter).to receive(:delay).and_return(1) + expect { + client.wait_until(:success_false_matcher, input, max_wait_time: 1) + }.to raise_error(max_wait_time_exceeded_error) end - expect(client).to receive(:get_widget).and_raise(my_error) - expect { - client.wait_until(:error_type_matcher, input, max_wait_time: 60) - }.to_not raise_error end - it 'fails when error does not match' do - expect(client).to receive(:get_widget).and_raise(StandardError) - expect { - client.wait_until(:error_type_matcher, input, max_wait_time: 60) - }.to raise_error(unexpected_error) + describe '#delay' do + it 'generates a random delay between min_delay and max_delay' do + min_delay = 5 + max_delay = 60 + options = { + max_wait_time: 60, + min_delay: min_delay, + max_delay: max_delay + } + expect_any_instance_of(poller).to receive(:call).and_return( + [{}, :retry], [{}, :retry], [{}, :retry], [{}, :success] + ) + expect_any_instance_of(waiter).to receive(:delay).with(1).and_wrap_original do |m, *args| + delay = m.call(*args) + expect(delay >= min_delay && delay <= max_delay).to be true + 0 + end + expect_any_instance_of(waiter).to receive(:delay).with(2).and_wrap_original do |m, *args| + delay = m.call(*args) + expect(delay >= min_delay && delay <= max_delay).to be true + 0 + end + expect_any_instance_of(waiter).to receive(:delay).with(3).and_wrap_original do |m, *args| + delay = m.call(*args) + expect(delay >= min_delay && delay <= max_delay).to be true + 0 + end + client.wait_until(:success_true_matcher, input, options) + end + + it 'sets the delay to remaining time for the last attempt' do + remaining_time = 40 + min_delay = 25 + max_delay = 30 + options = { + max_wait_time: remaining_time, + min_delay: min_delay, + max_delay: max_delay + } + expect_any_instance_of(poller).to receive(:call).and_return([{}, :retry], [{}, :success]) + expect_any_instance_of(waiter).to receive(:delay).and_wrap_original do |m, *args| + delay = m.call(*args) + expect(delay).to eq(remaining_time) + 0 + end + client.wait_until(:success_true_matcher, input, options) + end end - end - describe 'output matcher' do - context 'string equals comparator' do - it 'succeeds when output matches' do - output = { string_property: 'expected string' } + context 'errors' do + it 'raises an error when max wait time is exceeded' do + output = {} expect(client).to receive(:get_widget).and_return(output) expect { - client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) - }.to_not raise_error + client.wait_until(:success_false_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) end - it 'retries and succeeds when matched' do - output_expected = { string_property: 'expected string' } - output_unexpected = { string_property: 'unexpected string' } - 2.times do - expect(client).to receive(:get_widget).and_return(output_unexpected) - expect_any_instance_of(waiter).to receive(:delay).and_call_original - end - expect(client).to receive(:get_widget).and_return(output_expected) + it 'raises an error when max_wait_time is not provided' do expect { - client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) - }.to_not raise_error + client.wait_until(:success_true_matcher, input) + }.to raise_error(ArgumentError, "expected `:max_wait_time` to be an integer, got: #{nil}") end - it 'fails when output property does not match' do - output_unexpected = { string_property: 'unexpected string' } - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) - end + it 'raises an error when max_delay is less than 1' do + options = { + max_wait_time: 5, + max_delay: 0 + } expect { - client.wait_until(:output_string_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) + client.wait_until(:success_true_matcher, input, options) + }.to raise_error(ArgumentError, '`:max_delay` must be greater than 0') end - it 'fails when output property is null' do - output_unexpected = {} - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) - end + it 'raises an error when min_delay is less than 1' do + options = { + max_wait_time: 5, + min_delay: 0 + } expect { - client.wait_until(:output_string_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) + client.wait_until(:success_true_matcher, input, options) + }.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') + end + + it 'raises an error when max_delay is less than min_delay' do + options = { + max_wait_time: 5, + min_delay: 4, + max_delay: 2 + } + expect { + client.wait_until(:success_true_matcher, input, options) + }.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') end end + end - context 'boolean equals comparator' do - it 'succeeds when output matches' do - output = { boolean_property: false } + describe 'poller' do + describe 'success matcher' do + it 'succeeds when success is set to true and successful response is received' do + output = {} expect(client).to receive(:get_widget).and_return(output) expect { - client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) + client.wait_until(:success_true_matcher, input, max_wait_time: 60) }.to_not raise_error end - it 'retries and succeeds when matched' do - output_expected = { boolean_property: false } - output_unexpected = { boolean_property: true } - 2.times do - expect(client).to receive(:get_widget).and_return(output_unexpected) - expect_any_instance_of(waiter).to receive(:delay).and_call_original - end - expect(client).to receive(:get_widget).and_return(output_expected) + it 'succeeds when success is set to false and error is received' do + expect(client).to receive(:get_widget).and_raise(StandardError) expect { - client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) + client.wait_until(:success_false_matcher, input, max_wait_time: 60) }.to_not raise_error end - it 'fails when output property does not match' do - output_unexpected = { boolean_property: true } + it 'retries and succeeds when matched' do + output = {} 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) + expect(client).to receive(:get_widget).and_return(output) + expect_any_instance_of(waiter).to receive(:delay).and_return(0) end + expect(client).to receive(:get_widget).and_raise(StandardError) expect { - client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) + client.wait_until(:success_false_matcher, input, max_wait_time: 60) + }.to_not raise_error end - it 'fails when output property is null' do - output_unexpected = {} - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) - end + it 'fails when success is set to true and unexpected error is received' do + expect(client).to receive(:get_widget).and_raise(StandardError) expect { - client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) + client.wait_until(:success_true_matcher, input, max_wait_time: 60) + }.to raise_error(unexpected_error) end end - context 'all string equals comparator' do - it 'succeeds when output matches' do - output = { - string_array_property: [ - 'expected string', - 'expected string', - 'expected string' - ] - } - expect(client).to receive(:get_widget).and_return(output) + describe 'error type matcher' do + it 'succeeds when error matches' do + expect(client).to receive(:get_widget).and_raise(my_error) expect { - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) + client.wait_until(:error_type_matcher, input, max_wait_time: 60) }.to_not raise_error end it 'retries and succeeds when matched' do - output_expected = { - string_array_property: [ - 'expected string', - 'expected string', - 'expected string' - ] - } - output_unexpected = { - string_array_property: [ - 'expected string', - 'unexpected string', - 'unexpected string' - ] - } + output = {} 2.times do - expect(client).to receive(:get_widget).and_return(output_unexpected) - expect_any_instance_of(waiter).to receive(:delay).and_call_original + expect(client).to receive(:get_widget).and_return(output) + expect_any_instance_of(waiter).to receive(:delay).and_return(0) end - expect(client).to receive(:get_widget).and_return(output_expected) + expect(client).to receive(:get_widget).and_raise(my_error) expect { - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) + client.wait_until(:error_type_matcher, input, max_wait_time: 60) }.to_not raise_error end - it 'fails when output property does not match' do - output_unexpected = { - string_array_property: [ - 'expected string', - 'unexpected string', - 'unexpected string' - ] - } - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) - end + it 'fails when error does not match' do + expect(client).to receive(:get_widget).and_raise(StandardError) expect { - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) + client.wait_until(:error_type_matcher, input, max_wait_time: 60) + }.to raise_error(unexpected_error) end + end - it 'fails when output property is empty' do - output_unexpected = { string_array_property: [] } - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) + describe 'output matcher' do + context 'string equals comparator' do + it 'succeeds when output matches' do + output = { string_property: 'expected string' } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) + }.to_not raise_error end - expect { - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - it 'fails when output property is null' do - output_unexpected = {} - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) + it 'retries and succeeds when matched' do + output_expected = { string_property: 'expected string' } + output_unexpected = { string_property: 'unexpected string' } + 2.times do + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect_any_instance_of(waiter).to receive(:delay).and_return(0) + end + expect(client).to receive(:get_widget).and_return(output_expected) + expect { + client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) + }.to_not raise_error end - expect { - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - end - context 'any string equals comparator' do - it 'succeeds when output matches' do - output = { - string_array_property: [ - 'some other string', - 'another string', - 'expected string', - 'yet another string' - ] - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) - }.to_not raise_error - end + it 'fails when output property does not match' do + output_unexpected = { string_property: 'unexpected string' } + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect { + client.wait_until(:output_string_property_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) + end - it 'retries and succeeds when matched' do - output_expected = { - string_array_property: [ - 'some other string', - 'another string', - 'expected string', - 'yet another string' - ] - } - output_unexpected = { - string_array_property: [ - 'some other string', - 'another string', - 'unexpected string', - 'yet another string' - ] - } - 2.times do + it 'fails when output property is null' do + output_unexpected = {} expect(client).to receive(:get_widget).and_return(output_unexpected) - expect_any_instance_of(waiter).to receive(:delay).and_call_original + expect { + client.wait_until(:output_string_property_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) end - expect(client).to receive(:get_widget).and_return(output_expected) - expect { - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) - }.to_not raise_error end - it 'fails when output property does not match' do - output_unexpected = { - string_array_property: [ - 'some other string', - 'another string', - 'unexpected string', - 'yet another string' - ] - } - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) + context 'boolean equals comparator' do + it 'succeeds when output matches' do + output = { boolean_property: false } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) + }.to_not raise_error end - expect { - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - it 'fails when output property is empty' do - output_unexpected = { string_array_property: [] } - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) + it 'retries and succeeds when matched' do + output_expected = { boolean_property: false } + output_unexpected = { boolean_property: true } + 2.times do + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect_any_instance_of(waiter).to receive(:delay).and_return(0) + end + expect(client).to receive(:get_widget).and_return(output_expected) + expect { + client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) + }.to_not raise_error end - expect { - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - it 'fails when output property is null' do - output_unexpected = {} - 2.times do - allow(client).to receive(:get_widget).and_return(output_unexpected) + it 'fails when output property does not match' do + output_unexpected = { boolean_property: true } + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect { + client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is null' do + output_unexpected = {} + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect { + client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) end - expect { - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) end - end - context 'flatten' do - it 'succeeds when matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'expected name', - number: 1 - } - ] - }, - { - grandchildren: [ - { - name: 'unexpected name', - number: 1 - } - ] - } - ] - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:flatten_matcher, input, max_wait_time: 60) - }.to_not raise_error + context 'all string equals comparator' do + it 'succeeds when output matches' do + output = { + string_array_property: [ + 'expected string', + 'expected string', + 'expected string' + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'retries and succeeds when matched' do + output_expected = { + string_array_property: [ + 'expected string', + 'expected string', + 'expected string' + ] + } + output_unexpected = { + string_array_property: [ + 'expected string', + 'unexpected string', + 'unexpected string' + ] + } + 2.times do + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect_any_instance_of(waiter).to receive(:delay).and_return(0) + end + expect(client).to receive(:get_widget).and_return(output_expected) + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when output property does not match' do + output_unexpected = { + string_array_property: [ + 'expected string', + 'unexpected string', + 'unexpected string' + ] + } + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is empty' do + output_unexpected = { string_array_property: [] } + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is null' do + output_unexpected = {} + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect { + client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) + end end - it 'fails when not matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'unexpected name', - number: 1 - } - ] - } - ] - } - 2.times do - allow(client).to receive(:get_widget).and_return(output) + context 'any string equals comparator' do + it 'succeeds when output matches' do + output = { + string_array_property: [ + 'some other string', + 'another string', + 'expected string', + 'yet another string' + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'retries and succeeds when matched' do + output_expected = { + string_array_property: [ + 'some other string', + 'another string', + 'expected string', + 'yet another string' + ] + } + output_unexpected = { + string_array_property: [ + 'some other string', + 'another string', + 'unexpected string', + 'yet another string' + ] + } + 2.times do + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect_any_instance_of(waiter).to receive(:delay).and_return(0) + end + expect(client).to receive(:get_widget).and_return(output_expected) + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when output property does not match' do + output_unexpected = { + string_array_property: [ + 'some other string', + 'another string', + 'unexpected string', + 'yet another string' + ] + } + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is empty' do + output_unexpected = { string_array_property: [] } + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) + end + + it 'fails when output property is null' do + output_unexpected = {} + expect(client).to receive(:get_widget).and_return(output_unexpected) + expect { + client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) end - expect { - client.wait_until(:flatten_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) end - end - context 'flatten length' do - it 'succeeds when matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 4 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 5 - }, - { - name: 'name', - number: 6 - } - ] - } - ] - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:flatten_length_matcher, input, max_wait_time: 60) - }.to_not raise_error + context 'flatten' do + it 'succeeds when matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'expected name', + number: 1 + } + ] + }, + { + grandchildren: [ + { + name: 'unexpected name', + number: 1 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:flatten_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when not matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'unexpected name', + number: 1 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:flatten_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) + end end - it 'fails when not matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - } - ] - } - ] - } - 2.times do - allow(client).to receive(:get_widget).and_return(output) + context 'flatten length' do + it 'succeeds when matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 4 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 5 + }, + { + name: 'name', + number: 6 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:flatten_length_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when not matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:flatten_length_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) end - expect { - client.wait_until(:flatten_length_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) end - end - context 'flatten filter' do - it 'succeeds when matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 4 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 5 - }, - { - name: 'name', - number: 6 - } - ] - } - ] - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:flatten_filter_matcher, input, max_wait_time: 60) - }.to_not raise_error + context 'flatten filter' do + it 'succeeds when matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 4 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 5 + }, + { + name: 'name', + number: 6 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:flatten_filter_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when not matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 4 + }, + { + name: 'name', + number: 5 + }, + { + name: 'name', + number: 6 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:flatten_filter_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) + end end - it 'fails when not matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 4 - }, - { - name: 'name', - number: 5 - }, - { - name: 'name', - number: 6 - } - ] - } - ] - } - 2.times do - allow(client).to receive(:get_widget).and_return(output) + context 'length flatten filter' do + it 'succeeds when matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 5 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 6 + }, + { + name: 'name', + number: 7 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 60) + }.to_not raise_error + end + + it 'fails when not matched' do + output = { + children: [ + { + grandchildren: [ + { + name: 'name', + number: 1 + }, + { + name: 'name', + number: 2 + }, + { + name: 'name', + number: 3 + } + ] + }, + { + grandchildren: [ + { + name: 'name', + number: 3 + }, + { + name: 'name', + number: 4 + }, + { + name: 'name', + number: 5 + } + ] + } + ] + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) end - expect { - client.wait_until(:flatten_filter_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) end - end - context 'length flatten filter' do - it 'succeeds when matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 5 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 6 - }, - { - name: 'name', - number: 7 - } - ] + context 'projection' do + it 'succeeds when matched' do + output = { + data_map: { + 'key1' => 'abc', + 'key2' => 'abc', + 'key3' => 'abc', } - ] - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 60) - }.to_not raise_error - end + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:projection_matcher, input, max_wait_time: 60) + }.to_not raise_error + end - it 'fails when not matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 3 - }, - { - name: 'name', - number: 4 - }, - { - name: 'name', - number: 5 - } - ] + it 'fails when not matched' do + output = { + data_map: { + 'key1' => 'abc', + 'key2' => 'def', + 'key3' => 'ghi', } - ] - } - 2.times do - allow(client).to receive(:get_widget).and_return(output) + } + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:projection_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) end - expect { - client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) end - end - context 'projection' do - it 'succeeds when matched' do - output = { - data_map: { - 'key1' => 'abc', - 'key2' => 'abc', - 'key3' => 'abc', + context 'contains field' do + it 'succeeds when matched' do + output = { + string_property: 'match', + data_map: { + 'key1' => 'not a match', + 'key2' => 'match', + 'key3' => 'not a match', + } } - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:projection_matcher, input, max_wait_time: 60) - }.to_not raise_error - end + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:contains_field_matcher, input, max_wait_time: 60) + }.to_not raise_error + end - it 'fails when not matched' do - output = { - data_map: { - 'key1' => 'abc', - 'key2' => 'def', - 'key3' => 'ghi', + it 'fails when not matched' do + output = { + string_property: 'match', + data_map: { + 'key1' => 'not a match', + 'key2' => 'not a match', + 'key3' => 'not a match', + } } - } - 2.times do - allow(client).to receive(:get_widget).and_return(output) + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:contains_field_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) end - expect { - client.wait_until(:projection_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) end - end - context 'contains field' do - it 'succeeds when matched' do - output = { - string_property: 'match', - data_map: { - 'key1' => 'not a match', - 'key2' => 'match', - 'key3' => 'not a match', + context 'and inequality' do + it 'succeeds when matched' do + output = { + string_array_property: [ + 'some string', + 'another string' + ], + data_map: { + 'key1' => 'one', + 'key2' => 'two', + 'key3' => 'three', + } } - } - expect(client).to receive(:get_widget).and_return(output) - expect { - client.wait_until(:contains_field_matcher, input, max_wait_time: 60) - }.to_not raise_error - end + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:and_inequality_matcher, input, max_wait_time: 60) + }.to_not raise_error + end - it 'fails when not matched' do - output = { - string_property: 'match', - data_map: { - 'key1' => 'not a match', - 'key2' => 'not a match', - 'key3' => 'not a match', + it 'fails when not matched' do + output = { + string_array_property: [ + 'some string', + 'another string', + 'yet another string' + ], + data_map: { + 'key1' => 'one', + 'key2' => 'two', + 'key3' => 'three', + } } - } - 2.times do - allow(client).to receive(:get_widget).and_return(output) + expect(client).to receive(:get_widget).and_return(output) + expect { + client.wait_until(:and_inequality_matcher, input, max_wait_time: 0) + }.to raise_error(max_wait_time_exceeded_error) end - expect { - client.wait_until(:contains_field_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) end end - context 'and inequality' do - it 'succeeds when matched' do - output = { - string_array_property: [ - 'some string', - 'another string' - ], - data_map: { - 'key1' => 'one', - 'key2' => 'two', - 'key3' => 'three', - } - } + describe 'input output matcher' do + it 'succeeds for boolean equals comparator' do + output = { string_property: 'input_string' } expect(client).to receive(:get_widget).and_return(output) expect { - client.wait_until(:and_inequality_matcher, input, max_wait_time: 60) + client.wait_until(:input_output_boolean_property_matcher, input, max_wait_time: 60) }.to_not raise_error end - - it 'fails when not matched' do - output = { - string_array_property: [ - 'some string', - 'another string', - 'yet another string' - ], - data_map: { - 'key1' => 'one', - 'key2' => 'two', - 'key3' => 'three', - } - } - 2.times do - allow(client).to receive(:get_widget).and_return(output) - end - expect { - client.wait_until(:and_inequality_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end end - end - describe 'input output matcher' do - it 'succeeds for boolean equals comparator' do - output = { string_property: 'input_string' } - expect(client).to receive(:get_widget).and_return(output) + it 'checks acceptors in order' do + expect(client).to receive(:delete_widget).and_raise(widget_does_not_exist_error) expect { - client.wait_until(:input_output_boolean_property_matcher, input, max_wait_time: 60) + client.wait_until(:acceptor_order_success_matcher, input, max_wait_time: 60) }.to_not raise_error - end - end - - it 'checks acceptors in order' do - expect(client).to receive(:delete_widget).and_raise(widget_does_not_exist_error) - expect { - client.wait_until(:acceptor_order_success_matcher, input, max_wait_time: 60) - }.to_not raise_error - - expect(client).to receive(:delete_widget).and_raise(widget_does_not_exist_error) - expect { - client.wait_until(:acceptor_order_failure_matcher, input, max_wait_time: 60) - }.to raise_error(failure_state_error) - end - it 'allows configuration of min and max delay' do - options = { - max_wait_time: 5, - min_delay: 3, - max_delay: 4 - } - output = {} - 2.times do - allow(client).to receive(:get_widget).and_return(output) - end - expect_any_instance_of(waiter).to receive(:delay).and_wrap_original do |m, *args| - delay = m.call(*args) - expect(delay).to equal(5) - delay - end - expect { - client.wait_until(:success_false_matcher, input, options) - }.to raise_error(max_wait_time_exceeded_error) - end - - it 'raises an error when max wait time is exceeded' do - output = {} - 5.times do - allow(client).to receive(:get_widget).and_return(output) + expect(client).to receive(:delete_widget).and_raise(widget_does_not_exist_error) + expect { + client.wait_until(:acceptor_order_failure_matcher, input, max_wait_time: 60) + }.to raise_error(failure_state_error) end - expect { - client.wait_until(:success_false_matcher, input, max_wait_time: 2) - }.to raise_error(max_wait_time_exceeded_error) - end - - it 'raises an error when max_wait_time is not provided' do - expect { - client.wait_until(:success_true_matcher, input) - }.to raise_error(ArgumentError, "expected `:max_wait_time` to be an integer, got: #{nil}") - end - - it 'raises an error when max_delay is less than 1' do - options = { - max_wait_time: 5, - max_delay: 0 - } - expect { - client.wait_until(:success_true_matcher, input, options) - }.to raise_error(ArgumentError, '`:max_delay` must be greater than 0') - end - - it 'raises an error when min_delay is less than 1' do - options = { - max_wait_time: 5, - min_delay: 0 - } - expect { - client.wait_until(:success_true_matcher, input, options) - }.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') - end - - it 'raises an error when max_delay is less than min_delay' do - options = { - max_wait_time: 5, - min_delay: 4, - max_delay: 2 - } - expect { - client.wait_until(:success_true_matcher, input, options) - }.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') end end end From 4b64c833fcf1698a274c5d3b14c31353b77bada7 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 5 May 2025 13:15:08 -0700 Subject: [PATCH 24/48] Remove weather changes --- .../lib/smithy-client/waiters/poller.rb | 3 - model/weather.smithy | 58 +--------- projections/weather/lib/weather/client.rb | 9 +- projections/weather/lib/weather/schema.rb | 5 +- projections/weather/lib/weather/types.rb | 1 - projections/weather/lib/weather/waiters.rb | 101 ------------------ projections/weather/sig/weather/client.rbs | 1 - projections/weather/sig/weather/types.rbs | 2 - 8 files changed, 5 insertions(+), 175 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index 88948486c..512b3ed84 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -27,9 +27,6 @@ def evaluate_acceptors(output, error) @acceptors.each do |acceptor| return acceptor['state'] if acceptor_matches?(acceptor['matcher'], output, error) end - - # If none of the acceptors match and an error was encountered, - # transition to failure state. Otherwise, transition to retry state. if error 'error' else diff --git a/model/weather.smithy b/model/weather.smithy index 972d0bf01..2634de1fb 100644 --- a/model/weather.smithy +++ b/model/weather.smithy @@ -1,7 +1,6 @@ $version: "2" namespace example.weather -use smithy.waiters#waitable /// Provides weather forecasts. @paginated(inputToken: "nextToken", outputToken: "nextToken", pageSize: "pageSize") @@ -27,7 +26,7 @@ resource City { resource Forecast { identifiers: { cityId: CityId } - properties: { chanceOfRain: Float, statusProperty: String } + properties: { chanceOfRain: Float } read: GetForecast } @@ -36,30 +35,6 @@ resource Forecast { string CityId @readonly -@waitable( - CityExists: { - documentation: "Waits until city exists" - acceptors: [ - { - state: "success" - matcher: { - success: true - } - } - ] - } - CityDeleted: { - documentation: "Waits until city is deleted" - acceptors: [ - { - state: "success" - matcher: { - errorType: "NoSuchResource" - } - } - ] - } -) operation GetCity { input := for City { // "cityId" provides the identifier for the resource and @@ -149,36 +124,6 @@ operation GetCurrentTime { } @readonly -@waitable( - ForecastExists: { - documentation: "Waits until forecast is created" - acceptors: [ - { - state: "failure" - matcher: { - output: { - path: "statusProperty" - comparator: "stringEquals" - expected: "failed" - } - } - } - { - state: "success" - matcher: { - output: { - path: "statusProperty" - comparator: "stringEquals" - expected: "success" - } - } - } - ] - minDelay: 5 - maxDelay: 20 - deprecated: true - } -) operation GetForecast { input := for Forecast { // "cityId" provides the only identifier for the resource since @@ -189,6 +134,5 @@ operation GetForecast { output := for Forecast { $chanceOfRain - statusProperty: String } } \ No newline at end of file diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index 472644eef..0575d8a09 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -196,8 +196,7 @@ def get_current_time(params = {}, options = {}) # @example Response structure with placeholder values # output.to_h #=> # { - # chance_of_rain: 1.0, - # status_property: "String" + # chance_of_rain: 1.0 # } def get_forecast(params = {}, options = {}) input = build_input(:get_forecast, params) @@ -258,11 +257,7 @@ def waiter(waiter_name, options = {}) end def waiters - { - city_deleted: Waiters::CityDeleted, - city_exists: Waiters::CityExists, - forecast_exists: Waiters::ForecastExists - } + {} end class << self diff --git a/projections/weather/lib/weather/schema.rb b/projections/weather/lib/weather/schema.rb index 878fb7817..78946b8c3 100644 --- a/projections/weather/lib/weather/schema.rb +++ b/projections/weather/lib/weather/schema.rb @@ -44,7 +44,6 @@ module Schema GetForecastInput.type = Types::GetForecastInput GetForecastOutput.add_member(:chance_of_rain, 'chanceOfRain', Prelude::Float) - GetForecastOutput.add_member(:status_property, 'statusProperty', Prelude::String) GetForecastOutput.type = Types::GetForecastOutput ListCitiesInput.add_member(:next_token, 'nextToken', Prelude::String) @@ -68,7 +67,7 @@ module Schema operation.name = "GetCity" operation.input = GetCityInput operation.output = GetCityOutput - operation.traits = {"smithy.api#readonly"=>{}, "smithy.waiters#waitable"=>{"CityExists"=>{"documentation"=>"Waits until city exists", "acceptors"=>[{"state"=>"success", "matcher"=>{"success"=>true}}]}, "CityDeleted"=>{"documentation"=>"Waits until city is deleted", "acceptors"=>[{"state"=>"success", "matcher"=>{"errorType"=>"NoSuchResource"}}]}}} + operation.traits = {"smithy.api#readonly"=>{}} operation.errors << NoSuchResource end) service.add_operation(:get_current_time, OperationShape.new do |operation| @@ -83,7 +82,7 @@ module Schema operation.name = "GetForecast" operation.input = GetForecastInput operation.output = GetForecastOutput - operation.traits = {"smithy.api#readonly"=>{}, "smithy.waiters#waitable"=>{"ForecastExists"=>{"documentation"=>"Waits until forecast is created", "acceptors"=>[{"state"=>"failure", "matcher"=>{"output"=>{"path"=>"statusProperty", "comparator"=>"stringEquals", "expected"=>"failed"}}}, {"state"=>"success", "matcher"=>{"output"=>{"path"=>"statusProperty", "comparator"=>"stringEquals", "expected"=>"success"}}}], "minDelay"=>5, "maxDelay"=>20, "deprecated"=>true}}} + operation.traits = {"smithy.api#readonly"=>{}} end) service.add_operation(:list_cities, OperationShape.new do |operation| operation.id = "example.weather#ListCities" diff --git a/projections/weather/lib/weather/types.rb b/projections/weather/lib/weather/types.rb index 8ee2246fe..e27fed177 100644 --- a/projections/weather/lib/weather/types.rb +++ b/projections/weather/lib/weather/types.rb @@ -53,7 +53,6 @@ module Types GetForecastOutput = Struct.new( :chance_of_rain, - :status_property, keyword_init: true ) do include Smithy::Schema::Structure diff --git a/projections/weather/lib/weather/waiters.rb b/projections/weather/lib/weather/waiters.rb index cb0d08af8..cdcccf0eb 100644 --- a/projections/weather/lib/weather/waiters.rb +++ b/projections/weather/lib/weather/waiters.rb @@ -8,106 +8,5 @@ module Weather # @api private module Waiters - # @api private - # - # Waits until city is deleted - # - class CityDeleted - def initialize(options = {}) - @client = options[:client] - @waiter = Smithy::Client::Waiters::Waiter.new( - max_wait_time: options[:max_wait_time], - min_delay: options[:min_delay] || 2, - max_delay: options[:max_delay] || 120, - poller: Smithy::Client::Waiters::Poller.new( - operation_name: :get_city, - acceptors: [{ - "state" => "success", - "matcher" => { - "errorType" => "NoSuchResource" - } - }] - ) - ) - end - - def wait(params = {}) - @waiter.wait(@client, params) - end - end - - # @api private - # - # Waits until city exists - # - class CityExists - def initialize(options = {}) - @client = options[:client] - @waiter = Smithy::Client::Waiters::Waiter.new( - max_wait_time: options[:max_wait_time], - min_delay: options[:min_delay] || 2, - max_delay: options[:max_delay] || 120, - poller: Smithy::Client::Waiters::Poller.new( - operation_name: :get_city, - acceptors: [{ - "state" => "success", - "matcher" => { - "success" => true - } - }] - ) - ) - end - - def wait(params = {}) - @waiter.wait(@client, params) - end - end - - # @deprecated - # @api private - # - # Waits until forecast is created - # - class ForecastExists - def initialize(options = {}) - @client = options[:client] - @waiter = Smithy::Client::Waiters::Waiter.new( - max_wait_time: options[:max_wait_time], - min_delay: options[:min_delay] || 5, - max_delay: options[:max_delay] || 20, - poller: Smithy::Client::Waiters::Poller.new( - operation_name: :get_forecast, - acceptors: [ - { - "state" => "failure", - "matcher" => { - "output" => { - "path" => "status_property", - "comparator" => "stringEquals", - "expected" => "failed" - } - } - }, - { - "state" => "success", - "matcher" => { - "output" => { - "path" => "status_property", - "comparator" => "stringEquals", - "expected" => "success" - } - } - } - ] - ) - ) - end - - def wait(params = {}) - @waiter.wait(@client, params) - end - end - end end \ No newline at end of file diff --git a/projections/weather/sig/weather/client.rbs b/projections/weather/sig/weather/client.rbs index 6d8dc8c09..0aedf65d6 100644 --- a/projections/weather/sig/weather/client.rbs +++ b/projections/weather/sig/weather/client.rbs @@ -52,7 +52,6 @@ module Weather interface _GetForecastResponse include Smithy::Client::_Output[Types::GetForecastOutput] def chance_of_rain: () -> Float? - def status_property: () -> String? end def get_forecast: ( ?city_id: String diff --git a/projections/weather/sig/weather/types.rbs b/projections/weather/sig/weather/types.rbs index 63e5f28df..6407a201c 100644 --- a/projections/weather/sig/weather/types.rbs +++ b/projections/weather/sig/weather/types.rbs @@ -78,12 +78,10 @@ module Weather def initialize: ( ?chance_of_rain: Float, - ?status_property: String, ) -> void | (?Hash[Symbol, untyped]) -> void attr_accessor chance_of_rain: Float? - attr_accessor status_property: String? end class ListCitiesInput From 6da8bfb48fa0df6f0e96afb89a43513fee426fb0 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 5 May 2025 13:22:22 -0700 Subject: [PATCH 25/48] Build projections with waiters --- projections/shapes/lib/shapes/schema.rb | 20 ++++---- projections/weather/lib/weather/schema.rb | 51 ++++++++++--------- .../spec/weather/endpoint_provider_spec.rb | 6 +-- .../weather/spec/weather/protocol_spec.rb | 1 + smithy-build.json | 2 +- 5 files changed, 41 insertions(+), 39 deletions(-) diff --git a/projections/shapes/lib/shapes/schema.rb b/projections/shapes/lib/shapes/schema.rb index 5a56236cb..3300249a6 100644 --- a/projections/shapes/lib/shapes/schema.rb +++ b/projections/shapes/lib/shapes/schema.rb @@ -28,11 +28,11 @@ module Schema Timestamp = TimestampShape.new(id: 'smithy.ruby.tests#Timestamp', traits: {"smithy.ruby.tests#shape"=>{}}) Union = UnionShape.new(id: 'smithy.ruby.tests#Union', traits: {"smithy.ruby.tests#shape"=>{}}) - Enum.add_member(:foo, ShapeRef.new(shape: Prelude::Unit, location_name: 'FOO', traits: {"smithy.api#enumValue" => "bar"})) - IntEnum.add_member(:baz, ShapeRef.new(shape: Prelude::Unit, location_name: 'BAZ', traits: {"smithy.api#enumValue" => 1})) - List.member = ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape" => {}}) - Map.key = ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape" => {}}) - Map.value = ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape" => {}}) + Enum.add_member(:foo, ShapeRef.new(shape: Prelude::Unit, location_name: 'FOO', traits: {"smithy.api#enumValue"=>"bar"})) + IntEnum.add_member(:baz, ShapeRef.new(shape: Prelude::Unit, location_name: 'BAZ', traits: {"smithy.api#enumValue"=>1})) + List.member = ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape"=>{}}) + Map.key = ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape"=>{}}) + Map.value = ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape"=>{}}) OperationInputOutput.add_member(:blob, ShapeRef.new(shape: Blob, location_name: 'blob')) OperationInputOutput.add_member(:boolean, ShapeRef.new(shape: Boolean, location_name: 'boolean')) OperationInputOutput.add_member(:string, ShapeRef.new(shape: String, location_name: 'string')) @@ -53,11 +53,11 @@ module Schema OperationInputOutput.add_member(:structure, ShapeRef.new(shape: Structure, location_name: 'structure')) OperationInputOutput.add_member(:union, ShapeRef.new(shape: Union, location_name: 'union')) OperationInputOutput.type = Types::OperationInputOutput - Structure.add_member(:member, ShapeRef.new(shape: String, location_name: 'member', traits: {"smithy.ruby.tests#shape" => {}})) + Structure.add_member(:member, ShapeRef.new(shape: String, location_name: 'member', traits: {"smithy.ruby.tests#shape"=>{}})) Structure.type = Types::Structure - Union.add_member(:string, Types::Union::String, ShapeRef.new(shape: String, location_name: 'string', traits: {"smithy.ruby.tests#shape" => {}})) - Union.add_member(:structure, Types::Union::Structure, ShapeRef.new(shape: Structure, location_name: 'structure', traits: {"smithy.ruby.tests#shape" => {}})) - Union.add_member(:unit, Types::Union::Unit, ShapeRef.new(shape: Prelude::Unit, location_name: 'unit', traits: {"smithy.ruby.tests#shape" => {}})) + Union.add_member(:string, Types::Union::String, ShapeRef.new(shape: String, location_name: 'string', traits: {"smithy.ruby.tests#shape"=>{}})) + Union.add_member(:structure, Types::Union::Structure, ShapeRef.new(shape: Structure, location_name: 'structure', traits: {"smithy.ruby.tests#shape"=>{}})) + Union.add_member(:unit, Types::Union::Unit, ShapeRef.new(shape: Prelude::Unit, location_name: 'unit', traits: {"smithy.ruby.tests#shape"=>{}})) Union.add_member(:unknown, Types::Union::Unknown, ShapeRef.new(shape: Prelude::Unit)) Union.type = Types::Union @@ -72,7 +72,7 @@ module Schema operation.input = ShapeRef.new(shape: OperationInputOutput) operation.output = ShapeRef.new(shape: OperationInputOutput) # TODO: support parsing errors defined at the service level - operation.traits = {"smithy.ruby.tests#shape" => {}} + operation.traits = {"smithy.ruby.tests#shape"=>{}} end) end end diff --git a/projections/weather/lib/weather/schema.rb b/projections/weather/lib/weather/schema.rb index 1ce8a9e34..ef6f32adb 100644 --- a/projections/weather/lib/weather/schema.rb +++ b/projections/weather/lib/weather/schema.rb @@ -8,33 +8,33 @@ module Schema include Smithy::Schema::Shapes CityCoordinates = StructureShape.new(id: 'example.weather#CityCoordinates') - CityId = StringShape.new(id: 'example.weather#CityId', traits: {"smithy.api#pattern" => "^[A-Za-z0-9 ]+$"}) + CityId = StringShape.new(id: 'example.weather#CityId', traits: {"smithy.api#pattern"=>"^[A-Za-z0-9 ]+$"}) CitySummaries = ListShape.new(id: 'example.weather#CitySummaries') - CitySummary = StructureShape.new(id: 'example.weather#CitySummary', traits: {"smithy.api#references" => [{"resource" => "example.weather#City"}]}) - GetCityInput = StructureShape.new(id: 'example.weather#GetCityInput', traits: {"smithy.api#input" => {}}) - GetCityOutput = StructureShape.new(id: 'example.weather#GetCityOutput', traits: {"smithy.api#output" => {}}) - GetCurrentTimeOutput = StructureShape.new(id: 'example.weather#GetCurrentTimeOutput', traits: {"smithy.api#output" => {}}) - GetForecastInput = StructureShape.new(id: 'example.weather#GetForecastInput', traits: {"smithy.api#input" => {}}) - GetForecastOutput = StructureShape.new(id: 'example.weather#GetForecastOutput', traits: {"smithy.api#output" => {}}) - ListCitiesInput = StructureShape.new(id: 'example.weather#ListCitiesInput', traits: {"smithy.api#input" => {}}) - ListCitiesOutput = StructureShape.new(id: 'example.weather#ListCitiesOutput', traits: {"smithy.api#output" => {}}) - NoSuchResource = StructureShape.new(id: 'example.weather#NoSuchResource', traits: {"smithy.api#error" => "client"}) + CitySummary = StructureShape.new(id: 'example.weather#CitySummary', traits: {"smithy.api#references"=>[{"resource"=>"example.weather#City"}]}) + GetCityInput = StructureShape.new(id: 'example.weather#GetCityInput', traits: {"smithy.api#input"=>{}}) + GetCityOutput = StructureShape.new(id: 'example.weather#GetCityOutput', traits: {"smithy.api#output"=>{}}) + GetCurrentTimeOutput = StructureShape.new(id: 'example.weather#GetCurrentTimeOutput', traits: {"smithy.api#output"=>{}}) + GetForecastInput = StructureShape.new(id: 'example.weather#GetForecastInput', traits: {"smithy.api#input"=>{}}) + GetForecastOutput = StructureShape.new(id: 'example.weather#GetForecastOutput', traits: {"smithy.api#output"=>{}}) + ListCitiesInput = StructureShape.new(id: 'example.weather#ListCitiesInput', traits: {"smithy.api#input"=>{}}) + ListCitiesOutput = StructureShape.new(id: 'example.weather#ListCitiesOutput', traits: {"smithy.api#output"=>{}}) + NoSuchResource = StructureShape.new(id: 'example.weather#NoSuchResource', traits: {"smithy.api#error"=>"client"}) - CityCoordinates.add_member(:latitude, ShapeRef.new(shape: Prelude::Float, location_name: 'latitude', traits: {"smithy.api#required" => {}})) - CityCoordinates.add_member(:longitude, ShapeRef.new(shape: Prelude::Float, location_name: 'longitude', traits: {"smithy.api#required" => {}})) + CityCoordinates.add_member(:latitude, ShapeRef.new(shape: Prelude::Float, location_name: 'latitude', traits: {"smithy.api#required"=>{}})) + CityCoordinates.add_member(:longitude, ShapeRef.new(shape: Prelude::Float, location_name: 'longitude', traits: {"smithy.api#required"=>{}})) CityCoordinates.type = Types::CityCoordinates CitySummaries.member = ShapeRef.new(shape: CitySummary) - CitySummary.add_member(:city_id, ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required" => {}})) - CitySummary.add_member(:name, ShapeRef.new(shape: Prelude::String, location_name: 'name', traits: {"smithy.api#required" => {}})) + CitySummary.add_member(:city_id, ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required"=>{}})) + CitySummary.add_member(:name, ShapeRef.new(shape: Prelude::String, location_name: 'name', traits: {"smithy.api#required"=>{}})) CitySummary.type = Types::CitySummary - GetCityInput.add_member(:city_id, ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required" => {}})) + GetCityInput.add_member(:city_id, ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required"=>{}})) GetCityInput.type = Types::GetCityInput - GetCityOutput.add_member(:name, ShapeRef.new(shape: Prelude::String, location_name: 'name', traits: {"smithy.api#notProperty" => {}, "smithy.api#required" => {}})) - GetCityOutput.add_member(:coordinates, ShapeRef.new(shape: CityCoordinates, location_name: 'coordinates', traits: {"smithy.api#required" => {}})) + GetCityOutput.add_member(:name, ShapeRef.new(shape: Prelude::String, location_name: 'name', traits: {"smithy.api#notProperty"=>{}, "smithy.api#required"=>{}})) + GetCityOutput.add_member(:coordinates, ShapeRef.new(shape: CityCoordinates, location_name: 'coordinates', traits: {"smithy.api#required"=>{}})) GetCityOutput.type = Types::GetCityOutput - GetCurrentTimeOutput.add_member(:time, ShapeRef.new(shape: Prelude::Timestamp, location_name: 'time', traits: {"smithy.api#required" => {}})) + GetCurrentTimeOutput.add_member(:time, ShapeRef.new(shape: Prelude::Timestamp, location_name: 'time', traits: {"smithy.api#required"=>{}})) GetCurrentTimeOutput.type = Types::GetCurrentTimeOutput - GetForecastInput.add_member(:city_id, ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required" => {}})) + GetForecastInput.add_member(:city_id, ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required"=>{}})) GetForecastInput.type = Types::GetForecastInput GetForecastOutput.add_member(:chance_of_rain, ShapeRef.new(shape: Prelude::Float, location_name: 'chanceOfRain')) GetForecastOutput.type = Types::GetForecastOutput @@ -42,9 +42,9 @@ module Schema ListCitiesInput.add_member(:page_size, ShapeRef.new(shape: Prelude::Integer, location_name: 'pageSize')) ListCitiesInput.type = Types::ListCitiesInput ListCitiesOutput.add_member(:next_token, ShapeRef.new(shape: Prelude::String, location_name: 'nextToken')) - ListCitiesOutput.add_member(:items, ShapeRef.new(shape: CitySummaries, location_name: 'items', traits: {"smithy.api#required" => {}})) + ListCitiesOutput.add_member(:items, ShapeRef.new(shape: CitySummaries, location_name: 'items', traits: {"smithy.api#required"=>{}})) ListCitiesOutput.type = Types::ListCitiesOutput - NoSuchResource.add_member(:resource_type, ShapeRef.new(shape: Prelude::String, location_name: 'resourceType', traits: {"smithy.api#required" => {}})) + NoSuchResource.add_member(:resource_type, ShapeRef.new(shape: Prelude::String, location_name: 'resourceType', traits: {"smithy.api#required"=>{}})) NoSuchResource.type = Types::NoSuchResource SERVICE = ServiceShape.new do |service| @@ -59,7 +59,7 @@ module Schema operation.output = ShapeRef.new(shape: GetCityOutput) # TODO: support parsing errors defined at the service level operation.errors << ShapeRef.new(shape: NoSuchResource) - operation.traits = {"smithy.api#readonly" => {}} + operation.traits = {"smithy.api#readonly"=>{}} end) service.add_operation(:get_current_time, OperationShape.new do |operation| operation.id = "example.weather#GetCurrentTime" @@ -67,7 +67,7 @@ module Schema operation.input = ShapeRef.new(shape: Prelude::Unit) operation.output = ShapeRef.new(shape: GetCurrentTimeOutput) # TODO: support parsing errors defined at the service level - operation.traits = {"smithy.api#readonly" => {}} + operation.traits = {"smithy.api#readonly"=>{}} end) service.add_operation(:get_forecast, OperationShape.new do |operation| operation.id = "example.weather#GetForecast" @@ -75,7 +75,7 @@ module Schema operation.input = ShapeRef.new(shape: GetForecastInput) operation.output = ShapeRef.new(shape: GetForecastOutput) # TODO: support parsing errors defined at the service level - operation.traits = {"smithy.api#readonly" => {}} + operation.traits = {"smithy.api#readonly"=>{}} end) service.add_operation(:list_cities, OperationShape.new do |operation| operation.id = "example.weather#ListCities" @@ -83,7 +83,8 @@ module Schema operation.input = ShapeRef.new(shape: ListCitiesInput) operation.output = ShapeRef.new(shape: ListCitiesOutput) # TODO: support parsing errors defined at the service level - operation.traits = {"smithy.api#readonly" => {}} + operation.traits = {"smithy.api#readonly"=>{}} + operation[:paginator] = Paginators::ListCities.new end) end end diff --git a/projections/weather/spec/weather/endpoint_provider_spec.rb b/projections/weather/spec/weather/endpoint_provider_spec.rb index 226652f4c..5b7901ebd 100644 --- a/projections/weather/spec/weather/endpoint_provider_spec.rb +++ b/projections/weather/spec/weather/endpoint_provider_spec.rb @@ -10,11 +10,11 @@ module Weather context "Endpoint set" do let(:expected) do - {"endpoint" => {"url" => "https://example.com"}} + {"endpoint"=>{"url"=>"https://example.com"}} end it 'produces the expected output from the EndpointProvider' do - params = EndpointParameters.new(**{endpoint: "https://example.com"}) + params = EndpointParameters.new(**{:endpoint=>"https://example.com"}) endpoint = subject.resolve(params) expect(endpoint.uri).to eq(expected['endpoint']['url']) expect(endpoint.headers).to eq(expected['endpoint']['headers'] || {}) @@ -25,7 +25,7 @@ module Weather context "Endpoint not set" do let(:expected) do - {"error" => "Endpoint is not set - you must configure an endpoint."} + {"error"=>"Endpoint is not set - you must configure an endpoint."} end it 'produces the expected output from the EndpointProvider' do diff --git a/projections/weather/spec/weather/protocol_spec.rb b/projections/weather/spec/weather/protocol_spec.rb index cc80e1e2d..2fa45de7f 100644 --- a/projections/weather/spec/weather/protocol_spec.rb +++ b/projections/weather/spec/weather/protocol_spec.rb @@ -7,5 +7,6 @@ module Weather describe Client do let(:client_options) { { stub_responses: true } } let(:client) { Client.new(client_options) } + end end diff --git a/smithy-build.json b/smithy-build.json index 8005bbb5a..cbfbe5d22 100644 --- a/smithy-build.json +++ b/smithy-build.json @@ -1,5 +1,5 @@ { - "version": "1.0",t pu + "version": "1.0", "projections": { "weather": { "plugins": { From b788ecdc636b5f2098b6b101a290c4686ff78aa8 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 6 May 2025 14:09:32 -0700 Subject: [PATCH 26/48] Rubocop and changes from PR comments --- .../lib/smithy-client/waiters.rb | 2 +- .../lib/smithy-client/waiters/errors.rb | 21 +- .../lib/smithy-client/waiters/poller.rb | 49 +- .../lib/smithy-client/waiters/waiter.rb | 45 +- .../spec/smithy-client/waiters_spec.rb | 1177 ++++++++--------- .../lib/smithy/templates/client/client.erb | 4 - gems/smithy/lib/smithy/views/client/client.rb | 8 +- .../smithy/lib/smithy/views/client/waiters.rb | 14 +- .../model.json | 2 +- .../model.smithy | 2 +- .../smithy-build.json | 0 .../spec/interfaces/client/waiters_spec.rb | 23 +- 12 files changed, 669 insertions(+), 678 deletions(-) rename gems/smithy/spec/fixtures/{wait_service => waiter_service}/model.json (99%) rename gems/smithy/spec/fixtures/{wait_service => waiter_service}/model.smithy (98%) rename gems/smithy/spec/fixtures/{wait_service => waiter_service}/smithy-build.json (100%) diff --git a/gems/smithy-client/lib/smithy-client/waiters.rb b/gems/smithy-client/lib/smithy-client/waiters.rb index fec16853d..0ea0c7dab 100644 --- a/gems/smithy-client/lib/smithy-client/waiters.rb +++ b/gems/smithy-client/lib/smithy-client/waiters.rb @@ -2,4 +2,4 @@ require_relative 'waiters/errors' require_relative 'waiters/poller' -require_relative 'waiters/waiter' \ No newline at end of file +require_relative 'waiters/waiter' diff --git a/gems/smithy-client/lib/smithy-client/waiters/errors.rb b/gems/smithy-client/lib/smithy-client/waiters/errors.rb index cb8c12c8c..bd5b887b3 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/errors.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/errors.rb @@ -4,29 +4,32 @@ module Smithy module Client module Waiters module Errors - # Raised when a waiter detects a condition where the waiter can never # succeed. class WaiterFailed < StandardError; end + # Raised when a waiter enters a failure state. class FailureStateError < WaiterFailed def initialize(error) - msg = "stopped waiting, encountered a failure state: %s" - super(msg % [error]) + msg = "stopped waiting, encountered a failure state: #{error}" + super(msg) end end + # Raised when the total wait time of a waiter exceeds the maximum + # wait time. class MaxWaitTimeExceededError < WaiterFailed def initialize(max_wait_time) - msg = "stopped waiting after maximum wait time of %s seconds was exceeded" - super(msg % [max_wait_time]) + msg = "stopped waiting after maximum wait time of #{max_wait_time} seconds was exceeded" + super(msg) end end + # Raised when a waiter encounters an unexpected error. class UnexpectedError < WaiterFailed def initialize(error) - msg = "stopped waiting due to an unexpected error: %s" - super(msg % [error]) + msg = "stopped waiting due to an unexpected error: #{error}" + super(msg) end end @@ -34,8 +37,8 @@ def initialize(error) # been defined. class NoSuchWaiterError < ArgumentError def initialize(waiter_name, valid_waiters) - msg = "no such waiter: %s; valid waiter names are: %s" - super(msg % [waiter_name, valid_waiters]) + msg = "no such waiter: #{waiter_name}; valid waiter names are: #{valid_waiters}" + super(msg) end end end diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index 512b3ed84..b1415bd16 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -3,6 +3,8 @@ module Smithy module Client module Waiters + # Abstract poller class which polls a single API operation and inspects + # the output and/or error for states matching one of its acceptors. class Poller def initialize(options = {}) @operation_name = options[:operation_name] @@ -18,7 +20,7 @@ def call(client, params) end output_or_error = output || error status = evaluate_acceptors(output, error) - [output_or_error, status] + [output_or_error, status.to_sym] end private @@ -35,7 +37,7 @@ def evaluate_acceptors(output, error) end def acceptor_matches?(matcher, output, error) - matcher_type = matcher.keys[0] + matcher_type = matcher.keys.first send("matches_#{matcher_type}?", matcher[matcher_type], output, error) end @@ -43,10 +45,10 @@ def matches_output?(path_matcher, output, error) return false unless error.nil? actual = JMESPath.search(path_matcher['path'], output) - is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) + equal?(actual, path_matcher['expected'], path_matcher['comparator']) end - def matches_inputOutput?(path_matcher, output, error) + def matches_inputOutput?(path_matcher, output, error) # rubocop:disable Naming/MethodName return false unless error.nil? && @input data = { @@ -54,7 +56,7 @@ def matches_inputOutput?(path_matcher, output, error) output: output } actual = JMESPath.search(path_matcher['path'], data) - is_equal?(actual, path_matcher['expected'], path_matcher['comparator']) + equal?(actual, path_matcher['expected'], path_matcher['comparator']) end def matches_success?(path_matcher, output, error) @@ -65,30 +67,37 @@ def matches_success?(path_matcher, output, error) end end - def matches_errorType?(path_matcher, output, error) + def matches_errorType?(path_matcher, output, error) # rubocop:disable Naming/MethodName return false unless output.nil? err = path_matcher.split('#').last.split('#').first error.class.to_s.include?(err) end - def is_equal?(actual, expected, comparator) - case comparator - when 'stringEquals' - return actual == expected - when 'booleanEquals' - return actual.to_s == expected - when 'allStringEquals' - return false if actual.nil? || actual.empty? + def equal?(actual, expected, comparator) + send("#{comparator}?", actual, expected) + end - actual.all? { |value| value == expected } - when 'anyStringEquals' - return false if actual.nil? || actual.empty? + def stringEquals?(actual, expected) # rubocop:disable Naming/MethodName + actual == expected + end - actual.any? { |value| value == expected } - end + def booleanEquals?(actual, expected) # rubocop:disable Naming/MethodName + actual.to_s == expected + end + + def allStringEquals?(actual, expected) # rubocop:disable Naming/MethodName + return false if actual.nil? || actual.empty? + + actual.all? { |value| value == expected } + end + + def anyStringEquals?(actual, expected) # rubocop:disable Naming/MethodName + return false if actual.nil? || actual.empty? + + actual.any? { |value| value == expected } end end end end -end \ No newline at end of file +end diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index 952b8f2ba..692b3214e 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -3,13 +3,11 @@ module Smithy module Client module Waiters + # Abstract waiter class which waits for a resource to reach a desired + # state. class Waiter def initialize(options = {}) - unless options[:max_wait_time].is_a?(Integer) - raise ArgumentError, "expected `:max_wait_time` to be an integer, got: #{options[:max_wait_time]}" - end - - @max_wait_time = options[:max_wait_time] + @max_wait_time = max_wait_time(options[:max_wait_time]) @remaining_time = @max_wait_time @max_delay = max_delay(options[:max_delay]) @min_delay = min_delay(options[:min_delay]) @@ -22,10 +20,17 @@ def wait(client, params) private - def max_delay(delay) - if delay < 1 - raise ArgumentError, '`:max_delay` must be greater than 0' + def max_wait_time(time) + unless time.is_a?(Integer) + raise ArgumentError, "expected `:max_wait_time` to be an integer, got: #{time}" end + + time + end + + def max_delay(delay) + raise ArgumentError, '`:max_delay` must be greater than 0' if delay < 1 + delay end @@ -33,6 +38,7 @@ def min_delay(delay) if delay < 1 || delay > @max_delay raise ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`' end + delay end @@ -42,24 +48,23 @@ def poll(client, params) output_or_error, status = @poller.call(client, params) attempts += 1 - case status.to_sym - when :retry + case status when :success then return output_or_error - when :failure then raise Errors::FailureStateError.new(output_or_error) - when :error then raise Errors::UnexpectedError.new(output_or_error) - end - - raise Errors::MaxWaitTimeExceededError.new(@max_wait_time) if @remaining_time == 0 + when :failure then raise Errors::FailureStateError, output_or_error + when :error then raise Errors::UnexpectedError, output_or_error + when :retry + raise Errors::MaxWaitTimeExceededError, @max_wait_time if @remaining_time.zero? - delay = delay(attempts) - @remaining_time -= delay - sleep(delay) + delay = delay(attempts) + @remaining_time -= delay + sleep(delay) + end end end def delay(attempts) attempt_ceiling = (Math.log(@max_delay / @min_delay) / Math.log(2)) + 1 - delay = attempts > attempt_ceiling ? @max_delay : @min_delay * 2 ** (attempts - 1) + delay = attempts > attempt_ceiling ? @max_delay : @min_delay * (2**(attempts - 1)) delay = rand(@min_delay..delay) delay = @remaining_time if @remaining_time - delay <= @min_delay delay @@ -67,4 +72,4 @@ def delay(attempts) end end end -end \ No newline at end of file +end diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index 70b22c5ed..734e18952 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -6,407 +6,387 @@ module Smithy module Client module Waiters describe Waiters do + # rubocop:disable Layout/LineLength let(:shapes) do { - "smithy.ruby.tests#BooleanArray" => { - "type" => "list", - "member" => { - "target" => "smithy.api#Boolean" + 'smithy.ruby.tests#BooleanArray' => { + 'type' => 'list', + 'member' => { + 'target' => 'smithy.api#Boolean' } }, - "smithy.ruby.tests#Child" => { - "type" => "structure", - "members" => { - "grandchildren" => { - "target" => "smithy.ruby.tests#GrandchildArray" + 'smithy.ruby.tests#Child' => { + 'type' => 'structure', + 'members' => { + 'grandchildren' => { + 'target' => 'smithy.ruby.tests#GrandchildArray' } } }, - "smithy.ruby.tests#ChildArray" => { - "type" => "list", - "member" => { - "target" => "smithy.ruby.tests#Child" + 'smithy.ruby.tests#ChildArray' => { + 'type' => 'list', + 'member' => { + 'target' => 'smithy.ruby.tests#Child' } }, - "smithy.ruby.tests#DataMap" => { - "type" => "map", - "key" => { - "target" => "smithy.api#String" + 'smithy.ruby.tests#DataMap' => { + 'type' => 'map', + 'key' => { + 'target' => 'smithy.api#String' }, - "value" => { - "target" => "smithy.api#String" + 'value' => { + 'target' => 'smithy.api#String' } }, - "smithy.ruby.tests#DeleteWidget" => { - "type" => "operation", - "input" => { - "target" => "smithy.ruby.tests#WidgetInput" + 'smithy.ruby.tests#DeleteWidget' => { + 'type' => 'operation', + 'input' => { + 'target' => 'smithy.ruby.tests#WidgetInput' }, - "output" => { - "target" => "smithy.ruby.tests#DeletedWidgetOutput" + 'output' => { + 'target' => 'smithy.ruby.tests#DeletedWidgetOutput' }, - "errors" => [ + 'errors' => [ { - "target" => "smithy.ruby.tests#MyError" + 'target' => 'smithy.ruby.tests#MyError' }, { - "target" => "smithy.ruby.tests#WidgetDoesNotExistError" + 'target' => 'smithy.ruby.tests#WidgetDoesNotExistError' } ], - "traits" => { - "smithy.api#http" => { - "uri" => "/delete-widget", - "method" => "POST" + 'traits' => { + 'smithy.api#http' => { + 'uri' => '/delete-widget', + 'method' => 'POST' }, - "smithy.waiters#waitable" => { - "AcceptorOrderSuccessMatcher" => { - "documentation" => "Matcher with multiple acceptors", - "acceptors" => [ + 'smithy.waiters#waitable' => { + 'AcceptorOrderSuccessMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "errorType" => "WidgetDoesNotExistError" + 'state' => 'success', + 'matcher' => { + 'errorType' => 'WidgetDoesNotExistError' } }, { - "state" => "failure", - "matcher" => { - "errorType" => "WidgetDoesNotExistError" + 'state' => 'failure', + 'matcher' => { + 'errorType' => 'WidgetDoesNotExistError' } } ] }, - "AcceptorOrderFailureMatcher" => { - "documentation" => "Matcher with multiple acceptors", - "acceptors" => [ + 'AcceptorOrderFailureMatcher' => { + 'acceptors' => [ { - "state" => "failure", - "matcher" => { - "errorType" => "WidgetDoesNotExistError" + 'state' => 'failure', + 'matcher' => { + 'errorType' => 'WidgetDoesNotExistError' } }, { - "state" => "success", - "matcher" => { - "errorType" => "WidgetDoesNotExistError" + 'state' => 'success', + 'matcher' => { + 'errorType' => 'WidgetDoesNotExistError' } } ] }, - "FullyConfiguredMatcher" => { - "documentation" => "Fully configured waiter", - "acceptors" => [ + 'FullyConfiguredMatcher' => { + 'acceptors' => [ { - "state" => "retry", - "matcher" => { - "errorType" => "WidgetDoesNotExistError" + 'state' => 'retry', + 'matcher' => { + 'errorType' => 'WidgetDoesNotExistError' } }, { - "state" => "failure", - "matcher" => { - "output" => { - "path" => "stringProperty", - "expected" => "fail", - "comparator" => "stringEquals" + 'state' => 'failure', + 'matcher' => { + 'output' => { + 'path' => 'stringProperty', + 'expected' => 'fail', + 'comparator' => 'stringEquals' } } }, { - "state" => "success", - "matcher" => { - "success" => true + 'state' => 'success', + 'matcher' => { + 'success' => true } } ], - "minDelay" => 5, - "maxDelay" => 20, - "deprecated" => true, - "tags" => %w[some tags] + 'minDelay' => 5, + 'maxDelay' => 20, + 'deprecated' => true, + 'tags' => %w[some tags] } } } }, - "smithy.ruby.tests#DeletedWidgetOutput" => { - "type" => "structure", - "members" => { - "stringProperty" => { - "target" => "smithy.api#String" + 'smithy.ruby.tests#DeletedWidgetOutput' => { + 'type' => 'structure', + 'members' => { + 'stringProperty' => { + 'target' => 'smithy.api#String' } } }, - "smithy.ruby.tests#GetWidget" => { - "type" => "operation", - "input" => { - "target" => "smithy.ruby.tests#WidgetInput" + 'smithy.ruby.tests#GetWidget' => { + 'type' => 'operation', + 'input' => { + 'target' => 'smithy.ruby.tests#WidgetInput' }, - "output" => { - "target" => "smithy.ruby.tests#WidgetOutput" + 'output' => { + 'target' => 'smithy.ruby.tests#WidgetOutput' }, - "errors" => [ + 'errors' => [ { - "target" => "smithy.ruby.tests#MyError" + 'target' => 'smithy.ruby.tests#MyError' } ], - "traits" => { - "smithy.api#http" => { - "uri" => "/widget", - "method" => "POST" + 'traits' => { + 'smithy.api#http' => { + 'uri' => '/widget', + 'method' => 'POST' }, - "smithy.waiters#waitable" => { - "SuccessTrueMatcher" => { - "documentation" => "Acceptor matches on successful request", - "acceptors" => [ + 'smithy.waiters#waitable' => { + 'SuccessTrueMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "success" => true + 'state' => 'success', + 'matcher' => { + 'success' => true } } ] }, - "SuccessFalseMatcher" => { - "documentation" => "Acceptor matches on unsuccessful request", - "acceptors" => [ + 'SuccessFalseMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "success" => false + 'state' => 'success', + 'matcher' => { + 'success' => false } } ] }, - "ErrorTypeMatcher" => { - "documentation" => "Acceptor matches on receipt of specified error", - "acceptors" => [ + 'ErrorTypeMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "errorType" => "MyError" + 'state' => 'success', + 'matcher' => { + 'errorType' => 'MyError' } } ] }, - "OutputStringPropertyMatcher" => { - "documentation" => "Acceptor matches on output payload property", - "acceptors" => [ + 'OutputStringPropertyMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "output" => { - "path" => "stringProperty", - "expected" => "expected string", - "comparator" => "stringEquals" + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'stringProperty', + 'expected' => 'expected string', + 'comparator' => 'stringEquals' } } } ] }, - "OutputBooleanPropertyMatcher" => { - "documentation" => "Acceptor matches on output payload property", - "acceptors" => [ + 'OutputBooleanPropertyMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "output" => { - "path" => "booleanProperty", - "expected" => "false", - "comparator" => "booleanEquals" + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'booleanProperty', + 'expected' => 'false', + 'comparator' => 'booleanEquals' } } } ] }, - "OutputStringArrayAllPropertyMatcher" => { - "documentation" => "Acceptor matches on output payload property", - "acceptors" => [ + 'OutputStringArrayAllPropertyMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "output" => { - "path" => "stringArrayProperty", - "expected" => "expected string", - "comparator" => "allStringEquals" + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'stringArrayProperty', + 'expected' => 'expected string', + 'comparator' => 'allStringEquals' } } } ] }, - "OutputStringArrayAnyPropertyMatcher" => { - "documentation" => "Acceptor matches on output payload property", - "acceptors" => [ + 'OutputStringArrayAnyPropertyMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "output" => { - "path" => "stringArrayProperty", - "expected" => "expected string", - "comparator" => "anyStringEquals" + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'stringArrayProperty', + 'expected' => 'expected string', + 'comparator' => 'anyStringEquals' } } } ] }, - "InputOutputStringPropertyMatcher" => { - "documentation" => "Acceptor matches on string property of input and output", - "acceptors" => [ + 'InputOutputStringPropertyMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "inputOutput" => { - "path" => "input.stringProperty", - "expected" => "output.stringProperty", - "comparator" => "stringEquals" + 'state' => 'success', + 'matcher' => { + 'inputOutput' => { + 'path' => 'input.stringProperty', + 'expected' => 'output.stringProperty', + 'comparator' => 'stringEquals' } } } ] }, - "InputOutputBooleanPropertyMatcher" => { - "documentation" => "Acceptor matches on input property equaling output property", - "acceptors" => [ + 'InputOutputBooleanPropertyMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "inputOutput" => { - "path" => "input.stringProperty == output.stringProperty", - "expected" => "true", - "comparator" => "booleanEquals" + 'state' => 'success', + 'matcher' => { + 'inputOutput' => { + 'path' => 'input.stringProperty == output.stringProperty', + 'expected' => 'true', + 'comparator' => 'booleanEquals' } } } ] }, - "InputOutputStringArrayAllPropertyMatcher" => { - "documentation" => "Acceptor matches on string array property of input and output", - "acceptors" => [ + 'InputOutputStringArrayAllPropertyMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "inputOutput" => { - "path" => "input.stringArrayProperty", - "expected" => "output.stringArrayProperty", - "comparator" => "allStringEquals" + 'state' => 'success', + 'matcher' => { + 'inputOutput' => { + 'path' => 'input.stringArrayProperty', + 'expected' => 'output.stringArrayProperty', + 'comparator' => 'allStringEquals' } } } ] }, - "InputOutputStringArrayAnyPropertyMatcher" => { - "documentation" => "Acceptor matches on string array property of input and output", - "acceptors" => [ + 'InputOutputStringArrayAnyPropertyMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "inputOutput" => { - "path" => "input.stringArrayProperty", - "expected" => "output.stringArrayProperty", - "comparator" => "anyStringEquals" + 'state' => 'success', + 'matcher' => { + 'inputOutput' => { + 'path' => 'input.stringArrayProperty', + 'expected' => 'output.stringArrayProperty', + 'comparator' => 'anyStringEquals' } } } ] }, - "FlattenMatcher" => { - "documentation" => "Matches when any grandchild has name 'expected name'", - "acceptors" => [ + 'FlattenMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "output" => { - "path" => "children[].grandchildren[].name", - "expected" => "expected name", - "comparator" => "anyStringEquals" + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'children[].grandchildren[].name', + 'expected' => 'expected name', + 'comparator' => 'anyStringEquals' } } } ] }, - "FlattenLengthMatcher" => { - "documentation" => "Matches when there are 6 grandchildren total", - "acceptors" => [ + 'FlattenLengthMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "output" => { - "path" => "length(children[].grandchildren[]) == `6`", - "expected" => "true", - "comparator" => "booleanEquals" + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'length(children[].grandchildren[]) == `6`', + 'expected' => 'true', + 'comparator' => 'booleanEquals' } } } ] }, - "FlattenFilterMatcher" => { - "documentation" => "Matches when exactly one child has 3 grandchildren", - "acceptors" => [ + 'FlattenFilterMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "output" => { - "path" => "length(children[?length(grandchildren) == `3`]) == `1`", - "expected" => "true", - "comparator" => "booleanEquals" + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'length(children[?length(grandchildren) == `3`]) == `1`', + 'expected' => 'true', + 'comparator' => 'booleanEquals' } } } ] }, - "LengthFlattenFilterMatcher" => { - "documentation" => "Matches when exactly 3 grandchildren have numbers above 4", - "acceptors" => [ + 'LengthFlattenFilterMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "output" => { - "path" => "length((children[].grandchildren[])[?number > `4`]) == `3`", - "expected" => "true", - "comparator" => "booleanEquals" + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'length((children[].grandchildren[])[?number > `4`]) == `3`', + 'expected' => 'true', + 'comparator' => 'booleanEquals' } } } ] }, - "ProjectionMatcher" => { - "documentation" => "Matches when dataMap values are all `abc`", - "acceptors" => [ + 'ProjectionMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "output" => { - "path" => "dataMap.*", - "expected" => "abc", - "comparator" => "allStringEquals" + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'dataMap.*', + 'expected' => 'abc', + 'comparator' => 'allStringEquals' } } } ] }, - "ContainsFieldMatcher" => { - "documentation" => "Matches when any value of dataMap is the same as stringProperty", - "acceptors" => [ + 'ContainsFieldMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "output" => { - "path" => "contains(dataMap.*, stringProperty)", - "expected" => "true", - "comparator" => "booleanEquals" + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'contains(dataMap.*, stringProperty)', + 'expected' => 'true', + 'comparator' => 'booleanEquals' } } } ] }, - "AndInequalityMatcher" => { - "documentation" => "Matches when there are three elements in dataMap but not three in stringArrayProperty", - "acceptors" => [ + 'AndInequalityMatcher' => { + 'acceptors' => [ { - "state" => "success", - "matcher" => { - "output" => { - "path" => "length(dataMap) == `3` && length(stringArrayProperty) != `3`", - "expected" => "true", - "comparator" => "booleanEquals" + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'length(dataMap) == `3` && length(stringArrayProperty) != `3`', + 'expected' => 'true', + 'comparator' => 'booleanEquals' } } } @@ -415,374 +395,375 @@ module Waiters } } }, - "smithy.ruby.tests#Grandchild" => { - "type" => "structure", - "members" => { - "name" => { - "target" => "smithy.api#String" + 'smithy.ruby.tests#Grandchild' => { + 'type' => 'structure', + 'members' => { + 'name' => { + 'target' => 'smithy.api#String' }, - "number" => { - "target" => "smithy.api#Integer" + 'number' => { + 'target' => 'smithy.api#Integer' } } }, - "smithy.ruby.tests#GrandchildArray" => { - "type" => "list", - "member" => { - "target" => "smithy.ruby.tests#Grandchild" + 'smithy.ruby.tests#GrandchildArray' => { + 'type' => 'list', + 'member' => { + 'target' => 'smithy.ruby.tests#Grandchild' } }, - "smithy.ruby.tests#MyError" => { - "type" => "structure", - "members" => { - "message" => { - "target" => "smithy.api#String" + 'smithy.ruby.tests#MyError' => { + 'type' => 'structure', + 'members' => { + 'message' => { + 'target' => 'smithy.api#String' } }, - "traits" => { - "smithy.api#error" => "client" + 'traits' => { + 'smithy.api#error' => 'client' } }, - "smithy.ruby.tests#StringArray" => { - "type" => "list", - "member" => { - "target" => "smithy.api#String" + 'smithy.ruby.tests#StringArray' => { + 'type' => 'list', + 'member' => { + 'target' => 'smithy.api#String' } }, - "smithy.ruby.tests#WaitService" => { - "type" => "service", - "version" => "2022-11-30", - "operations" => [ + 'smithy.ruby.tests#WaitService' => { + 'type' => 'service', + 'version' => '2022-11-30', + 'operations' => [ { - "target" => "smithy.ruby.tests#DeleteWidget" + 'target' => 'smithy.ruby.tests#DeleteWidget' }, { - "target" => "smithy.ruby.tests#GetWidget" + 'target' => 'smithy.ruby.tests#GetWidget' } ] }, - "smithy.ruby.tests#WidgetDoesNotExistError" => { - "type" => "structure", - "members" => { - "message" => { - "target" => "smithy.api#String" + 'smithy.ruby.tests#WidgetDoesNotExistError' => { + 'type' => 'structure', + 'members' => { + 'message' => { + 'target' => 'smithy.api#String' } }, - "traits" => { - "smithy.api#error" => "client" + 'traits' => { + 'smithy.api#error' => 'client' } }, - "smithy.ruby.tests#WidgetInput" => { - "type" => "structure", - "members" => { - "stringProperty" => { - "target" => "smithy.api#String" + 'smithy.ruby.tests#WidgetInput' => { + 'type' => 'structure', + 'members' => { + 'stringProperty' => { + 'target' => 'smithy.api#String' }, - "stringArrayProperty" => { - "target" => "smithy.ruby.tests#StringArray" + 'stringArrayProperty' => { + 'target' => 'smithy.ruby.tests#StringArray' }, - "booleanProperty" => { - "target" => "smithy.api#Boolean" + 'booleanProperty' => { + 'target' => 'smithy.api#Boolean' }, - "booleanArrayProperty" => { - "target" => "smithy.ruby.tests#BooleanArray" + 'booleanArrayProperty' => { + 'target' => 'smithy.ruby.tests#BooleanArray' }, - "children" => { - "target" => "smithy.ruby.tests#ChildArray" + 'children' => { + 'target' => 'smithy.ruby.tests#ChildArray' }, - "dataMap" => { - "target" => "smithy.ruby.tests#DataMap" + 'dataMap' => { + 'target' => 'smithy.ruby.tests#DataMap' } } }, - "smithy.ruby.tests#WidgetOutput" => { - "type" => "structure", - "members" => { - "stringProperty" => { - "target" => "smithy.api#String" + 'smithy.ruby.tests#WidgetOutput' => { + 'type' => 'structure', + 'members' => { + 'stringProperty' => { + 'target' => 'smithy.api#String' }, - "stringArrayProperty" => { - "target" => "smithy.ruby.tests#StringArray" + 'stringArrayProperty' => { + 'target' => 'smithy.ruby.tests#StringArray' }, - "booleanProperty" => { - "target" => "smithy.api#Boolean" + 'booleanProperty' => { + 'target' => 'smithy.api#Boolean' }, - "booleanArrayProperty" => { - "target" => "smithy.ruby.tests#BooleanArray" + 'booleanArrayProperty' => { + 'target' => 'smithy.ruby.tests#BooleanArray' }, - "children" => { - "target" => "smithy.ruby.tests#ChildArray" + 'children' => { + 'target' => 'smithy.ruby.tests#ChildArray' }, - "dataMap" => { - "target" => "smithy.ruby.tests#DataMap" + 'dataMap' => { + 'target' => 'smithy.ruby.tests#DataMap' } } }, - "smithy.waiters#Acceptor" => { - "type" => "structure", - "members" => { - "state" => { - "target" => "smithy.waiters#AcceptorState", - "traits" => { - "smithy.api#documentation" => "The state the acceptor transitions to when matched.", - "smithy.api#required" => {} + 'smithy.waiters#Acceptor' => { + 'type' => 'structure', + 'members' => { + 'state' => { + 'target' => 'smithy.waiters#AcceptorState', + 'traits' => { + 'smithy.api#documentation' => 'The state the acceptor transitions to when matched.', + 'smithy.api#required' => {} } }, - "matcher" => { - "target" => "smithy.waiters#Matcher", - "traits" => { - "smithy.api#documentation" => "The matcher used to test if the resource is in a given state.", - "smithy.api#required" => {} + 'matcher' => { + 'target' => 'smithy.waiters#Matcher', + 'traits' => { + 'smithy.api#documentation' => 'The matcher used to test if the resource is in a given state.', + 'smithy.api#required' => {} } } }, - "traits" => { - "smithy.api#documentation" => "Represents an acceptor in a waiter's state machine.", - "smithy.api#private" => {} + 'traits' => { + 'smithy.api#documentation' => "Represents an acceptor in a waiter's state machine.", + 'smithy.api#private' => {} } }, - "smithy.waiters#AcceptorState" => { - "type" => "enum", - "members" => { - "SUCCESS" => { - "target" => "smithy.api#Unit", - "traits" => { - "smithy.api#documentation" => "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", - "smithy.api#enumValue" => "success" + 'smithy.waiters#AcceptorState' => { + 'type' => 'enum', + 'members' => { + 'SUCCESS' => { + 'target' => 'smithy.api#Unit', + 'traits' => { + 'smithy.api#documentation' => "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", + 'smithy.api#enumValue' => 'success' } }, - "FAILURE" => { - "target" => "smithy.api#Unit", - "traits" => { - "smithy.api#documentation" => "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", - "smithy.api#enumValue" => "failure" + 'FAILURE' => { + 'target' => 'smithy.api#Unit', + 'traits' => { + 'smithy.api#documentation' => "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", + 'smithy.api#enumValue' => 'failure' } }, - "RETRY" => { - "target" => "smithy.api#Unit", - "traits" => { - "smithy.api#documentation" => "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", - "smithy.api#enumValue" => "retry" + 'RETRY' => { + 'target' => 'smithy.api#Unit', + 'traits' => { + 'smithy.api#documentation' => "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", + 'smithy.api#enumValue' => 'retry' } } }, - "traits" => { - "smithy.api#documentation" => "The transition state of a waiter.", - "smithy.api#private" => {} + 'traits' => { + 'smithy.api#documentation' => 'The transition state of a waiter.', + 'smithy.api#private' => {} } }, - "smithy.waiters#Acceptors" => { - "type" => "list", - "member" => { - "target" => "smithy.waiters#Acceptor" + 'smithy.waiters#Acceptors' => { + 'type' => 'list', + 'member' => { + 'target' => 'smithy.waiters#Acceptor' }, - "traits" => { - "smithy.api#length" => { - "min" => 1 + 'traits' => { + 'smithy.api#length' => { + 'min' => 1 }, - "smithy.api#private" => {} + 'smithy.api#private' => {} } }, - "smithy.waiters#Matcher" => { - "type" => "union", - "members" => { - "output" => { - "target" => "smithy.waiters#PathMatcher", - "traits" => { - "smithy.api#documentation" => "Matches on the successful output of an operation using a\nJMESPath expression." + 'smithy.waiters#Matcher' => { + 'type' => 'union', + 'members' => { + 'output' => { + 'target' => 'smithy.waiters#PathMatcher', + 'traits' => { + 'smithy.api#documentation' => "Matches on the successful output of an operation using a\nJMESPath expression." } }, - "inputOutput" => { - "target" => "smithy.waiters#PathMatcher", - "traits" => { - "smithy.api#documentation" => "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." + 'inputOutput' => { + 'target' => 'smithy.waiters#PathMatcher', + 'traits' => { + 'smithy.api#documentation' => "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." } }, - "errorType" => { - "target" => "smithy.api#String", - "traits" => { - "smithy.api#documentation" => "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." + 'errorType' => { + 'target' => 'smithy.api#String', + 'traits' => { + 'smithy.api#documentation' => "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." } }, - "success" => { - "target" => "smithy.api#Boolean", - "traits" => { - "smithy.api#documentation" => "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." + 'success' => { + 'target' => 'smithy.api#Boolean', + 'traits' => { + 'smithy.api#documentation' => "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." } } }, - "traits" => { - "smithy.api#documentation" => "Defines how an acceptor determines if it matches the current state of\na resource.", - "smithy.api#private" => {} + 'traits' => { + 'smithy.api#documentation' => "Defines how an acceptor determines if it matches the current state of\na resource.", + 'smithy.api#private' => {} } }, - "smithy.waiters#NonEmptyString" => { - "type" => "string", - "traits" => { - "smithy.api#length" => { - "min" => 1 + 'smithy.waiters#NonEmptyString' => { + 'type' => 'string', + 'traits' => { + 'smithy.api#length' => { + 'min' => 1 }, - "smithy.api#private" => {} + 'smithy.api#private' => {} } }, - "smithy.waiters#NonEmptyStringList" => { - "type" => "list", - "member" => { - "target" => "smithy.waiters#NonEmptyString" + 'smithy.waiters#NonEmptyStringList' => { + 'type' => 'list', + 'member' => { + 'target' => 'smithy.waiters#NonEmptyString' }, - "traits" => { - "smithy.api#private" => {} + 'traits' => { + 'smithy.api#private' => {} } }, - "smithy.waiters#PathComparator" => { - "type" => "enum", - "members" => { - "STRING_EQUALS" => { - "target" => "smithy.api#Unit", - "traits" => { - "smithy.api#documentation" => "Matches if the return value is a string that is equal to the expected string.", - "smithy.api#enumValue" => "stringEquals" + 'smithy.waiters#PathComparator' => { + 'type' => 'enum', + 'members' => { + 'STRING_EQUALS' => { + 'target' => 'smithy.api#Unit', + 'traits' => { + 'smithy.api#documentation' => 'Matches if the return value is a string that is equal to the expected string.', + 'smithy.api#enumValue' => 'stringEquals' } }, - "BOOLEAN_EQUALS" => { - "target" => "smithy.api#Unit", - "traits" => { - "smithy.api#documentation" => "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", - "smithy.api#enumValue" => "booleanEquals" + 'BOOLEAN_EQUALS' => { + 'target' => 'smithy.api#Unit', + 'traits' => { + 'smithy.api#documentation' => "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", + 'smithy.api#enumValue' => 'booleanEquals' } }, - "ALL_STRING_EQUALS" => { - "target" => "smithy.api#Unit", - "traits" => { - "smithy.api#documentation" => "Matches if all values in the list matches the expected string.", - "smithy.api#enumValue" => "allStringEquals" + 'ALL_STRING_EQUALS' => { + 'target' => 'smithy.api#Unit', + 'traits' => { + 'smithy.api#documentation' => 'Matches if all values in the list matches the expected string.', + 'smithy.api#enumValue' => 'allStringEquals' } }, - "ANY_STRING_EQUALS" => { - "target" => "smithy.api#Unit", - "traits" => { - "smithy.api#documentation" => "Matches if any value in the list matches the expected string.", - "smithy.api#enumValue" => "anyStringEquals" + 'ANY_STRING_EQUALS' => { + 'target' => 'smithy.api#Unit', + 'traits' => { + 'smithy.api#documentation' => 'Matches if any value in the list matches the expected string.', + 'smithy.api#enumValue' => 'anyStringEquals' } } }, - "traits" => { - "smithy.api#documentation" => "Defines a comparison to perform in a PathMatcher.", - "smithy.api#private" => {} + 'traits' => { + 'smithy.api#documentation' => 'Defines a comparison to perform in a PathMatcher.', + 'smithy.api#private' => {} } }, - "smithy.waiters#PathMatcher" => { - "type" => "structure", - "members" => { - "path" => { - "target" => "smithy.api#String", - "traits" => { - "smithy.api#documentation" => "A JMESPath expression applied to the input or output of an operation.", - "smithy.api#required" => {} + 'smithy.waiters#PathMatcher' => { + 'type' => 'structure', + 'members' => { + 'path' => { + 'target' => 'smithy.api#String', + 'traits' => { + 'smithy.api#documentation' => 'A JMESPath expression applied to the input or output of an operation.', + 'smithy.api#required' => {} } }, - "expected" => { - "target" => "smithy.api#String", - "traits" => { - "smithy.api#documentation" => "The expected return value of the expression.", - "smithy.api#required" => {} + 'expected' => { + 'target' => 'smithy.api#String', + 'traits' => { + 'smithy.api#documentation' => 'The expected return value of the expression.', + 'smithy.api#required' => {} } }, - "comparator" => { - "target" => "smithy.waiters#PathComparator", - "traits" => { - "smithy.api#documentation" => "The comparator used to compare the result of the expression with the\nexpected value.", - "smithy.api#required" => {} + 'comparator' => { + 'target' => 'smithy.waiters#PathComparator', + 'traits' => { + 'smithy.api#documentation' => "The comparator used to compare the result of the expression with the\nexpected value.", + 'smithy.api#required' => {} } } }, - "traits" => { - "smithy.api#documentation" => "Defines how to test the result of a JMESPath expression against\nan expected value.", - "smithy.api#private" => {} + 'traits' => { + 'smithy.api#documentation' => "Defines how to test the result of a JMESPath expression against\nan expected value.", + 'smithy.api#private' => {} } }, - "smithy.waiters#Waiter" => { - "type" => "structure", - "members" => { - "documentation" => { - "target" => "smithy.api#String", - "traits" => { - "smithy.api#documentation" => "Documentation about the waiter. Can use CommonMark." + 'smithy.waiters#Waiter' => { + 'type' => 'structure', + 'members' => { + 'documentation' => { + 'target' => 'smithy.api#String', + 'traits' => { + 'smithy.api#documentation' => 'Documentation about the waiter. Can use CommonMark.' } }, - "acceptors" => { - "target" => "smithy.waiters#Acceptors", - "traits" => { - "smithy.api#documentation" => "An ordered array of acceptors to check after executing an operation.", - "smithy.api#required" => {} + 'acceptors' => { + 'target' => 'smithy.waiters#Acceptors', + 'traits' => { + 'smithy.api#documentation' => 'An ordered array of acceptors to check after executing an operation.', + 'smithy.api#required' => {} } }, - "minDelay" => { - "target" => "smithy.waiters#WaiterDelay", - "traits" => { - "smithy.api#default" => 2, - "smithy.api#documentation" => "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." + 'minDelay' => { + 'target' => 'smithy.waiters#WaiterDelay', + 'traits' => { + 'smithy.api#default' => 2, + 'smithy.api#documentation' => "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." } }, - "maxDelay" => { - "target" => "smithy.waiters#WaiterDelay", - "traits" => { - "smithy.api#default" => 120, - "smithy.api#documentation" => "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." + 'maxDelay' => { + 'target' => 'smithy.waiters#WaiterDelay', + 'traits' => { + 'smithy.api#default' => 120, + 'smithy.api#documentation' => "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." } }, - "deprecated" => { - "target" => "smithy.api#Boolean", - "traits" => { - "smithy.api#documentation" => "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." + 'deprecated' => { + 'target' => 'smithy.api#Boolean', + 'traits' => { + 'smithy.api#documentation' => "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." } }, - "tags" => { - "target" => "smithy.waiters#NonEmptyStringList", - "traits" => { - "smithy.api#documentation" => "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." + 'tags' => { + 'target' => 'smithy.waiters#NonEmptyStringList', + 'traits' => { + 'smithy.api#documentation' => "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." } } }, - "traits" => { - "smithy.api#documentation" => "Defines an individual operation waiter.", - "smithy.api#private" => {} + 'traits' => { + 'smithy.api#documentation' => 'Defines an individual operation waiter.', + 'smithy.api#private' => {} } }, - "smithy.waiters#WaiterDelay" => { - "type" => "integer", - "traits" => { - "smithy.api#range" => { - "min" => 1 + 'smithy.waiters#WaiterDelay' => { + 'type' => 'integer', + 'traits' => { + 'smithy.api#range' => { + 'min' => 1 } } }, - "smithy.waiters#WaiterName" => { - "type" => "string", - "traits" => { - "smithy.api#pattern" => "^[A-Z]+[A-Za-z0-9]*$" + 'smithy.waiters#WaiterName' => { + 'type' => 'string', + 'traits' => { + 'smithy.api#pattern' => '^[A-Z]+[A-Za-z0-9]*$' } }, - "smithy.waiters#waitable" => { - "type" => "map", - "key" => { - "target" => "smithy.waiters#WaiterName" + 'smithy.waiters#waitable' => { + 'type' => 'map', + 'key' => { + 'target' => 'smithy.waiters#WaiterName' }, - "value" => { - "target" => "smithy.waiters#Waiter" + 'value' => { + 'target' => 'smithy.waiters#Waiter' }, - "traits" => { - "smithy.api#documentation" => "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", - "smithy.api#length" => { - "min" => 1 + 'traits' => { + 'smithy.api#documentation' => "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", + 'smithy.api#length' => { + 'min' => 1 }, - "smithy.api#trait" => { - "selector" => "operation :not(-[input, output]-> structure > member > union[trait|streaming])" + 'smithy.api#trait' => { + 'selector' => 'operation :not(-[input, output]-> structure > member > union[trait|streaming])' } } } } end + # rubocop:enable Layout/LineLength let(:sample_client) { ClientHelper.sample_client(shapes: shapes) } let(:client_class) do client_class = sample_client.const_get(:Client) @@ -796,9 +777,9 @@ module Waiters let(:waiter) { Waiter } let(:poller) { Poller } let(:my_error) { sample_client::Errors::MyError.new({}, message: 'my error message') } - let(:widget_does_not_exist_error) { + let(:widget_does_not_exist_error) do sample_client::Errors::WidgetDoesNotExistError.new({}, message: 'widget does not exist message') - } + end let(:unexpected_error) { Errors::UnexpectedError } let(:failure_state_error) { Errors::FailureStateError } let(:max_wait_time_exceeded_error) { Errors::MaxWaitTimeExceededError } @@ -823,24 +804,24 @@ module Waiters it 'raises a failure state error when status is failure' do expect_any_instance_of(poller).to receive(:call).and_return([my_error, :failure]) - expect { + expect do client.wait_until(:success_false_matcher, input, max_wait_time: 60) - }.to raise_error(failure_state_error) + end.to raise_error(failure_state_error) end it 'raises an unexpected error when status is error' do expect_any_instance_of(poller).to receive(:call).and_return([StandardError, :error]) - expect { + expect do client.wait_until(:success_false_matcher, input, max_wait_time: 60) - }.to raise_error(unexpected_error) + end.to raise_error(unexpected_error) end it 'raises a max wait time exceeded error when there is no more remaining time' do expect_any_instance_of(poller).to receive(:call).and_return([{}, :retry], [{}, :retry]) expect_any_instance_of(waiter).to receive(:delay).and_return(1) - expect { + expect do client.wait_until(:success_false_matcher, input, max_wait_time: 1) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end end @@ -858,17 +839,17 @@ module Waiters ) expect_any_instance_of(waiter).to receive(:delay).with(1).and_wrap_original do |m, *args| delay = m.call(*args) - expect(delay >= min_delay && delay <= max_delay).to be true + expect(delay.between?(min_delay, max_delay)).to be true 0 end expect_any_instance_of(waiter).to receive(:delay).with(2).and_wrap_original do |m, *args| delay = m.call(*args) - expect(delay >= min_delay && delay <= max_delay).to be true + expect(delay.between?(min_delay, max_delay)).to be true 0 end expect_any_instance_of(waiter).to receive(:delay).with(3).and_wrap_original do |m, *args| delay = m.call(*args) - expect(delay >= min_delay && delay <= max_delay).to be true + expect(delay.between?(min_delay, max_delay)).to be true 0 end client.wait_until(:success_true_matcher, input, options) @@ -897,15 +878,15 @@ module Waiters it 'raises an error when max wait time is exceeded' do output = {} expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:success_false_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end it 'raises an error when max_wait_time is not provided' do - expect { + expect do client.wait_until(:success_true_matcher, input) - }.to raise_error(ArgumentError, "expected `:max_wait_time` to be an integer, got: #{nil}") + end.to raise_error(ArgumentError, 'expected `:max_wait_time` to be an integer, got: ') end it 'raises an error when max_delay is less than 1' do @@ -913,9 +894,9 @@ module Waiters max_wait_time: 5, max_delay: 0 } - expect { + expect do client.wait_until(:success_true_matcher, input, options) - }.to raise_error(ArgumentError, '`:max_delay` must be greater than 0') + end.to raise_error(ArgumentError, '`:max_delay` must be greater than 0') end it 'raises an error when min_delay is less than 1' do @@ -923,9 +904,10 @@ module Waiters max_wait_time: 5, min_delay: 0 } - expect { + expect do client.wait_until(:success_true_matcher, input, options) - }.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') + end.to raise_error(ArgumentError, + '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') end it 'raises an error when max_delay is less than min_delay' do @@ -934,9 +916,10 @@ module Waiters min_delay: 4, max_delay: 2 } - expect { + expect do client.wait_until(:success_true_matcher, input, options) - }.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') + end.to raise_error(ArgumentError, + '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') end end end @@ -946,16 +929,16 @@ module Waiters it 'succeeds when success is set to true and successful response is received' do output = {} expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:success_true_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'succeeds when success is set to false and error is received' do expect(client).to receive(:get_widget).and_raise(StandardError) - expect { + expect do client.wait_until(:success_false_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'retries and succeeds when matched' do @@ -965,25 +948,25 @@ module Waiters expect_any_instance_of(waiter).to receive(:delay).and_return(0) end expect(client).to receive(:get_widget).and_raise(StandardError) - expect { + expect do client.wait_until(:success_false_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'fails when success is set to true and unexpected error is received' do expect(client).to receive(:get_widget).and_raise(StandardError) - expect { + expect do client.wait_until(:success_true_matcher, input, max_wait_time: 60) - }.to raise_error(unexpected_error) + end.to raise_error(unexpected_error) end end describe 'error type matcher' do it 'succeeds when error matches' do expect(client).to receive(:get_widget).and_raise(my_error) - expect { + expect do client.wait_until(:error_type_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'retries and succeeds when matched' do @@ -993,16 +976,16 @@ module Waiters expect_any_instance_of(waiter).to receive(:delay).and_return(0) end expect(client).to receive(:get_widget).and_raise(my_error) - expect { + expect do client.wait_until(:error_type_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'fails when error does not match' do expect(client).to receive(:get_widget).and_raise(StandardError) - expect { + expect do client.wait_until(:error_type_matcher, input, max_wait_time: 60) - }.to raise_error(unexpected_error) + end.to raise_error(unexpected_error) end end @@ -1011,9 +994,9 @@ module Waiters it 'succeeds when output matches' do output = { string_property: 'expected string' } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'retries and succeeds when matched' do @@ -1024,25 +1007,25 @@ module Waiters expect_any_instance_of(waiter).to receive(:delay).and_return(0) end expect(client).to receive(:get_widget).and_return(output_expected) - expect { + expect do client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'fails when output property does not match' do output_unexpected = { string_property: 'unexpected string' } expect(client).to receive(:get_widget).and_return(output_unexpected) - expect { + expect do client.wait_until(:output_string_property_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end it 'fails when output property is null' do output_unexpected = {} expect(client).to receive(:get_widget).and_return(output_unexpected) - expect { + expect do client.wait_until(:output_string_property_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end end @@ -1050,9 +1033,9 @@ module Waiters it 'succeeds when output matches' do output = { boolean_property: false } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'retries and succeeds when matched' do @@ -1063,25 +1046,25 @@ module Waiters expect_any_instance_of(waiter).to receive(:delay).and_return(0) end expect(client).to receive(:get_widget).and_return(output_expected) - expect { + expect do client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'fails when output property does not match' do output_unexpected = { boolean_property: true } expect(client).to receive(:get_widget).and_return(output_unexpected) - expect { + expect do client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end it 'fails when output property is null' do output_unexpected = {} expect(client).to receive(:get_widget).and_return(output_unexpected) - expect { + expect do client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end end @@ -1095,9 +1078,9 @@ module Waiters ] } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'retries and succeeds when matched' do @@ -1120,9 +1103,9 @@ module Waiters expect_any_instance_of(waiter).to receive(:delay).and_return(0) end expect(client).to receive(:get_widget).and_return(output_expected) - expect { + expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'fails when output property does not match' do @@ -1134,25 +1117,25 @@ module Waiters ] } expect(client).to receive(:get_widget).and_return(output_unexpected) - expect { + expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end it 'fails when output property is empty' do output_unexpected = { string_array_property: [] } expect(client).to receive(:get_widget).and_return(output_unexpected) - expect { + expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end it 'fails when output property is null' do output_unexpected = {} expect(client).to receive(:get_widget).and_return(output_unexpected) - expect { + expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end end @@ -1167,9 +1150,9 @@ module Waiters ] } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'retries and succeeds when matched' do @@ -1194,9 +1177,9 @@ module Waiters expect_any_instance_of(waiter).to receive(:delay).and_return(0) end expect(client).to receive(:get_widget).and_return(output_expected) - expect { + expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'fails when output property does not match' do @@ -1209,25 +1192,25 @@ module Waiters ] } expect(client).to receive(:get_widget).and_return(output_unexpected) - expect { + expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end it 'fails when output property is empty' do output_unexpected = { string_array_property: [] } expect(client).to receive(:get_widget).and_return(output_unexpected) - expect { + expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end it 'fails when output property is null' do output_unexpected = {} expect(client).to receive(:get_widget).and_return(output_unexpected) - expect { + expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end end @@ -1254,9 +1237,9 @@ module Waiters ] } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:flatten_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'fails when not matched' do @@ -1273,9 +1256,9 @@ module Waiters ] } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:flatten_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end end @@ -1322,9 +1305,9 @@ module Waiters ] } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:flatten_length_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'fails when not matched' do @@ -1341,9 +1324,9 @@ module Waiters ] } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:flatten_length_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end end @@ -1390,9 +1373,9 @@ module Waiters ] } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:flatten_filter_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'fails when not matched' do @@ -1433,9 +1416,9 @@ module Waiters ] } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:flatten_filter_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end end @@ -1482,9 +1465,9 @@ module Waiters ] } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'fails when not matched' do @@ -1525,9 +1508,9 @@ module Waiters ] } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end end @@ -1537,13 +1520,13 @@ module Waiters data_map: { 'key1' => 'abc', 'key2' => 'abc', - 'key3' => 'abc', + 'key3' => 'abc' } } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:projection_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'fails when not matched' do @@ -1551,13 +1534,13 @@ module Waiters data_map: { 'key1' => 'abc', 'key2' => 'def', - 'key3' => 'ghi', + 'key3' => 'ghi' } } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:projection_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end end @@ -1568,13 +1551,13 @@ module Waiters data_map: { 'key1' => 'not a match', 'key2' => 'match', - 'key3' => 'not a match', + 'key3' => 'not a match' } } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:contains_field_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'fails when not matched' do @@ -1583,13 +1566,13 @@ module Waiters data_map: { 'key1' => 'not a match', 'key2' => 'not a match', - 'key3' => 'not a match', + 'key3' => 'not a match' } } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:contains_field_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end end @@ -1603,13 +1586,13 @@ module Waiters data_map: { 'key1' => 'one', 'key2' => 'two', - 'key3' => 'three', + 'key3' => 'three' } } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:and_inequality_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'fails when not matched' do @@ -1622,13 +1605,13 @@ module Waiters data_map: { 'key1' => 'one', 'key2' => 'two', - 'key3' => 'three', + 'key3' => 'three' } } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:and_inequality_matcher, input, max_wait_time: 0) - }.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(max_wait_time_exceeded_error) end end end @@ -1637,22 +1620,22 @@ module Waiters it 'succeeds for boolean equals comparator' do output = { string_property: 'input_string' } expect(client).to receive(:get_widget).and_return(output) - expect { + expect do client.wait_until(:input_output_boolean_property_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end end it 'checks acceptors in order' do expect(client).to receive(:delete_widget).and_raise(widget_does_not_exist_error) - expect { + expect do client.wait_until(:acceptor_order_success_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error expect(client).to receive(:delete_widget).and_raise(widget_does_not_exist_error) - expect { + expect do client.wait_until(:acceptor_order_failure_matcher, input, max_wait_time: 60) - }.to raise_error(failure_state_error) + end.to raise_error(failure_state_error) end end end diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index 02fc2e562..6a1a358b7 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -67,12 +67,8 @@ module <%= module_name %> end def waiters -<% if waiters? -%> <% waiters.each do |line| -%> <%= line %> -<% end -%> -<% else -%> - {} <% end -%> end diff --git a/gems/smithy/lib/smithy/views/client/client.rb b/gems/smithy/lib/smithy/views/client/client.rb index 7dff79c3e..ff211ee0f 100644 --- a/gems/smithy/lib/smithy/views/client/client.rb +++ b/gems/smithy/lib/smithy/views/client/client.rb @@ -62,9 +62,11 @@ def protocols def waiters waiters = Views::Client::Waiters.new(@plan).waiters + return ['{}'] if waiters.empty? + lines = ['{'] waiters.each_with_index do |waiter, i| - line = ' ' + waiter.name.underscore + ': Waiters::' + waiter.name + ',' + line = " #{waiter.name.underscore}: Waiters::#{waiter.name}," line.chomp!(',') if i == waiters.length - 1 lines << line end @@ -72,10 +74,6 @@ def waiters lines end - def waiters? - Views::Client::Waiters.new(@plan).waiters.size > 0 - end - private def option_docstrings(option) diff --git a/gems/smithy/lib/smithy/views/client/waiters.rb b/gems/smithy/lib/smithy/views/client/waiters.rb index 9b1a0966c..bf1baa4d5 100644 --- a/gems/smithy/lib/smithy/views/client/waiters.rb +++ b/gems/smithy/lib/smithy/views/client/waiters.rb @@ -20,11 +20,11 @@ def waiters operations = Model::ServiceIndex.new(@model).operations_for(@plan.service) operations.each do |operation_id, operation| waiters_from_trait = waitable_trait(operation) - unless waiters_from_trait.empty? - operation_name = Model::Shape.name(operation_id).underscore - waiters_from_trait.map do |waiter_name, waiter| - waiters << Waiter.new(operation_name, waiter_name, waiter) - end + next if waiters_from_trait.empty? + + operation_name = Model::Shape.name(operation_id).underscore + waiters_from_trait.map do |waiter_name, waiter| + waiters << Waiter.new(operation_name, waiter_name, waiter) end end waiters.sort_by(&:name) @@ -52,9 +52,7 @@ def initialize(operation, name, waiter) def formatted_acceptors(acceptors) acceptors.each do |acceptor| - if (matcher = acceptor['matcher']['output']) - matcher['path'] = Util::Underscore.underscore_jmespath(matcher['path']) - elsif (matcher = acceptor['matcher']['inputOutput']) + if (matcher = acceptor['matcher']['output'] || acceptor['matcher']['inputOutput']) matcher['path'] = Util::Underscore.underscore_jmespath(matcher['path']) end end diff --git a/gems/smithy/spec/fixtures/wait_service/model.json b/gems/smithy/spec/fixtures/waiter_service/model.json similarity index 99% rename from gems/smithy/spec/fixtures/wait_service/model.json rename to gems/smithy/spec/fixtures/waiter_service/model.json index d298816dd..57a8a698c 100644 --- a/gems/smithy/spec/fixtures/wait_service/model.json +++ b/gems/smithy/spec/fixtures/waiter_service/model.json @@ -147,7 +147,7 @@ "target": "smithy.api#String" } }, - "smithy.ruby.tests#WaitService": { + "smithy.ruby.tests#WaiterService": { "type": "service", "version": "2022-11-30", "operations": [ diff --git a/gems/smithy/spec/fixtures/wait_service/model.smithy b/gems/smithy/spec/fixtures/waiter_service/model.smithy similarity index 98% rename from gems/smithy/spec/fixtures/wait_service/model.smithy rename to gems/smithy/spec/fixtures/waiter_service/model.smithy index be64a2523..b22226f4b 100644 --- a/gems/smithy/spec/fixtures/wait_service/model.smithy +++ b/gems/smithy/spec/fixtures/waiter_service/model.smithy @@ -4,7 +4,7 @@ namespace smithy.ruby.tests use smithy.waiters#waitable -service WaitService { +service WaiterService { version: "2022-11-30", operations: [GetOperation] } diff --git a/gems/smithy/spec/fixtures/wait_service/smithy-build.json b/gems/smithy/spec/fixtures/waiter_service/smithy-build.json similarity index 100% rename from gems/smithy/spec/fixtures/wait_service/smithy-build.json rename to gems/smithy/spec/fixtures/waiter_service/smithy-build.json diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index bd9c38356..093bffa21 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -4,20 +4,19 @@ describe 'Client: Waiters' do let(:input) { { string_property: 'input_string' } } - let(:client) { Wait_Service::Client.new(stub_responses: true) } - let(:unexpected_error) { Smithy::Client::Waiters::Errors::UnexpectedError } + let(:client) { WaiterService::Client.new(stub_responses: true) } let(:no_such_waiter_error) { Smithy::Client::Waiters::Errors::NoSuchWaiterError } ['generated client gem', 'generated client from source code'].each do |context| context context do - include_context context, 'Wait_Service' + include_context context, 'WaiterService' it 'returns when successful' do output = {} expect(client).to receive(:get_operation).and_return(output) - expect { + expect do client.wait_until(:success_matcher, input, max_wait_time: 60) - }.to_not raise_error + end.to_not raise_error end it 'returns output when successful' do @@ -29,15 +28,15 @@ it 'raises an error when unsuccessful' do expect(client).to receive(:get_operation).and_raise(StandardError) - expect { + expect do client.wait_until(:success_matcher, input, max_wait_time: 60) - }.to raise_error(unexpected_error) + end.to raise_error(Smithy::Client::Waiters::Errors::UnexpectedError) end it 'raises an error for nonexistent waiters' do - expect { + expect do client.wait_until(:nonexistent_waiter, input, max_wait_time: 60) - }.to raise_error(no_such_waiter_error) + end.to raise_error(no_such_waiter_error) end it 'does not allow custom waiters' do @@ -54,10 +53,10 @@ } } client.config.service.operations[:get_operation].traits['smithy.waiters#waitable'].merge!(custom_waiter) - expect { + expect do client.wait_until(:custom_waiter_matcher, input, max_wait_time: 60) - }.to raise_error(no_such_waiter_error) + end.to raise_error(no_such_waiter_error) end end end -end \ No newline at end of file +end From 416a74db40bbff42d57acd631bc37cf5456937cd Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 7 May 2025 09:56:28 -0700 Subject: [PATCH 27/48] Clean up and shave down unit tests --- .../lib/smithy-client/waiters/waiter.rb | 4 +- .../spec/smithy-client/waiters_spec.rb | 1036 ++++++----------- 2 files changed, 380 insertions(+), 660 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index 692b3214e..3fdcf2414 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -21,9 +21,7 @@ def wait(client, params) private def max_wait_time(time) - unless time.is_a?(Integer) - raise ArgumentError, "expected `:max_wait_time` to be an integer, got: #{time}" - end + raise ArgumentError, "expected `:max_wait_time` to be an integer, got: #{time}" unless time.is_a?(Integer) time end diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index 734e18952..710e92bcd 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -6,132 +6,16 @@ module Smithy module Client module Waiters describe Waiters do - # rubocop:disable Layout/LineLength let(:shapes) do { - 'smithy.ruby.tests#BooleanArray' => { - 'type' => 'list', - 'member' => { - 'target' => 'smithy.api#Boolean' - } - }, - 'smithy.ruby.tests#Child' => { - 'type' => 'structure', - 'members' => { - 'grandchildren' => { - 'target' => 'smithy.ruby.tests#GrandchildArray' - } - } - }, - 'smithy.ruby.tests#ChildArray' => { - 'type' => 'list', - 'member' => { - 'target' => 'smithy.ruby.tests#Child' - } - }, - 'smithy.ruby.tests#DataMap' => { - 'type' => 'map', - 'key' => { - 'target' => 'smithy.api#String' - }, - 'value' => { - 'target' => 'smithy.api#String' - } - }, - 'smithy.ruby.tests#DeleteWidget' => { - 'type' => 'operation', - 'input' => { - 'target' => 'smithy.ruby.tests#WidgetInput' - }, - 'output' => { - 'target' => 'smithy.ruby.tests#DeletedWidgetOutput' - }, - 'errors' => [ - { - 'target' => 'smithy.ruby.tests#MyError' - }, + 'smithy.ruby.tests#WaitService' => { + 'type' => 'service', + 'version' => '2022-11-30', + 'operations' => [ { - 'target' => 'smithy.ruby.tests#WidgetDoesNotExistError' - } - ], - 'traits' => { - 'smithy.api#http' => { - 'uri' => '/delete-widget', - 'method' => 'POST' - }, - 'smithy.waiters#waitable' => { - 'AcceptorOrderSuccessMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'errorType' => 'WidgetDoesNotExistError' - } - }, - { - 'state' => 'failure', - 'matcher' => { - 'errorType' => 'WidgetDoesNotExistError' - } - } - ] - }, - 'AcceptorOrderFailureMatcher' => { - 'acceptors' => [ - { - 'state' => 'failure', - 'matcher' => { - 'errorType' => 'WidgetDoesNotExistError' - } - }, - { - 'state' => 'success', - 'matcher' => { - 'errorType' => 'WidgetDoesNotExistError' - } - } - ] - }, - 'FullyConfiguredMatcher' => { - 'acceptors' => [ - { - 'state' => 'retry', - 'matcher' => { - 'errorType' => 'WidgetDoesNotExistError' - } - }, - { - 'state' => 'failure', - 'matcher' => { - 'output' => { - 'path' => 'stringProperty', - 'expected' => 'fail', - 'comparator' => 'stringEquals' - } - } - }, - { - 'state' => 'success', - 'matcher' => { - 'success' => true - } - } - ], - 'minDelay' => 5, - 'maxDelay' => 20, - 'deprecated' => true, - 'tags' => %w[some tags] - } - } - } - }, - 'smithy.ruby.tests#DeletedWidgetOutput' => { - 'type' => 'structure', - 'members' => { - 'stringProperty' => { - 'target' => 'smithy.api#String' + 'target' => 'smithy.ruby.tests#GetWidget' } - } + ] }, 'smithy.ruby.tests#GetWidget' => { 'type' => 'operation', @@ -144,312 +28,13 @@ module Waiters 'errors' => [ { 'target' => 'smithy.ruby.tests#MyError' - } - ], - 'traits' => { - 'smithy.api#http' => { - 'uri' => '/widget', - 'method' => 'POST' - }, - 'smithy.waiters#waitable' => { - 'SuccessTrueMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'success' => true - } - } - ] - }, - 'SuccessFalseMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'success' => false - } - } - ] - }, - 'ErrorTypeMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'errorType' => 'MyError' - } - } - ] - }, - 'OutputStringPropertyMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'stringProperty', - 'expected' => 'expected string', - 'comparator' => 'stringEquals' - } - } - } - ] - }, - 'OutputBooleanPropertyMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'booleanProperty', - 'expected' => 'false', - 'comparator' => 'booleanEquals' - } - } - } - ] - }, - 'OutputStringArrayAllPropertyMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'stringArrayProperty', - 'expected' => 'expected string', - 'comparator' => 'allStringEquals' - } - } - } - ] - }, - 'OutputStringArrayAnyPropertyMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'stringArrayProperty', - 'expected' => 'expected string', - 'comparator' => 'anyStringEquals' - } - } - } - ] - }, - 'InputOutputStringPropertyMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'inputOutput' => { - 'path' => 'input.stringProperty', - 'expected' => 'output.stringProperty', - 'comparator' => 'stringEquals' - } - } - } - ] - }, - 'InputOutputBooleanPropertyMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'inputOutput' => { - 'path' => 'input.stringProperty == output.stringProperty', - 'expected' => 'true', - 'comparator' => 'booleanEquals' - } - } - } - ] - }, - 'InputOutputStringArrayAllPropertyMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'inputOutput' => { - 'path' => 'input.stringArrayProperty', - 'expected' => 'output.stringArrayProperty', - 'comparator' => 'allStringEquals' - } - } - } - ] - }, - 'InputOutputStringArrayAnyPropertyMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'inputOutput' => { - 'path' => 'input.stringArrayProperty', - 'expected' => 'output.stringArrayProperty', - 'comparator' => 'anyStringEquals' - } - } - } - ] - }, - 'FlattenMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'children[].grandchildren[].name', - 'expected' => 'expected name', - 'comparator' => 'anyStringEquals' - } - } - } - ] - }, - 'FlattenLengthMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'length(children[].grandchildren[]) == `6`', - 'expected' => 'true', - 'comparator' => 'booleanEquals' - } - } - } - ] - }, - 'FlattenFilterMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'length(children[?length(grandchildren) == `3`]) == `1`', - 'expected' => 'true', - 'comparator' => 'booleanEquals' - } - } - } - ] - }, - 'LengthFlattenFilterMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'length((children[].grandchildren[])[?number > `4`]) == `3`', - 'expected' => 'true', - 'comparator' => 'booleanEquals' - } - } - } - ] - }, - 'ProjectionMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'dataMap.*', - 'expected' => 'abc', - 'comparator' => 'allStringEquals' - } - } - } - ] - }, - 'ContainsFieldMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'contains(dataMap.*, stringProperty)', - 'expected' => 'true', - 'comparator' => 'booleanEquals' - } - } - } - ] - }, - 'AndInequalityMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'length(dataMap) == `3` && length(stringArrayProperty) != `3`', - 'expected' => 'true', - 'comparator' => 'booleanEquals' - } - } - } - ] - } - } - } - }, - 'smithy.ruby.tests#Grandchild' => { - 'type' => 'structure', - 'members' => { - 'name' => { - 'target' => 'smithy.api#String' - }, - 'number' => { - 'target' => 'smithy.api#Integer' - } - } - }, - 'smithy.ruby.tests#GrandchildArray' => { - 'type' => 'list', - 'member' => { - 'target' => 'smithy.ruby.tests#Grandchild' - } - }, - 'smithy.ruby.tests#MyError' => { - 'type' => 'structure', - 'members' => { - 'message' => { - 'target' => 'smithy.api#String' - } - }, - 'traits' => { - 'smithy.api#error' => 'client' - } - }, - 'smithy.ruby.tests#StringArray' => { - 'type' => 'list', - 'member' => { - 'target' => 'smithy.api#String' - } - }, - 'smithy.ruby.tests#WaitService' => { - 'type' => 'service', - 'version' => '2022-11-30', - 'operations' => [ - { - 'target' => 'smithy.ruby.tests#DeleteWidget' }, { - 'target' => 'smithy.ruby.tests#GetWidget' - } - ] - }, - 'smithy.ruby.tests#WidgetDoesNotExistError' => { - 'type' => 'structure', - 'members' => { - 'message' => { - 'target' => 'smithy.api#String' + 'target' => 'smithy.ruby.tests#WidgetDoesNotExistError' } - }, + ], 'traits' => { - 'smithy.api#error' => 'client' + 'smithy.waiters#waitable' => {} } }, 'smithy.ruby.tests#WidgetInput' => { @@ -498,272 +83,82 @@ module Waiters } } }, - 'smithy.waiters#Acceptor' => { - 'type' => 'structure', - 'members' => { - 'state' => { - 'target' => 'smithy.waiters#AcceptorState', - 'traits' => { - 'smithy.api#documentation' => 'The state the acceptor transitions to when matched.', - 'smithy.api#required' => {} - } - }, - 'matcher' => { - 'target' => 'smithy.waiters#Matcher', - 'traits' => { - 'smithy.api#documentation' => 'The matcher used to test if the resource is in a given state.', - 'smithy.api#required' => {} - } - } - }, - 'traits' => { - 'smithy.api#documentation' => "Represents an acceptor in a waiter's state machine.", - 'smithy.api#private' => {} + 'smithy.ruby.tests#BooleanArray' => { + 'type' => 'list', + 'member' => { + 'target' => 'smithy.api#Boolean' } }, - 'smithy.waiters#AcceptorState' => { - 'type' => 'enum', + 'smithy.ruby.tests#Child' => { + 'type' => 'structure', 'members' => { - 'SUCCESS' => { - 'target' => 'smithy.api#Unit', - 'traits' => { - 'smithy.api#documentation' => "The waiter successfully finished waiting. This is a terminal\nstate that causes the waiter to stop.", - 'smithy.api#enumValue' => 'success' - } - }, - 'FAILURE' => { - 'target' => 'smithy.api#Unit', - 'traits' => { - 'smithy.api#documentation' => "The waiter failed to enter into the desired state. This is a\nterminal state that causes the waiter to stop.", - 'smithy.api#enumValue' => 'failure' - } - }, - 'RETRY' => { - 'target' => 'smithy.api#Unit', - 'traits' => { - 'smithy.api#documentation' => "The waiter will retry the operation. This state transition is\nimplicit if no accepter causes a state transition.", - 'smithy.api#enumValue' => 'retry' - } + 'grandchildren' => { + 'target' => 'smithy.ruby.tests#GrandchildArray' } - }, - 'traits' => { - 'smithy.api#documentation' => 'The transition state of a waiter.', - 'smithy.api#private' => {} } }, - 'smithy.waiters#Acceptors' => { + 'smithy.ruby.tests#ChildArray' => { 'type' => 'list', 'member' => { - 'target' => 'smithy.waiters#Acceptor' - }, - 'traits' => { - 'smithy.api#length' => { - 'min' => 1 - }, - 'smithy.api#private' => {} + 'target' => 'smithy.ruby.tests#Child' } }, - 'smithy.waiters#Matcher' => { - 'type' => 'union', - 'members' => { - 'output' => { - 'target' => 'smithy.waiters#PathMatcher', - 'traits' => { - 'smithy.api#documentation' => "Matches on the successful output of an operation using a\nJMESPath expression." - } - }, - 'inputOutput' => { - 'target' => 'smithy.waiters#PathMatcher', - 'traits' => { - 'smithy.api#documentation' => "Matches on both the input and output of an operation using a JMESPath\nexpression. Input parameters are available through the top-level\n`input` field, and output data is available through the top-level\n`output` field. This matcher can only be used on operations that\ndefine both input and output. This matcher is checked only if an\noperation completes successfully." - } - }, - 'errorType' => { - 'target' => 'smithy.api#String', - 'traits' => { - 'smithy.api#documentation' => "Matches if an operation returns an error and the error matches\nthe expected error type. If an absolute shape ID is provided, the\nerror is matched exactly on the shape ID. A shape name can be\nprovided to match an error in any namespace with the given name." - } - }, - 'success' => { - 'target' => 'smithy.api#Boolean', - 'traits' => { - 'smithy.api#documentation' => "When set to `true`, matches when an operation returns a successful\nresponse. When set to `false`, matches when an operation fails with\nany error." - } - } + 'smithy.ruby.tests#DataMap' => { + 'type' => 'map', + 'key' => { + 'target' => 'smithy.api#String' }, - 'traits' => { - 'smithy.api#documentation' => "Defines how an acceptor determines if it matches the current state of\na resource.", - 'smithy.api#private' => {} + 'value' => { + 'target' => 'smithy.api#String' } }, - 'smithy.waiters#NonEmptyString' => { - 'type' => 'string', - 'traits' => { - 'smithy.api#length' => { - 'min' => 1 + 'smithy.ruby.tests#Grandchild' => { + 'type' => 'structure', + 'members' => { + 'name' => { + 'target' => 'smithy.api#String' }, - 'smithy.api#private' => {} + 'number' => { + 'target' => 'smithy.api#Integer' + } } }, - 'smithy.waiters#NonEmptyStringList' => { + 'smithy.ruby.tests#GrandchildArray' => { 'type' => 'list', 'member' => { - 'target' => 'smithy.waiters#NonEmptyString' - }, - 'traits' => { - 'smithy.api#private' => {} - } - }, - 'smithy.waiters#PathComparator' => { - 'type' => 'enum', - 'members' => { - 'STRING_EQUALS' => { - 'target' => 'smithy.api#Unit', - 'traits' => { - 'smithy.api#documentation' => 'Matches if the return value is a string that is equal to the expected string.', - 'smithy.api#enumValue' => 'stringEquals' - } - }, - 'BOOLEAN_EQUALS' => { - 'target' => 'smithy.api#Unit', - 'traits' => { - 'smithy.api#documentation' => "Matches if the return value is a boolean that is equal to the string literal 'true' or 'false'.", - 'smithy.api#enumValue' => 'booleanEquals' - } - }, - 'ALL_STRING_EQUALS' => { - 'target' => 'smithy.api#Unit', - 'traits' => { - 'smithy.api#documentation' => 'Matches if all values in the list matches the expected string.', - 'smithy.api#enumValue' => 'allStringEquals' - } - }, - 'ANY_STRING_EQUALS' => { - 'target' => 'smithy.api#Unit', - 'traits' => { - 'smithy.api#documentation' => 'Matches if any value in the list matches the expected string.', - 'smithy.api#enumValue' => 'anyStringEquals' - } - } - }, - 'traits' => { - 'smithy.api#documentation' => 'Defines a comparison to perform in a PathMatcher.', - 'smithy.api#private' => {} + 'target' => 'smithy.ruby.tests#Grandchild' } }, - 'smithy.waiters#PathMatcher' => { - 'type' => 'structure', - 'members' => { - 'path' => { - 'target' => 'smithy.api#String', - 'traits' => { - 'smithy.api#documentation' => 'A JMESPath expression applied to the input or output of an operation.', - 'smithy.api#required' => {} - } - }, - 'expected' => { - 'target' => 'smithy.api#String', - 'traits' => { - 'smithy.api#documentation' => 'The expected return value of the expression.', - 'smithy.api#required' => {} - } - }, - 'comparator' => { - 'target' => 'smithy.waiters#PathComparator', - 'traits' => { - 'smithy.api#documentation' => "The comparator used to compare the result of the expression with the\nexpected value.", - 'smithy.api#required' => {} - } - } - }, - 'traits' => { - 'smithy.api#documentation' => "Defines how to test the result of a JMESPath expression against\nan expected value.", - 'smithy.api#private' => {} + 'smithy.ruby.tests#StringArray' => { + 'type' => 'list', + 'member' => { + 'target' => 'smithy.api#String' } }, - 'smithy.waiters#Waiter' => { + 'smithy.ruby.tests#MyError' => { 'type' => 'structure', 'members' => { - 'documentation' => { - 'target' => 'smithy.api#String', - 'traits' => { - 'smithy.api#documentation' => 'Documentation about the waiter. Can use CommonMark.' - } - }, - 'acceptors' => { - 'target' => 'smithy.waiters#Acceptors', - 'traits' => { - 'smithy.api#documentation' => 'An ordered array of acceptors to check after executing an operation.', - 'smithy.api#required' => {} - } - }, - 'minDelay' => { - 'target' => 'smithy.waiters#WaiterDelay', - 'traits' => { - 'smithy.api#default' => 2, - 'smithy.api#documentation' => "The minimum amount of time in seconds to delay between each retry.\nThis value defaults to 2 if not specified. If specified, this value\nMUST be greater than or equal to 1 and less than or equal to\n`maxDelay`." - } - }, - 'maxDelay' => { - 'target' => 'smithy.waiters#WaiterDelay', - 'traits' => { - 'smithy.api#default' => 120, - 'smithy.api#documentation' => "The maximum amount of time in seconds to delay between each retry.\nThis value defaults to 120 if not specified (or, 2 minutes). If\nspecified, this value MUST be greater than or equal to 1." - } - }, - 'deprecated' => { - 'target' => 'smithy.api#Boolean', - 'traits' => { - 'smithy.api#documentation' => "Indicates if the waiter is considered deprecated. A waiter SHOULD\nbe marked as deprecated if it has been replaced by another waiter or\nif it is no longer needed (for example, if a resource changes from\neventually consistent to strongly consistent)." - } - }, - 'tags' => { - 'target' => 'smithy.waiters#NonEmptyStringList', - 'traits' => { - 'smithy.api#documentation' => "A list of tags associated with the waiter that allow waiters to be\ncategorized and grouped." - } + 'message' => { + 'target' => 'smithy.api#String' } }, 'traits' => { - 'smithy.api#documentation' => 'Defines an individual operation waiter.', - 'smithy.api#private' => {} + 'smithy.api#error' => 'client' } }, - 'smithy.waiters#WaiterDelay' => { - 'type' => 'integer', - 'traits' => { - 'smithy.api#range' => { - 'min' => 1 + 'smithy.ruby.tests#WidgetDoesNotExistError' => { + 'type' => 'structure', + 'members' => { + 'message' => { + 'target' => 'smithy.api#String' } - } - }, - 'smithy.waiters#WaiterName' => { - 'type' => 'string', - 'traits' => { - 'smithy.api#pattern' => '^[A-Z]+[A-Za-z0-9]*$' - } - }, - 'smithy.waiters#waitable' => { - 'type' => 'map', - 'key' => { - 'target' => 'smithy.waiters#WaiterName' - }, - 'value' => { - 'target' => 'smithy.waiters#Waiter' }, 'traits' => { - 'smithy.api#documentation' => "Indicates that an operation has various named \"waiters\" that can be used\nto poll a resource until it enters a desired state.", - 'smithy.api#length' => { - 'min' => 1 - }, - 'smithy.api#trait' => { - 'selector' => 'operation :not(-[input, output]-> structure > member > union[trait|streaming])' - } + 'smithy.api#error' => 'client' } } } end - # rubocop:enable Layout/LineLength let(:sample_client) { ClientHelper.sample_client(shapes: shapes) } let(:client_class) do client_class = sample_client.const_get(:Client) @@ -786,7 +181,31 @@ module Waiters let(:no_such_waiter_error) { Errors::NoSuchWaiterError } describe 'waiter' do - before(:each) { client } + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'SuccessTrueMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'success' => true + } + } + ] + }, + 'SuccessFalseMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'success' => false + } + } + ] + } + } + client + end describe '#poll' do it 'delays when status is retry' do @@ -926,6 +345,31 @@ module Waiters describe 'poller' do describe 'success matcher' do + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'SuccessTrueMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'success' => true + } + } + ] + }, + 'SuccessFalseMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'success' => false + } + } + ] + } + } + end + it 'succeeds when success is set to true and successful response is received' do output = {} expect(client).to receive(:get_widget).and_return(output) @@ -962,6 +406,21 @@ module Waiters end describe 'error type matcher' do + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'ErrorTypeMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'errorType' => 'MyError' + } + } + ] + } + } + end + it 'succeeds when error matches' do expect(client).to receive(:get_widget).and_raise(my_error) expect do @@ -991,6 +450,25 @@ module Waiters describe 'output matcher' do context 'string equals comparator' do + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'OutputStringPropertyMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'stringProperty', + 'expected' => 'expected string', + 'comparator' => 'stringEquals' + } + } + } + ] + } + } + end + it 'succeeds when output matches' do output = { string_property: 'expected string' } expect(client).to receive(:get_widget).and_return(output) @@ -1030,6 +508,25 @@ module Waiters end context 'boolean equals comparator' do + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'OutputBooleanPropertyMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'booleanProperty', + 'expected' => 'false', + 'comparator' => 'booleanEquals' + } + } + } + ] + } + } + end + it 'succeeds when output matches' do output = { boolean_property: false } expect(client).to receive(:get_widget).and_return(output) @@ -1069,6 +566,25 @@ module Waiters end context 'all string equals comparator' do + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'OutputStringArrayAllPropertyMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'stringArrayProperty', + 'expected' => 'expected string', + 'comparator' => 'allStringEquals' + } + } + } + ] + } + } + end + it 'succeeds when output matches' do output = { string_array_property: [ @@ -1140,6 +656,25 @@ module Waiters end context 'any string equals comparator' do + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'OutputStringArrayAnyPropertyMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'stringArrayProperty', + 'expected' => 'expected string', + 'comparator' => 'anyStringEquals' + } + } + } + ] + } + } + end + it 'succeeds when output matches' do output = { string_array_property: [ @@ -1215,6 +750,25 @@ module Waiters end context 'flatten' do + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'FlattenMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'children[].grandchildren[].name', + 'expected' => 'expected name', + 'comparator' => 'anyStringEquals' + } + } + } + ] + } + } + end + it 'succeeds when matched' do output = { children: [ @@ -1263,6 +817,25 @@ module Waiters end context 'flatten length' do + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'FlattenLengthMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'length(children[].grandchildren[]) == `6`', + 'expected' => 'true', + 'comparator' => 'booleanEquals' + } + } + } + ] + } + } + end + it 'succeeds when matched' do output = { children: [ @@ -1331,6 +904,25 @@ module Waiters end context 'flatten filter' do + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'FlattenFilterMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'length(children[?length(grandchildren) == `3`]) == `1`', + 'expected' => 'true', + 'comparator' => 'booleanEquals' + } + } + } + ] + } + } + end + it 'succeeds when matched' do output = { children: [ @@ -1423,6 +1015,25 @@ module Waiters end context 'length flatten filter' do + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'LengthFlattenFilterMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'length((children[].grandchildren[])[?number > `4`]) == `3`', + 'expected' => 'true', + 'comparator' => 'booleanEquals' + } + } + } + ] + } + } + end + it 'succeeds when matched' do output = { children: [ @@ -1515,6 +1126,25 @@ module Waiters end context 'projection' do + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'ProjectionMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'dataMap.*', + 'expected' => 'abc', + 'comparator' => 'allStringEquals' + } + } + } + ] + } + } + end + it 'succeeds when matched' do output = { data_map: { @@ -1545,6 +1175,25 @@ module Waiters end context 'contains field' do + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'ContainsFieldMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'contains(dataMap.*, stringProperty)', + 'expected' => 'true', + 'comparator' => 'booleanEquals' + } + } + } + ] + } + } + end + it 'succeeds when matched' do output = { string_property: 'match', @@ -1577,6 +1226,25 @@ module Waiters end context 'and inequality' do + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'AndInequalityMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'length(dataMap) == `3` && length(stringArrayProperty) != `3`', + 'expected' => 'true', + 'comparator' => 'booleanEquals' + } + } + } + ] + } + } + end + it 'succeeds when matched' do output = { string_array_property: [ @@ -1617,6 +1285,25 @@ module Waiters end describe 'input output matcher' do + before(:each) do + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'InputOutputBooleanPropertyMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'inputOutput' => { + 'path' => 'input.stringProperty == output.stringProperty', + 'expected' => 'true', + 'comparator' => 'booleanEquals' + } + } + } + ] + } + } + end + it 'succeeds for boolean equals comparator' do output = { string_property: 'input_string' } expect(client).to receive(:get_widget).and_return(output) @@ -1627,12 +1314,47 @@ module Waiters end it 'checks acceptors in order' do - expect(client).to receive(:delete_widget).and_raise(widget_does_not_exist_error) + shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + 'AcceptorOrderSuccessMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'errorType' => 'WidgetDoesNotExistError' + } + }, + { + 'state' => 'failure', + 'matcher' => { + 'errorType' => 'WidgetDoesNotExistError' + } + } + ] + }, + 'AcceptorOrderFailureMatcher' => { + 'acceptors' => [ + { + 'state' => 'failure', + 'matcher' => { + 'errorType' => 'WidgetDoesNotExistError' + } + }, + { + 'state' => 'success', + 'matcher' => { + 'errorType' => 'WidgetDoesNotExistError' + } + } + ] + } + } + + expect(client).to receive(:get_widget).and_raise(widget_does_not_exist_error) expect do client.wait_until(:acceptor_order_success_matcher, input, max_wait_time: 60) end.to_not raise_error - expect(client).to receive(:delete_widget).and_raise(widget_does_not_exist_error) + expect(client).to receive(:get_widget).and_raise(widget_does_not_exist_error) expect do client.wait_until(:acceptor_order_failure_matcher, input, max_wait_time: 60) end.to raise_error(failure_state_error) From 93cd13db358b8e89ab755fa13f37c822c53943a0 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 7 May 2025 09:58:58 -0700 Subject: [PATCH 28/48] Remove extra error from spec --- .../spec/smithy-client/waiters_spec.rb | 29 ++++--------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index 710e92bcd..16eb5c1ae 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -28,9 +28,6 @@ module Waiters 'errors' => [ { 'target' => 'smithy.ruby.tests#MyError' - }, - { - 'target' => 'smithy.ruby.tests#WidgetDoesNotExistError' } ], 'traits' => { @@ -145,17 +142,6 @@ module Waiters 'traits' => { 'smithy.api#error' => 'client' } - }, - 'smithy.ruby.tests#WidgetDoesNotExistError' => { - 'type' => 'structure', - 'members' => { - 'message' => { - 'target' => 'smithy.api#String' - } - }, - 'traits' => { - 'smithy.api#error' => 'client' - } } } end @@ -172,9 +158,6 @@ module Waiters let(:waiter) { Waiter } let(:poller) { Poller } let(:my_error) { sample_client::Errors::MyError.new({}, message: 'my error message') } - let(:widget_does_not_exist_error) do - sample_client::Errors::WidgetDoesNotExistError.new({}, message: 'widget does not exist message') - end let(:unexpected_error) { Errors::UnexpectedError } let(:failure_state_error) { Errors::FailureStateError } let(:max_wait_time_exceeded_error) { Errors::MaxWaitTimeExceededError } @@ -1320,13 +1303,13 @@ module Waiters { 'state' => 'success', 'matcher' => { - 'errorType' => 'WidgetDoesNotExistError' + 'errorType' => 'MyError' } }, { 'state' => 'failure', 'matcher' => { - 'errorType' => 'WidgetDoesNotExistError' + 'errorType' => 'MyError' } } ] @@ -1336,25 +1319,25 @@ module Waiters { 'state' => 'failure', 'matcher' => { - 'errorType' => 'WidgetDoesNotExistError' + 'errorType' => 'MyError' } }, { 'state' => 'success', 'matcher' => { - 'errorType' => 'WidgetDoesNotExistError' + 'errorType' => 'MyError' } } ] } } - expect(client).to receive(:get_widget).and_raise(widget_does_not_exist_error) + expect(client).to receive(:get_widget).and_raise(my_error) expect do client.wait_until(:acceptor_order_success_matcher, input, max_wait_time: 60) end.to_not raise_error - expect(client).to receive(:get_widget).and_raise(widget_does_not_exist_error) + expect(client).to receive(:get_widget).and_raise(my_error) expect do client.wait_until(:acceptor_order_failure_matcher, input, max_wait_time: 60) end.to raise_error(failure_state_error) From 1fdd251d5a18db2382c67a6985bd7f3581b591a1 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 7 May 2025 12:53:57 -0700 Subject: [PATCH 29/48] Add wait_until documentation --- .../lib/smithy/templates/client/client.erb | 62 +++++++++++++++++++ projections/shapes/lib/shapes/client.rb | 62 +++++++++++++++++++ projections/shapes/lib/shapes/schema.rb | 60 +++++++++--------- .../spec/shapes/endpoint_provider_spec.rb | 6 +- projections/weather/lib/weather/client.rb | 62 +++++++++++++++++++ projections/weather/lib/weather/schema.rb | 50 +++++++-------- .../spec/weather/endpoint_provider_spec.rb | 6 +- 7 files changed, 247 insertions(+), 61 deletions(-) diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index 6a1a358b7..e46543ace 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -36,6 +36,68 @@ module <%= module_name %> end <% end -%> + # Polls an API operation until a resource enters a desired state. + # + # ## Basic Usage + # + # A waiter will call an API operation until: + # + # * It is successful + # * It enters a terminal state + # * It reaches the maximum wait time allowed + # + # In between attempts, the waiter will sleep. + # + # # polls in a loop, sleeping between attempts + # client.wait_until(waiter_name, params, options) + # + # ## Configuration + # + # You must configure the maximum amount of time in seconds a + # waiter should wait for. You may also configure the minimum + # and maximum amount of time in seconds to delay between + # retries. You can pass these configuration as the final + # arguments hash. + # + # # poll for a maximum of 25 seconds + # client.wait_until(waiter_name, params, { + # max_wait_time: 25, + # min_delay: 2, + # max_delay: 10 + # }) + # + # ## Handling Errors + # + # When a waiter is unsuccessful, it will raise an error. + # All the failure errors extend from + # {Smithy::Client::Waiters::Errors:WaiterFailed}. + # + # begin + # client.wait_until(...) + # rescue Smithy::Client::Waiters::Errors:WaiterFailed + # # resource did not enter the desired state in time + # end + # + # @raise [Errors::FailureStateError] Raised when the waiter terminates + # because the waiter has entered a state that it will not transition + # out of, preventing success. + # + # @raise [Errors::MaxWaitTimeExceededError] Raised when the configured + # maximum wait time is reached and the waiter is not yet successful. + # + # @raise [Errors::UnexpectedError] Raised when an error that is not + # expected is encountered while polling for a resource. + # + # @raise [Errors::NoSuchWaiterError] Raised when you request to wait + # for an unknown state. + # + # @return [Boolean] Returns `true` if the waiter was successful. + # @param [Symbol] waiter_name + # @param [Hash] params ({}) + # @param [Hash] options ({}) + # @option options [Integer] :max_wait_time + # @option options [Integer] :min_delay + # @option options [Integer] :max_delay def wait_until(waiter_name, params = {}, options = {}) w = waiter(waiter_name, options) w.wait(params) diff --git a/projections/shapes/lib/shapes/client.rb b/projections/shapes/lib/shapes/client.rb index 9b1ac2a89..8ec22f94c 100644 --- a/projections/shapes/lib/shapes/client.rb +++ b/projections/shapes/lib/shapes/client.rb @@ -264,6 +264,68 @@ def operation(params = {}, options = {}) input.send_request(options) end + # Polls an API operation until a resource enters a desired state. + # + # ## Basic Usage + # + # A waiter will call an API operation until: + # + # * It is successful + # * It enters a terminal state + # * It reaches the maximum wait time allowed + # + # In between attempts, the waiter will sleep. + # + # # polls in a loop, sleeping between attempts + # client.wait_until(waiter_name, params, options) + # + # ## Configuration + # + # You must configure the maximum amount of time in seconds a + # waiter should wait for. You may also configure the minimum + # and maximum amount of time in seconds to delay between + # retries. You can pass these configuration as the final + # arguments hash. + # + # # poll for a maximum of 25 seconds + # client.wait_until(waiter_name, params, { + # max_wait_time: 25, + # min_delay: 2, + # max_delay: 10 + # }) + # + # ## Handling Errors + # + # When a waiter is unsuccessful, it will raise an error. + # All the failure errors extend from + # {Smithy::Client::Waiters::Errors:WaiterFailed}. + # + # begin + # client.wait_until(...) + # rescue Smithy::Client::Waiters::Errors:WaiterFailed + # # resource did not enter the desired state in time + # end + # + # @raise [Errors::FailureStateError] Raised when the waiter terminates + # because the waiter has entered a state that it will not transition + # out of, preventing success. + # + # @raise [Errors::MaxWaitTimeExceededError] Raised when the configured + # maximum wait time is reached and the waiter is not yet successful. + # + # @raise [Errors::UnexpectedError] Raised when an error that is not + # expected is encountered while polling for a resource. + # + # @raise [Errors::NoSuchWaiterError] Raised when you request to wait + # for an unknown state. + # + # @return [Boolean] Returns `true` if the waiter was successful. + # @param [Symbol] waiter_name + # @param [Hash] params ({}) + # @param [Hash] options ({}) + # @option options [Integer] :max_wait_time + # @option options [Integer] :min_delay + # @option options [Integer] :max_delay def wait_until(waiter_name, params = {}, options = {}) w = waiter(waiter_name, options) w.wait(params) diff --git a/projections/shapes/lib/shapes/schema.rb b/projections/shapes/lib/shapes/schema.rb index 3300249a6..ea4c281ef 100644 --- a/projections/shapes/lib/shapes/schema.rb +++ b/projections/shapes/lib/shapes/schema.rb @@ -7,32 +7,32 @@ module ShapeService module Schema include Smithy::Schema::Shapes - BigDecimal = BigDecimalShape.new(id: 'smithy.ruby.tests#BigDecimal', traits: {"smithy.ruby.tests#shape"=>{}}) - BigInteger = IntegerShape.new(id: 'smithy.ruby.tests#BigInteger', traits: {"smithy.ruby.tests#shape"=>{}}) - Blob = BlobShape.new(id: 'smithy.ruby.tests#Blob', traits: {"smithy.ruby.tests#shape"=>{}}) - Boolean = BooleanShape.new(id: 'smithy.ruby.tests#Boolean', traits: {"smithy.ruby.tests#shape"=>{}}) - Byte = IntegerShape.new(id: 'smithy.ruby.tests#Byte', traits: {"smithy.ruby.tests#shape"=>{}}) - Document = DocumentShape.new(id: 'smithy.ruby.tests#Document', traits: {"smithy.ruby.tests#shape"=>{}}) - Double = FloatShape.new(id: 'smithy.ruby.tests#Double', traits: {"smithy.ruby.tests#shape"=>{}}) - Enum = EnumShape.new(id: 'smithy.ruby.tests#Enum', traits: {"smithy.ruby.tests#shape"=>{}}) - Float = FloatShape.new(id: 'smithy.ruby.tests#Float', traits: {"smithy.ruby.tests#shape"=>{}}) - IntEnum = IntEnumShape.new(id: 'smithy.ruby.tests#IntEnum', traits: {"smithy.ruby.tests#shape"=>{}}) - Integer = IntegerShape.new(id: 'smithy.ruby.tests#Integer', traits: {"smithy.ruby.tests#shape"=>{}}) - List = ListShape.new(id: 'smithy.ruby.tests#List', traits: {"smithy.ruby.tests#shape"=>{}}) - Long = IntegerShape.new(id: 'smithy.ruby.tests#Long', traits: {"smithy.ruby.tests#shape"=>{}}) - Map = MapShape.new(id: 'smithy.ruby.tests#Map', traits: {"smithy.ruby.tests#shape"=>{}}) + BigDecimal = BigDecimalShape.new(id: 'smithy.ruby.tests#BigDecimal', traits: {"smithy.ruby.tests#shape" => {}}) + BigInteger = IntegerShape.new(id: 'smithy.ruby.tests#BigInteger', traits: {"smithy.ruby.tests#shape" => {}}) + Blob = BlobShape.new(id: 'smithy.ruby.tests#Blob', traits: {"smithy.ruby.tests#shape" => {}}) + Boolean = BooleanShape.new(id: 'smithy.ruby.tests#Boolean', traits: {"smithy.ruby.tests#shape" => {}}) + Byte = IntegerShape.new(id: 'smithy.ruby.tests#Byte', traits: {"smithy.ruby.tests#shape" => {}}) + Document = DocumentShape.new(id: 'smithy.ruby.tests#Document', traits: {"smithy.ruby.tests#shape" => {}}) + Double = FloatShape.new(id: 'smithy.ruby.tests#Double', traits: {"smithy.ruby.tests#shape" => {}}) + Enum = EnumShape.new(id: 'smithy.ruby.tests#Enum', traits: {"smithy.ruby.tests#shape" => {}}) + Float = FloatShape.new(id: 'smithy.ruby.tests#Float', traits: {"smithy.ruby.tests#shape" => {}}) + IntEnum = IntEnumShape.new(id: 'smithy.ruby.tests#IntEnum', traits: {"smithy.ruby.tests#shape" => {}}) + Integer = IntegerShape.new(id: 'smithy.ruby.tests#Integer', traits: {"smithy.ruby.tests#shape" => {}}) + List = ListShape.new(id: 'smithy.ruby.tests#List', traits: {"smithy.ruby.tests#shape" => {}}) + Long = IntegerShape.new(id: 'smithy.ruby.tests#Long', traits: {"smithy.ruby.tests#shape" => {}}) + Map = MapShape.new(id: 'smithy.ruby.tests#Map', traits: {"smithy.ruby.tests#shape" => {}}) OperationInputOutput = StructureShape.new(id: 'smithy.ruby.tests#OperationInputOutput') - Short = IntegerShape.new(id: 'smithy.ruby.tests#Short', traits: {"smithy.ruby.tests#shape"=>{}}) - String = StringShape.new(id: 'smithy.ruby.tests#String', traits: {"smithy.ruby.tests#shape"=>{}}) - Structure = StructureShape.new(id: 'smithy.ruby.tests#Structure', traits: {"smithy.ruby.tests#shape"=>{}}) - Timestamp = TimestampShape.new(id: 'smithy.ruby.tests#Timestamp', traits: {"smithy.ruby.tests#shape"=>{}}) - Union = UnionShape.new(id: 'smithy.ruby.tests#Union', traits: {"smithy.ruby.tests#shape"=>{}}) + Short = IntegerShape.new(id: 'smithy.ruby.tests#Short', traits: {"smithy.ruby.tests#shape" => {}}) + String = StringShape.new(id: 'smithy.ruby.tests#String', traits: {"smithy.ruby.tests#shape" => {}}) + Structure = StructureShape.new(id: 'smithy.ruby.tests#Structure', traits: {"smithy.ruby.tests#shape" => {}}) + Timestamp = TimestampShape.new(id: 'smithy.ruby.tests#Timestamp', traits: {"smithy.ruby.tests#shape" => {}}) + Union = UnionShape.new(id: 'smithy.ruby.tests#Union', traits: {"smithy.ruby.tests#shape" => {}}) - Enum.add_member(:foo, ShapeRef.new(shape: Prelude::Unit, location_name: 'FOO', traits: {"smithy.api#enumValue"=>"bar"})) - IntEnum.add_member(:baz, ShapeRef.new(shape: Prelude::Unit, location_name: 'BAZ', traits: {"smithy.api#enumValue"=>1})) - List.member = ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape"=>{}}) - Map.key = ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape"=>{}}) - Map.value = ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape"=>{}}) + Enum.add_member(:foo, ShapeRef.new(shape: Prelude::Unit, location_name: 'FOO', traits: {"smithy.api#enumValue" => "bar"})) + IntEnum.add_member(:baz, ShapeRef.new(shape: Prelude::Unit, location_name: 'BAZ', traits: {"smithy.api#enumValue" => 1})) + List.member = ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape" => {}}) + Map.key = ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape" => {}}) + Map.value = ShapeRef.new(shape: String, traits: {"smithy.ruby.tests#shape" => {}}) OperationInputOutput.add_member(:blob, ShapeRef.new(shape: Blob, location_name: 'blob')) OperationInputOutput.add_member(:boolean, ShapeRef.new(shape: Boolean, location_name: 'boolean')) OperationInputOutput.add_member(:string, ShapeRef.new(shape: String, location_name: 'string')) @@ -53,11 +53,11 @@ module Schema OperationInputOutput.add_member(:structure, ShapeRef.new(shape: Structure, location_name: 'structure')) OperationInputOutput.add_member(:union, ShapeRef.new(shape: Union, location_name: 'union')) OperationInputOutput.type = Types::OperationInputOutput - Structure.add_member(:member, ShapeRef.new(shape: String, location_name: 'member', traits: {"smithy.ruby.tests#shape"=>{}})) + Structure.add_member(:member, ShapeRef.new(shape: String, location_name: 'member', traits: {"smithy.ruby.tests#shape" => {}})) Structure.type = Types::Structure - Union.add_member(:string, Types::Union::String, ShapeRef.new(shape: String, location_name: 'string', traits: {"smithy.ruby.tests#shape"=>{}})) - Union.add_member(:structure, Types::Union::Structure, ShapeRef.new(shape: Structure, location_name: 'structure', traits: {"smithy.ruby.tests#shape"=>{}})) - Union.add_member(:unit, Types::Union::Unit, ShapeRef.new(shape: Prelude::Unit, location_name: 'unit', traits: {"smithy.ruby.tests#shape"=>{}})) + Union.add_member(:string, Types::Union::String, ShapeRef.new(shape: String, location_name: 'string', traits: {"smithy.ruby.tests#shape" => {}})) + Union.add_member(:structure, Types::Union::Structure, ShapeRef.new(shape: Structure, location_name: 'structure', traits: {"smithy.ruby.tests#shape" => {}})) + Union.add_member(:unit, Types::Union::Unit, ShapeRef.new(shape: Prelude::Unit, location_name: 'unit', traits: {"smithy.ruby.tests#shape" => {}})) Union.add_member(:unknown, Types::Union::Unknown, ShapeRef.new(shape: Prelude::Unit)) Union.type = Types::Union @@ -65,14 +65,14 @@ module Schema service.id = "smithy.ruby.tests#ShapeService" service.name = "ShapeService" service.version = "2018-10-31" - service.traits = {"smithy.ruby.tests#shape"=>{}} + service.traits = {"smithy.ruby.tests#shape" => {}} service.add_operation(:operation, OperationShape.new do |operation| operation.id = "smithy.ruby.tests#Operation" operation.name = "Operation" operation.input = ShapeRef.new(shape: OperationInputOutput) operation.output = ShapeRef.new(shape: OperationInputOutput) # TODO: support parsing errors defined at the service level - operation.traits = {"smithy.ruby.tests#shape"=>{}} + operation.traits = {"smithy.ruby.tests#shape" => {}} end) end end diff --git a/projections/shapes/spec/shapes/endpoint_provider_spec.rb b/projections/shapes/spec/shapes/endpoint_provider_spec.rb index ef6f43250..4a984e3c4 100644 --- a/projections/shapes/spec/shapes/endpoint_provider_spec.rb +++ b/projections/shapes/spec/shapes/endpoint_provider_spec.rb @@ -10,11 +10,11 @@ module ShapeService context "Endpoint set" do let(:expected) do - {"endpoint"=>{"url"=>"https://example.com"}} + {"endpoint" => {"url" => "https://example.com"}} end it 'produces the expected output from the EndpointProvider' do - params = EndpointParameters.new(**{:endpoint=>"https://example.com"}) + params = EndpointParameters.new(**{endpoint: "https://example.com"}) endpoint = subject.resolve(params) expect(endpoint.uri).to eq(expected['endpoint']['url']) expect(endpoint.headers).to eq(expected['endpoint']['headers'] || {}) @@ -25,7 +25,7 @@ module ShapeService context "Endpoint not set" do let(:expected) do - {"error"=>"Endpoint is not set - you must configure an endpoint."} + {"error" => "Endpoint is not set - you must configure an endpoint."} end it 'produces the expected output from the EndpointProvider' do diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index a00425181..77da6361b 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -252,6 +252,68 @@ def list_cities(params = {}, options = {}) input.send_request(options) end + # Polls an API operation until a resource enters a desired state. + # + # ## Basic Usage + # + # A waiter will call an API operation until: + # + # * It is successful + # * It enters a terminal state + # * It reaches the maximum wait time allowed + # + # In between attempts, the waiter will sleep. + # + # # polls in a loop, sleeping between attempts + # client.wait_until(waiter_name, params, options) + # + # ## Configuration + # + # You must configure the maximum amount of time in seconds a + # waiter should wait for. You may also configure the minimum + # and maximum amount of time in seconds to delay between + # retries. You can pass these configuration as the final + # arguments hash. + # + # # poll for a maximum of 25 seconds + # client.wait_until(waiter_name, params, { + # max_wait_time: 25, + # min_delay: 2, + # max_delay: 10 + # }) + # + # ## Handling Errors + # + # When a waiter is unsuccessful, it will raise an error. + # All the failure errors extend from + # {Smithy::Client::Waiters::Errors:WaiterFailed}. + # + # begin + # client.wait_until(...) + # rescue Smithy::Client::Waiters::Errors:WaiterFailed + # # resource did not enter the desired state in time + # end + # + # @raise [Errors::FailureStateError] Raised when the waiter terminates + # because the waiter has entered a state that it will not transition + # out of, preventing success. + # + # @raise [Errors::MaxWaitTimeExceededError] Raised when the configured + # maximum wait time is reached and the waiter is not yet successful. + # + # @raise [Errors::UnexpectedError] Raised when an error that is not + # expected is encountered while polling for a resource. + # + # @raise [Errors::NoSuchWaiterError] Raised when you request to wait + # for an unknown state. + # + # @return [Boolean] Returns `true` if the waiter was successful. + # @param [Symbol] waiter_name + # @param [Hash] params ({}) + # @param [Hash] options ({}) + # @option options [Integer] :max_wait_time + # @option options [Integer] :min_delay + # @option options [Integer] :max_delay def wait_until(waiter_name, params = {}, options = {}) w = waiter(waiter_name, options) w.wait(params) diff --git a/projections/weather/lib/weather/schema.rb b/projections/weather/lib/weather/schema.rb index ef6f32adb..7e3096f66 100644 --- a/projections/weather/lib/weather/schema.rb +++ b/projections/weather/lib/weather/schema.rb @@ -8,33 +8,33 @@ module Schema include Smithy::Schema::Shapes CityCoordinates = StructureShape.new(id: 'example.weather#CityCoordinates') - CityId = StringShape.new(id: 'example.weather#CityId', traits: {"smithy.api#pattern"=>"^[A-Za-z0-9 ]+$"}) + CityId = StringShape.new(id: 'example.weather#CityId', traits: {"smithy.api#pattern" => "^[A-Za-z0-9 ]+$"}) CitySummaries = ListShape.new(id: 'example.weather#CitySummaries') - CitySummary = StructureShape.new(id: 'example.weather#CitySummary', traits: {"smithy.api#references"=>[{"resource"=>"example.weather#City"}]}) - GetCityInput = StructureShape.new(id: 'example.weather#GetCityInput', traits: {"smithy.api#input"=>{}}) - GetCityOutput = StructureShape.new(id: 'example.weather#GetCityOutput', traits: {"smithy.api#output"=>{}}) - GetCurrentTimeOutput = StructureShape.new(id: 'example.weather#GetCurrentTimeOutput', traits: {"smithy.api#output"=>{}}) - GetForecastInput = StructureShape.new(id: 'example.weather#GetForecastInput', traits: {"smithy.api#input"=>{}}) - GetForecastOutput = StructureShape.new(id: 'example.weather#GetForecastOutput', traits: {"smithy.api#output"=>{}}) - ListCitiesInput = StructureShape.new(id: 'example.weather#ListCitiesInput', traits: {"smithy.api#input"=>{}}) - ListCitiesOutput = StructureShape.new(id: 'example.weather#ListCitiesOutput', traits: {"smithy.api#output"=>{}}) - NoSuchResource = StructureShape.new(id: 'example.weather#NoSuchResource', traits: {"smithy.api#error"=>"client"}) + CitySummary = StructureShape.new(id: 'example.weather#CitySummary', traits: {"smithy.api#references" => [{"resource" => "example.weather#City"}]}) + GetCityInput = StructureShape.new(id: 'example.weather#GetCityInput', traits: {"smithy.api#input" => {}}) + GetCityOutput = StructureShape.new(id: 'example.weather#GetCityOutput', traits: {"smithy.api#output" => {}}) + GetCurrentTimeOutput = StructureShape.new(id: 'example.weather#GetCurrentTimeOutput', traits: {"smithy.api#output" => {}}) + GetForecastInput = StructureShape.new(id: 'example.weather#GetForecastInput', traits: {"smithy.api#input" => {}}) + GetForecastOutput = StructureShape.new(id: 'example.weather#GetForecastOutput', traits: {"smithy.api#output" => {}}) + ListCitiesInput = StructureShape.new(id: 'example.weather#ListCitiesInput', traits: {"smithy.api#input" => {}}) + ListCitiesOutput = StructureShape.new(id: 'example.weather#ListCitiesOutput', traits: {"smithy.api#output" => {}}) + NoSuchResource = StructureShape.new(id: 'example.weather#NoSuchResource', traits: {"smithy.api#error" => "client"}) - CityCoordinates.add_member(:latitude, ShapeRef.new(shape: Prelude::Float, location_name: 'latitude', traits: {"smithy.api#required"=>{}})) - CityCoordinates.add_member(:longitude, ShapeRef.new(shape: Prelude::Float, location_name: 'longitude', traits: {"smithy.api#required"=>{}})) + CityCoordinates.add_member(:latitude, ShapeRef.new(shape: Prelude::Float, location_name: 'latitude', traits: {"smithy.api#required" => {}})) + CityCoordinates.add_member(:longitude, ShapeRef.new(shape: Prelude::Float, location_name: 'longitude', traits: {"smithy.api#required" => {}})) CityCoordinates.type = Types::CityCoordinates CitySummaries.member = ShapeRef.new(shape: CitySummary) - CitySummary.add_member(:city_id, ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required"=>{}})) - CitySummary.add_member(:name, ShapeRef.new(shape: Prelude::String, location_name: 'name', traits: {"smithy.api#required"=>{}})) + CitySummary.add_member(:city_id, ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required" => {}})) + CitySummary.add_member(:name, ShapeRef.new(shape: Prelude::String, location_name: 'name', traits: {"smithy.api#required" => {}})) CitySummary.type = Types::CitySummary - GetCityInput.add_member(:city_id, ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required"=>{}})) + GetCityInput.add_member(:city_id, ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required" => {}})) GetCityInput.type = Types::GetCityInput - GetCityOutput.add_member(:name, ShapeRef.new(shape: Prelude::String, location_name: 'name', traits: {"smithy.api#notProperty"=>{}, "smithy.api#required"=>{}})) - GetCityOutput.add_member(:coordinates, ShapeRef.new(shape: CityCoordinates, location_name: 'coordinates', traits: {"smithy.api#required"=>{}})) + GetCityOutput.add_member(:name, ShapeRef.new(shape: Prelude::String, location_name: 'name', traits: {"smithy.api#notProperty" => {}, "smithy.api#required" => {}})) + GetCityOutput.add_member(:coordinates, ShapeRef.new(shape: CityCoordinates, location_name: 'coordinates', traits: {"smithy.api#required" => {}})) GetCityOutput.type = Types::GetCityOutput - GetCurrentTimeOutput.add_member(:time, ShapeRef.new(shape: Prelude::Timestamp, location_name: 'time', traits: {"smithy.api#required"=>{}})) + GetCurrentTimeOutput.add_member(:time, ShapeRef.new(shape: Prelude::Timestamp, location_name: 'time', traits: {"smithy.api#required" => {}})) GetCurrentTimeOutput.type = Types::GetCurrentTimeOutput - GetForecastInput.add_member(:city_id, ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required"=>{}})) + GetForecastInput.add_member(:city_id, ShapeRef.new(shape: CityId, location_name: 'cityId', traits: {"smithy.api#required" => {}})) GetForecastInput.type = Types::GetForecastInput GetForecastOutput.add_member(:chance_of_rain, ShapeRef.new(shape: Prelude::Float, location_name: 'chanceOfRain')) GetForecastOutput.type = Types::GetForecastOutput @@ -42,9 +42,9 @@ module Schema ListCitiesInput.add_member(:page_size, ShapeRef.new(shape: Prelude::Integer, location_name: 'pageSize')) ListCitiesInput.type = Types::ListCitiesInput ListCitiesOutput.add_member(:next_token, ShapeRef.new(shape: Prelude::String, location_name: 'nextToken')) - ListCitiesOutput.add_member(:items, ShapeRef.new(shape: CitySummaries, location_name: 'items', traits: {"smithy.api#required"=>{}})) + ListCitiesOutput.add_member(:items, ShapeRef.new(shape: CitySummaries, location_name: 'items', traits: {"smithy.api#required" => {}})) ListCitiesOutput.type = Types::ListCitiesOutput - NoSuchResource.add_member(:resource_type, ShapeRef.new(shape: Prelude::String, location_name: 'resourceType', traits: {"smithy.api#required"=>{}})) + NoSuchResource.add_member(:resource_type, ShapeRef.new(shape: Prelude::String, location_name: 'resourceType', traits: {"smithy.api#required" => {}})) NoSuchResource.type = Types::NoSuchResource SERVICE = ServiceShape.new do |service| @@ -59,7 +59,7 @@ module Schema operation.output = ShapeRef.new(shape: GetCityOutput) # TODO: support parsing errors defined at the service level operation.errors << ShapeRef.new(shape: NoSuchResource) - operation.traits = {"smithy.api#readonly"=>{}} + operation.traits = {"smithy.api#readonly" => {}} end) service.add_operation(:get_current_time, OperationShape.new do |operation| operation.id = "example.weather#GetCurrentTime" @@ -67,7 +67,7 @@ module Schema operation.input = ShapeRef.new(shape: Prelude::Unit) operation.output = ShapeRef.new(shape: GetCurrentTimeOutput) # TODO: support parsing errors defined at the service level - operation.traits = {"smithy.api#readonly"=>{}} + operation.traits = {"smithy.api#readonly" => {}} end) service.add_operation(:get_forecast, OperationShape.new do |operation| operation.id = "example.weather#GetForecast" @@ -75,7 +75,7 @@ module Schema operation.input = ShapeRef.new(shape: GetForecastInput) operation.output = ShapeRef.new(shape: GetForecastOutput) # TODO: support parsing errors defined at the service level - operation.traits = {"smithy.api#readonly"=>{}} + operation.traits = {"smithy.api#readonly" => {}} end) service.add_operation(:list_cities, OperationShape.new do |operation| operation.id = "example.weather#ListCities" @@ -83,7 +83,7 @@ module Schema operation.input = ShapeRef.new(shape: ListCitiesInput) operation.output = ShapeRef.new(shape: ListCitiesOutput) # TODO: support parsing errors defined at the service level - operation.traits = {"smithy.api#readonly"=>{}} + operation.traits = {"smithy.api#readonly" => {}} operation[:paginator] = Paginators::ListCities.new end) end diff --git a/projections/weather/spec/weather/endpoint_provider_spec.rb b/projections/weather/spec/weather/endpoint_provider_spec.rb index 5b7901ebd..226652f4c 100644 --- a/projections/weather/spec/weather/endpoint_provider_spec.rb +++ b/projections/weather/spec/weather/endpoint_provider_spec.rb @@ -10,11 +10,11 @@ module Weather context "Endpoint set" do let(:expected) do - {"endpoint"=>{"url"=>"https://example.com"}} + {"endpoint" => {"url" => "https://example.com"}} end it 'produces the expected output from the EndpointProvider' do - params = EndpointParameters.new(**{:endpoint=>"https://example.com"}) + params = EndpointParameters.new(**{endpoint: "https://example.com"}) endpoint = subject.resolve(params) expect(endpoint.uri).to eq(expected['endpoint']['url']) expect(endpoint.headers).to eq(expected['endpoint']['headers'] || {}) @@ -25,7 +25,7 @@ module Weather context "Endpoint not set" do let(:expected) do - {"error"=>"Endpoint is not set - you must configure an endpoint."} + {"error" => "Endpoint is not set - you must configure an endpoint."} end it 'produces the expected output from the EndpointProvider' do From b01734dfe87ed025dc83bbc2e0e9ab315d5a3f0f Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 7 May 2025 13:05:22 -0700 Subject: [PATCH 30/48] Move waiters errors to smithy client errors --- .../smithy-client/lib/smithy-client/errors.rb | 38 +++++++++++++++++++ .../lib/smithy-client/waiters/waiter.rb | 6 +-- .../spec/smithy-client/waiters_spec.rb | 8 ++-- .../lib/smithy/templates/client/client.erb | 4 +- .../spec/interfaces/client/waiters_spec.rb | 4 +- projections/shapes/lib/shapes/client.rb | 4 +- projections/weather/lib/weather/client.rb | 4 +- 7 files changed, 53 insertions(+), 15 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/errors.rb b/gems/smithy-client/lib/smithy-client/errors.rb index 766c5ae9e..065853f6f 100644 --- a/gems/smithy-client/lib/smithy-client/errors.rb +++ b/gems/smithy-client/lib/smithy-client/errors.rb @@ -3,6 +3,44 @@ module Smithy module Client module Errors + # Raised when a waiter detects a condition where the waiter can never + # succeed. + class WaiterFailed < StandardError; end + + # Raised when a waiter enters a failure state. + class FailureStateError < WaiterFailed + def initialize(error) + msg = "stopped waiting, encountered a failure state: #{error}" + super(msg) + end + end + + # Raised when the total wait time of a waiter exceeds the maximum + # wait time. + class MaxWaitTimeExceededError < WaiterFailed + def initialize(max_wait_time) + msg = "stopped waiting after maximum wait time of #{max_wait_time} seconds was exceeded" + super(msg) + end + end + + # Raised when a waiter encounters an unexpected error. + class UnexpectedError < WaiterFailed + def initialize(error) + msg = "stopped waiting due to an unexpected error: #{error}" + super(msg) + end + end + + # Raised when attempting to get a waiter by name and the waiter has not + # been defined. + class NoSuchWaiterError < ArgumentError + def initialize(waiter_name, valid_waiters) + msg = "no such waiter: #{waiter_name}; valid waiter names are: #{valid_waiters}" + super(msg) + end + end + # Raised when calling {PageableOutput#next_page} on a paginator that # is on the last page of results. You can call {PageableOutput#last_page?} # or {PageableOutput#next_page?} to know if there are more pages. diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index 3fdcf2414..e9a5ea20e 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -48,10 +48,10 @@ def poll(client, params) case status when :success then return output_or_error - when :failure then raise Errors::FailureStateError, output_or_error - when :error then raise Errors::UnexpectedError, output_or_error + when :failure then raise Smithy::Client::Errors::FailureStateError, output_or_error + when :error then raise Smithy::Client::Errors::UnexpectedError, output_or_error when :retry - raise Errors::MaxWaitTimeExceededError, @max_wait_time if @remaining_time.zero? + raise Smithy::Client::Errors::MaxWaitTimeExceededError, @max_wait_time if @remaining_time.zero? delay = delay(attempts) @remaining_time -= delay diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index 16eb5c1ae..4a2ffb703 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -158,10 +158,10 @@ module Waiters let(:waiter) { Waiter } let(:poller) { Poller } let(:my_error) { sample_client::Errors::MyError.new({}, message: 'my error message') } - let(:unexpected_error) { Errors::UnexpectedError } - let(:failure_state_error) { Errors::FailureStateError } - let(:max_wait_time_exceeded_error) { Errors::MaxWaitTimeExceededError } - let(:no_such_waiter_error) { Errors::NoSuchWaiterError } + let(:unexpected_error) { Smithy::Client::Errors::UnexpectedError } + let(:failure_state_error) { Smithy::Client::Errors::FailureStateError } + let(:max_wait_time_exceeded_error) { Smithy::Client::Errors::MaxWaitTimeExceededError } + let(:no_such_waiter_error) { Smithy::Client::Errors::NoSuchWaiterError } describe 'waiter' do before(:each) do diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index e46543ace..e36188235 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -74,7 +74,7 @@ module <%= module_name %> # # begin # client.wait_until(...) - # rescue Smithy::Client::Waiters::Errors:WaiterFailed + # rescue Smithy::Client::Errors:WaiterFailed # # resource did not enter the desired state in time # end # @@ -124,7 +124,7 @@ module <%= module_name %> if waiter_class waiter_class.new(options.merge(client: self)) else - raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new(waiter_name, waiters.keys) + raise Smithy::Client::Errors::NoSuchWaiterError.new(waiter_name, waiters.keys) end end diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index 093bffa21..ce5462f18 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -5,7 +5,7 @@ describe 'Client: Waiters' do let(:input) { { string_property: 'input_string' } } let(:client) { WaiterService::Client.new(stub_responses: true) } - let(:no_such_waiter_error) { Smithy::Client::Waiters::Errors::NoSuchWaiterError } + let(:no_such_waiter_error) { Smithy::Client::Errors::NoSuchWaiterError } ['generated client gem', 'generated client from source code'].each do |context| context context do @@ -30,7 +30,7 @@ expect(client).to receive(:get_operation).and_raise(StandardError) expect do client.wait_until(:success_matcher, input, max_wait_time: 60) - end.to raise_error(Smithy::Client::Waiters::Errors::UnexpectedError) + end.to raise_error(Smithy::Client::Errors::UnexpectedError) end it 'raises an error for nonexistent waiters' do diff --git a/projections/shapes/lib/shapes/client.rb b/projections/shapes/lib/shapes/client.rb index 8ec22f94c..157826cbb 100644 --- a/projections/shapes/lib/shapes/client.rb +++ b/projections/shapes/lib/shapes/client.rb @@ -302,7 +302,7 @@ def operation(params = {}, options = {}) # # begin # client.wait_until(...) - # rescue Smithy::Client::Waiters::Errors:WaiterFailed + # rescue Smithy::Client::Errors:WaiterFailed # # resource did not enter the desired state in time # end # @@ -352,7 +352,7 @@ def waiter(waiter_name, options = {}) if waiter_class waiter_class.new(options.merge(client: self)) else - raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new(waiter_name, waiters.keys) + raise Smithy::Client::Errors::NoSuchWaiterError.new(waiter_name, waiters.keys) end end diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index 77da6361b..55b1171fc 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -290,7 +290,7 @@ def list_cities(params = {}, options = {}) # # begin # client.wait_until(...) - # rescue Smithy::Client::Waiters::Errors:WaiterFailed + # rescue Smithy::Client::Errors:WaiterFailed # # resource did not enter the desired state in time # end # @@ -340,7 +340,7 @@ def waiter(waiter_name, options = {}) if waiter_class waiter_class.new(options.merge(client: self)) else - raise Smithy::Client::Waiters::Errors::NoSuchWaiterError.new(waiter_name, waiters.keys) + raise Smithy::Client::Errors::NoSuchWaiterError.new(waiter_name, waiters.keys) end end From 7a6b4d276f68e71e4c2f1192ebd6c5ad7c00e685 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 7 May 2025 14:26:04 -0700 Subject: [PATCH 31/48] Preprocess error type --- .../lib/smithy-client/waiters/poller.rb | 3 +-- .../spec/smithy-client/waiters_spec.rb | 19 ++++++++++++++++++- .../smithy/lib/smithy/views/client/waiters.rb | 14 +++++++++----- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index b1415bd16..aa383576b 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -70,8 +70,7 @@ def matches_success?(path_matcher, output, error) def matches_errorType?(path_matcher, output, error) # rubocop:disable Naming/MethodName return false unless output.nil? - err = path_matcher.split('#').last.split('#').first - error.class.to_s.include?(err) + error.class.to_s.include?(path_matcher) end def equal?(actual, expected, comparator) diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index 4a2ffb703..eaf363615 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -400,17 +400,34 @@ module Waiters } } ] + }, + 'AbsoluteErrorTypeMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'errorType' => 'smithy.ruby.tests#MyError' + } + } + ] } } end - it 'succeeds when error matches' do + it 'succeeds when error matches for relative shape name' do expect(client).to receive(:get_widget).and_raise(my_error) expect do client.wait_until(:error_type_matcher, input, max_wait_time: 60) end.to_not raise_error end + it 'succeeds when error matches for absolute shape id' do + expect(client).to receive(:get_widget).and_raise(my_error) + expect do + client.wait_until(:absolute_error_type_matcher, input, max_wait_time: 60) + end.to_not raise_error + end + it 'retries and succeeds when matched' do output = {} 2.times do diff --git a/gems/smithy/lib/smithy/views/client/waiters.rb b/gems/smithy/lib/smithy/views/client/waiters.rb index bf1baa4d5..76c9e2945 100644 --- a/gems/smithy/lib/smithy/views/client/waiters.rb +++ b/gems/smithy/lib/smithy/views/client/waiters.rb @@ -51,11 +51,7 @@ def initialize(operation, name, waiter) attr_reader :operation_name, :name, :documentation, :acceptors, :min_delay, :max_delay, :deprecated def formatted_acceptors(acceptors) - acceptors.each do |acceptor| - if (matcher = acceptor['matcher']['output'] || acceptor['matcher']['inputOutput']) - matcher['path'] = Util::Underscore.underscore_jmespath(matcher['path']) - end - end + acceptors.each { |acceptor| preprocess_acceptor(acceptor) } Util::HashFormatter.new( wrap: false, @@ -64,6 +60,14 @@ def formatted_acceptors(acceptors) indent: ' ' ).format(acceptors: acceptors) end + + def preprocess_acceptor(acceptor) + if (matcher = acceptor['matcher']['output'] || acceptor['matcher']['inputOutput']) + matcher['path'] = Util::Underscore.underscore_jmespath(matcher['path']) + elsif (error_type = acceptor['matcher']['errorType']) + acceptor['matcher']['errorType'] = error_type.split('#').last.split('#').first + end + end end end end From f8493edd4b53574a690033c9d27beb80d1bd32bd Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 7 May 2025 14:43:39 -0700 Subject: [PATCH 32/48] Use docstrings --- gems/smithy/lib/smithy/templates/client/waiters.erb | 4 +++- gems/smithy/lib/smithy/views/client/waiters.rb | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/gems/smithy/lib/smithy/templates/client/waiters.erb b/gems/smithy/lib/smithy/templates/client/waiters.erb index 636d62bc6..25f892e6e 100644 --- a/gems/smithy/lib/smithy/templates/client/waiters.erb +++ b/gems/smithy/lib/smithy/templates/client/waiters.erb @@ -14,7 +14,9 @@ module <%= module_name %> <% end -%> # @api private # - # <%= waiter.documentation %> +<% waiter.docstrings.each do |docstring| -%> + # <%= docstring %> +<% end -%> # class <%= waiter.name %> def initialize(options = {}) diff --git a/gems/smithy/lib/smithy/views/client/waiters.rb b/gems/smithy/lib/smithy/views/client/waiters.rb index 76c9e2945..b2765e379 100644 --- a/gems/smithy/lib/smithy/views/client/waiters.rb +++ b/gems/smithy/lib/smithy/views/client/waiters.rb @@ -50,6 +50,10 @@ def initialize(operation, name, waiter) attr_reader :operation_name, :name, :documentation, :acceptors, :min_delay, :max_delay, :deprecated + def docstrings + @documentation.split("\n") + end + def formatted_acceptors(acceptors) acceptors.each { |acceptor| preprocess_acceptor(acceptor) } From 6ef2dfd39726712527be735c3d1e734d55545988 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 7 May 2025 14:54:15 -0700 Subject: [PATCH 33/48] Remove waiters/errors --- .../lib/smithy-client/waiters.rb | 1 - .../lib/smithy-client/waiters/errors.rb | 47 ------------------- 2 files changed, 48 deletions(-) delete mode 100644 gems/smithy-client/lib/smithy-client/waiters/errors.rb diff --git a/gems/smithy-client/lib/smithy-client/waiters.rb b/gems/smithy-client/lib/smithy-client/waiters.rb index 0ea0c7dab..af72f6309 100644 --- a/gems/smithy-client/lib/smithy-client/waiters.rb +++ b/gems/smithy-client/lib/smithy-client/waiters.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require_relative 'waiters/errors' require_relative 'waiters/poller' require_relative 'waiters/waiter' diff --git a/gems/smithy-client/lib/smithy-client/waiters/errors.rb b/gems/smithy-client/lib/smithy-client/waiters/errors.rb deleted file mode 100644 index bd5b887b3..000000000 --- a/gems/smithy-client/lib/smithy-client/waiters/errors.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -module Smithy - module Client - module Waiters - module Errors - # Raised when a waiter detects a condition where the waiter can never - # succeed. - class WaiterFailed < StandardError; end - - # Raised when a waiter enters a failure state. - class FailureStateError < WaiterFailed - def initialize(error) - msg = "stopped waiting, encountered a failure state: #{error}" - super(msg) - end - end - - # Raised when the total wait time of a waiter exceeds the maximum - # wait time. - class MaxWaitTimeExceededError < WaiterFailed - def initialize(max_wait_time) - msg = "stopped waiting after maximum wait time of #{max_wait_time} seconds was exceeded" - super(msg) - end - end - - # Raised when a waiter encounters an unexpected error. - class UnexpectedError < WaiterFailed - def initialize(error) - msg = "stopped waiting due to an unexpected error: #{error}" - super(msg) - end - end - - # Raised when attempting to get a waiter by name and the waiter has not - # been defined. - class NoSuchWaiterError < ArgumentError - def initialize(waiter_name, valid_waiters) - msg = "no such waiter: #{waiter_name}; valid waiter names are: #{valid_waiters}" - super(msg) - end - end - end - end - end -end From df637698d427c581e7498a22faea1556661ecf5a Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 7 May 2025 14:58:48 -0700 Subject: [PATCH 34/48] Add documentation check --- gems/smithy/lib/smithy/views/client/waiters.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gems/smithy/lib/smithy/views/client/waiters.rb b/gems/smithy/lib/smithy/views/client/waiters.rb index b2765e379..63856283f 100644 --- a/gems/smithy/lib/smithy/views/client/waiters.rb +++ b/gems/smithy/lib/smithy/views/client/waiters.rb @@ -51,7 +51,7 @@ def initialize(operation, name, waiter) attr_reader :operation_name, :name, :documentation, :acceptors, :min_delay, :max_delay, :deprecated def docstrings - @documentation.split("\n") + @documentation.split("\n") if @documentation end def formatted_acceptors(acceptors) From e58f50c892c03db3b76a0836e674b5f13d5f4497 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 7 May 2025 15:06:27 -0700 Subject: [PATCH 35/48] Fix documentation check --- gems/smithy/lib/smithy/views/client/waiters.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gems/smithy/lib/smithy/views/client/waiters.rb b/gems/smithy/lib/smithy/views/client/waiters.rb index 63856283f..9b5fbb71b 100644 --- a/gems/smithy/lib/smithy/views/client/waiters.rb +++ b/gems/smithy/lib/smithy/views/client/waiters.rb @@ -51,7 +51,7 @@ def initialize(operation, name, waiter) attr_reader :operation_name, :name, :documentation, :acceptors, :min_delay, :max_delay, :deprecated def docstrings - @documentation.split("\n") if @documentation + @documentation ? @documentation.split("\n") : [] end def formatted_acceptors(acceptors) From 874cf2825075351fc06284031d40bcba75e7d6e1 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 8 May 2025 13:06:37 -0700 Subject: [PATCH 36/48] Handle raise response error enabled and use stub responses for tests --- .../lib/smithy-client/waiters/poller.rb | 48 +++-- .../lib/smithy-client/waiters/waiter.rb | 8 +- .../spec/smithy-client/waiters_spec.rb | 192 +++++++++--------- .../spec/fixtures/waiter_service/model.json | 52 ++++- .../spec/fixtures/waiter_service/model.smithy | 2 + .../fixtures/waiter_service/smithy-build.json | 3 +- .../spec/interfaces/client/waiters_spec.rb | 8 +- 7 files changed, 180 insertions(+), 133 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index aa383576b..a70d6b554 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -13,64 +13,62 @@ def initialize(options = {}) def call(client, params) @input = params - begin - output = client.send(@operation_name, params) - rescue StandardError => e - error = e - end - output_or_error = output || error - status = evaluate_acceptors(output, error) - [output_or_error, status.to_sym] + # TODO: make build_input public and update this line + input = client.send(:build_input, @operation_name, params) + input.handlers.remove(Smithy::Client::Plugins::RaiseResponseErrors::Handler) + output = input.send_request + status = evaluate_acceptors(output) + [output, status.to_sym] end private - def evaluate_acceptors(output, error) + def evaluate_acceptors(output) @acceptors.each do |acceptor| - return acceptor['state'] if acceptor_matches?(acceptor['matcher'], output, error) + return acceptor['state'] if acceptor_matches?(acceptor['matcher'], output) end - if error + if !output.error.nil? 'error' else 'retry' end end - def acceptor_matches?(matcher, output, error) + def acceptor_matches?(matcher, output) matcher_type = matcher.keys.first - send("matches_#{matcher_type}?", matcher[matcher_type], output, error) + send("matches_#{matcher_type}?", matcher[matcher_type], output) end - def matches_output?(path_matcher, output, error) - return false unless error.nil? + def matches_output?(path_matcher, output) + return false unless !output.data.nil? - actual = JMESPath.search(path_matcher['path'], output) + actual = JMESPath.search(path_matcher['path'], output.data) equal?(actual, path_matcher['expected'], path_matcher['comparator']) end - def matches_inputOutput?(path_matcher, output, error) # rubocop:disable Naming/MethodName - return false unless error.nil? && @input + def matches_inputOutput?(path_matcher, output) # rubocop:disable Naming/MethodName + return false unless !output.data.nil? && @input data = { input: @input, - output: output + output: output.data } actual = JMESPath.search(path_matcher['path'], data) equal?(actual, path_matcher['expected'], path_matcher['comparator']) end - def matches_success?(path_matcher, output, error) + def matches_success?(path_matcher, output) if path_matcher == true - !output.nil? + !output.data.nil? else - !error.nil? + !output.error.nil? end end - def matches_errorType?(path_matcher, output, error) # rubocop:disable Naming/MethodName - return false unless output.nil? + def matches_errorType?(path_matcher, output) # rubocop:disable Naming/MethodName + return false unless !output.error.nil? - error.class.to_s.include?(path_matcher) + output.error.class.to_s.include?(path_matcher) end def equal?(actual, expected, comparator) diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index e9a5ea20e..d1186c269 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -43,13 +43,13 @@ def min_delay(delay) def poll(client, params) attempts = 0 loop do - output_or_error, status = @poller.call(client, params) + output, status = @poller.call(client, params) attempts += 1 case status - when :success then return output_or_error - when :failure then raise Smithy::Client::Errors::FailureStateError, output_or_error - when :error then raise Smithy::Client::Errors::UnexpectedError, output_or_error + when :success then return output.data + when :failure then raise Smithy::Client::Errors::FailureStateError, output.error + when :error then raise Smithy::Client::Errors::UnexpectedError, output.error when :retry raise Smithy::Client::Errors::MaxWaitTimeExceededError, @max_wait_time if @remaining_time.zero? diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index eaf363615..ad2b8ec78 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -15,7 +15,8 @@ module Waiters { 'target' => 'smithy.ruby.tests#GetWidget' } - ] + ], + 'traits' => { 'smithy.protocols#rpcv2Cbor' => {} } }, 'smithy.ruby.tests#GetWidget' => { 'type' => 'operation', @@ -150,6 +151,8 @@ module Waiters client_class = sample_client.const_get(:Client) client_class.clear_plugins client_class.add_plugin(sample_client::Plugins::Endpoint) + client_class.add_plugin(Smithy::Client::Plugins::Protocol) + client_class.add_plugin(Smithy::Client::Plugins::RaiseResponseErrors) client_class.add_plugin(Smithy::Client::Plugins::StubResponses) client_class end @@ -192,27 +195,29 @@ module Waiters describe '#poll' do it 'delays when status is retry' do - output = { string_property: 'expected' } + output = Smithy::Client::Output.new(data: { string_property: 'expected' }) expect_any_instance_of(poller).to receive(:call).and_return([{}, :retry], [output, :success]) expect_any_instance_of(waiter).to receive(:delay).and_return(0) expect(client.wait_until(:success_true_matcher, input, max_wait_time: 60)).to eq(output) end it 'returns output when status is success' do - output = { string_property: 'expected' } + output = Smithy::Client::Output.new(data: { string_property: 'expected' }) expect_any_instance_of(poller).to receive(:call).and_return([output, :success]) expect(client.wait_until(:success_true_matcher, input, max_wait_time: 60)).to eq(output) end it 'raises a failure state error when status is failure' do - expect_any_instance_of(poller).to receive(:call).and_return([my_error, :failure]) + output = Smithy::Client::Output.new(error: my_error) + expect_any_instance_of(poller).to receive(:call).and_return([output, :failure]) expect do client.wait_until(:success_false_matcher, input, max_wait_time: 60) end.to raise_error(failure_state_error) end it 'raises an unexpected error when status is error' do - expect_any_instance_of(poller).to receive(:call).and_return([StandardError, :error]) + output = Smithy::Client::Output.new(error: StandardError) + expect_any_instance_of(poller).to receive(:call).and_return([output, :error]) expect do client.wait_until(:success_false_matcher, input, max_wait_time: 60) end.to raise_error(unexpected_error) @@ -236,8 +241,9 @@ module Waiters min_delay: min_delay, max_delay: max_delay } + output = Smithy::Client::Output.new(data: {}) expect_any_instance_of(poller).to receive(:call).and_return( - [{}, :retry], [{}, :retry], [{}, :retry], [{}, :success] + [output, :retry], [output, :retry], [output, :retry], [output, :success] ) expect_any_instance_of(waiter).to receive(:delay).with(1).and_wrap_original do |m, *args| delay = m.call(*args) @@ -266,7 +272,8 @@ module Waiters min_delay: min_delay, max_delay: max_delay } - expect_any_instance_of(poller).to receive(:call).and_return([{}, :retry], [{}, :success]) + output = Smithy::Client::Output.new(data: {}) + expect_any_instance_of(poller).to receive(:call).and_return([output, :retry], [output, :success]) expect_any_instance_of(waiter).to receive(:delay).and_wrap_original do |m, *args| delay = m.call(*args) expect(delay).to eq(remaining_time) @@ -278,8 +285,7 @@ module Waiters context 'errors' do it 'raises an error when max wait time is exceeded' do - output = {} - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, {}) expect do client.wait_until(:success_false_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) @@ -354,34 +360,34 @@ module Waiters end it 'succeeds when success is set to true and successful response is received' do - output = {} - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, {}) expect do client.wait_until(:success_true_matcher, input, max_wait_time: 60) end.to_not raise_error end it 'succeeds when success is set to false and error is received' do - expect(client).to receive(:get_widget).and_raise(StandardError) + client.stub_responses(:get_widget, StandardError.new) expect do - client.wait_until(:success_false_matcher, input, max_wait_time: 60) + client.wait_until(:success_false_matcher, input, max_wait_time: 3) end.to_not raise_error end it 'retries and succeeds when matched' do - output = {} - 2.times do - expect(client).to receive(:get_widget).and_return(output) - expect_any_instance_of(waiter).to receive(:delay).and_return(0) - end - expect(client).to receive(:get_widget).and_raise(StandardError) + client.stub_responses( + :get_widget, + {}, + {}, + StandardError + ) + expect_any_instance_of(waiter).to receive(:delay).twice.and_return(0) expect do client.wait_until(:success_false_matcher, input, max_wait_time: 60) end.to_not raise_error end it 'fails when success is set to true and unexpected error is received' do - expect(client).to receive(:get_widget).and_raise(StandardError) + client.stub_responses(:get_widget, StandardError) expect do client.wait_until(:success_true_matcher, input, max_wait_time: 60) end.to raise_error(unexpected_error) @@ -415,33 +421,34 @@ module Waiters end it 'succeeds when error matches for relative shape name' do - expect(client).to receive(:get_widget).and_raise(my_error) + client.stub_responses(:get_widget, my_error) expect do client.wait_until(:error_type_matcher, input, max_wait_time: 60) end.to_not raise_error end it 'succeeds when error matches for absolute shape id' do - expect(client).to receive(:get_widget).and_raise(my_error) + client.stub_responses(:get_widget, my_error) expect do client.wait_until(:absolute_error_type_matcher, input, max_wait_time: 60) end.to_not raise_error end it 'retries and succeeds when matched' do - output = {} - 2.times do - expect(client).to receive(:get_widget).and_return(output) - expect_any_instance_of(waiter).to receive(:delay).and_return(0) - end - expect(client).to receive(:get_widget).and_raise(my_error) + client.stub_responses( + :get_widget, + {}, + {}, + my_error + ) + expect_any_instance_of(waiter).to receive(:delay).twice.and_return(0) expect do client.wait_until(:error_type_matcher, input, max_wait_time: 60) end.to_not raise_error end it 'fails when error does not match' do - expect(client).to receive(:get_widget).and_raise(StandardError) + client.stub_responses(:get_widget, StandardError) expect do client.wait_until(:error_type_matcher, input, max_wait_time: 60) end.to raise_error(unexpected_error) @@ -470,37 +477,34 @@ module Waiters end it 'succeeds when output matches' do - output = { string_property: 'expected string' } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, { string_property: 'expected string' }) expect do client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) end.to_not raise_error end it 'retries and succeeds when matched' do - output_expected = { string_property: 'expected string' } - output_unexpected = { string_property: 'unexpected string' } - 2.times do - expect(client).to receive(:get_widget).and_return(output_unexpected) - expect_any_instance_of(waiter).to receive(:delay).and_return(0) - end - expect(client).to receive(:get_widget).and_return(output_expected) + client.stub_responses( + :get_widget, + { string_property: 'unexpected string' }, + { string_property: 'unexpected string' }, + { string_property: 'expected string' } + ) + expect_any_instance_of(waiter).to receive(:delay).twice.and_return(0) expect do client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) end.to_not raise_error end it 'fails when output property does not match' do - output_unexpected = { string_property: 'unexpected string' } - expect(client).to receive(:get_widget).and_return(output_unexpected) + client.stub_responses(:get_widget, { string_property: 'unexpected string' }) expect do client.wait_until(:output_string_property_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) end it 'fails when output property is null' do - output_unexpected = {} - expect(client).to receive(:get_widget).and_return(output_unexpected) + client.stub_responses(:get_widget, {}) expect do client.wait_until(:output_string_property_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) @@ -528,37 +532,34 @@ module Waiters end it 'succeeds when output matches' do - output = { boolean_property: false } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, { boolean_property: false }) expect do client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) end.to_not raise_error end it 'retries and succeeds when matched' do - output_expected = { boolean_property: false } - output_unexpected = { boolean_property: true } - 2.times do - expect(client).to receive(:get_widget).and_return(output_unexpected) - expect_any_instance_of(waiter).to receive(:delay).and_return(0) - end - expect(client).to receive(:get_widget).and_return(output_expected) + client.stub_responses( + :get_widget, + { boolean_property: true }, + { boolean_property: true }, + { boolean_property: false } + ) + expect_any_instance_of(waiter).to receive(:delay).twice.and_return(0) expect do client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) end.to_not raise_error end it 'fails when output property does not match' do - output_unexpected = { boolean_property: true } - expect(client).to receive(:get_widget).and_return(output_unexpected) + client.stub_responses(:get_widget, { boolean_property: true }) expect do client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) end it 'fails when output property is null' do - output_unexpected = {} - expect(client).to receive(:get_widget).and_return(output_unexpected) + client.stub_responses(:get_widget, {}) expect do client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) @@ -593,7 +594,7 @@ module Waiters 'expected string' ] } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -614,11 +615,13 @@ module Waiters 'unexpected string' ] } - 2.times do - expect(client).to receive(:get_widget).and_return(output_unexpected) - expect_any_instance_of(waiter).to receive(:delay).and_return(0) - end - expect(client).to receive(:get_widget).and_return(output_expected) + client.stub_responses( + :get_widget, + output_unexpected, + output_unexpected, + output_expected + ) + expect_any_instance_of(waiter).to receive(:delay).twice.and_return(0) expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -632,23 +635,21 @@ module Waiters 'unexpected string' ] } - expect(client).to receive(:get_widget).and_return(output_unexpected) + client.stub_responses(:get_widget, output_unexpected) expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) end it 'fails when output property is empty' do - output_unexpected = { string_array_property: [] } - expect(client).to receive(:get_widget).and_return(output_unexpected) + client.stub_responses(:get_widget, { string_array_property: [] }) expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) end it 'fails when output property is null' do - output_unexpected = {} - expect(client).to receive(:get_widget).and_return(output_unexpected) + client.stub_responses(:get_widget, {}) expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) @@ -684,7 +685,7 @@ module Waiters 'yet another string' ] } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -707,11 +708,13 @@ module Waiters 'yet another string' ] } - 2.times do - expect(client).to receive(:get_widget).and_return(output_unexpected) - expect_any_instance_of(waiter).to receive(:delay).and_return(0) - end - expect(client).to receive(:get_widget).and_return(output_expected) + client.stub_responses( + :get_widget, + output_unexpected, + output_unexpected, + output_expected + ) + expect_any_instance_of(waiter).to receive(:delay).twice.and_return(0) expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -726,23 +729,21 @@ module Waiters 'yet another string' ] } - expect(client).to receive(:get_widget).and_return(output_unexpected) + client.stub_responses(:get_widget, output_unexpected) expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) end it 'fails when output property is empty' do - output_unexpected = { string_array_property: [] } - expect(client).to receive(:get_widget).and_return(output_unexpected) + client.stub_responses(:get_widget, { string_array_property: [] }) expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) end it 'fails when output property is null' do - output_unexpected = {} - expect(client).to receive(:get_widget).and_return(output_unexpected) + client.stub_responses(:get_widget, {}) expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) @@ -790,7 +791,7 @@ module Waiters } ] } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:flatten_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -809,7 +810,7 @@ module Waiters } ] } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:flatten_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) @@ -877,7 +878,7 @@ module Waiters } ] } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:flatten_length_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -896,7 +897,7 @@ module Waiters } ] } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:flatten_length_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) @@ -964,7 +965,7 @@ module Waiters } ] } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:flatten_filter_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -1007,7 +1008,7 @@ module Waiters } ] } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:flatten_filter_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) @@ -1075,7 +1076,7 @@ module Waiters } ] } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -1118,7 +1119,7 @@ module Waiters } ] } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) @@ -1153,7 +1154,7 @@ module Waiters 'key3' => 'abc' } } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:projection_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -1167,7 +1168,7 @@ module Waiters 'key3' => 'ghi' } } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:projection_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) @@ -1203,7 +1204,7 @@ module Waiters 'key3' => 'not a match' } } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:contains_field_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -1218,7 +1219,7 @@ module Waiters 'key3' => 'not a match' } } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:contains_field_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) @@ -1257,7 +1258,7 @@ module Waiters 'key3' => 'three' } } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:and_inequality_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -1276,7 +1277,7 @@ module Waiters 'key3' => 'three' } } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, output) expect do client.wait_until(:and_inequality_matcher, input, max_wait_time: 0) end.to raise_error(max_wait_time_exceeded_error) @@ -1305,8 +1306,7 @@ module Waiters end it 'succeeds for boolean equals comparator' do - output = { string_property: 'input_string' } - expect(client).to receive(:get_widget).and_return(output) + client.stub_responses(:get_widget, { string_property: 'input_string' }) expect do client.wait_until(:input_output_boolean_property_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -1348,13 +1348,11 @@ module Waiters ] } } - - expect(client).to receive(:get_widget).and_raise(my_error) + client.stub_responses(:get_widget, my_error) expect do client.wait_until(:acceptor_order_success_matcher, input, max_wait_time: 60) end.to_not raise_error - - expect(client).to receive(:get_widget).and_raise(my_error) + client.stub_responses(:get_widget, my_error) expect do client.wait_until(:acceptor_order_failure_matcher, input, max_wait_time: 60) end.to raise_error(failure_state_error) diff --git a/gems/smithy/spec/fixtures/waiter_service/model.json b/gems/smithy/spec/fixtures/waiter_service/model.json index 57a8a698c..610e349ed 100644 --- a/gems/smithy/spec/fixtures/waiter_service/model.json +++ b/gems/smithy/spec/fixtures/waiter_service/model.json @@ -1,6 +1,53 @@ { "smithy": "2.0", "shapes": { + "smithy.protocols#StringList": { + "type": "list", + "member": { + "target": "smithy.api#String" + }, + "traits": { + "smithy.api#documentation": "A list of String shapes.", + "smithy.api#private": {} + } + }, + "smithy.protocols#rpcv2Cbor": { + "type": "structure", + "members": { + "http": { + "target": "smithy.protocols#StringList", + "traits": { + "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions." + } + }, + "eventStreamHttp": { + "target": "smithy.protocols#StringList", + "traits": { + "smithy.api#documentation": "Priority ordered list of supported HTTP protocol versions\nthat are required when using event streams." + } + } + }, + "traits": { + "smithy.api#documentation": "An RPC-based protocol that serializes CBOR payloads.", + "smithy.api#protocolDefinition": { + "traits": [ + "smithy.api#cors", + "smithy.api#endpoint", + "smithy.api#hostLabel", + "smithy.api#httpError" + ] + }, + "smithy.api#trait": { + "selector": "service" + }, + "smithy.api#traitValidators": { + "rpcv2Cbor.NoDocuments": { + "selector": "service ~> member :test(> document)", + "message": "This protocol does not support document types" + } + } + } + }, "smithy.ruby.tests#BooleanArray": { "type": "list", "member": { @@ -154,7 +201,10 @@ { "target": "smithy.ruby.tests#GetOperation" } - ] + ], + "traits": { + "smithy.protocols#rpcv2Cbor": {} + } }, "smithy.waiters#Acceptor": { "type": "structure", diff --git a/gems/smithy/spec/fixtures/waiter_service/model.smithy b/gems/smithy/spec/fixtures/waiter_service/model.smithy index b22226f4b..9dc83c3ad 100644 --- a/gems/smithy/spec/fixtures/waiter_service/model.smithy +++ b/gems/smithy/spec/fixtures/waiter_service/model.smithy @@ -3,7 +3,9 @@ $version: "2" namespace smithy.ruby.tests use smithy.waiters#waitable +use smithy.protocols#rpcv2Cbor +@rpcv2Cbor service WaiterService { version: "2022-11-30", operations: [GetOperation] diff --git a/gems/smithy/spec/fixtures/waiter_service/smithy-build.json b/gems/smithy/spec/fixtures/waiter_service/smithy-build.json index 7cb8c3841..6a48179f7 100644 --- a/gems/smithy/spec/fixtures/waiter_service/smithy-build.json +++ b/gems/smithy/spec/fixtures/waiter_service/smithy-build.json @@ -2,7 +2,8 @@ "version": "1.0", "maven": { "dependencies": [ - "software.amazon.smithy:smithy-waiters:1.56.0" + "software.amazon.smithy:smithy-waiters:1.56.0", + "software.amazon.smithy:smithy-protocol-traits:1.56.0" ] } } \ No newline at end of file diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index ce5462f18..23d5fd8f3 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -12,22 +12,20 @@ include_context context, 'WaiterService' it 'returns when successful' do - output = {} - expect(client).to receive(:get_operation).and_return(output) + client.stub_responses(:get_operation, {}) expect do client.wait_until(:success_matcher, input, max_wait_time: 60) end.to_not raise_error end it 'returns output when successful' do - output = { string_property: 'success' } - expect(client).to receive(:get_operation).and_return(output) + client.stub_responses(:get_operation, { string_property: 'success' }) resp = client.wait_until(:success_matcher, input, max_wait_time: 60) expect(resp[:string_property]).to eq('success') end it 'raises an error when unsuccessful' do - expect(client).to receive(:get_operation).and_raise(StandardError) + client.stub_responses(:get_operation, StandardError) expect do client.wait_until(:success_matcher, input, max_wait_time: 60) end.to raise_error(Smithy::Client::Errors::UnexpectedError) From c7c81dd82230d5c961a4b774eca0d440ab70f62e Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 8 May 2025 13:16:14 -0700 Subject: [PATCH 37/48] Update wait_until to return nil upon success --- .../lib/smithy-client/waiters/poller.rb | 10 +++++----- .../lib/smithy-client/waiters/waiter.rb | 2 +- .../spec/smithy-client/waiters_spec.rb | 4 ++-- .../lib/smithy/templates/client/client.erb | 2 +- .../spec/interfaces/client/waiters_spec.rb | 16 ++++------------ projections/shapes/lib/shapes/client.rb | 2 +- projections/weather/lib/weather/client.rb | 2 +- 7 files changed, 15 insertions(+), 23 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index a70d6b554..10fa05e46 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -27,10 +27,10 @@ def evaluate_acceptors(output) @acceptors.each do |acceptor| return acceptor['state'] if acceptor_matches?(acceptor['matcher'], output) end - if !output.error.nil? - 'error' - else + if output.error.nil? 'retry' + else + 'error' end end @@ -40,7 +40,7 @@ def acceptor_matches?(matcher, output) end def matches_output?(path_matcher, output) - return false unless !output.data.nil? + return false if output.data.nil? actual = JMESPath.search(path_matcher['path'], output.data) equal?(actual, path_matcher['expected'], path_matcher['comparator']) @@ -66,7 +66,7 @@ def matches_success?(path_matcher, output) end def matches_errorType?(path_matcher, output) # rubocop:disable Naming/MethodName - return false unless !output.error.nil? + return false if output.error.nil? output.error.class.to_s.include?(path_matcher) end diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index d1186c269..9c4302cbd 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -47,7 +47,7 @@ def poll(client, params) attempts += 1 case status - when :success then return output.data + when :success then return when :failure then raise Smithy::Client::Errors::FailureStateError, output.error when :error then raise Smithy::Client::Errors::UnexpectedError, output.error when :retry diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index ad2b8ec78..0795f4e17 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -198,13 +198,13 @@ module Waiters output = Smithy::Client::Output.new(data: { string_property: 'expected' }) expect_any_instance_of(poller).to receive(:call).and_return([{}, :retry], [output, :success]) expect_any_instance_of(waiter).to receive(:delay).and_return(0) - expect(client.wait_until(:success_true_matcher, input, max_wait_time: 60)).to eq(output) + expect(client.wait_until(:success_true_matcher, input, max_wait_time: 60)).to eq(nil) end it 'returns output when status is success' do output = Smithy::Client::Output.new(data: { string_property: 'expected' }) expect_any_instance_of(poller).to receive(:call).and_return([output, :success]) - expect(client.wait_until(:success_true_matcher, input, max_wait_time: 60)).to eq(output) + expect(client.wait_until(:success_true_matcher, input, max_wait_time: 60)).to eq(nil) end it 'raises a failure state error when status is failure' do diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index e36188235..bbe31e81e 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -91,7 +91,7 @@ module <%= module_name %> # @raise [Errors::NoSuchWaiterError] Raised when you request to wait # for an unknown state. # - # @return [Boolean] Returns `true` if the waiter was successful. + # @return [nil] Returns `nil` if the waiter was successful. # @param [Symbol] waiter_name # @param [Hash] params ({}) # @param [Hash] options ({}) diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index 23d5fd8f3..f0d3f88dc 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -11,24 +11,16 @@ context context do include_context context, 'WaiterService' - it 'returns when successful' do - client.stub_responses(:get_operation, {}) - expect do - client.wait_until(:success_matcher, input, max_wait_time: 60) - end.to_not raise_error - end - - it 'returns output when successful' do + it 'returns nil when successful' do client.stub_responses(:get_operation, { string_property: 'success' }) - resp = client.wait_until(:success_matcher, input, max_wait_time: 60) - expect(resp[:string_property]).to eq('success') + expect(client.wait_until(:success_matcher, input, max_wait_time: 60)).to be(nil) end - it 'raises an error when unsuccessful' do + it 'raises waiter failed error when unsuccessful' do client.stub_responses(:get_operation, StandardError) expect do client.wait_until(:success_matcher, input, max_wait_time: 60) - end.to raise_error(Smithy::Client::Errors::UnexpectedError) + end.to raise_error(Smithy::Client::Errors::WaiterFailed) end it 'raises an error for nonexistent waiters' do diff --git a/projections/shapes/lib/shapes/client.rb b/projections/shapes/lib/shapes/client.rb index 157826cbb..dd4de4fb2 100644 --- a/projections/shapes/lib/shapes/client.rb +++ b/projections/shapes/lib/shapes/client.rb @@ -319,7 +319,7 @@ def operation(params = {}, options = {}) # @raise [Errors::NoSuchWaiterError] Raised when you request to wait # for an unknown state. # - # @return [Boolean] Returns `true` if the waiter was successful. + # @return [nil] Returns `nil` if the waiter was successful. # @param [Symbol] waiter_name # @param [Hash] params ({}) # @param [Hash] options ({}) diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index 55b1171fc..45bd1a1d6 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -307,7 +307,7 @@ def list_cities(params = {}, options = {}) # @raise [Errors::NoSuchWaiterError] Raised when you request to wait # for an unknown state. # - # @return [Boolean] Returns `true` if the waiter was successful. + # @return [nil] Returns `nil` if the waiter was successful. # @param [Symbol] waiter_name # @param [Hash] params ({}) # @param [Hash] options ({}) From 470b0d3d814046be2af487c73473bb757529a944 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Thu, 8 May 2025 13:27:38 -0700 Subject: [PATCH 38/48] Cleanup fixture --- .../spec/smithy-client/waiters_spec.rb | 2 +- .../spec/fixtures/waiter_service/model.json | 106 ------------------ .../spec/fixtures/waiter_service/model.smithy | 52 +-------- 3 files changed, 2 insertions(+), 158 deletions(-) diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index 0795f4e17..accaab508 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -201,7 +201,7 @@ module Waiters expect(client.wait_until(:success_true_matcher, input, max_wait_time: 60)).to eq(nil) end - it 'returns output when status is success' do + it 'returns nil when status is success' do output = Smithy::Client::Output.new(data: { string_property: 'expected' }) expect_any_instance_of(poller).to receive(:call).and_return([output, :success]) expect(client.wait_until(:success_true_matcher, input, max_wait_time: 60)).to eq(nil) diff --git a/gems/smithy/spec/fixtures/waiter_service/model.json b/gems/smithy/spec/fixtures/waiter_service/model.json index 610e349ed..af68663c6 100644 --- a/gems/smithy/spec/fixtures/waiter_service/model.json +++ b/gems/smithy/spec/fixtures/waiter_service/model.json @@ -48,43 +48,6 @@ } } }, - "smithy.ruby.tests#BooleanArray": { - "type": "list", - "member": { - "target": "smithy.api#Boolean" - } - }, - "smithy.ruby.tests#Child": { - "type": "structure", - "members": { - "grandchildren": { - "target": "smithy.ruby.tests#GrandchildArray" - } - } - }, - "smithy.ruby.tests#ChildArray": { - "type": "list", - "member": { - "target": "smithy.ruby.tests#Child" - } - }, - "smithy.ruby.tests#DataMap": { - "type": "map", - "key": { - "target": "smithy.api#String" - }, - "value": { - "target": "smithy.api#String" - } - }, - "smithy.ruby.tests#DeletedWidgetOutput": { - "type": "structure", - "members": { - "stringProperty": { - "target": "smithy.api#String" - } - } - }, "smithy.ruby.tests#GetOperation": { "type": "operation", "input": { @@ -93,11 +56,6 @@ "output": { "target": "smithy.ruby.tests#OperationOutput" }, - "errors": [ - { - "target": "smithy.ruby.tests#MyError" - } - ], "traits": { "smithy.waiters#waitable": { "SuccessMatcher": { @@ -114,54 +72,11 @@ } } }, - "smithy.ruby.tests#Grandchild": { - "type": "structure", - "members": { - "name": { - "target": "smithy.api#String" - }, - "number": { - "target": "smithy.api#Integer" - } - } - }, - "smithy.ruby.tests#GrandchildArray": { - "type": "list", - "member": { - "target": "smithy.ruby.tests#Grandchild" - } - }, - "smithy.ruby.tests#MyError": { - "type": "structure", - "members": { - "message": { - "target": "smithy.api#String" - } - }, - "traits": { - "smithy.api#error": "client" - } - }, "smithy.ruby.tests#OperationInput": { "type": "structure", "members": { "stringProperty": { "target": "smithy.api#String" - }, - "stringArrayProperty": { - "target": "smithy.ruby.tests#StringArray" - }, - "booleanProperty": { - "target": "smithy.api#Boolean" - }, - "booleanArrayProperty": { - "target": "smithy.ruby.tests#BooleanArray" - }, - "children": { - "target": "smithy.ruby.tests#ChildArray" - }, - "dataMap": { - "target": "smithy.ruby.tests#DataMap" } } }, @@ -170,30 +85,9 @@ "members": { "stringProperty": { "target": "smithy.api#String" - }, - "stringArrayProperty": { - "target": "smithy.ruby.tests#StringArray" - }, - "booleanProperty": { - "target": "smithy.api#Boolean" - }, - "booleanArrayProperty": { - "target": "smithy.ruby.tests#BooleanArray" - }, - "children": { - "target": "smithy.ruby.tests#ChildArray" - }, - "dataMap": { - "target": "smithy.ruby.tests#DataMap" } } }, - "smithy.ruby.tests#StringArray": { - "type": "list", - "member": { - "target": "smithy.api#String" - } - }, "smithy.ruby.tests#WaiterService": { "type": "service", "version": "2022-11-30", diff --git a/gems/smithy/spec/fixtures/waiter_service/model.smithy b/gems/smithy/spec/fixtures/waiter_service/model.smithy index 9dc83c3ad..e06e63193 100644 --- a/gems/smithy/spec/fixtures/waiter_service/model.smithy +++ b/gems/smithy/spec/fixtures/waiter_service/model.smithy @@ -27,62 +27,12 @@ service WaiterService { operation GetOperation { input: OperationInput, output: OperationOutput - errors: [MyError] } structure OperationInput { stringProperty: String - stringArrayProperty: StringArray - booleanProperty: Boolean - booleanArrayProperty: BooleanArray - children: ChildArray - dataMap: DataMap } structure OperationOutput { stringProperty: String - stringArrayProperty: StringArray - booleanProperty: Boolean - booleanArrayProperty: BooleanArray - children: ChildArray - dataMap: DataMap -} - -structure DeletedWidgetOutput { - stringProperty: String -} - -structure Child { - grandchildren: GrandchildArray -} - -structure Grandchild { - name: String - number: Integer -} - -list StringArray{ - member: String -} - -list BooleanArray{ - member: Boolean -} - -list ChildArray { - member: Child -} - -list GrandchildArray { - member: Grandchild -} - -map DataMap { - key: String - value: String -} - -@error("client") -structure MyError { - message: String -} +} \ No newline at end of file From dd11d0ec4fd4970c60a025dc8c4ee1ecf7f14023 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Fri, 9 May 2025 08:58:11 -0700 Subject: [PATCH 39/48] Fix RBS errors --- gems/smithy-client/spec/smithy-client/waiters_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index accaab508..2776897b2 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -160,7 +160,7 @@ module Waiters let(:input) { { string_property: 'input_string' } } let(:waiter) { Waiter } let(:poller) { Poller } - let(:my_error) { sample_client::Errors::MyError.new({}, message: 'my error message') } + let(:my_error) { sample_client::Errors::MyError.new(nil, nil) } let(:unexpected_error) { Smithy::Client::Errors::UnexpectedError } let(:failure_state_error) { Smithy::Client::Errors::FailureStateError } let(:max_wait_time_exceeded_error) { Smithy::Client::Errors::MaxWaitTimeExceededError } @@ -503,7 +503,7 @@ module Waiters end.to raise_error(max_wait_time_exceeded_error) end - it 'fails when output property is null' do + it 'fails when output property is nil' do client.stub_responses(:get_widget, {}) expect do client.wait_until(:output_string_property_matcher, input, max_wait_time: 0) @@ -558,7 +558,7 @@ module Waiters end.to raise_error(max_wait_time_exceeded_error) end - it 'fails when output property is null' do + it 'fails when output property is nil' do client.stub_responses(:get_widget, {}) expect do client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 0) @@ -648,7 +648,7 @@ module Waiters end.to raise_error(max_wait_time_exceeded_error) end - it 'fails when output property is null' do + it 'fails when output property is nil' do client.stub_responses(:get_widget, {}) expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) @@ -742,7 +742,7 @@ module Waiters end.to raise_error(max_wait_time_exceeded_error) end - it 'fails when output property is null' do + it 'fails when output property is nil' do client.stub_responses(:get_widget, {}) expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) From 25394d54717b8cfa1a1b724a7d889f8dcd5de441 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Mon, 19 May 2025 13:44:47 -0700 Subject: [PATCH 40/48] Add some fixes from PR comments --- gems/smithy-client/lib/smithy-client.rb | 2 + .../smithy-client/lib/smithy-client/errors.rb | 38 --- .../lib/smithy-client/waiters.rb | 4 - .../lib/smithy-client/waiters/poller.rb | 26 +- .../lib/smithy-client/waiters/waiter.rb | 44 +++- .../spec/smithy-client/waiters_spec.rb | 247 +++++++++--------- .../lib/smithy/templates/client/client.erb | 14 +- .../lib/smithy/templates/client/waiters.erb | 2 - .../spec/interfaces/client/waiters_spec.rb | 4 +- 9 files changed, 187 insertions(+), 194 deletions(-) delete mode 100644 gems/smithy-client/lib/smithy-client/waiters.rb diff --git a/gems/smithy-client/lib/smithy-client.rb b/gems/smithy-client/lib/smithy-client.rb index a92a23ab4..f05c5791b 100644 --- a/gems/smithy-client/lib/smithy-client.rb +++ b/gems/smithy-client/lib/smithy-client.rb @@ -25,6 +25,8 @@ require_relative 'smithy-client/plugin_list' require_relative 'smithy-client/retry' require_relative 'smithy-client/util' +require_relative 'smithy-client/waiters/poller' +require_relative 'smithy-client/waiters/waiter' require_relative 'smithy-client/input' require_relative 'smithy-client/output' require_relative 'smithy-client/base' diff --git a/gems/smithy-client/lib/smithy-client/errors.rb b/gems/smithy-client/lib/smithy-client/errors.rb index 065853f6f..766c5ae9e 100644 --- a/gems/smithy-client/lib/smithy-client/errors.rb +++ b/gems/smithy-client/lib/smithy-client/errors.rb @@ -3,44 +3,6 @@ module Smithy module Client module Errors - # Raised when a waiter detects a condition where the waiter can never - # succeed. - class WaiterFailed < StandardError; end - - # Raised when a waiter enters a failure state. - class FailureStateError < WaiterFailed - def initialize(error) - msg = "stopped waiting, encountered a failure state: #{error}" - super(msg) - end - end - - # Raised when the total wait time of a waiter exceeds the maximum - # wait time. - class MaxWaitTimeExceededError < WaiterFailed - def initialize(max_wait_time) - msg = "stopped waiting after maximum wait time of #{max_wait_time} seconds was exceeded" - super(msg) - end - end - - # Raised when a waiter encounters an unexpected error. - class UnexpectedError < WaiterFailed - def initialize(error) - msg = "stopped waiting due to an unexpected error: #{error}" - super(msg) - end - end - - # Raised when attempting to get a waiter by name and the waiter has not - # been defined. - class NoSuchWaiterError < ArgumentError - def initialize(waiter_name, valid_waiters) - msg = "no such waiter: #{waiter_name}; valid waiter names are: #{valid_waiters}" - super(msg) - end - end - # Raised when calling {PageableOutput#next_page} on a paginator that # is on the last page of results. You can call {PageableOutput#last_page?} # or {PageableOutput#next_page?} to know if there are more pages. diff --git a/gems/smithy-client/lib/smithy-client/waiters.rb b/gems/smithy-client/lib/smithy-client/waiters.rb deleted file mode 100644 index af72f6309..000000000 --- a/gems/smithy-client/lib/smithy-client/waiters.rb +++ /dev/null @@ -1,4 +0,0 @@ -# frozen_string_literal: true - -require_relative 'waiters/poller' -require_relative 'waiters/waiter' diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index 10fa05e46..68ef17527 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -27,11 +27,7 @@ def evaluate_acceptors(output) @acceptors.each do |acceptor| return acceptor['state'] if acceptor_matches?(acceptor['matcher'], output) end - if output.error.nil? - 'retry' - else - 'error' - end + output.error.nil? ? 'retry' : 'error' end def acceptor_matches?(matcher, output) @@ -46,7 +42,8 @@ def matches_output?(path_matcher, output) equal?(actual, path_matcher['expected'], path_matcher['comparator']) end - def matches_inputOutput?(path_matcher, output) # rubocop:disable Naming/MethodName + # rubocop:disable Naming/MethodName + def matches_inputOutput?(path_matcher, output) return false unless !output.data.nil? && @input data = { @@ -58,14 +55,10 @@ def matches_inputOutput?(path_matcher, output) # rubocop:disable Naming/MethodNa end def matches_success?(path_matcher, output) - if path_matcher == true - !output.data.nil? - else - !output.error.nil? - end + path_matcher == true ? !output.data.nil? : !output.error.nil? end - def matches_errorType?(path_matcher, output) # rubocop:disable Naming/MethodName + def matches_errorType?(path_matcher, output) return false if output.error.nil? output.error.class.to_s.include?(path_matcher) @@ -75,25 +68,26 @@ def equal?(actual, expected, comparator) send("#{comparator}?", actual, expected) end - def stringEquals?(actual, expected) # rubocop:disable Naming/MethodName + def stringEquals?(actual, expected) actual == expected end - def booleanEquals?(actual, expected) # rubocop:disable Naming/MethodName + def booleanEquals?(actual, expected) actual.to_s == expected end - def allStringEquals?(actual, expected) # rubocop:disable Naming/MethodName + def allStringEquals?(actual, expected) return false if actual.nil? || actual.empty? actual.all? { |value| value == expected } end - def anyStringEquals?(actual, expected) # rubocop:disable Naming/MethodName + def anyStringEquals?(actual, expected) return false if actual.nil? || actual.empty? actual.any? { |value| value == expected } end + # rubocop:enable Naming/MethodName end end end diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index 9c4302cbd..a69271f7b 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -3,6 +3,44 @@ module Smithy module Client module Waiters + # Raised when a waiter detects a condition where the waiter can never + # succeed. + class WaiterFailed < StandardError; end + + # Raised when a waiter enters a failure state. + class FailureStateError < WaiterFailed + def initialize(error) + msg = "stopped waiting, encountered a failure state: #{error}" + super(msg) + end + end + + # Raised when the total wait time of a waiter exceeds the maximum + # wait time. + class MaxWaitTimeExceededError < WaiterFailed + def initialize(max_wait_time) + msg = "stopped waiting after maximum wait time of #{max_wait_time} seconds was exceeded" + super(msg) + end + end + + # Raised when a waiter encounters an unexpected error. + class UnexpectedError < WaiterFailed + def initialize(error) + msg = "stopped waiting due to an unexpected error: #{error}" + super(msg) + end + end + + # Raised when attempting to get a waiter by name and the waiter has not + # been defined. + class NoSuchWaiterError < ArgumentError + def initialize(waiter_name, valid_waiters) + msg = "no such waiter: #{waiter_name}; valid waiter names are: #{valid_waiters}" + super(msg) + end + end + # Abstract waiter class which waits for a resource to reach a desired # state. class Waiter @@ -48,10 +86,10 @@ def poll(client, params) case status when :success then return - when :failure then raise Smithy::Client::Errors::FailureStateError, output.error - when :error then raise Smithy::Client::Errors::UnexpectedError, output.error + when :failure then raise FailureStateError, output.error + when :error then raise UnexpectedError, output.error when :retry - raise Smithy::Client::Errors::MaxWaitTimeExceededError, @max_wait_time if @remaining_time.zero? + raise MaxWaitTimeExceededError, @max_wait_time if @remaining_time.zero? delay = delay(attempts) @remaining_time -= delay diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index 2776897b2..566ab81b1 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -32,7 +32,7 @@ module Waiters } ], 'traits' => { - 'smithy.waiters#waitable' => {} + 'smithy.waiters#waitable' => matchers } }, 'smithy.ruby.tests#WidgetInput' => { @@ -146,7 +146,9 @@ module Waiters } } end + let(:sample_client) { ClientHelper.sample_client(shapes: shapes) } + let(:client_class) do client_class = sample_client.const_get(:Client) client_class.clear_plugins @@ -156,19 +158,16 @@ module Waiters client_class.add_plugin(Smithy::Client::Plugins::StubResponses) client_class end + let(:client) { client_class.new(stub_responses: true) } + let(:input) { { string_property: 'input_string' } } - let(:waiter) { Waiter } - let(:poller) { Poller } + let(:my_error) { sample_client::Errors::MyError.new(nil, nil) } - let(:unexpected_error) { Smithy::Client::Errors::UnexpectedError } - let(:failure_state_error) { Smithy::Client::Errors::FailureStateError } - let(:max_wait_time_exceeded_error) { Smithy::Client::Errors::MaxWaitTimeExceededError } - let(:no_such_waiter_error) { Smithy::Client::Errors::NoSuchWaiterError } - - describe 'waiter' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + + describe 'Waiter' do + let(:matchers) do + { 'SuccessTrueMatcher' => { 'acceptors' => [ { @@ -190,45 +189,44 @@ module Waiters ] } } - client end describe '#poll' do it 'delays when status is retry' do output = Smithy::Client::Output.new(data: { string_property: 'expected' }) - expect_any_instance_of(poller).to receive(:call).and_return([{}, :retry], [output, :success]) - expect_any_instance_of(waiter).to receive(:delay).and_return(0) + expect_any_instance_of(Poller).to receive(:call).and_return([{}, :retry], [output, :success]) + expect_any_instance_of(Waiter).to receive(:delay).and_return(0) expect(client.wait_until(:success_true_matcher, input, max_wait_time: 60)).to eq(nil) end it 'returns nil when status is success' do output = Smithy::Client::Output.new(data: { string_property: 'expected' }) - expect_any_instance_of(poller).to receive(:call).and_return([output, :success]) + expect_any_instance_of(Poller).to receive(:call).and_return([output, :success]) expect(client.wait_until(:success_true_matcher, input, max_wait_time: 60)).to eq(nil) end it 'raises a failure state error when status is failure' do output = Smithy::Client::Output.new(error: my_error) - expect_any_instance_of(poller).to receive(:call).and_return([output, :failure]) + expect_any_instance_of(Poller).to receive(:call).and_return([output, :failure]) expect do client.wait_until(:success_false_matcher, input, max_wait_time: 60) - end.to raise_error(failure_state_error) + end.to raise_error(FailureStateError) end it 'raises an unexpected error when status is error' do output = Smithy::Client::Output.new(error: StandardError) - expect_any_instance_of(poller).to receive(:call).and_return([output, :error]) + expect_any_instance_of(Poller).to receive(:call).and_return([output, :error]) expect do client.wait_until(:success_false_matcher, input, max_wait_time: 60) - end.to raise_error(unexpected_error) + end.to raise_error(UnexpectedError) end it 'raises a max wait time exceeded error when there is no more remaining time' do - expect_any_instance_of(poller).to receive(:call).and_return([{}, :retry], [{}, :retry]) - expect_any_instance_of(waiter).to receive(:delay).and_return(1) + expect_any_instance_of(Poller).to receive(:call).and_return([{}, :retry], [{}, :retry]) + expect_any_instance_of(Waiter).to receive(:delay).and_return(1) expect do client.wait_until(:success_false_matcher, input, max_wait_time: 1) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end end @@ -242,20 +240,20 @@ module Waiters max_delay: max_delay } output = Smithy::Client::Output.new(data: {}) - expect_any_instance_of(poller).to receive(:call).and_return( + expect_any_instance_of(Poller).to receive(:call).and_return( [output, :retry], [output, :retry], [output, :retry], [output, :success] ) - expect_any_instance_of(waiter).to receive(:delay).with(1).and_wrap_original do |m, *args| + expect_any_instance_of(Waiter).to receive(:delay).with(1).and_wrap_original do |m, *args| delay = m.call(*args) expect(delay.between?(min_delay, max_delay)).to be true 0 end - expect_any_instance_of(waiter).to receive(:delay).with(2).and_wrap_original do |m, *args| + expect_any_instance_of(Waiter).to receive(:delay).with(2).and_wrap_original do |m, *args| delay = m.call(*args) expect(delay.between?(min_delay, max_delay)).to be true 0 end - expect_any_instance_of(waiter).to receive(:delay).with(3).and_wrap_original do |m, *args| + expect_any_instance_of(Waiter).to receive(:delay).with(3).and_wrap_original do |m, *args| delay = m.call(*args) expect(delay.between?(min_delay, max_delay)).to be true 0 @@ -273,8 +271,8 @@ module Waiters max_delay: max_delay } output = Smithy::Client::Output.new(data: {}) - expect_any_instance_of(poller).to receive(:call).and_return([output, :retry], [output, :success]) - expect_any_instance_of(waiter).to receive(:delay).and_wrap_original do |m, *args| + expect_any_instance_of(Poller).to receive(:call).and_return([output, :retry], [output, :success]) + expect_any_instance_of(Waiter).to receive(:delay).and_wrap_original do |m, *args| delay = m.call(*args) expect(delay).to eq(remaining_time) 0 @@ -288,7 +286,7 @@ module Waiters client.stub_responses(:get_widget, {}) expect do client.wait_until(:success_false_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end it 'raises an error when max_wait_time is not provided' do @@ -334,8 +332,8 @@ module Waiters describe 'poller' do describe 'success matcher' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + let(:matchers) do + { 'SuccessTrueMatcher' => { 'acceptors' => [ { @@ -380,7 +378,7 @@ module Waiters {}, StandardError ) - expect_any_instance_of(waiter).to receive(:delay).twice.and_return(0) + expect_any_instance_of(Waiter).to receive(:delay).twice.and_return(0) expect do client.wait_until(:success_false_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -390,13 +388,13 @@ module Waiters client.stub_responses(:get_widget, StandardError) expect do client.wait_until(:success_true_matcher, input, max_wait_time: 60) - end.to raise_error(unexpected_error) + end.to raise_error(UnexpectedError) end end describe 'error type matcher' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + let(:matchers) do + { 'ErrorTypeMatcher' => { 'acceptors' => [ { @@ -441,7 +439,7 @@ module Waiters {}, my_error ) - expect_any_instance_of(waiter).to receive(:delay).twice.and_return(0) + expect_any_instance_of(Waiter).to receive(:delay).twice.and_return(0) expect do client.wait_until(:error_type_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -451,14 +449,14 @@ module Waiters client.stub_responses(:get_widget, StandardError) expect do client.wait_until(:error_type_matcher, input, max_wait_time: 60) - end.to raise_error(unexpected_error) + end.to raise_error(UnexpectedError) end end describe 'output matcher' do context 'string equals comparator' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + let(:matchers) do + { 'OutputStringPropertyMatcher' => { 'acceptors' => [ { @@ -490,7 +488,7 @@ module Waiters { string_property: 'unexpected string' }, { string_property: 'expected string' } ) - expect_any_instance_of(waiter).to receive(:delay).twice.and_return(0) + expect_any_instance_of(Waiter).to receive(:delay).twice.and_return(0) expect do client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -500,20 +498,20 @@ module Waiters client.stub_responses(:get_widget, { string_property: 'unexpected string' }) expect do client.wait_until(:output_string_property_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end it 'fails when output property is nil' do client.stub_responses(:get_widget, {}) expect do client.wait_until(:output_string_property_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end end context 'boolean equals comparator' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + let(:matchers) do + { 'OutputBooleanPropertyMatcher' => { 'acceptors' => [ { @@ -545,7 +543,7 @@ module Waiters { boolean_property: true }, { boolean_property: false } ) - expect_any_instance_of(waiter).to receive(:delay).twice.and_return(0) + expect_any_instance_of(Waiter).to receive(:delay).twice.and_return(0) expect do client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -555,20 +553,20 @@ module Waiters client.stub_responses(:get_widget, { boolean_property: true }) expect do client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end it 'fails when output property is nil' do client.stub_responses(:get_widget, {}) expect do client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end end context 'all string equals comparator' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + let(:matchers) do + { 'OutputStringArrayAllPropertyMatcher' => { 'acceptors' => [ { @@ -621,7 +619,7 @@ module Waiters output_unexpected, output_expected ) - expect_any_instance_of(waiter).to receive(:delay).twice.and_return(0) + expect_any_instance_of(Waiter).to receive(:delay).twice.and_return(0) expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -638,27 +636,27 @@ module Waiters client.stub_responses(:get_widget, output_unexpected) expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end it 'fails when output property is empty' do client.stub_responses(:get_widget, { string_array_property: [] }) expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end it 'fails when output property is nil' do client.stub_responses(:get_widget, {}) expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end end context 'any string equals comparator' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + let(:matchers) do + { 'OutputStringArrayAnyPropertyMatcher' => { 'acceptors' => [ { @@ -714,7 +712,7 @@ module Waiters output_unexpected, output_expected ) - expect_any_instance_of(waiter).to receive(:delay).twice.and_return(0) + expect_any_instance_of(Waiter).to receive(:delay).twice.and_return(0) expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -732,27 +730,27 @@ module Waiters client.stub_responses(:get_widget, output_unexpected) expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end it 'fails when output property is empty' do client.stub_responses(:get_widget, { string_array_property: [] }) expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end it 'fails when output property is nil' do client.stub_responses(:get_widget, {}) expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end end context 'flatten' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + let(:matchers) do + { 'FlattenMatcher' => { 'acceptors' => [ { @@ -813,13 +811,13 @@ module Waiters client.stub_responses(:get_widget, output) expect do client.wait_until(:flatten_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end end context 'flatten length' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + let(:matchers) do + { 'FlattenLengthMatcher' => { 'acceptors' => [ { @@ -900,13 +898,13 @@ module Waiters client.stub_responses(:get_widget, output) expect do client.wait_until(:flatten_length_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end end context 'flatten filter' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + let(:matchers) do + { 'FlattenFilterMatcher' => { 'acceptors' => [ { @@ -1011,13 +1009,13 @@ module Waiters client.stub_responses(:get_widget, output) expect do client.wait_until(:flatten_filter_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end end context 'length flatten filter' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + let(:matchers) do + { 'LengthFlattenFilterMatcher' => { 'acceptors' => [ { @@ -1122,13 +1120,13 @@ module Waiters client.stub_responses(:get_widget, output) expect do client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end end context 'projection' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + let(:matchers) do + { 'ProjectionMatcher' => { 'acceptors' => [ { @@ -1171,13 +1169,13 @@ module Waiters client.stub_responses(:get_widget, output) expect do client.wait_until(:projection_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end end context 'contains field' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + let(:matchers) do + { 'ContainsFieldMatcher' => { 'acceptors' => [ { @@ -1222,13 +1220,13 @@ module Waiters client.stub_responses(:get_widget, output) expect do client.wait_until(:contains_field_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end end context 'and inequality' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + let(:matchers) do + { 'AndInequalityMatcher' => { 'acceptors' => [ { @@ -1280,14 +1278,14 @@ module Waiters client.stub_responses(:get_widget, output) expect do client.wait_until(:and_inequality_matcher, input, max_wait_time: 0) - end.to raise_error(max_wait_time_exceeded_error) + end.to raise_error(MaxWaitTimeExceededError) end end end describe 'input output matcher' do - before(:each) do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { + let(:matchers) do + { 'InputOutputBooleanPropertyMatcher' => { 'acceptors' => [ { @@ -1313,49 +1311,54 @@ module Waiters end end - it 'checks acceptors in order' do - shapes['smithy.ruby.tests#GetWidget']['traits']['smithy.waiters#waitable'] = { - 'AcceptorOrderSuccessMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'errorType' => 'MyError' - } - }, - { - 'state' => 'failure', - 'matcher' => { - 'errorType' => 'MyError' - } - } - ] - }, - 'AcceptorOrderFailureMatcher' => { - 'acceptors' => [ - { - 'state' => 'failure', - 'matcher' => { - 'errorType' => 'MyError' + context 'order' do + let(:matchers) do + { + 'AcceptorOrderSuccessMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'errorType' => 'MyError' + } + }, + { + 'state' => 'failure', + 'matcher' => { + 'errorType' => 'MyError' + } } - }, - { - 'state' => 'success', - 'matcher' => { - 'errorType' => 'MyError' + ] + }, + 'AcceptorOrderFailureMatcher' => { + 'acceptors' => [ + { + 'state' => 'failure', + 'matcher' => { + 'errorType' => 'MyError' + } + }, + { + 'state' => 'success', + 'matcher' => { + 'errorType' => 'MyError' + } } - } - ] + ] + } } - } - client.stub_responses(:get_widget, my_error) - expect do - client.wait_until(:acceptor_order_success_matcher, input, max_wait_time: 60) - end.to_not raise_error - client.stub_responses(:get_widget, my_error) - expect do - client.wait_until(:acceptor_order_failure_matcher, input, max_wait_time: 60) - end.to raise_error(failure_state_error) + end + + it 'checks acceptors in order' do + client.stub_responses(:get_widget, my_error) + expect do + client.wait_until(:acceptor_order_success_matcher, input, max_wait_time: 60) + end.to_not raise_error + client.stub_responses(:get_widget, my_error) + expect do + client.wait_until(:acceptor_order_failure_matcher, input, max_wait_time: 60) + end.to raise_error(FailureStateError) + end end end end diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index bbe31e81e..ee577fd92 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -70,25 +70,25 @@ module <%= module_name %> # # When a waiter is unsuccessful, it will raise an error. # All the failure errors extend from - # {Smithy::Client::Waiters::Errors:WaiterFailed}. + # {Smithy::Client::Waiters::WaiterFailed}. # # begin # client.wait_until(...) - # rescue Smithy::Client::Errors:WaiterFailed + # rescue Smithy::Client::Waiters:WaiterFailed # # resource did not enter the desired state in time # end # - # @raise [Errors::FailureStateError] Raised when the waiter terminates + # @raise [FailureStateError] Raised when the waiter terminates # because the waiter has entered a state that it will not transition # out of, preventing success. # - # @raise [Errors::MaxWaitTimeExceededError] Raised when the configured + # @raise [MaxWaitTimeExceededError] Raised when the configured # maximum wait time is reached and the waiter is not yet successful. # - # @raise [Errors::UnexpectedError] Raised when an error that is not + # @raise [UnexpectedError] Raised when an error that is not # expected is encountered while polling for a resource. # - # @raise [Errors::NoSuchWaiterError] Raised when you request to wait + # @raise [NoSuchWaiterError] Raised when you request to wait # for an unknown state. # # @return [nil] Returns `nil` if the waiter was successful. @@ -124,7 +124,7 @@ module <%= module_name %> if waiter_class waiter_class.new(options.merge(client: self)) else - raise Smithy::Client::Errors::NoSuchWaiterError.new(waiter_name, waiters.keys) + raise Smithy::Client::Waiters::NoSuchWaiterError.new(waiter_name, waiters.keys) end end diff --git a/gems/smithy/lib/smithy/templates/client/waiters.erb b/gems/smithy/lib/smithy/templates/client/waiters.erb index 25f892e6e..e087614bd 100644 --- a/gems/smithy/lib/smithy/templates/client/waiters.erb +++ b/gems/smithy/lib/smithy/templates/client/waiters.erb @@ -2,8 +2,6 @@ # This is generated code! -require 'smithy-client/waiters' - module <%= module_name %> # @api private diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index f0d3f88dc..64095f8a1 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -5,7 +5,7 @@ describe 'Client: Waiters' do let(:input) { { string_property: 'input_string' } } let(:client) { WaiterService::Client.new(stub_responses: true) } - let(:no_such_waiter_error) { Smithy::Client::Errors::NoSuchWaiterError } + let(:no_such_waiter_error) { Smithy::Client::Waiters::NoSuchWaiterError } ['generated client gem', 'generated client from source code'].each do |context| context context do @@ -20,7 +20,7 @@ client.stub_responses(:get_operation, StandardError) expect do client.wait_until(:success_matcher, input, max_wait_time: 60) - end.to raise_error(Smithy::Client::Errors::WaiterFailed) + end.to raise_error(Smithy::Client::Waiters::WaiterFailed) end it 'raises an error for nonexistent waiters' do From 108834bb850f59d0fc82aff9348ee4550702a24e Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 20 May 2025 10:27:31 -0700 Subject: [PATCH 41/48] Add rest of PR comment fixes --- gems/smithy-client/lib/smithy-client/base.rb | 7 + .../spec/smithy-client/waiters_spec.rb | 831 ++---------------- .../lib/smithy/templates/client/client.erb | 40 +- .../lib/smithy/templates/client/waiters.erb | 4 +- gems/smithy/lib/smithy/views/client/client.rb | 4 +- .../smithy/lib/smithy/views/client/waiters.rb | 15 +- .../spec/interfaces/client/waiters_spec.rb | 26 +- projections/shapes/lib/shapes/client.rb | 46 +- projections/shapes/lib/shapes/waiters.rb | 2 - projections/weather/lib/weather/client.rb | 46 +- projections/weather/lib/weather/waiters.rb | 2 - 11 files changed, 160 insertions(+), 863 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/base.rb b/gems/smithy-client/lib/smithy-client/base.rb index 8f8e07d56..f91eaf7af 100644 --- a/gems/smithy-client/lib/smithy-client/base.rb +++ b/gems/smithy-client/lib/smithy-client/base.rb @@ -41,6 +41,13 @@ def inspect "#<#{self.class.name || 'Smithy::Client::Base'}>" end + def waiter(waiter_name, options = {}) + waiter_class = waiters[waiter_name] + return waiter_class.new(options.merge(client: self)) if waiter_class + + raise Smithy::Client::Waiters::NoSuchWaiterError.new(waiter_name, waiters.keys) + end + private # Constructs a {Configuration} object and gives each plugin the diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index 566ab81b1..fd9ef0bfc 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -11,138 +11,46 @@ module Waiters 'smithy.ruby.tests#WaitService' => { 'type' => 'service', 'version' => '2022-11-30', - 'operations' => [ - { - 'target' => 'smithy.ruby.tests#GetWidget' - } - ], + 'operations' => [{ 'target' => 'smithy.ruby.tests#GetWidget' }], 'traits' => { 'smithy.protocols#rpcv2Cbor' => {} } }, 'smithy.ruby.tests#GetWidget' => { 'type' => 'operation', - 'input' => { - 'target' => 'smithy.ruby.tests#WidgetInput' - }, - 'output' => { - 'target' => 'smithy.ruby.tests#WidgetOutput' - }, - 'errors' => [ - { - 'target' => 'smithy.ruby.tests#MyError' - } - ], - 'traits' => { - 'smithy.waiters#waitable' => matchers - } + 'input' => { 'target' => 'smithy.ruby.tests#WidgetInput' }, + 'output' => { 'target' => 'smithy.ruby.tests#WidgetOutput' }, + 'errors' => [{ 'target' => 'smithy.ruby.tests#MyError' }], + 'traits' => { 'smithy.waiters#waitable' => matchers } }, 'smithy.ruby.tests#WidgetInput' => { 'type' => 'structure', 'members' => { - 'stringProperty' => { - 'target' => 'smithy.api#String' - }, - 'stringArrayProperty' => { - 'target' => 'smithy.ruby.tests#StringArray' - }, - 'booleanProperty' => { - 'target' => 'smithy.api#Boolean' - }, - 'booleanArrayProperty' => { - 'target' => 'smithy.ruby.tests#BooleanArray' - }, - 'children' => { - 'target' => 'smithy.ruby.tests#ChildArray' - }, - 'dataMap' => { - 'target' => 'smithy.ruby.tests#DataMap' - } + 'stringProperty' => { 'target' => 'smithy.api#String' }, + 'stringArrayProperty' => { 'target' => 'smithy.ruby.tests#StringArray' }, + 'booleanProperty' => { 'target' => 'smithy.api#Boolean' }, + 'booleanArrayProperty' => { 'target' => 'smithy.ruby.tests#BooleanArray' } } }, 'smithy.ruby.tests#WidgetOutput' => { 'type' => 'structure', 'members' => { - 'stringProperty' => { - 'target' => 'smithy.api#String' - }, - 'stringArrayProperty' => { - 'target' => 'smithy.ruby.tests#StringArray' - }, - 'booleanProperty' => { - 'target' => 'smithy.api#Boolean' - }, - 'booleanArrayProperty' => { - 'target' => 'smithy.ruby.tests#BooleanArray' - }, - 'children' => { - 'target' => 'smithy.ruby.tests#ChildArray' - }, - 'dataMap' => { - 'target' => 'smithy.ruby.tests#DataMap' - } + 'stringProperty' => { 'target' => 'smithy.api#String' }, + 'stringArrayProperty' => { 'target' => 'smithy.ruby.tests#StringArray' }, + 'booleanProperty' => { 'target' => 'smithy.api#Boolean' }, + 'booleanArrayProperty' => { 'target' => 'smithy.ruby.tests#BooleanArray' } } }, 'smithy.ruby.tests#BooleanArray' => { 'type' => 'list', - 'member' => { - 'target' => 'smithy.api#Boolean' - } - }, - 'smithy.ruby.tests#Child' => { - 'type' => 'structure', - 'members' => { - 'grandchildren' => { - 'target' => 'smithy.ruby.tests#GrandchildArray' - } - } - }, - 'smithy.ruby.tests#ChildArray' => { - 'type' => 'list', - 'member' => { - 'target' => 'smithy.ruby.tests#Child' - } - }, - 'smithy.ruby.tests#DataMap' => { - 'type' => 'map', - 'key' => { - 'target' => 'smithy.api#String' - }, - 'value' => { - 'target' => 'smithy.api#String' - } - }, - 'smithy.ruby.tests#Grandchild' => { - 'type' => 'structure', - 'members' => { - 'name' => { - 'target' => 'smithy.api#String' - }, - 'number' => { - 'target' => 'smithy.api#Integer' - } - } - }, - 'smithy.ruby.tests#GrandchildArray' => { - 'type' => 'list', - 'member' => { - 'target' => 'smithy.ruby.tests#Grandchild' - } + 'member' => { 'target' => 'smithy.api#Boolean' } }, 'smithy.ruby.tests#StringArray' => { 'type' => 'list', - 'member' => { - 'target' => 'smithy.api#String' - } + 'member' => { 'target' => 'smithy.api#String' } }, 'smithy.ruby.tests#MyError' => { 'type' => 'structure', - 'members' => { - 'message' => { - 'target' => 'smithy.api#String' - } - }, - 'traits' => { - 'smithy.api#error' => 'client' - } + 'members' => { 'message' => { 'target' => 'smithy.api#String' } }, + 'traits' => { 'smithy.api#error' => 'client' } } } end @@ -165,25 +73,41 @@ module Waiters let(:my_error) { sample_client::Errors::MyError.new(nil, nil) } + before(:each) { allow_any_instance_of(Waiter).to receive(:sleep) } + describe 'Waiter' do let(:matchers) do { - 'SuccessTrueMatcher' => { + 'OutputStringPropertyMatcher' => { 'acceptors' => [ { 'state' => 'success', 'matcher' => { - 'success' => true + 'output' => { + 'path' => 'stringProperty', + 'expected' => 'success', + 'comparator' => 'stringEquals' + } } - } - ] - }, - 'SuccessFalseMatcher' => { - 'acceptors' => [ + }, { - 'state' => 'success', + 'state' => 'retry', + 'matcher' => { + 'output' => { + 'path' => 'stringProperty', + 'expected' => 'retry', + 'comparator' => 'stringEquals' + } + } + }, + { + 'state' => 'failure', 'matcher' => { - 'success' => false + 'output' => { + 'path' => 'stringProperty', + 'expected' => 'failure', + 'comparator' => 'stringEquals' + } } } ] @@ -193,39 +117,38 @@ module Waiters describe '#poll' do it 'delays when status is retry' do - output = Smithy::Client::Output.new(data: { string_property: 'expected' }) - expect_any_instance_of(Poller).to receive(:call).and_return([{}, :retry], [output, :success]) - expect_any_instance_of(Waiter).to receive(:delay).and_return(0) - expect(client.wait_until(:success_true_matcher, input, max_wait_time: 60)).to eq(nil) - end - - it 'returns nil when status is success' do - output = Smithy::Client::Output.new(data: { string_property: 'expected' }) - expect_any_instance_of(Poller).to receive(:call).and_return([output, :success]) - expect(client.wait_until(:success_true_matcher, input, max_wait_time: 60)).to eq(nil) + client.stub_responses( + :get_widget, + { string_property: 'retry' }, + { string_property: 'retry' }, + { string_property: 'success' } + ) + expect_any_instance_of(Waiter).to receive(:delay).exactly(2).times.and_call_original + client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) end it 'raises a failure state error when status is failure' do - output = Smithy::Client::Output.new(error: my_error) - expect_any_instance_of(Poller).to receive(:call).and_return([output, :failure]) + client.stub_responses(:get_widget, { string_property: 'failure' }) expect do - client.wait_until(:success_false_matcher, input, max_wait_time: 60) + client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) end.to raise_error(FailureStateError) end it 'raises an unexpected error when status is error' do - output = Smithy::Client::Output.new(error: StandardError) - expect_any_instance_of(Poller).to receive(:call).and_return([output, :error]) + client.stub_responses(:get_widget, StandardError.new) expect do - client.wait_until(:success_false_matcher, input, max_wait_time: 60) + client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) end.to raise_error(UnexpectedError) end it 'raises a max wait time exceeded error when there is no more remaining time' do - expect_any_instance_of(Poller).to receive(:call).and_return([{}, :retry], [{}, :retry]) - expect_any_instance_of(Waiter).to receive(:delay).and_return(1) + client.stub_responses( + :get_widget, + { string_property: 'retry' }, + { string_property: 'retry' } + ) expect do - client.wait_until(:success_false_matcher, input, max_wait_time: 1) + client.wait_until(:output_string_property_matcher, input, max_wait_time: 1) end.to raise_error(MaxWaitTimeExceededError) end end @@ -258,7 +181,7 @@ module Waiters expect(delay.between?(min_delay, max_delay)).to be true 0 end - client.wait_until(:success_true_matcher, input, options) + client.wait_until(:output_string_property_matcher, input, options) end it 'sets the delay to remaining time for the last attempt' do @@ -277,7 +200,7 @@ module Waiters expect(delay).to eq(remaining_time) 0 end - client.wait_until(:success_true_matcher, input, options) + client.wait_until(:output_string_property_matcher, input, options) end end @@ -285,13 +208,13 @@ module Waiters it 'raises an error when max wait time is exceeded' do client.stub_responses(:get_widget, {}) expect do - client.wait_until(:success_false_matcher, input, max_wait_time: 0) + client.wait_until(:output_string_property_matcher, input, max_wait_time: 0) end.to raise_error(MaxWaitTimeExceededError) end it 'raises an error when max_wait_time is not provided' do expect do - client.wait_until(:success_true_matcher, input) + client.wait_until(:output_string_property_matcher, input) end.to raise_error(ArgumentError, 'expected `:max_wait_time` to be an integer, got: ') end @@ -301,7 +224,7 @@ module Waiters max_delay: 0 } expect do - client.wait_until(:success_true_matcher, input, options) + client.wait_until(:output_string_property_matcher, input, options) end.to raise_error(ArgumentError, '`:max_delay` must be greater than 0') end @@ -311,7 +234,7 @@ module Waiters min_delay: 0 } expect do - client.wait_until(:success_true_matcher, input, options) + client.wait_until(:output_string_property_matcher, input, options) end.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') end @@ -323,36 +246,22 @@ module Waiters max_delay: 2 } expect do - client.wait_until(:success_true_matcher, input, options) + client.wait_until(:output_string_property_matcher, input, options) end.to raise_error(ArgumentError, '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') end end end - describe 'poller' do - describe 'success matcher' do + describe 'Waiters::Poller' do + context 'success matcher' do let(:matchers) do { 'SuccessTrueMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'success' => true - } - } - ] + 'acceptors' => [{ 'state' => 'success', 'matcher' => { 'success' => true } }] }, 'SuccessFalseMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'success' => false - } - } - ] + 'acceptors' => [{ 'state' => 'success', 'matcher' => { 'success' => false } }] } } end @@ -378,7 +287,7 @@ module Waiters {}, StandardError ) - expect_any_instance_of(Waiter).to receive(:delay).twice.and_return(0) + expect_any_instance_of(Waiter).to receive(:delay).twice.and_call_original expect do client.wait_until(:success_false_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -392,28 +301,14 @@ module Waiters end end - describe 'error type matcher' do + context 'error type matcher' do let(:matchers) do { 'ErrorTypeMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'errorType' => 'MyError' - } - } - ] + 'acceptors' => [{ 'state' => 'success', 'matcher' => { 'errorType' => 'MyError' } }] }, 'AbsoluteErrorTypeMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'errorType' => 'smithy.ruby.tests#MyError' - } - } - ] + 'acceptors' => [{ 'state' => 'success', 'matcher' => { 'errorType' => 'smithy.ruby.tests#MyError' } }] } } end @@ -439,7 +334,7 @@ module Waiters {}, my_error ) - expect_any_instance_of(Waiter).to receive(:delay).twice.and_return(0) + expect_any_instance_of(Waiter).to receive(:delay).twice.and_call_original expect do client.wait_until(:error_type_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -453,7 +348,7 @@ module Waiters end end - describe 'output matcher' do + context 'output matcher' do context 'string equals comparator' do let(:matchers) do { @@ -488,7 +383,7 @@ module Waiters { string_property: 'unexpected string' }, { string_property: 'expected string' } ) - expect_any_instance_of(Waiter).to receive(:delay).twice.and_return(0) + expect_any_instance_of(Waiter).to receive(:delay).twice.and_call_original expect do client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -543,7 +438,7 @@ module Waiters { boolean_property: true }, { boolean_property: false } ) - expect_any_instance_of(Waiter).to receive(:delay).twice.and_return(0) + expect_any_instance_of(Waiter).to receive(:delay).twice.and_call_original expect do client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -619,7 +514,7 @@ module Waiters output_unexpected, output_expected ) - expect_any_instance_of(Waiter).to receive(:delay).twice.and_return(0) + expect_any_instance_of(Waiter).to receive(:delay).twice.and_call_original expect do client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -712,7 +607,7 @@ module Waiters output_unexpected, output_expected ) - expect_any_instance_of(Waiter).to receive(:delay).twice.and_return(0) + expect_any_instance_of(Waiter).to receive(:delay).twice.and_call_original expect do client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) end.to_not raise_error @@ -747,543 +642,9 @@ module Waiters end.to raise_error(MaxWaitTimeExceededError) end end - - context 'flatten' do - let(:matchers) do - { - 'FlattenMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'children[].grandchildren[].name', - 'expected' => 'expected name', - 'comparator' => 'anyStringEquals' - } - } - } - ] - } - } - end - - it 'succeeds when matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'expected name', - number: 1 - } - ] - }, - { - grandchildren: [ - { - name: 'unexpected name', - number: 1 - } - ] - } - ] - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:flatten_matcher, input, max_wait_time: 60) - end.to_not raise_error - end - - it 'fails when not matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'unexpected name', - number: 1 - } - ] - } - ] - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:flatten_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end - end - - context 'flatten length' do - let(:matchers) do - { - 'FlattenLengthMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'length(children[].grandchildren[]) == `6`', - 'expected' => 'true', - 'comparator' => 'booleanEquals' - } - } - } - ] - } - } - end - - it 'succeeds when matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 4 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 5 - }, - { - name: 'name', - number: 6 - } - ] - } - ] - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:flatten_length_matcher, input, max_wait_time: 60) - end.to_not raise_error - end - - it 'fails when not matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - } - ] - } - ] - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:flatten_length_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end - end - - context 'flatten filter' do - let(:matchers) do - { - 'FlattenFilterMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'length(children[?length(grandchildren) == `3`]) == `1`', - 'expected' => 'true', - 'comparator' => 'booleanEquals' - } - } - } - ] - } - } - end - - it 'succeeds when matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 4 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 5 - }, - { - name: 'name', - number: 6 - } - ] - } - ] - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:flatten_filter_matcher, input, max_wait_time: 60) - end.to_not raise_error - end - - it 'fails when not matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 4 - }, - { - name: 'name', - number: 5 - }, - { - name: 'name', - number: 6 - } - ] - } - ] - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:flatten_filter_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end - end - - context 'length flatten filter' do - let(:matchers) do - { - 'LengthFlattenFilterMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'length((children[].grandchildren[])[?number > `4`]) == `3`', - 'expected' => 'true', - 'comparator' => 'booleanEquals' - } - } - } - ] - } - } - end - - it 'succeeds when matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 5 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 6 - }, - { - name: 'name', - number: 7 - } - ] - } - ] - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 60) - end.to_not raise_error - end - - it 'fails when not matched' do - output = { - children: [ - { - grandchildren: [ - { - name: 'name', - number: 1 - }, - { - name: 'name', - number: 2 - }, - { - name: 'name', - number: 3 - } - ] - }, - { - grandchildren: [ - { - name: 'name', - number: 3 - }, - { - name: 'name', - number: 4 - }, - { - name: 'name', - number: 5 - } - ] - } - ] - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:length_flatten_filter_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end - end - - context 'projection' do - let(:matchers) do - { - 'ProjectionMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'dataMap.*', - 'expected' => 'abc', - 'comparator' => 'allStringEquals' - } - } - } - ] - } - } - end - - it 'succeeds when matched' do - output = { - data_map: { - 'key1' => 'abc', - 'key2' => 'abc', - 'key3' => 'abc' - } - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:projection_matcher, input, max_wait_time: 60) - end.to_not raise_error - end - - it 'fails when not matched' do - output = { - data_map: { - 'key1' => 'abc', - 'key2' => 'def', - 'key3' => 'ghi' - } - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:projection_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end - end - - context 'contains field' do - let(:matchers) do - { - 'ContainsFieldMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'contains(dataMap.*, stringProperty)', - 'expected' => 'true', - 'comparator' => 'booleanEquals' - } - } - } - ] - } - } - end - - it 'succeeds when matched' do - output = { - string_property: 'match', - data_map: { - 'key1' => 'not a match', - 'key2' => 'match', - 'key3' => 'not a match' - } - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:contains_field_matcher, input, max_wait_time: 60) - end.to_not raise_error - end - - it 'fails when not matched' do - output = { - string_property: 'match', - data_map: { - 'key1' => 'not a match', - 'key2' => 'not a match', - 'key3' => 'not a match' - } - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:contains_field_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end - end - - context 'and inequality' do - let(:matchers) do - { - 'AndInequalityMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'length(dataMap) == `3` && length(stringArrayProperty) != `3`', - 'expected' => 'true', - 'comparator' => 'booleanEquals' - } - } - } - ] - } - } - end - - it 'succeeds when matched' do - output = { - string_array_property: [ - 'some string', - 'another string' - ], - data_map: { - 'key1' => 'one', - 'key2' => 'two', - 'key3' => 'three' - } - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:and_inequality_matcher, input, max_wait_time: 60) - end.to_not raise_error - end - - it 'fails when not matched' do - output = { - string_array_property: [ - 'some string', - 'another string', - 'yet another string' - ], - data_map: { - 'key1' => 'one', - 'key2' => 'two', - 'key3' => 'three' - } - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:and_inequality_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end - end end - describe 'input output matcher' do + context 'input output matcher' do let(:matchers) do { 'InputOutputBooleanPropertyMatcher' => { @@ -1316,34 +677,14 @@ module Waiters { 'AcceptorOrderSuccessMatcher' => { 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'errorType' => 'MyError' - } - }, - { - 'state' => 'failure', - 'matcher' => { - 'errorType' => 'MyError' - } - } + { 'state' => 'success', 'matcher' => { 'errorType' => 'MyError' } }, + { 'state' => 'failure', 'matcher' => { 'errorType' => 'MyError' } } ] }, 'AcceptorOrderFailureMatcher' => { 'acceptors' => [ - { - 'state' => 'failure', - 'matcher' => { - 'errorType' => 'MyError' - } - }, - { - 'state' => 'success', - 'matcher' => { - 'errorType' => 'MyError' - } - } + { 'state' => 'failure', 'matcher' => { 'errorType' => 'MyError' } }, + { 'state' => 'success', 'matcher' => { 'errorType' => 'MyError' } } ] } } diff --git a/gems/smithy/lib/smithy/templates/client/client.erb b/gems/smithy/lib/smithy/templates/client/client.erb index ee577fd92..9c82d0ab5 100644 --- a/gems/smithy/lib/smithy/templates/client/client.erb +++ b/gems/smithy/lib/smithy/templates/client/client.erb @@ -59,8 +59,10 @@ module <%= module_name %> # retries. You can pass these configuration as the final # arguments hash. # + # weather = Weather::Client.new + # # # poll for a maximum of 25 seconds - # client.wait_until(waiter_name, params, { + # weather.wait_until(:forecast_exists, { forecast_id: '1' }, { # max_wait_time: 25, # min_delay: 2, # max_delay: 10 @@ -72,35 +74,32 @@ module <%= module_name %> # All the failure errors extend from # {Smithy::Client::Waiters::WaiterFailed}. # + # weather = Weather::Client.new # begin - # client.wait_until(...) - # rescue Smithy::Client::Waiters:WaiterFailed + # weather.wait_until(:forecast_exists, { forecast_id: '1' }, max_wait_time: 60) + # rescue Smithy::Client::Waiters::WaiterFailed # # resource did not enter the desired state in time # end # + # + # @param [Symbol] waiter_name + # @param [Hash] params ({}) + # @param [Hash] options ({}) + # @option options [Integer] :max_wait_time + # @option options [Integer] :min_delay + # @option options [Integer] :max_delay + # @return [nil] Returns `nil` if the waiter was successful. # @raise [FailureStateError] Raised when the waiter terminates # because the waiter has entered a state that it will not transition # out of, preventing success. - # # @raise [MaxWaitTimeExceededError] Raised when the configured # maximum wait time is reached and the waiter is not yet successful. - # # @raise [UnexpectedError] Raised when an error that is not # expected is encountered while polling for a resource. - # # @raise [NoSuchWaiterError] Raised when you request to wait # for an unknown state. - # - # @return [nil] Returns `nil` if the waiter was successful. - # @param [Symbol] waiter_name - # @param [Hash] params ({}) - # @param [Hash] options ({}) - # @option options [Integer] :max_wait_time - # @option options [Integer] :min_delay - # @option options [Integer] :max_delay def wait_until(waiter_name, params = {}, options = {}) - w = waiter(waiter_name, options) - w.wait(params) + waiter(waiter_name, options).wait(params) end private @@ -119,15 +118,6 @@ module <%= module_name %> Smithy::Client::Input.new(handlers: handlers, context: context) end - def waiter(waiter_name, options = {}) - waiter_class = waiters[waiter_name] - if waiter_class - waiter_class.new(options.merge(client: self)) - else - raise Smithy::Client::Waiters::NoSuchWaiterError.new(waiter_name, waiters.keys) - end - end - def waiters <% waiters.each do |line| -%> <%= line %> diff --git a/gems/smithy/lib/smithy/templates/client/waiters.erb b/gems/smithy/lib/smithy/templates/client/waiters.erb index e087614bd..c5b546dce 100644 --- a/gems/smithy/lib/smithy/templates/client/waiters.erb +++ b/gems/smithy/lib/smithy/templates/client/waiters.erb @@ -25,7 +25,9 @@ module <%= module_name %> max_delay: options[:max_delay] || <%= waiter.max_delay %>, poller: Smithy::Client::Waiters::Poller.new( operation_name: :<%= waiter.operation_name %>, -<%= waiter.acceptors %> +<% waiter.acceptors.each do |acceptor| -%> + <%= acceptor %> +<% end -%> ) ) end diff --git a/gems/smithy/lib/smithy/views/client/client.rb b/gems/smithy/lib/smithy/views/client/client.rb index ff211ee0f..27476717e 100644 --- a/gems/smithy/lib/smithy/views/client/client.rb +++ b/gems/smithy/lib/smithy/views/client/client.rb @@ -65,11 +65,11 @@ def waiters return ['{}'] if waiters.empty? lines = ['{'] - waiters.each_with_index do |waiter, i| + waiters.each_with_index do |waiter, _i| line = " #{waiter.name.underscore}: Waiters::#{waiter.name}," - line.chomp!(',') if i == waiters.length - 1 lines << line end + lines.last.chomp!(',') if lines.last.end_with?(',') lines << '}' lines end diff --git a/gems/smithy/lib/smithy/views/client/waiters.rb b/gems/smithy/lib/smithy/views/client/waiters.rb index 9b5fbb71b..a700b71f9 100644 --- a/gems/smithy/lib/smithy/views/client/waiters.rb +++ b/gems/smithy/lib/smithy/views/client/waiters.rb @@ -38,10 +38,10 @@ def waitable_trait(operation) # @api private class Waiter - def initialize(operation, name, waiter) - @operation_name = operation + def initialize(operation_name, name, waiter) + @operation_name = operation_name @name = name - @documentation = waiter['documentation'] + @documentation = waiter.fetch('documentation', '') @acceptors = formatted_acceptors(waiter['acceptors']) @min_delay = waiter['minDelay'] || 2 @max_delay = waiter['maxDelay'] || 120 @@ -51,7 +51,7 @@ def initialize(operation, name, waiter) attr_reader :operation_name, :name, :documentation, :acceptors, :min_delay, :max_delay, :deprecated def docstrings - @documentation ? @documentation.split("\n") : [] + @documentation.split("\n") end def formatted_acceptors(acceptors) @@ -60,16 +60,15 @@ def formatted_acceptors(acceptors) Util::HashFormatter.new( wrap: false, inline: false, - quote_strings: true, - indent: ' ' - ).format(acceptors: acceptors) + quote_strings: true + ).format(acceptors: acceptors).split("\n") end def preprocess_acceptor(acceptor) if (matcher = acceptor['matcher']['output'] || acceptor['matcher']['inputOutput']) matcher['path'] = Util::Underscore.underscore_jmespath(matcher['path']) elsif (error_type = acceptor['matcher']['errorType']) - acceptor['matcher']['errorType'] = error_type.split('#').last.split('#').first + acceptor['matcher']['errorType'] = Model::Shape.name(error_type) end end end diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index 64095f8a1..d53fb1de3 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -12,6 +12,7 @@ include_context context, 'WaiterService' it 'returns nil when successful' do + input = { string_property: 'input_string' } client.stub_responses(:get_operation, { string_property: 'success' }) expect(client.wait_until(:success_matcher, input, max_wait_time: 60)).to be(nil) end @@ -19,33 +20,14 @@ it 'raises waiter failed error when unsuccessful' do client.stub_responses(:get_operation, StandardError) expect do - client.wait_until(:success_matcher, input, max_wait_time: 60) + client.wait_until(:success_matcher, { string_property: 'input_string' }, max_wait_time: 60) end.to raise_error(Smithy::Client::Waiters::WaiterFailed) end it 'raises an error for nonexistent waiters' do expect do - client.wait_until(:nonexistent_waiter, input, max_wait_time: 60) - end.to raise_error(no_such_waiter_error) - end - - it 'does not allow custom waiters' do - custom_waiter = { - 'CustomWaiterMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'success' => false - } - } - ] - } - } - client.config.service.operations[:get_operation].traits['smithy.waiters#waitable'].merge!(custom_waiter) - expect do - client.wait_until(:custom_waiter_matcher, input, max_wait_time: 60) - end.to raise_error(no_such_waiter_error) + client.wait_until(:nonexistent_waiter, { string_property: 'input_string' }, max_wait_time: 60) + end.to raise_error(Smithy::Client::Waiters::NoSuchWaiterError) end end end diff --git a/projections/shapes/lib/shapes/client.rb b/projections/shapes/lib/shapes/client.rb index dd4de4fb2..05d30bd3b 100644 --- a/projections/shapes/lib/shapes/client.rb +++ b/projections/shapes/lib/shapes/client.rb @@ -287,8 +287,10 @@ def operation(params = {}, options = {}) # retries. You can pass these configuration as the final # arguments hash. # + # weather = Weather::Client.new + # # # poll for a maximum of 25 seconds - # client.wait_until(waiter_name, params, { + # weather.wait_until(:forecast_exists, { forecast_id: '1' }, { # max_wait_time: 25, # min_delay: 2, # max_delay: 10 @@ -298,37 +300,34 @@ def operation(params = {}, options = {}) # # When a waiter is unsuccessful, it will raise an error. # All the failure errors extend from - # {Smithy::Client::Waiters::Errors:WaiterFailed}. + # {Smithy::Client::Waiters::WaiterFailed}. # + # weather = Weather::Client.new # begin - # client.wait_until(...) - # rescue Smithy::Client::Errors:WaiterFailed + # weather.wait_until(:forecast_exists, { forecast_id: '1' }, max_wait_time: 60) + # rescue Smithy::Client::Waiters::WaiterFailed # # resource did not enter the desired state in time # end # - # @raise [Errors::FailureStateError] Raised when the waiter terminates - # because the waiter has entered a state that it will not transition - # out of, preventing success. - # - # @raise [Errors::MaxWaitTimeExceededError] Raised when the configured - # maximum wait time is reached and the waiter is not yet successful. - # - # @raise [Errors::UnexpectedError] Raised when an error that is not - # expected is encountered while polling for a resource. # - # @raise [Errors::NoSuchWaiterError] Raised when you request to wait - # for an unknown state. - # - # @return [nil] Returns `nil` if the waiter was successful. # @param [Symbol] waiter_name # @param [Hash] params ({}) # @param [Hash] options ({}) # @option options [Integer] :max_wait_time # @option options [Integer] :min_delay # @option options [Integer] :max_delay + # @return [nil] Returns `nil` if the waiter was successful. + # @raise [FailureStateError] Raised when the waiter terminates + # because the waiter has entered a state that it will not transition + # out of, preventing success. + # @raise [MaxWaitTimeExceededError] Raised when the configured + # maximum wait time is reached and the waiter is not yet successful. + # @raise [UnexpectedError] Raised when an error that is not + # expected is encountered while polling for a resource. + # @raise [NoSuchWaiterError] Raised when you request to wait + # for an unknown state. def wait_until(waiter_name, params = {}, options = {}) - w = waiter(waiter_name, options) - w.wait(params) + waiter(waiter_name, options).wait(params) end private @@ -347,15 +346,6 @@ def build_input(operation_name, params) Smithy::Client::Input.new(handlers: handlers, context: context) end - def waiter(waiter_name, options = {}) - waiter_class = waiters[waiter_name] - if waiter_class - waiter_class.new(options.merge(client: self)) - else - raise Smithy::Client::Errors::NoSuchWaiterError.new(waiter_name, waiters.keys) - end - end - def waiters {} end diff --git a/projections/shapes/lib/shapes/waiters.rb b/projections/shapes/lib/shapes/waiters.rb index 162af715f..89181cd0b 100644 --- a/projections/shapes/lib/shapes/waiters.rb +++ b/projections/shapes/lib/shapes/waiters.rb @@ -2,8 +2,6 @@ # This is generated code! -require 'smithy-client/waiters' - module ShapeService # @api private diff --git a/projections/weather/lib/weather/client.rb b/projections/weather/lib/weather/client.rb index 45bd1a1d6..716881111 100644 --- a/projections/weather/lib/weather/client.rb +++ b/projections/weather/lib/weather/client.rb @@ -275,8 +275,10 @@ def list_cities(params = {}, options = {}) # retries. You can pass these configuration as the final # arguments hash. # + # weather = Weather::Client.new + # # # poll for a maximum of 25 seconds - # client.wait_until(waiter_name, params, { + # weather.wait_until(:forecast_exists, { forecast_id: '1' }, { # max_wait_time: 25, # min_delay: 2, # max_delay: 10 @@ -286,37 +288,34 @@ def list_cities(params = {}, options = {}) # # When a waiter is unsuccessful, it will raise an error. # All the failure errors extend from - # {Smithy::Client::Waiters::Errors:WaiterFailed}. + # {Smithy::Client::Waiters::WaiterFailed}. # + # weather = Weather::Client.new # begin - # client.wait_until(...) - # rescue Smithy::Client::Errors:WaiterFailed + # weather.wait_until(:forecast_exists, { forecast_id: '1' }, max_wait_time: 60) + # rescue Smithy::Client::Waiters::WaiterFailed # # resource did not enter the desired state in time # end # - # @raise [Errors::FailureStateError] Raised when the waiter terminates - # because the waiter has entered a state that it will not transition - # out of, preventing success. - # - # @raise [Errors::MaxWaitTimeExceededError] Raised when the configured - # maximum wait time is reached and the waiter is not yet successful. - # - # @raise [Errors::UnexpectedError] Raised when an error that is not - # expected is encountered while polling for a resource. # - # @raise [Errors::NoSuchWaiterError] Raised when you request to wait - # for an unknown state. - # - # @return [nil] Returns `nil` if the waiter was successful. # @param [Symbol] waiter_name # @param [Hash] params ({}) # @param [Hash] options ({}) # @option options [Integer] :max_wait_time # @option options [Integer] :min_delay # @option options [Integer] :max_delay + # @return [nil] Returns `nil` if the waiter was successful. + # @raise [FailureStateError] Raised when the waiter terminates + # because the waiter has entered a state that it will not transition + # out of, preventing success. + # @raise [MaxWaitTimeExceededError] Raised when the configured + # maximum wait time is reached and the waiter is not yet successful. + # @raise [UnexpectedError] Raised when an error that is not + # expected is encountered while polling for a resource. + # @raise [NoSuchWaiterError] Raised when you request to wait + # for an unknown state. def wait_until(waiter_name, params = {}, options = {}) - w = waiter(waiter_name, options) - w.wait(params) + waiter(waiter_name, options).wait(params) end private @@ -335,15 +334,6 @@ def build_input(operation_name, params) Smithy::Client::Input.new(handlers: handlers, context: context) end - def waiter(waiter_name, options = {}) - waiter_class = waiters[waiter_name] - if waiter_class - waiter_class.new(options.merge(client: self)) - else - raise Smithy::Client::Errors::NoSuchWaiterError.new(waiter_name, waiters.keys) - end - end - def waiters {} end diff --git a/projections/weather/lib/weather/waiters.rb b/projections/weather/lib/weather/waiters.rb index cdcccf0eb..ce7aac632 100644 --- a/projections/weather/lib/weather/waiters.rb +++ b/projections/weather/lib/weather/waiters.rb @@ -2,8 +2,6 @@ # This is generated code! -require 'smithy-client/waiters' - module Weather # @api private From 835e376a8eacba0155a6c0401e2411e16973fd7a Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Tue, 20 May 2025 10:58:35 -0700 Subject: [PATCH 42/48] Define variables inside context --- gems/smithy/spec/interfaces/client/waiters_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index d53fb1de3..b3ba1a3b7 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -3,14 +3,14 @@ require_relative '../../spec_helper' describe 'Client: Waiters' do - let(:input) { { string_property: 'input_string' } } - let(:client) { WaiterService::Client.new(stub_responses: true) } - let(:no_such_waiter_error) { Smithy::Client::Waiters::NoSuchWaiterError } - ['generated client gem', 'generated client from source code'].each do |context| context context do include_context context, 'WaiterService' + let(:input) { { string_property: 'input_string' } } + let(:client) { WaiterService::Client.new(stub_responses: true) } + let(:no_such_waiter_error) { Smithy::Client::Waiters::NoSuchWaiterError } + it 'returns nil when successful' do input = { string_property: 'input_string' } client.stub_responses(:get_operation, { string_property: 'success' }) From 342032589564e907cc3c4b44a9ec9e07543d17a2 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 21 May 2025 12:07:09 -0700 Subject: [PATCH 43/48] Make PR comment changes --- gems/smithy-client/lib/smithy-client/base.rb | 14 +- .../lib/smithy-client/waiters/poller.rb | 2 +- .../lib/smithy-client/waiters/waiter.rb | 4 +- .../spec/smithy-client/waiters_spec.rb | 1161 ++++++++--------- .../lib/smithy/templates/client/waiters.erb | 2 +- gems/smithy/lib/smithy/views/client/client.rb | 5 +- .../smithy/lib/smithy/views/client/waiters.rb | 6 +- .../spec/interfaces/client/waiters_spec.rb | 9 +- 8 files changed, 574 insertions(+), 629 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/base.rb b/gems/smithy-client/lib/smithy-client/base.rb index f91eaf7af..255409dac 100644 --- a/gems/smithy-client/lib/smithy-client/base.rb +++ b/gems/smithy-client/lib/smithy-client/base.rb @@ -41,13 +41,6 @@ def inspect "#<#{self.class.name || 'Smithy::Client::Base'}>" end - def waiter(waiter_name, options = {}) - waiter_class = waiters[waiter_name] - return waiter_class.new(options.merge(client: self)) if waiter_class - - raise Smithy::Client::Waiters::NoSuchWaiterError.new(waiter_name, waiters.keys) - end - private # Constructs a {Configuration} object and gives each plugin the @@ -86,6 +79,13 @@ def context_for(operation_name, params) ) end + def waiter(waiter_name, options = {}) + waiter_class = waiters[waiter_name] + raise Waiters::NoSuchWaiterError.new(waiter_name, waiters.keys) unless waiter_class + + waiter_class.new(options.merge(client: self)) + end + class << self def new(options = {}) plugins = build_plugins diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index 68ef17527..78c11a966 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -15,7 +15,7 @@ def call(client, params) @input = params # TODO: make build_input public and update this line input = client.send(:build_input, @operation_name, params) - input.handlers.remove(Smithy::Client::Plugins::RaiseResponseErrors::Handler) + input.handlers.remove(Plugins::RaiseResponseErrors::Handler) output = input.send_request status = evaluate_acceptors(output) [output, status.to_sym] diff --git a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb index a69271f7b..9a1474119 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/waiter.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/waiter.rb @@ -59,7 +59,9 @@ def wait(client, params) private def max_wait_time(time) - raise ArgumentError, "expected `:max_wait_time` to be an integer, got: #{time}" unless time.is_a?(Integer) + unless time.is_a?(Integer) + raise ArgumentError, "expected `:max_wait_time` to be an Integer, got: #{time.class}" + end time end diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index fd9ef0bfc..36ff5fdad 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -4,702 +4,645 @@ module Smithy module Client - module Waiters - describe Waiters do - let(:shapes) do - { - 'smithy.ruby.tests#WaitService' => { - 'type' => 'service', - 'version' => '2022-11-30', - 'operations' => [{ 'target' => 'smithy.ruby.tests#GetWidget' }], - 'traits' => { 'smithy.protocols#rpcv2Cbor' => {} } - }, - 'smithy.ruby.tests#GetWidget' => { - 'type' => 'operation', - 'input' => { 'target' => 'smithy.ruby.tests#WidgetInput' }, - 'output' => { 'target' => 'smithy.ruby.tests#WidgetOutput' }, - 'errors' => [{ 'target' => 'smithy.ruby.tests#MyError' }], - 'traits' => { 'smithy.waiters#waitable' => matchers } - }, - 'smithy.ruby.tests#WidgetInput' => { - 'type' => 'structure', - 'members' => { - 'stringProperty' => { 'target' => 'smithy.api#String' }, - 'stringArrayProperty' => { 'target' => 'smithy.ruby.tests#StringArray' }, - 'booleanProperty' => { 'target' => 'smithy.api#Boolean' }, - 'booleanArrayProperty' => { 'target' => 'smithy.ruby.tests#BooleanArray' } - } - }, - 'smithy.ruby.tests#WidgetOutput' => { - 'type' => 'structure', - 'members' => { - 'stringProperty' => { 'target' => 'smithy.api#String' }, - 'stringArrayProperty' => { 'target' => 'smithy.ruby.tests#StringArray' }, - 'booleanProperty' => { 'target' => 'smithy.api#Boolean' }, - 'booleanArrayProperty' => { 'target' => 'smithy.ruby.tests#BooleanArray' } - } - }, - 'smithy.ruby.tests#BooleanArray' => { - 'type' => 'list', - 'member' => { 'target' => 'smithy.api#Boolean' } - }, - 'smithy.ruby.tests#StringArray' => { - 'type' => 'list', - 'member' => { 'target' => 'smithy.api#String' } - }, - 'smithy.ruby.tests#MyError' => { - 'type' => 'structure', - 'members' => { 'message' => { 'target' => 'smithy.api#String' } }, - 'traits' => { 'smithy.api#error' => 'client' } + describe Waiters do + let(:shapes) do + { + 'smithy.ruby.tests#WaitService' => { + 'type' => 'service', + 'version' => '2022-11-30', + 'operations' => [{ 'target' => 'smithy.ruby.tests#GetWidget' }], + 'traits' => { 'smithy.protocols#rpcv2Cbor' => {} } + }, + 'smithy.ruby.tests#GetWidget' => { + 'type' => 'operation', + 'input' => { 'target' => 'smithy.ruby.tests#WidgetInput' }, + 'output' => { 'target' => 'smithy.ruby.tests#WidgetOutput' }, + 'errors' => [{ 'target' => 'smithy.ruby.tests#Error' }], + 'traits' => { 'smithy.waiters#waitable' => matchers } + }, + 'smithy.ruby.tests#WidgetInput' => { + 'type' => 'structure', + 'members' => { + 'stringProperty' => { 'target' => 'smithy.api#String' }, + 'stringArrayProperty' => { 'target' => 'smithy.ruby.tests#StringArray' }, + 'booleanProperty' => { 'target' => 'smithy.api#Boolean' }, + 'booleanArrayProperty' => { 'target' => 'smithy.ruby.tests#BooleanArray' } } + }, + 'smithy.ruby.tests#WidgetOutput' => { + 'type' => 'structure', + 'members' => { + 'stringProperty' => { 'target' => 'smithy.api#String' }, + 'stringArrayProperty' => { 'target' => 'smithy.ruby.tests#StringArray' }, + 'booleanProperty' => { 'target' => 'smithy.api#Boolean' }, + 'booleanArrayProperty' => { 'target' => 'smithy.ruby.tests#BooleanArray' } + } + }, + 'smithy.ruby.tests#BooleanArray' => { + 'type' => 'list', + 'member' => { 'target' => 'smithy.api#Boolean' } + }, + 'smithy.ruby.tests#StringArray' => { + 'type' => 'list', + 'member' => { 'target' => 'smithy.api#String' } + }, + 'smithy.ruby.tests#Error' => { + 'type' => 'structure', + 'members' => { 'message' => { 'target' => 'smithy.api#String' } }, + 'traits' => { 'smithy.api#error' => 'client' } } - end - - let(:sample_client) { ClientHelper.sample_client(shapes: shapes) } + } + end - let(:client_class) do - client_class = sample_client.const_get(:Client) - client_class.clear_plugins - client_class.add_plugin(sample_client::Plugins::Endpoint) - client_class.add_plugin(Smithy::Client::Plugins::Protocol) - client_class.add_plugin(Smithy::Client::Plugins::RaiseResponseErrors) - client_class.add_plugin(Smithy::Client::Plugins::StubResponses) - client_class - end + let(:sample_client) { ClientHelper.sample_client(shapes: shapes) } - let(:client) { client_class.new(stub_responses: true) } + let(:client_class) do + client_class = sample_client.const_get(:Client) + client_class.clear_plugins + client_class.add_plugin(sample_client::Plugins::Endpoint) + client_class.add_plugin(Plugins::Protocol) + client_class.add_plugin(Plugins::RaiseResponseErrors) + client_class.add_plugin(Plugins::StubResponses) + client_class + end - let(:input) { { string_property: 'input_string' } } + let(:client) { client_class.new(stub_responses: true) } - let(:my_error) { sample_client::Errors::MyError.new(nil, nil) } + before(:each) { allow_any_instance_of(Waiters::Waiter).to receive(:sleep) } - before(:each) { allow_any_instance_of(Waiter).to receive(:sleep) } + def wait(waiter_name) + client.wait_until(waiter_name, { string_property: 'input' }, { max_wait_time: 60 }) + end - describe 'Waiter' do - let(:matchers) do - { - 'OutputStringPropertyMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'stringProperty', - 'expected' => 'success', - 'comparator' => 'stringEquals' - } + describe Waiters::Waiter do + let(:matchers) do + { + 'OutputStringPropertyMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'stringProperty', + 'expected' => 'success', + 'comparator' => 'stringEquals' } - }, - { - 'state' => 'retry', - 'matcher' => { - 'output' => { - 'path' => 'stringProperty', - 'expected' => 'retry', - 'comparator' => 'stringEquals' - } + } + }, + { + 'state' => 'retry', + 'matcher' => { + 'output' => { + 'path' => 'stringProperty', + 'expected' => 'retry', + 'comparator' => 'stringEquals' } - }, - { - 'state' => 'failure', - 'matcher' => { - 'output' => { - 'path' => 'stringProperty', - 'expected' => 'failure', - 'comparator' => 'stringEquals' - } + } + }, + { + 'state' => 'failure', + 'matcher' => { + 'output' => { + 'path' => 'stringProperty', + 'expected' => 'failure', + 'comparator' => 'stringEquals' } } - ] - } + } + ] } - end + } + end - describe '#poll' do - it 'delays when status is retry' do - client.stub_responses( - :get_widget, - { string_property: 'retry' }, - { string_property: 'retry' }, - { string_property: 'success' } - ) - expect_any_instance_of(Waiter).to receive(:delay).exactly(2).times.and_call_original - client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) - end + describe '#poll' do + it 'delays when status is retry' do + client.stub_responses( + :get_widget, + { string_property: 'retry' }, + { string_property: 'retry' }, + { string_property: 'success' } + ) + expect_any_instance_of(Waiters::Waiter).to receive(:delay).exactly(2).times.and_call_original + wait(:output_string_property_matcher) + end - it 'raises a failure state error when status is failure' do - client.stub_responses(:get_widget, { string_property: 'failure' }) - expect do - client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) - end.to raise_error(FailureStateError) - end + it 'raises a failure state error when status is failure' do + client.stub_responses(:get_widget, { string_property: 'failure' }) + expect { wait(:output_string_property_matcher) } + .to raise_error(Waiters::FailureStateError) + end - it 'raises an unexpected error when status is error' do - client.stub_responses(:get_widget, StandardError.new) - expect do - client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) - end.to raise_error(UnexpectedError) - end + it 'raises an unexpected error when status is error' do + client.stub_responses(:get_widget, StandardError.new) + expect { wait(:output_string_property_matcher) } + .to raise_error(Waiters::UnexpectedError) + end - it 'raises a max wait time exceeded error when there is no more remaining time' do - client.stub_responses( - :get_widget, - { string_property: 'retry' }, - { string_property: 'retry' } - ) - expect do - client.wait_until(:output_string_property_matcher, input, max_wait_time: 1) - end.to raise_error(MaxWaitTimeExceededError) - end + it 'raises a max wait time exceeded error when there is no more remaining time' do + client.stub_responses( + :get_widget, + { string_property: 'retry' }, + { string_property: 'retry' } + ) + expect { wait(:output_string_property_matcher) } + .to raise_error(Waiters::MaxWaitTimeExceededError) end + end - describe '#delay' do - it 'generates a random delay between min_delay and max_delay' do - min_delay = 5 - max_delay = 60 - options = { - max_wait_time: 60, - min_delay: min_delay, - max_delay: max_delay - } - output = Smithy::Client::Output.new(data: {}) - expect_any_instance_of(Poller).to receive(:call).and_return( - [output, :retry], [output, :retry], [output, :retry], [output, :success] - ) - expect_any_instance_of(Waiter).to receive(:delay).with(1).and_wrap_original do |m, *args| - delay = m.call(*args) - expect(delay.between?(min_delay, max_delay)).to be true - 0 - end - expect_any_instance_of(Waiter).to receive(:delay).with(2).and_wrap_original do |m, *args| - delay = m.call(*args) - expect(delay.between?(min_delay, max_delay)).to be true - 0 - end - expect_any_instance_of(Waiter).to receive(:delay).with(3).and_wrap_original do |m, *args| + describe '#delay' do + it 'generates a random delay between min_delay and max_delay' do + min_delay = 5 + max_delay = 60 + options = { + max_wait_time: 60, + min_delay: min_delay, + max_delay: max_delay + } + client.stub_responses( + :get_widget, + { string_property: 'retry' }, + { string_property: 'retry' }, + { string_property: 'retry' }, + { string_property: 'success' } + ) + 1.upto(3) do |attempt| + expect_any_instance_of(Waiters::Waiter).to receive(:delay).with(attempt).and_wrap_original do |m, *args| delay = m.call(*args) expect(delay.between?(min_delay, max_delay)).to be true - 0 + delay end - client.wait_until(:output_string_property_matcher, input, options) end + client.wait_until(:output_string_property_matcher, {}, options) + end - it 'sets the delay to remaining time for the last attempt' do - remaining_time = 40 - min_delay = 25 - max_delay = 30 - options = { - max_wait_time: remaining_time, - min_delay: min_delay, - max_delay: max_delay - } - output = Smithy::Client::Output.new(data: {}) - expect_any_instance_of(Poller).to receive(:call).and_return([output, :retry], [output, :success]) - expect_any_instance_of(Waiter).to receive(:delay).and_wrap_original do |m, *args| - delay = m.call(*args) - expect(delay).to eq(remaining_time) - 0 - end - client.wait_until(:output_string_property_matcher, input, options) + it 'sets the delay to remaining time for the last attempt' do + remaining_time = 40 + options = { + max_wait_time: remaining_time, + min_delay: 25, + max_delay: 30 + } + client.stub_responses( + :get_widget, + { string_property: 'retry' }, + { string_property: 'success' } + ) + expect_any_instance_of(Waiters::Waiter).to receive(:delay).and_wrap_original do |m, *args| + delay = m.call(*args) + expect(delay).to eq(remaining_time) + delay end + client.wait_until(:output_string_property_matcher, {}, options) end + end - context 'errors' do - it 'raises an error when max wait time is exceeded' do - client.stub_responses(:get_widget, {}) - expect do - client.wait_until(:output_string_property_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end + context 'errors' do + it 'raises an error when max wait time is exceeded' do + client.stub_responses(:get_widget, {}) + expect do + client.wait_until(:output_string_property_matcher, {}, max_wait_time: 0) + end.to raise_error(Waiters::MaxWaitTimeExceededError) + end - it 'raises an error when max_wait_time is not provided' do - expect do - client.wait_until(:output_string_property_matcher, input) - end.to raise_error(ArgumentError, 'expected `:max_wait_time` to be an integer, got: ') - end + it 'raises an error when max_wait_time is not provided' do + expect do + client.wait_until(:output_string_property_matcher, {}) + end.to raise_error(ArgumentError, 'expected `:max_wait_time` to be an Integer, got: NilClass') + end - it 'raises an error when max_delay is less than 1' do - options = { - max_wait_time: 5, - max_delay: 0 - } - expect do - client.wait_until(:output_string_property_matcher, input, options) - end.to raise_error(ArgumentError, '`:max_delay` must be greater than 0') - end + it 'raises an error when max_delay is less than 1' do + options = { + max_wait_time: 5, + max_delay: 0 + } + expect do + client.wait_until(:output_string_property_matcher, {}, options) + end.to raise_error(ArgumentError, '`:max_delay` must be greater than 0') + end - it 'raises an error when min_delay is less than 1' do - options = { - max_wait_time: 5, - min_delay: 0 - } - expect do - client.wait_until(:output_string_property_matcher, input, options) - end.to raise_error(ArgumentError, - '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') - end + it 'raises an error when min_delay is less than 1' do + options = { + max_wait_time: 5, + min_delay: 0 + } + expect do + client.wait_until(:output_string_property_matcher, {}, options) + end.to raise_error(ArgumentError, + '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') + end - it 'raises an error when max_delay is less than min_delay' do - options = { - max_wait_time: 5, - min_delay: 4, - max_delay: 2 - } - expect do - client.wait_until(:output_string_property_matcher, input, options) - end.to raise_error(ArgumentError, - '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') - end + it 'raises an error when max_delay is less than min_delay' do + options = { + max_wait_time: 5, + min_delay: 4, + max_delay: 2 + } + expect do + client.wait_until(:output_string_property_matcher, {}, options) + end.to raise_error(ArgumentError, + '`:min_delay` must be greater than 0 and less than or equal to `:max_delay`') end end + end - describe 'Waiters::Poller' do - context 'success matcher' do - let(:matchers) do - { - 'SuccessTrueMatcher' => { - 'acceptors' => [{ 'state' => 'success', 'matcher' => { 'success' => true } }] - }, - 'SuccessFalseMatcher' => { - 'acceptors' => [{ 'state' => 'success', 'matcher' => { 'success' => false } }] - } + describe Waiters::Poller do + context 'success matcher' do + let(:matchers) do + { + 'SuccessTrueMatcher' => { + 'acceptors' => [{ 'state' => 'success', 'matcher' => { 'success' => true } }] + }, + 'SuccessFalseMatcher' => { + 'acceptors' => [{ 'state' => 'success', 'matcher' => { 'success' => false } }] } - end + } + end - it 'succeeds when success is set to true and successful response is received' do - client.stub_responses(:get_widget, {}) - expect do - client.wait_until(:success_true_matcher, input, max_wait_time: 60) - end.to_not raise_error - end + it 'succeeds when success is set to true and successful response is received' do + client.stub_responses(:get_widget, {}) + expect { wait(:success_true_matcher) }.to_not raise_error + end - it 'succeeds when success is set to false and error is received' do - client.stub_responses(:get_widget, StandardError.new) - expect do - client.wait_until(:success_false_matcher, input, max_wait_time: 3) - end.to_not raise_error - end + it 'succeeds when success is set to false and error is received' do + client.stub_responses(:get_widget, StandardError.new) + expect { wait(:success_false_matcher) }.to_not raise_error + end - it 'retries and succeeds when matched' do - client.stub_responses( - :get_widget, - {}, - {}, - StandardError - ) - expect_any_instance_of(Waiter).to receive(:delay).twice.and_call_original - expect do - client.wait_until(:success_false_matcher, input, max_wait_time: 60) - end.to_not raise_error - end + it 'retries and succeeds when matched' do + client.stub_responses( + :get_widget, + {}, + {}, + StandardError + ) + expect_any_instance_of(Waiters::Waiter).to receive(:delay).twice.and_call_original + expect { wait(:success_false_matcher) }.to_not raise_error + end - it 'fails when success is set to true and unexpected error is received' do - client.stub_responses(:get_widget, StandardError) - expect do - client.wait_until(:success_true_matcher, input, max_wait_time: 60) - end.to raise_error(UnexpectedError) - end + it 'fails when success is set to true and unexpected error is received' do + client.stub_responses(:get_widget, StandardError) + expect { wait(:success_true_matcher) } + .to raise_error(Waiters::UnexpectedError) end + end - context 'error type matcher' do - let(:matchers) do - { - 'ErrorTypeMatcher' => { - 'acceptors' => [{ 'state' => 'success', 'matcher' => { 'errorType' => 'MyError' } }] - }, - 'AbsoluteErrorTypeMatcher' => { - 'acceptors' => [{ 'state' => 'success', 'matcher' => { 'errorType' => 'smithy.ruby.tests#MyError' } }] - } + context 'error type matcher' do + let(:matchers) do + { + 'ErrorTypeMatcher' => { + 'acceptors' => [{ 'state' => 'success', 'matcher' => { 'errorType' => 'Error' } }] + }, + 'AbsoluteErrorTypeMatcher' => { + 'acceptors' => [{ 'state' => 'success', 'matcher' => { 'errorType' => 'smithy.ruby.tests#Error' } }] } - end + } + end - it 'succeeds when error matches for relative shape name' do - client.stub_responses(:get_widget, my_error) - expect do - client.wait_until(:error_type_matcher, input, max_wait_time: 60) - end.to_not raise_error - end + it 'succeeds when error matches for relative shape name' do + client.stub_responses(:get_widget, sample_client::Errors::Error.new(nil, nil)) + expect { wait(:error_type_matcher) }.to_not raise_error + end - it 'succeeds when error matches for absolute shape id' do - client.stub_responses(:get_widget, my_error) - expect do - client.wait_until(:absolute_error_type_matcher, input, max_wait_time: 60) - end.to_not raise_error - end + it 'succeeds when error matches for absolute shape id' do + client.stub_responses(:get_widget, sample_client::Errors::Error.new(nil, nil)) + expect { wait(:error_type_matcher) }.to_not raise_error + end - it 'retries and succeeds when matched' do - client.stub_responses( - :get_widget, - {}, - {}, - my_error - ) - expect_any_instance_of(Waiter).to receive(:delay).twice.and_call_original - expect do - client.wait_until(:error_type_matcher, input, max_wait_time: 60) - end.to_not raise_error - end + it 'retries and succeeds when matched' do + client.stub_responses( + :get_widget, + {}, + {}, + sample_client::Errors::Error.new(nil, nil) + ) + expect_any_instance_of(Waiters::Waiter).to receive(:delay).twice.and_call_original + expect { wait(:error_type_matcher) }.to_not raise_error + end - it 'fails when error does not match' do - client.stub_responses(:get_widget, StandardError) - expect do - client.wait_until(:error_type_matcher, input, max_wait_time: 60) - end.to raise_error(UnexpectedError) - end + it 'fails when error does not match' do + client.stub_responses(:get_widget, StandardError) + expect { wait(:error_type_matcher) } + .to raise_error(Waiters::UnexpectedError) end + end - context 'output matcher' do - context 'string equals comparator' do - let(:matchers) do - { - 'OutputStringPropertyMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'stringProperty', - 'expected' => 'expected string', - 'comparator' => 'stringEquals' - } - } + context 'string equals comparator' do + let(:matchers) do + { + 'OutputStringPropertyMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'stringProperty', + 'expected' => 'expected string', + 'comparator' => 'stringEquals' } - ] + } } - } - end + ] + } + } + end - it 'succeeds when output matches' do - client.stub_responses(:get_widget, { string_property: 'expected string' }) - expect do - client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) - end.to_not raise_error - end + it 'succeeds when output matches' do + client.stub_responses(:get_widget, { string_property: 'expected string' }) + expect { wait(:output_string_property_matcher) }.to_not raise_error + end - it 'retries and succeeds when matched' do - client.stub_responses( - :get_widget, - { string_property: 'unexpected string' }, - { string_property: 'unexpected string' }, - { string_property: 'expected string' } - ) - expect_any_instance_of(Waiter).to receive(:delay).twice.and_call_original - expect do - client.wait_until(:output_string_property_matcher, input, max_wait_time: 60) - end.to_not raise_error - end + it 'retries and succeeds when matched' do + client.stub_responses( + :get_widget, + { string_property: 'unexpected string' }, + { string_property: 'unexpected string' }, + { string_property: 'expected string' } + ) + expect_any_instance_of(Waiters::Waiter).to receive(:delay).twice.and_call_original + expect { wait(:output_string_property_matcher) }.to_not raise_error + end - it 'fails when output property does not match' do - client.stub_responses(:get_widget, { string_property: 'unexpected string' }) - expect do - client.wait_until(:output_string_property_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end + it 'fails when output property does not match' do + client.stub_responses(:get_widget, { string_property: 'unexpected string' }) + expect { wait(:output_string_property_matcher) } + .to raise_error(Waiters::MaxWaitTimeExceededError) + end - it 'fails when output property is nil' do - client.stub_responses(:get_widget, {}) - expect do - client.wait_until(:output_string_property_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end - end + it 'fails when output property is nil' do + client.stub_responses(:get_widget, {}) + expect { wait(:output_string_property_matcher) } + .to raise_error(Waiters::MaxWaitTimeExceededError) + end + end - context 'boolean equals comparator' do - let(:matchers) do - { - 'OutputBooleanPropertyMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'booleanProperty', - 'expected' => 'false', - 'comparator' => 'booleanEquals' - } - } + context 'boolean equals comparator' do + let(:matchers) do + { + 'OutputBooleanPropertyMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'booleanProperty', + 'expected' => 'false', + 'comparator' => 'booleanEquals' } - ] + } } - } - end + ] + } + } + end - it 'succeeds when output matches' do - client.stub_responses(:get_widget, { boolean_property: false }) - expect do - client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) - end.to_not raise_error - end + it 'succeeds when output matches' do + client.stub_responses(:get_widget, { boolean_property: false }) + expect { wait(:output_boolean_property_matcher) }.to_not raise_error + end - it 'retries and succeeds when matched' do - client.stub_responses( - :get_widget, - { boolean_property: true }, - { boolean_property: true }, - { boolean_property: false } - ) - expect_any_instance_of(Waiter).to receive(:delay).twice.and_call_original - expect do - client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 60) - end.to_not raise_error - end + it 'retries and succeeds when matched' do + client.stub_responses( + :get_widget, + { boolean_property: true }, + { boolean_property: true }, + { boolean_property: false } + ) + expect_any_instance_of(Waiters::Waiter).to receive(:delay).twice.and_call_original + expect { wait(:output_boolean_property_matcher) }.to_not raise_error + end - it 'fails when output property does not match' do - client.stub_responses(:get_widget, { boolean_property: true }) - expect do - client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end + it 'fails when output property does not match' do + client.stub_responses(:get_widget, { boolean_property: true }) + expect { wait(:output_boolean_property_matcher) } + .to raise_error(Waiters::MaxWaitTimeExceededError) + end - it 'fails when output property is nil' do - client.stub_responses(:get_widget, {}) - expect do - client.wait_until(:output_boolean_property_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end - end + it 'fails when output property is nil' do + client.stub_responses(:get_widget, {}) + expect { wait(:output_boolean_property_matcher) } + .to raise_error(Waiters::MaxWaitTimeExceededError) + end + end - context 'all string equals comparator' do - let(:matchers) do - { - 'OutputStringArrayAllPropertyMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'stringArrayProperty', - 'expected' => 'expected string', - 'comparator' => 'allStringEquals' - } - } + context 'all string equals comparator' do + let(:matchers) do + { + 'OutputStringArrayAllPropertyMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'stringArrayProperty', + 'expected' => 'expected string', + 'comparator' => 'allStringEquals' } - ] + } } - } - end + ] + } + } + end - it 'succeeds when output matches' do - output = { - string_array_property: [ - 'expected string', - 'expected string', - 'expected string' - ] - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) - end.to_not raise_error - end + it 'succeeds when output matches' do + output = { + string_array_property: [ + 'expected string', + 'expected string', + 'expected string' + ] + } + client.stub_responses(:get_widget, output) + expect { wait(:output_string_array_all_property_matcher) }.to_not raise_error + end - it 'retries and succeeds when matched' do - output_expected = { - string_array_property: [ - 'expected string', - 'expected string', - 'expected string' - ] - } - output_unexpected = { - string_array_property: [ - 'expected string', - 'unexpected string', - 'unexpected string' - ] - } - client.stub_responses( - :get_widget, - output_unexpected, - output_unexpected, - output_expected - ) - expect_any_instance_of(Waiter).to receive(:delay).twice.and_call_original - expect do - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 60) - end.to_not raise_error - end + it 'retries and succeeds when matched' do + output_expected = { + string_array_property: [ + 'expected string', + 'expected string', + 'expected string' + ] + } + output_unexpected = { + string_array_property: [ + 'expected string', + 'unexpected string', + 'unexpected string' + ] + } + client.stub_responses( + :get_widget, + output_unexpected, + output_unexpected, + output_expected + ) + expect_any_instance_of(Waiters::Waiter).to receive(:delay).twice.and_call_original + expect { wait(:output_string_array_all_property_matcher) }.to_not raise_error + end - it 'fails when output property does not match' do - output_unexpected = { - string_array_property: [ - 'expected string', - 'unexpected string', - 'unexpected string' - ] - } - client.stub_responses(:get_widget, output_unexpected) - expect do - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end + it 'fails when output property does not match' do + output_unexpected = { + string_array_property: [ + 'expected string', + 'unexpected string', + 'unexpected string' + ] + } + client.stub_responses(:get_widget, output_unexpected) + expect { wait(:output_string_array_all_property_matcher) } + .to raise_error(Waiters::MaxWaitTimeExceededError) + end - it 'fails when output property is empty' do - client.stub_responses(:get_widget, { string_array_property: [] }) - expect do - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end + it 'fails when output property is empty' do + client.stub_responses(:get_widget, { string_array_property: [] }) + expect { wait(:output_string_array_all_property_matcher) } + .to raise_error(Waiters::MaxWaitTimeExceededError) + end - it 'fails when output property is nil' do - client.stub_responses(:get_widget, {}) - expect do - client.wait_until(:output_string_array_all_property_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end - end + it 'fails when output property is nil' do + client.stub_responses(:get_widget, {}) + expect { wait(:output_string_array_all_property_matcher) } + .to raise_error(Waiters::MaxWaitTimeExceededError) + end + end - context 'any string equals comparator' do - let(:matchers) do - { - 'OutputStringArrayAnyPropertyMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'output' => { - 'path' => 'stringArrayProperty', - 'expected' => 'expected string', - 'comparator' => 'anyStringEquals' - } - } + context 'any string equals comparator' do + let(:matchers) do + { + 'OutputStringArrayAnyPropertyMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'output' => { + 'path' => 'stringArrayProperty', + 'expected' => 'expected string', + 'comparator' => 'anyStringEquals' } - ] + } } - } - end + ] + } + } + end - it 'succeeds when output matches' do - output = { - string_array_property: [ - 'some other string', - 'another string', - 'expected string', - 'yet another string' - ] - } - client.stub_responses(:get_widget, output) - expect do - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) - end.to_not raise_error - end + it 'succeeds when output matches' do + output = { + string_array_property: [ + 'some other string', + 'another string', + 'expected string', + 'yet another string' + ] + } + client.stub_responses(:get_widget, output) + expect { wait(:output_string_array_any_property_matcher) }.to_not raise_error + end - it 'retries and succeeds when matched' do - output_expected = { - string_array_property: [ - 'some other string', - 'another string', - 'expected string', - 'yet another string' - ] - } - output_unexpected = { - string_array_property: [ - 'some other string', - 'another string', - 'unexpected string', - 'yet another string' - ] - } - client.stub_responses( - :get_widget, - output_unexpected, - output_unexpected, - output_expected - ) - expect_any_instance_of(Waiter).to receive(:delay).twice.and_call_original - expect do - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 60) - end.to_not raise_error - end + it 'retries and succeeds when matched' do + output_expected = { + string_array_property: [ + 'some other string', + 'another string', + 'expected string', + 'yet another string' + ] + } + output_unexpected = { + string_array_property: [ + 'some other string', + 'another string', + 'unexpected string', + 'yet another string' + ] + } + client.stub_responses( + :get_widget, + output_unexpected, + output_unexpected, + output_expected + ) + expect_any_instance_of(Waiters::Waiter).to receive(:delay).twice.and_call_original + expect { wait(:output_string_array_any_property_matcher) }.to_not raise_error + end - it 'fails when output property does not match' do - output_unexpected = { - string_array_property: [ - 'some other string', - 'another string', - 'unexpected string', - 'yet another string' - ] - } - client.stub_responses(:get_widget, output_unexpected) - expect do - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end + it 'fails when output property does not match' do + output_unexpected = { + string_array_property: [ + 'some other string', + 'another string', + 'unexpected string', + 'yet another string' + ] + } + client.stub_responses(:get_widget, output_unexpected) + expect { wait(:output_string_array_any_property_matcher) } + .to raise_error(Waiters::MaxWaitTimeExceededError) + end - it 'fails when output property is empty' do - client.stub_responses(:get_widget, { string_array_property: [] }) - expect do - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end + it 'fails when output property is empty' do + client.stub_responses(:get_widget, { string_array_property: [] }) + expect { wait(:output_string_array_any_property_matcher) } + .to raise_error(Waiters::MaxWaitTimeExceededError) + end - it 'fails when output property is nil' do - client.stub_responses(:get_widget, {}) - expect do - client.wait_until(:output_string_array_any_property_matcher, input, max_wait_time: 0) - end.to raise_error(MaxWaitTimeExceededError) - end - end + it 'fails when output property is nil' do + client.stub_responses(:get_widget, {}) + expect { wait(:output_string_array_any_property_matcher) } + .to raise_error(Waiters::MaxWaitTimeExceededError) end + end - context 'input output matcher' do - let(:matchers) do - { - 'InputOutputBooleanPropertyMatcher' => { - 'acceptors' => [ - { - 'state' => 'success', - 'matcher' => { - 'inputOutput' => { - 'path' => 'input.stringProperty == output.stringProperty', - 'expected' => 'true', - 'comparator' => 'booleanEquals' - } + context 'input output matcher' do + let(:matchers) do + { + 'InputOutputBooleanPropertyMatcher' => { + 'acceptors' => [ + { + 'state' => 'success', + 'matcher' => { + 'inputOutput' => { + 'path' => 'input.stringProperty == output.stringProperty', + 'expected' => 'true', + 'comparator' => 'booleanEquals' } } - ] - } + } + ] } - end + } + end - it 'succeeds for boolean equals comparator' do - client.stub_responses(:get_widget, { string_property: 'input_string' }) - expect do - client.wait_until(:input_output_boolean_property_matcher, input, max_wait_time: 60) - end.to_not raise_error - end + it 'succeeds for boolean equals comparator' do + client.stub_responses(:get_widget, { string_property: 'input' }) + expect { wait(:input_output_boolean_property_matcher) }.to_not raise_error end + end - context 'order' do - let(:matchers) do - { - 'AcceptorOrderSuccessMatcher' => { - 'acceptors' => [ - { 'state' => 'success', 'matcher' => { 'errorType' => 'MyError' } }, - { 'state' => 'failure', 'matcher' => { 'errorType' => 'MyError' } } - ] - }, - 'AcceptorOrderFailureMatcher' => { - 'acceptors' => [ - { 'state' => 'failure', 'matcher' => { 'errorType' => 'MyError' } }, - { 'state' => 'success', 'matcher' => { 'errorType' => 'MyError' } } - ] - } + context 'order' do + let(:matchers) do + { + 'AcceptorOrderSuccessMatcher' => { + 'acceptors' => [ + { 'state' => 'success', 'matcher' => { 'errorType' => 'Error' } }, + { 'state' => 'failure', 'matcher' => { 'errorType' => 'Error' } } + ] + }, + 'AcceptorOrderFailureMatcher' => { + 'acceptors' => [ + { 'state' => 'failure', 'matcher' => { 'errorType' => 'Error' } }, + { 'state' => 'success', 'matcher' => { 'errorType' => 'Error' } } + ] } - end + } + end - it 'checks acceptors in order' do - client.stub_responses(:get_widget, my_error) - expect do - client.wait_until(:acceptor_order_success_matcher, input, max_wait_time: 60) - end.to_not raise_error - client.stub_responses(:get_widget, my_error) - expect do - client.wait_until(:acceptor_order_failure_matcher, input, max_wait_time: 60) - end.to raise_error(FailureStateError) - end + it 'checks acceptors in order' do + client.stub_responses(:get_widget, sample_client::Errors::Error.new(nil, nil)) + expect { wait(:acceptor_order_success_matcher) }.to_not raise_error + expect { wait(:acceptor_order_failure_matcher) } + .to raise_error(Waiters::FailureStateError) end end end diff --git a/gems/smithy/lib/smithy/templates/client/waiters.erb b/gems/smithy/lib/smithy/templates/client/waiters.erb index c5b546dce..70cb16706 100644 --- a/gems/smithy/lib/smithy/templates/client/waiters.erb +++ b/gems/smithy/lib/smithy/templates/client/waiters.erb @@ -7,7 +7,7 @@ module <%= module_name %> # @api private module Waiters <% waiters.each do |waiter| -%> -<% if waiter.deprecated -%> +<% if waiter.deprecated? -%> # @deprecated <% end -%> # @api private diff --git a/gems/smithy/lib/smithy/views/client/client.rb b/gems/smithy/lib/smithy/views/client/client.rb index 27476717e..ddfe6c1a8 100644 --- a/gems/smithy/lib/smithy/views/client/client.rb +++ b/gems/smithy/lib/smithy/views/client/client.rb @@ -65,9 +65,8 @@ def waiters return ['{}'] if waiters.empty? lines = ['{'] - waiters.each_with_index do |waiter, _i| - line = " #{waiter.name.underscore}: Waiters::#{waiter.name}," - lines << line + waiters.each do |waiter| + lines << " #{waiter.name.underscore}: Waiters::#{waiter.name}," end lines.last.chomp!(',') if lines.last.end_with?(',') lines << '}' diff --git a/gems/smithy/lib/smithy/views/client/waiters.rb b/gems/smithy/lib/smithy/views/client/waiters.rb index a700b71f9..888417ede 100644 --- a/gems/smithy/lib/smithy/views/client/waiters.rb +++ b/gems/smithy/lib/smithy/views/client/waiters.rb @@ -48,7 +48,7 @@ def initialize(operation_name, name, waiter) @deprecated = waiter['deprecated'] end - attr_reader :operation_name, :name, :documentation, :acceptors, :min_delay, :max_delay, :deprecated + attr_reader :operation_name, :name, :documentation, :acceptors, :min_delay, :max_delay def docstrings @documentation.split("\n") @@ -71,6 +71,10 @@ def preprocess_acceptor(acceptor) acceptor['matcher']['errorType'] = Model::Shape.name(error_type) end end + + def deprecated? + @deprecated + end end end end diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index b3ba1a3b7..6d68d53ff 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -7,26 +7,23 @@ context context do include_context context, 'WaiterService' - let(:input) { { string_property: 'input_string' } } let(:client) { WaiterService::Client.new(stub_responses: true) } let(:no_such_waiter_error) { Smithy::Client::Waiters::NoSuchWaiterError } it 'returns nil when successful' do - input = { string_property: 'input_string' } - client.stub_responses(:get_operation, { string_property: 'success' }) - expect(client.wait_until(:success_matcher, input, max_wait_time: 60)).to be(nil) + expect(client.wait_until(:success_matcher, {}, max_wait_time: 60)).to be(nil) end it 'raises waiter failed error when unsuccessful' do client.stub_responses(:get_operation, StandardError) expect do - client.wait_until(:success_matcher, { string_property: 'input_string' }, max_wait_time: 60) + client.wait_until(:success_matcher, {}, max_wait_time: 60) end.to raise_error(Smithy::Client::Waiters::WaiterFailed) end it 'raises an error for nonexistent waiters' do expect do - client.wait_until(:nonexistent_waiter, { string_property: 'input_string' }, max_wait_time: 60) + client.wait_until(:nonexistent_waiter) end.to raise_error(Smithy::Client::Waiters::NoSuchWaiterError) end end From 70c33157e7f637306c051563cd43480ea60c2202 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 21 May 2025 14:03:16 -0700 Subject: [PATCH 44/48] Add todo --- .../lib/smithy-client/waiters/poller.rb | 2 ++ .../spec/smithy-client/waiters_spec.rb | 23 ++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index 78c11a966..3a54a0278 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -58,6 +58,8 @@ def matches_success?(path_matcher, output) path_matcher == true ? !output.data.nil? : !output.error.nil? end + # TODO: fix matcher to check for error classes in errors_module + # and update corresponding test in smithy-client/waiters_spec.rb def matches_errorType?(path_matcher, output) return false if output.error.nil? diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index 36ff5fdad..50bd4ff26 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -122,7 +122,7 @@ def wait(waiter_name) { string_property: 'retry' }, { string_property: 'success' } ) - expect_any_instance_of(Waiters::Waiter).to receive(:delay).exactly(2).times.and_call_original + expect_any_instance_of(Waiters::Waiter).to receive(:sleep).exactly(2).times wait(:output_string_property_matcher) end @@ -275,7 +275,7 @@ def wait(waiter_name) {}, StandardError ) - expect_any_instance_of(Waiters::Waiter).to receive(:delay).twice.and_call_original + expect_any_instance_of(Waiters::Waiter).to receive(:sleep).twice expect { wait(:success_false_matcher) }.to_not raise_error end @@ -315,15 +315,22 @@ def wait(waiter_name) {}, sample_client::Errors::Error.new(nil, nil) ) - expect_any_instance_of(Waiters::Waiter).to receive(:delay).twice.and_call_original + expect_any_instance_of(Waiters::Waiter).to receive(:sleep).twice expect { wait(:error_type_matcher) }.to_not raise_error end it 'fails when error does not match' do - client.stub_responses(:get_widget, StandardError) + client.stub_responses(:get_widget, Exception) expect { wait(:error_type_matcher) } .to raise_error(Waiters::UnexpectedError) end + + # TODO: update this test when Poller matches_errorType is fixed + it 'incorrectly matches when expected error is a substring of actual error' do + client.stub_responses(:get_widget, StandardError) + expect { wait(:error_type_matcher) } + .to_not raise_error + end end context 'string equals comparator' do @@ -358,7 +365,7 @@ def wait(waiter_name) { string_property: 'unexpected string' }, { string_property: 'expected string' } ) - expect_any_instance_of(Waiters::Waiter).to receive(:delay).twice.and_call_original + expect_any_instance_of(Waiters::Waiter).to receive(:sleep).twice expect { wait(:output_string_property_matcher) }.to_not raise_error end @@ -407,7 +414,7 @@ def wait(waiter_name) { boolean_property: true }, { boolean_property: false } ) - expect_any_instance_of(Waiters::Waiter).to receive(:delay).twice.and_call_original + expect_any_instance_of(Waiters::Waiter).to receive(:sleep).twice expect { wait(:output_boolean_property_matcher) }.to_not raise_error end @@ -477,7 +484,7 @@ def wait(waiter_name) output_unexpected, output_expected ) - expect_any_instance_of(Waiters::Waiter).to receive(:delay).twice.and_call_original + expect_any_instance_of(Waiters::Waiter).to receive(:sleep).twice expect { wait(:output_string_array_all_property_matcher) }.to_not raise_error end @@ -563,7 +570,7 @@ def wait(waiter_name) output_unexpected, output_expected ) - expect_any_instance_of(Waiters::Waiter).to receive(:delay).twice.and_call_original + expect_any_instance_of(Waiters::Waiter).to receive(:sleep).twice expect { wait(:output_string_array_any_property_matcher) }.to_not raise_error end From 7ebe9b0ba8df1c8372f03e572bc52d2c4b7abf71 Mon Sep 17 00:00:00 2001 From: Matt Muller Date: Wed, 21 May 2025 17:37:13 -0400 Subject: [PATCH 45/48] Fix namespace issue with plugins --- gems/smithy/lib/smithy/generators/client.rb | 4 ++-- .../spec/fixtures/{waiter_service => waiters}/model.json | 0 .../spec/fixtures/{waiter_service => waiters}/model.smithy | 0 .../fixtures/{waiter_service => waiters}/smithy-build.json | 0 gems/smithy/spec/interfaces/client/waiters_spec.rb | 4 ++-- 5 files changed, 4 insertions(+), 4 deletions(-) rename gems/smithy/spec/fixtures/{waiter_service => waiters}/model.json (100%) rename gems/smithy/spec/fixtures/{waiter_service => waiters}/model.smithy (100%) rename gems/smithy/spec/fixtures/{waiter_service => waiters}/smithy-build.json (100%) diff --git a/gems/smithy/lib/smithy/generators/client.rb b/gems/smithy/lib/smithy/generators/client.rb index 05ea99aab..689cb34b8 100644 --- a/gems/smithy/lib/smithy/generators/client.rb +++ b/gems/smithy/lib/smithy/generators/client.rb @@ -84,13 +84,13 @@ def rbs_files def code_generated_plugins Enumerator.new do |e| e.yield "lib/#{@gem_name}/plugins/auth.rb", Views::Client::Plugin.new( - class_name: "#{@plan.module_name}::Plugins::Auth", + class_name: "::#{@plan.module_name}::Plugins::Auth", require_path: 'plugins/auth', require_relative: true, source: Views::Client::AuthPlugin.new(@plan).render ) e.yield "lib/#{@gem_name}/plugins/endpoint.rb", Views::Client::Plugin.new( - class_name: "#{@plan.module_name}::Plugins::Endpoint", + class_name: "::#{@plan.module_name}::Plugins::Endpoint", require_path: 'plugins/endpoint', require_relative: true, source: Views::Client::EndpointPlugin.new(@plan).render diff --git a/gems/smithy/spec/fixtures/waiter_service/model.json b/gems/smithy/spec/fixtures/waiters/model.json similarity index 100% rename from gems/smithy/spec/fixtures/waiter_service/model.json rename to gems/smithy/spec/fixtures/waiters/model.json diff --git a/gems/smithy/spec/fixtures/waiter_service/model.smithy b/gems/smithy/spec/fixtures/waiters/model.smithy similarity index 100% rename from gems/smithy/spec/fixtures/waiter_service/model.smithy rename to gems/smithy/spec/fixtures/waiters/model.smithy diff --git a/gems/smithy/spec/fixtures/waiter_service/smithy-build.json b/gems/smithy/spec/fixtures/waiters/smithy-build.json similarity index 100% rename from gems/smithy/spec/fixtures/waiter_service/smithy-build.json rename to gems/smithy/spec/fixtures/waiters/smithy-build.json diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index 6d68d53ff..47d83ee1f 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -5,9 +5,9 @@ describe 'Client: Waiters' do ['generated client gem', 'generated client from source code'].each do |context| context context do - include_context context, 'WaiterService' + include_context context, 'Waiters' - let(:client) { WaiterService::Client.new(stub_responses: true) } + let(:client) { ::Waiters::Client.new(stub_responses: true) } let(:no_such_waiter_error) { Smithy::Client::Waiters::NoSuchWaiterError } it 'returns nil when successful' do From 87185bc5c98e4d5b2d1f6f185d8ee00b4cb5bec9 Mon Sep 17 00:00:00 2001 From: Matt Muller Date: Wed, 21 May 2025 17:41:23 -0400 Subject: [PATCH 46/48] Rubocop --- gems/smithy/spec/interfaces/client/waiters_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gems/smithy/spec/interfaces/client/waiters_spec.rb b/gems/smithy/spec/interfaces/client/waiters_spec.rb index 47d83ee1f..0916b4d4a 100644 --- a/gems/smithy/spec/interfaces/client/waiters_spec.rb +++ b/gems/smithy/spec/interfaces/client/waiters_spec.rb @@ -7,7 +7,7 @@ context context do include_context context, 'Waiters' - let(:client) { ::Waiters::Client.new(stub_responses: true) } + let(:client) { Waiters::Client.new(stub_responses: true) } let(:no_such_waiter_error) { Smithy::Client::Waiters::NoSuchWaiterError } it 'returns nil when successful' do From 61ada8c5199abf44021ce306755cbe1dd2feb0ee Mon Sep 17 00:00:00 2001 From: Matt Muller Date: Wed, 21 May 2025 18:42:42 -0400 Subject: [PATCH 47/48] Fix TODO --- .../lib/smithy-client/waiters/poller.rb | 4 +--- .../spec/smithy-client/waiters_spec.rb | 13 ++++++------- gems/smithy/lib/smithy/views/client/waiters.rb | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/gems/smithy-client/lib/smithy-client/waiters/poller.rb b/gems/smithy-client/lib/smithy-client/waiters/poller.rb index 3a54a0278..bc6050c95 100644 --- a/gems/smithy-client/lib/smithy-client/waiters/poller.rb +++ b/gems/smithy-client/lib/smithy-client/waiters/poller.rb @@ -58,12 +58,10 @@ def matches_success?(path_matcher, output) path_matcher == true ? !output.data.nil? : !output.error.nil? end - # TODO: fix matcher to check for error classes in errors_module - # and update corresponding test in smithy-client/waiters_spec.rb def matches_errorType?(path_matcher, output) return false if output.error.nil? - output.error.class.to_s.include?(path_matcher) + output.error.class.to_s.end_with?("Errors::#{path_matcher}") end def equal?(actual, expected, comparator) diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index 50bd4ff26..76a5e63c1 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -299,13 +299,13 @@ def wait(waiter_name) end it 'succeeds when error matches for relative shape name' do - client.stub_responses(:get_widget, sample_client::Errors::Error.new(nil, nil)) + client.stub_responses(:get_widget, 'Error') expect { wait(:error_type_matcher) }.to_not raise_error end it 'succeeds when error matches for absolute shape id' do - client.stub_responses(:get_widget, sample_client::Errors::Error.new(nil, nil)) - expect { wait(:error_type_matcher) }.to_not raise_error + client.stub_responses(:get_widget, 'Error') + expect { wait(:absolute_error_type_matcher) }.to_not raise_error end it 'retries and succeeds when matched' do @@ -313,7 +313,7 @@ def wait(waiter_name) :get_widget, {}, {}, - sample_client::Errors::Error.new(nil, nil) + 'Error' ) expect_any_instance_of(Waiters::Waiter).to receive(:sleep).twice expect { wait(:error_type_matcher) }.to_not raise_error @@ -325,11 +325,10 @@ def wait(waiter_name) .to raise_error(Waiters::UnexpectedError) end - # TODO: update this test when Poller matches_errorType is fixed it 'incorrectly matches when expected error is a substring of actual error' do client.stub_responses(:get_widget, StandardError) expect { wait(:error_type_matcher) } - .to_not raise_error + .to raise_error(Waiters::UnexpectedError) end end @@ -646,7 +645,7 @@ def wait(waiter_name) end it 'checks acceptors in order' do - client.stub_responses(:get_widget, sample_client::Errors::Error.new(nil, nil)) + client.stub_responses(:get_widget, 'Error') expect { wait(:acceptor_order_success_matcher) }.to_not raise_error expect { wait(:acceptor_order_failure_matcher) } .to raise_error(Waiters::FailureStateError) diff --git a/gems/smithy/lib/smithy/views/client/waiters.rb b/gems/smithy/lib/smithy/views/client/waiters.rb index 888417ede..432dc74a0 100644 --- a/gems/smithy/lib/smithy/views/client/waiters.rb +++ b/gems/smithy/lib/smithy/views/client/waiters.rb @@ -73,7 +73,7 @@ def preprocess_acceptor(acceptor) end def deprecated? - @deprecated + !!@deprecated end end end From 01a9483ce5be4133791c403105b55bd3b13dede6 Mon Sep 17 00:00:00 2001 From: Richard Wang Date: Wed, 21 May 2025 16:01:55 -0700 Subject: [PATCH 48/48] Remove fixed test --- gems/smithy-client/spec/smithy-client/waiters_spec.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/gems/smithy-client/spec/smithy-client/waiters_spec.rb b/gems/smithy-client/spec/smithy-client/waiters_spec.rb index 76a5e63c1..2b2b7d200 100644 --- a/gems/smithy-client/spec/smithy-client/waiters_spec.rb +++ b/gems/smithy-client/spec/smithy-client/waiters_spec.rb @@ -320,12 +320,6 @@ def wait(waiter_name) end it 'fails when error does not match' do - client.stub_responses(:get_widget, Exception) - expect { wait(:error_type_matcher) } - .to raise_error(Waiters::UnexpectedError) - end - - it 'incorrectly matches when expected error is a substring of actual error' do client.stub_responses(:get_widget, StandardError) expect { wait(:error_type_matcher) } .to raise_error(Waiters::UnexpectedError)