123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- package protocol_test
- import (
- "fmt"
- "net/http"
- "net/url"
- "testing"
- "github.com/stretchr/testify/assert"
- "github.com/aws/aws-sdk-go/aws/client/metadata"
- "github.com/aws/aws-sdk-go/aws/request"
- "github.com/aws/aws-sdk-go/awstesting"
- "github.com/aws/aws-sdk-go/private/protocol"
- "github.com/aws/aws-sdk-go/private/protocol/ec2query"
- "github.com/aws/aws-sdk-go/private/protocol/jsonrpc"
- "github.com/aws/aws-sdk-go/private/protocol/query"
- "github.com/aws/aws-sdk-go/private/protocol/rest"
- "github.com/aws/aws-sdk-go/private/protocol/restjson"
- "github.com/aws/aws-sdk-go/private/protocol/restxml"
- )
- func xmlData(set bool, b []byte, size, delta int) {
- if !set {
- copy(b, []byte("<B><A>"))
- }
- if size == 0 {
- copy(b[delta-len("</B></A>"):], []byte("</B></A>"))
- }
- }
- func jsonData(set bool, b []byte, size, delta int) {
- if !set {
- copy(b, []byte("{\"A\": \""))
- }
- if size == 0 {
- copy(b[delta-len("\"}"):], []byte("\"}"))
- }
- }
- func buildNewRequest(data interface{}) *request.Request {
- v := url.Values{}
- v.Set("test", "TEST")
- v.Add("test1", "TEST1")
- req := &request.Request{
- HTTPRequest: &http.Request{
- Header: make(http.Header),
- Body: &awstesting.ReadCloser{Size: 2048},
- URL: &url.URL{
- RawQuery: v.Encode(),
- },
- },
- Params: &struct {
- LocationName string `locationName:"test"`
- }{
- "Test",
- },
- ClientInfo: metadata.ClientInfo{
- ServiceName: "test",
- TargetPrefix: "test",
- JSONVersion: "test",
- APIVersion: "test",
- Endpoint: "test",
- SigningName: "test",
- SigningRegion: "test",
- },
- Operation: &request.Operation{
- Name: "test",
- },
- }
- req.HTTPResponse = &http.Response{
- Body: &awstesting.ReadCloser{Size: 2048},
- Header: http.Header{
- "X-Amzn-Requestid": []string{"1"},
- },
- StatusCode: http.StatusOK,
- }
- if data == nil {
- data = &struct {
- _ struct{} `type:"structure"`
- LocationName *string `locationName:"testName"`
- Location *string `location:"statusCode"`
- A *string `type:"string"`
- }{}
- }
- req.Data = data
- return req
- }
- type expected struct {
- dataType int
- closed bool
- size int
- errExists bool
- }
- const (
- jsonType = iota
- xmlType
- )
- func checkForLeak(data interface{}, build, fn func(*request.Request), t *testing.T, result expected) {
- req := buildNewRequest(data)
- reader := req.HTTPResponse.Body.(*awstesting.ReadCloser)
- switch result.dataType {
- case jsonType:
- reader.FillData = jsonData
- case xmlType:
- reader.FillData = xmlData
- }
- build(req)
- fn(req)
- if result.errExists {
- assert.NotNil(t, req.Error)
- } else {
- fmt.Println(req.Error)
- assert.Nil(t, req.Error)
- }
- assert.Equal(t, reader.Closed, result.closed)
- assert.Equal(t, reader.Size, result.size)
- }
- func TestJSONRpc(t *testing.T) {
- checkForLeak(nil, jsonrpc.Build, jsonrpc.Unmarshal, t, expected{jsonType, true, 0, false})
- checkForLeak(nil, jsonrpc.Build, jsonrpc.UnmarshalMeta, t, expected{jsonType, false, 2048, false})
- checkForLeak(nil, jsonrpc.Build, jsonrpc.UnmarshalError, t, expected{jsonType, true, 0, true})
- }
- func TestQuery(t *testing.T) {
- checkForLeak(nil, query.Build, query.Unmarshal, t, expected{jsonType, true, 0, false})
- checkForLeak(nil, query.Build, query.UnmarshalMeta, t, expected{jsonType, false, 2048, false})
- checkForLeak(nil, query.Build, query.UnmarshalError, t, expected{jsonType, true, 0, true})
- }
- func TestRest(t *testing.T) {
- // case 1: Payload io.ReadSeeker
- checkForLeak(nil, rest.Build, rest.Unmarshal, t, expected{jsonType, false, 2048, false})
- checkForLeak(nil, query.Build, query.UnmarshalMeta, t, expected{jsonType, false, 2048, false})
- // case 2: Payload *string
- // should close the body
- dataStr := struct {
- _ struct{} `type:"structure" payload:"Payload"`
- LocationName *string `locationName:"testName"`
- Location *string `location:"statusCode"`
- A *string `type:"string"`
- Payload *string `locationName:"payload" type:"blob" required:"true"`
- }{}
- checkForLeak(&dataStr, rest.Build, rest.Unmarshal, t, expected{jsonType, true, 0, false})
- checkForLeak(&dataStr, query.Build, query.UnmarshalMeta, t, expected{jsonType, false, 2048, false})
- // case 3: Payload []byte
- // should close the body
- dataBytes := struct {
- _ struct{} `type:"structure" payload:"Payload"`
- LocationName *string `locationName:"testName"`
- Location *string `location:"statusCode"`
- A *string `type:"string"`
- Payload []byte `locationName:"payload" type:"blob" required:"true"`
- }{}
- checkForLeak(&dataBytes, rest.Build, rest.Unmarshal, t, expected{jsonType, true, 0, false})
- checkForLeak(&dataBytes, query.Build, query.UnmarshalMeta, t, expected{jsonType, false, 2048, false})
- // case 4: Payload unsupported type
- // should close the body
- dataUnsupported := struct {
- _ struct{} `type:"structure" payload:"Payload"`
- LocationName *string `locationName:"testName"`
- Location *string `location:"statusCode"`
- A *string `type:"string"`
- Payload string `locationName:"payload" type:"blob" required:"true"`
- }{}
- checkForLeak(&dataUnsupported, rest.Build, rest.Unmarshal, t, expected{jsonType, true, 0, true})
- checkForLeak(&dataUnsupported, query.Build, query.UnmarshalMeta, t, expected{jsonType, false, 2048, false})
- }
- func TestRestJSON(t *testing.T) {
- checkForLeak(nil, restjson.Build, restjson.Unmarshal, t, expected{jsonType, true, 0, false})
- checkForLeak(nil, restjson.Build, restjson.UnmarshalMeta, t, expected{jsonType, false, 2048, false})
- checkForLeak(nil, restjson.Build, restjson.UnmarshalError, t, expected{jsonType, true, 0, true})
- }
- func TestRestXML(t *testing.T) {
- checkForLeak(nil, restxml.Build, restxml.Unmarshal, t, expected{xmlType, true, 0, false})
- checkForLeak(nil, restxml.Build, restxml.UnmarshalMeta, t, expected{xmlType, false, 2048, false})
- checkForLeak(nil, restxml.Build, restxml.UnmarshalError, t, expected{xmlType, true, 0, true})
- }
- func TestXML(t *testing.T) {
- checkForLeak(nil, ec2query.Build, ec2query.Unmarshal, t, expected{jsonType, true, 0, false})
- checkForLeak(nil, ec2query.Build, ec2query.UnmarshalMeta, t, expected{jsonType, false, 2048, false})
- checkForLeak(nil, ec2query.Build, ec2query.UnmarshalError, t, expected{jsonType, true, 0, true})
- }
- func TestProtocol(t *testing.T) {
- checkForLeak(nil, restxml.Build, protocol.UnmarshalDiscardBody, t, expected{xmlType, true, 0, false})
- }
|