Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Panic when attempting to mock SelectObjectContentEventStream for unit testing #3412

Closed
3 tasks done
thesilentg opened this issue Jul 7, 2020 · 2 comments · Fixed by #3473 or #3479
Closed
3 tasks done

Panic when attempting to mock SelectObjectContentEventStream for unit testing #3412

thesilentg opened this issue Jul 7, 2020 · 2 comments · Fixed by #3473 or #3479
Labels
bug This issue is a bug.

Comments

@thesilentg
Copy link

thesilentg commented Jul 7, 2020

Confirm by changing [ ] to [x] below to ensure that it's a bug:

Describe the bug
I'm using SelectObjectContent in my code. Example below:

	queryResp, err := s.s3.SelectObjectContentWithContext(ctx, queryRequest)
	if err != nil {
		return errors.Wrap(err, "failed to call select object")
	}
	defer func() {
		 _ = queryResp.EventStream.Close()
	}()

As part of unit testing, I would like mock out the S3 client. I've created my own fakeS3Client which conforms to the s3iface.S3API interface. The SelectObjectContentWithContext method returns a fake stream reader which satisfies SelectObjectContentEventStreamReader and a fake iocloser which satisfies io.Closer.

func (f *fakeS3Client) SelectObjectContentWithContext(ctx aws.Context, input *s3.SelectObjectContentInput, opts ...request.Option) (*s3.SelectObjectContentOutput, error) {
        // Details omitted for brevity

	return &s3.SelectObjectContentOutput{
		EventStream: &s3.SelectObjectContentEventStream{
			Reader:       fakeStreamReader{event: &s3.RecordsEvent{Payload: payload}},
			StreamCloser: fakeIOCloser{},
		},
	}, nil
}

However, when trying to run the testing code, there is a panic inside of the deferred queryResp.EventStream.Close(). The cleaned stack trace looks like:

github.com/aws/aws-sdk-go/private/protocol/eventstream/eventstreamapi.(*OnceError).Err()
	github.com/aws/aws-sdk-go/private/protocol/eventstream/eventstreamapi/error.go:50 
github.com/aws/aws-sdk-go/service/s3.(*SelectObjectContentEventStream).Err()
	github.com/aws/aws-sdk-go/service/s3/api.go:9733 
github.com/aws/aws-sdk-go/service/s3.(*SelectObjectContentEventStream).Close()
	github.com/aws/aws-sdk-go/service/s3/api.go:9714 

Diving into this code more, it appears that SelectObjectContentEventStream has a non-exported field err which is a pointer to eventstreamapi.OnceError. When the deferred queryResp.EventStream.Close() is called, it calls es.err.Err(), which panics for a nil es.err. However, there is no way to set the value of this non-exported field, or call newSelectObjectContentEventStream, as this is also non-exported. What is the expectation here? I see three paths forward:

  1. Modify my application code to remove the call to queryResp.EventStream.Close(). Given the documentation for this method, this seems dangerous.
  2. Modify my application code to include a deferred recover to catch this during unit testing. Also not ideal, as this is only necessitated because of the internal implementation details of the SelectObjectContentEventStream, which could change at any time
  3. (Desired) Update the SelectObjectContentEventStream to validate that ecs.err is non-nil before calling Err()

Version of AWS SDK for Go?
1.33.1

Version of Go (go version)?
go version go1.14.3 darwin/amd64

@thesilentg thesilentg added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Jul 7, 2020
@diehlaws diehlaws self-assigned this Aug 3, 2020
@diehlaws diehlaws removed the needs-triage This issue or PR still needs to be triaged. label Aug 3, 2020
@diehlaws
Copy link
Contributor

diehlaws commented Aug 3, 2020

Hi @thesilentg, thanks for bringing this to our attention and I do apologize for the delay in response on our end. We're investigating this behavior, and will update the issue once we have additional information on the matter.

jasdel added a commit to jasdel/aws-sdk-go that referenced this issue Aug 10, 2020
Fixes aws#3412 by exporting the operation's EventStream type's constructor
function so it can be used to fully initialize fully when mocking out
behavior for API operations with event streams.
jasdel added a commit to jasdel/aws-sdk-go that referenced this issue Aug 11, 2020
Fixes aws#3412 by exporting the operation's EventStream type's constructor
function so it can be used to fully initialize fully when mocking out
behavior for API operations with event streams.
jasdel added a commit that referenced this issue Aug 11, 2020
Fixes #3412 by exporting the operation's EventStream type's constructor function so it can be used to fully initialize fully when mocking out behavior for API operations with event streams.
@jasdel
Copy link
Contributor

jasdel commented Aug 11, 2020

Thanks for reporting this issue @thesilentg, and providing a detailed debug. I merged in change #3473 which exports the NewSelectObjectContentEventStream constructor function for SelectObjectContentEventStream. This will ensure that any internal state behavior that is needed by the SelectObjectContentEventStream will be initialized.

The constructor also takes functional arguments to configure the Reader and stream closer at the same time.

return &s3.SelectObjectContentOutput{
	EventStream: s3.NewSelectObjectContentEventStream(func(o *s3.SelectObjectContentEventStream) {
		o.Reader = myStreamReader
		o.StreamCloser = myStreamCloser
	}),
}

aws-sdk-go-automation pushed a commit that referenced this issue Aug 12, 2020
===

### Service Client Updates
* `service/cloud9`: Updates service API and documentation
  * Add ConnectionType input parameter to CreateEnvironmentEC2 endpoint. New parameter enables creation of environments with SSM connection.
* `service/comprehend`: Updates service documentation
* `service/ec2`: Updates service API and documentation
  * Introduces support for IPv6-in-IPv4 IPsec tunnels. A user can now send traffic from their on-premise IPv6 network to AWS VPCs that have IPv6 support enabled.
* `service/fsx`: Updates service API and documentation
* `service/iot`: Updates service API, documentation, and paginators
  * Audit finding suppressions: Device Defender enables customers to turn off non-compliant findings for specific resources on a per check basis.
* `service/lambda`: Updates service API and examples
  * Support for creating Lambda Functions using 'java8.al2' and 'provided.al2'
* `service/transfer`: Updates service API, documentation, and paginators
  * Adds security policies to control cryptographic algorithms advertised by your server, additional characters in usernames and length increase, and FIPS compliant endpoints in the US and Canada regions.
* `service/workspaces`: Updates service API and documentation
  * Adds optional EnableWorkDocs property to WorkspaceCreationProperties in the ModifyWorkspaceCreationProperties API

### SDK Enhancements
* `codegen`: Add XXX_Values functions for getting slice of API enums by type.
  * Fixes [#3441](#3441) by adding a new XXX_Values function for each API enum type that returns a slice of enum values, e.g `DomainStatus_Values`.
* `aws/request`: Update default retry to retry "use of closed network connection" errors ([#3476](#3476))
  * Fixes [#3406](#3406)

### SDK Bugs
* `private/protocol/json/jsonutil`: Fixes a bug that truncated millisecond precision time in API response to seconds. ([#3474](#3474))
  * Fixes [#3464](#3464)
  * Fixes [#3410](#3410)
* `codegen`: Export event stream constructor for easier mocking ([#3473](#3473))
  * Fixes [#3412](#3412) by exporting the operation's EventStream type's constructor function so it can be used to fully initialize fully when mocking out behavior for API operations with event streams.
* `service/ec2`: Fix max retries with client customizations ([#3465](#3465))
  * Fixes [#3374](#3374) by correcting the EC2 API client's customization for ModifyNetworkInterfaceAttribute and AssignPrivateIpAddresses operations to use the aws.Config.MaxRetries value if set. Previously the API client's customizations would ignore MaxRetries specified in the SDK's aws.Config.MaxRetries field.
aws-sdk-go-automation added a commit that referenced this issue Aug 12, 2020
Release v1.34.3 (2020-08-12)
===

### Service Client Updates
* `service/cloud9`: Updates service API and documentation
  * Add ConnectionType input parameter to CreateEnvironmentEC2 endpoint. New parameter enables creation of environments with SSM connection.
* `service/comprehend`: Updates service documentation
* `service/ec2`: Updates service API and documentation
  * Introduces support for IPv6-in-IPv4 IPsec tunnels. A user can now send traffic from their on-premise IPv6 network to AWS VPCs that have IPv6 support enabled.
* `service/fsx`: Updates service API and documentation
* `service/iot`: Updates service API, documentation, and paginators
  * Audit finding suppressions: Device Defender enables customers to turn off non-compliant findings for specific resources on a per check basis.
* `service/lambda`: Updates service API and examples
  * Support for creating Lambda Functions using 'java8.al2' and 'provided.al2'
* `service/transfer`: Updates service API, documentation, and paginators
  * Adds security policies to control cryptographic algorithms advertised by your server, additional characters in usernames and length increase, and FIPS compliant endpoints in the US and Canada regions.
* `service/workspaces`: Updates service API and documentation
  * Adds optional EnableWorkDocs property to WorkspaceCreationProperties in the ModifyWorkspaceCreationProperties API

### SDK Enhancements
* `codegen`: Add XXX_Values functions for getting slice of API enums by type.
  * Fixes [#3441](#3441) by adding a new XXX_Values function for each API enum type that returns a slice of enum values, e.g `DomainStatus_Values`.
* `aws/request`: Update default retry to retry "use of closed network connection" errors ([#3476](#3476))
  * Fixes [#3406](#3406)

### SDK Bugs
* `private/protocol/json/jsonutil`: Fixes a bug that truncated millisecond precision time in API response to seconds. ([#3474](#3474))
  * Fixes [#3464](#3464)
  * Fixes [#3410](#3410)
* `codegen`: Export event stream constructor for easier mocking ([#3473](#3473))
  * Fixes [#3412](#3412) by exporting the operation's EventStream type's constructor function so it can be used to fully initialize fully when mocking out behavior for API operations with event streams.
* `service/ec2`: Fix max retries with client customizations ([#3465](#3465))
  * Fixes [#3374](#3374) by correcting the EC2 API client's customization for ModifyNetworkInterfaceAttribute and AssignPrivateIpAddresses operations to use the aws.Config.MaxRetries value if set. Previously the API client's customizations would ignore MaxRetries specified in the SDK's aws.Config.MaxRetries field.
@diehlaws diehlaws removed their assignment Aug 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug.
Projects
None yet
3 participants