github.com/aavshr/aws-sdk-go@v1.41.3/service/lexruntimev2/eventstream_test.go (about)

     1  // Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
     2  
     3  //go:build go1.16
     4  // +build go1.16
     5  
     6  package lexruntimev2
     7  
     8  import (
     9  	"bytes"
    10  	"context"
    11  	"io/ioutil"
    12  	"net/http"
    13  	"reflect"
    14  	"strings"
    15  	"sync"
    16  	"testing"
    17  	"time"
    18  
    19  	"github.com/aavshr/aws-sdk-go/aws"
    20  	"github.com/aavshr/aws-sdk-go/aws/awserr"
    21  	"github.com/aavshr/aws-sdk-go/aws/corehandlers"
    22  	"github.com/aavshr/aws-sdk-go/aws/request"
    23  	"github.com/aavshr/aws-sdk-go/awstesting/unit"
    24  	"github.com/aavshr/aws-sdk-go/private/protocol"
    25  	"github.com/aavshr/aws-sdk-go/private/protocol/eventstream"
    26  	"github.com/aavshr/aws-sdk-go/private/protocol/eventstream/eventstreamapi"
    27  	"github.com/aavshr/aws-sdk-go/private/protocol/eventstream/eventstreamtest"
    28  	"github.com/aavshr/aws-sdk-go/private/protocol/restjson"
    29  )
    30  
    31  var _ time.Time
    32  var _ awserr.Error
    33  var _ context.Context
    34  var _ sync.WaitGroup
    35  var _ strings.Reader
    36  
    37  func TestStartConversation_Read(t *testing.T) {
    38  	expectEvents, eventMsgs := mockStartConversationReadEvents()
    39  	sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
    40  		eventstreamtest.ServeEventStream{
    41  			T:      t,
    42  			Events: eventMsgs,
    43  		},
    44  		true,
    45  	)
    46  	if err != nil {
    47  		t.Fatalf("expect no error, %v", err)
    48  	}
    49  	defer cleanupFn()
    50  
    51  	svc := New(sess)
    52  	resp, err := svc.StartConversation(nil)
    53  	if err != nil {
    54  		t.Fatalf("expect no error got, %v", err)
    55  	}
    56  	defer resp.GetStream().Close()
    57  
    58  	var i int
    59  	for event := range resp.GetStream().Events() {
    60  		if event == nil {
    61  			t.Errorf("%d, expect event, got nil", i)
    62  		}
    63  		if e, a := expectEvents[i], event; !reflect.DeepEqual(e, a) {
    64  			t.Errorf("%d, expect %T %v, got %T %v", i, e, e, a, a)
    65  		}
    66  		i++
    67  	}
    68  
    69  	if err := resp.GetStream().Err(); err != nil {
    70  		t.Errorf("expect no error, %v", err)
    71  	}
    72  }
    73  
    74  func TestStartConversation_ReadClose(t *testing.T) {
    75  	_, eventMsgs := mockStartConversationReadEvents()
    76  	sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
    77  		eventstreamtest.ServeEventStream{
    78  			T:      t,
    79  			Events: eventMsgs,
    80  		},
    81  		true,
    82  	)
    83  	if err != nil {
    84  		t.Fatalf("expect no error, %v", err)
    85  	}
    86  	defer cleanupFn()
    87  
    88  	svc := New(sess)
    89  	resp, err := svc.StartConversation(nil)
    90  	if err != nil {
    91  		t.Fatalf("expect no error got, %v", err)
    92  	}
    93  
    94  	// Assert calling Err before close does not close the stream.
    95  	resp.GetStream().Err()
    96  	select {
    97  	case _, ok := <-resp.GetStream().Events():
    98  		if !ok {
    99  			t.Fatalf("expect stream not to be closed, but was")
   100  		}
   101  	default:
   102  	}
   103  
   104  	resp.GetStream().Close()
   105  	<-resp.GetStream().Events()
   106  
   107  	if err := resp.GetStream().Err(); err != nil {
   108  		t.Errorf("expect no error, %v", err)
   109  	}
   110  }
   111  
   112  func TestStartConversation_ReadUnknownEvent(t *testing.T) {
   113  	expectEvents, eventMsgs := mockStartConversationReadEvents()
   114  	var eventOffset int
   115  
   116  	unknownEvent := eventstream.Message{
   117  		Headers: eventstream.Headers{
   118  			eventstreamtest.EventMessageTypeHeader,
   119  			{
   120  				Name:  eventstreamapi.EventTypeHeader,
   121  				Value: eventstream.StringValue("UnknownEventName"),
   122  			},
   123  		},
   124  		Payload: []byte("some unknown event"),
   125  	}
   126  
   127  	eventMsgs = append(eventMsgs[:eventOffset],
   128  		append([]eventstream.Message{unknownEvent}, eventMsgs[eventOffset:]...)...)
   129  
   130  	expectEvents = append(expectEvents[:eventOffset],
   131  		append([]StartConversationResponseEventStreamEvent{
   132  			&StartConversationResponseEventStreamUnknownEvent{
   133  				Type:    "UnknownEventName",
   134  				Message: unknownEvent,
   135  			},
   136  		},
   137  			expectEvents[eventOffset:]...)...)
   138  
   139  	sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
   140  		eventstreamtest.ServeEventStream{
   141  			T:      t,
   142  			Events: eventMsgs,
   143  		},
   144  		true,
   145  	)
   146  	if err != nil {
   147  		t.Fatalf("expect no error, %v", err)
   148  	}
   149  	defer cleanupFn()
   150  
   151  	svc := New(sess)
   152  	resp, err := svc.StartConversation(nil)
   153  	if err != nil {
   154  		t.Fatalf("expect no error got, %v", err)
   155  	}
   156  	defer resp.GetStream().Close()
   157  
   158  	var i int
   159  	for event := range resp.GetStream().Events() {
   160  		if event == nil {
   161  			t.Errorf("%d, expect event, got nil", i)
   162  		}
   163  		if e, a := expectEvents[i], event; !reflect.DeepEqual(e, a) {
   164  			t.Errorf("%d, expect %T %v, got %T %v", i, e, e, a, a)
   165  		}
   166  		i++
   167  	}
   168  
   169  	if err := resp.GetStream().Err(); err != nil {
   170  		t.Errorf("expect no error, %v", err)
   171  	}
   172  }
   173  
   174  func BenchmarkStartConversation_Read(b *testing.B) {
   175  	_, eventMsgs := mockStartConversationReadEvents()
   176  	var buf bytes.Buffer
   177  	encoder := eventstream.NewEncoder(&buf)
   178  	for _, msg := range eventMsgs {
   179  		if err := encoder.Encode(msg); err != nil {
   180  			b.Fatalf("failed to encode message, %v", err)
   181  		}
   182  	}
   183  	stream := &loopReader{source: bytes.NewReader(buf.Bytes())}
   184  
   185  	sess := unit.Session
   186  	svc := New(sess, &aws.Config{
   187  		Endpoint:               aws.String("https://example.com"),
   188  		DisableParamValidation: aws.Bool(true),
   189  	})
   190  	svc.Handlers.Send.Swap(corehandlers.SendHandler.Name,
   191  		request.NamedHandler{Name: "mockSend",
   192  			Fn: func(r *request.Request) {
   193  				r.HTTPResponse = &http.Response{
   194  					Status:     "200 OK",
   195  					StatusCode: 200,
   196  					Header:     http.Header{},
   197  					Body:       ioutil.NopCloser(stream),
   198  				}
   199  			},
   200  		},
   201  	)
   202  
   203  	resp, err := svc.StartConversation(nil)
   204  	if err != nil {
   205  		b.Fatalf("failed to create request, %v", err)
   206  	}
   207  	defer resp.GetStream().Close()
   208  	b.ResetTimer()
   209  
   210  	for i := 0; i < b.N; i++ {
   211  		if err = resp.GetStream().Err(); err != nil {
   212  			b.Fatalf("expect no error, got %v", err)
   213  		}
   214  		event := <-resp.GetStream().Events()
   215  		if event == nil {
   216  			b.Fatalf("expect event, got nil, %v, %d", resp.GetStream().Err(), i)
   217  		}
   218  	}
   219  }
   220  
   221  func mockStartConversationReadEvents() (
   222  	[]StartConversationResponseEventStreamEvent,
   223  	[]eventstream.Message,
   224  ) {
   225  	expectEvents := []StartConversationResponseEventStreamEvent{
   226  		&AudioResponseEvent{
   227  			AudioChunk:  []byte("blob value goes here"),
   228  			ContentType: aws.String("string value goes here"),
   229  			EventId:     aws.String("string value goes here"),
   230  		},
   231  		&HeartbeatEvent{
   232  			EventId: aws.String("string value goes here"),
   233  		},
   234  		&IntentResultEvent{
   235  			EventId:   aws.String("string value goes here"),
   236  			InputMode: aws.String("string value goes here"),
   237  			Interpretations: []*Interpretation{
   238  				{
   239  					Intent: &Intent{
   240  						ConfirmationState: aws.String("string value goes here"),
   241  						Name:              aws.String("string value goes here"),
   242  						Slots: map[string]*Slot{
   243  							"a": {
   244  								Shape: aws.String("string value goes here"),
   245  								Value: &Value{
   246  									InterpretedValue: aws.String("string value goes here"),
   247  									OriginalValue:    aws.String("string value goes here"),
   248  									ResolvedValues: []*string{
   249  										aws.String("string value goes here"),
   250  										aws.String("string value goes here"),
   251  										aws.String("string value goes here"),
   252  									},
   253  								},
   254  								Values: []*Slot{},
   255  							},
   256  							"b": {
   257  								Shape: aws.String("string value goes here"),
   258  								Value: &Value{
   259  									InterpretedValue: aws.String("string value goes here"),
   260  									OriginalValue:    aws.String("string value goes here"),
   261  									ResolvedValues: []*string{
   262  										aws.String("string value goes here"),
   263  										aws.String("string value goes here"),
   264  										aws.String("string value goes here"),
   265  									},
   266  								},
   267  								Values: []*Slot{},
   268  							},
   269  							"c": {
   270  								Shape: aws.String("string value goes here"),
   271  								Value: &Value{
   272  									InterpretedValue: aws.String("string value goes here"),
   273  									OriginalValue:    aws.String("string value goes here"),
   274  									ResolvedValues: []*string{
   275  										aws.String("string value goes here"),
   276  										aws.String("string value goes here"),
   277  										aws.String("string value goes here"),
   278  									},
   279  								},
   280  								Values: []*Slot{},
   281  							},
   282  						},
   283  						State: aws.String("string value goes here"),
   284  					},
   285  					NluConfidence: &ConfidenceScore{
   286  						Score: aws.Float64(123.45),
   287  					},
   288  					SentimentResponse: &SentimentResponse{
   289  						Sentiment: aws.String("string value goes here"),
   290  						SentimentScore: &SentimentScore{
   291  							Mixed:    aws.Float64(123.45),
   292  							Negative: aws.Float64(123.45),
   293  							Neutral:  aws.Float64(123.45),
   294  							Positive: aws.Float64(123.45),
   295  						},
   296  					},
   297  				},
   298  				{
   299  					Intent: &Intent{
   300  						ConfirmationState: aws.String("string value goes here"),
   301  						Name:              aws.String("string value goes here"),
   302  						Slots: map[string]*Slot{
   303  							"a": {
   304  								Shape: aws.String("string value goes here"),
   305  								Value: &Value{
   306  									InterpretedValue: aws.String("string value goes here"),
   307  									OriginalValue:    aws.String("string value goes here"),
   308  									ResolvedValues: []*string{
   309  										aws.String("string value goes here"),
   310  										aws.String("string value goes here"),
   311  										aws.String("string value goes here"),
   312  									},
   313  								},
   314  								Values: []*Slot{},
   315  							},
   316  							"b": {
   317  								Shape: aws.String("string value goes here"),
   318  								Value: &Value{
   319  									InterpretedValue: aws.String("string value goes here"),
   320  									OriginalValue:    aws.String("string value goes here"),
   321  									ResolvedValues: []*string{
   322  										aws.String("string value goes here"),
   323  										aws.String("string value goes here"),
   324  										aws.String("string value goes here"),
   325  									},
   326  								},
   327  								Values: []*Slot{},
   328  							},
   329  							"c": {
   330  								Shape: aws.String("string value goes here"),
   331  								Value: &Value{
   332  									InterpretedValue: aws.String("string value goes here"),
   333  									OriginalValue:    aws.String("string value goes here"),
   334  									ResolvedValues: []*string{
   335  										aws.String("string value goes here"),
   336  										aws.String("string value goes here"),
   337  										aws.String("string value goes here"),
   338  									},
   339  								},
   340  								Values: []*Slot{},
   341  							},
   342  						},
   343  						State: aws.String("string value goes here"),
   344  					},
   345  					NluConfidence: &ConfidenceScore{
   346  						Score: aws.Float64(123.45),
   347  					},
   348  					SentimentResponse: &SentimentResponse{
   349  						Sentiment: aws.String("string value goes here"),
   350  						SentimentScore: &SentimentScore{
   351  							Mixed:    aws.Float64(123.45),
   352  							Negative: aws.Float64(123.45),
   353  							Neutral:  aws.Float64(123.45),
   354  							Positive: aws.Float64(123.45),
   355  						},
   356  					},
   357  				},
   358  				{
   359  					Intent: &Intent{
   360  						ConfirmationState: aws.String("string value goes here"),
   361  						Name:              aws.String("string value goes here"),
   362  						Slots: map[string]*Slot{
   363  							"a": {
   364  								Shape: aws.String("string value goes here"),
   365  								Value: &Value{
   366  									InterpretedValue: aws.String("string value goes here"),
   367  									OriginalValue:    aws.String("string value goes here"),
   368  									ResolvedValues: []*string{
   369  										aws.String("string value goes here"),
   370  										aws.String("string value goes here"),
   371  										aws.String("string value goes here"),
   372  									},
   373  								},
   374  								Values: []*Slot{},
   375  							},
   376  							"b": {
   377  								Shape: aws.String("string value goes here"),
   378  								Value: &Value{
   379  									InterpretedValue: aws.String("string value goes here"),
   380  									OriginalValue:    aws.String("string value goes here"),
   381  									ResolvedValues: []*string{
   382  										aws.String("string value goes here"),
   383  										aws.String("string value goes here"),
   384  										aws.String("string value goes here"),
   385  									},
   386  								},
   387  								Values: []*Slot{},
   388  							},
   389  							"c": {
   390  								Shape: aws.String("string value goes here"),
   391  								Value: &Value{
   392  									InterpretedValue: aws.String("string value goes here"),
   393  									OriginalValue:    aws.String("string value goes here"),
   394  									ResolvedValues: []*string{
   395  										aws.String("string value goes here"),
   396  										aws.String("string value goes here"),
   397  										aws.String("string value goes here"),
   398  									},
   399  								},
   400  								Values: []*Slot{},
   401  							},
   402  						},
   403  						State: aws.String("string value goes here"),
   404  					},
   405  					NluConfidence: &ConfidenceScore{
   406  						Score: aws.Float64(123.45),
   407  					},
   408  					SentimentResponse: &SentimentResponse{
   409  						Sentiment: aws.String("string value goes here"),
   410  						SentimentScore: &SentimentScore{
   411  							Mixed:    aws.Float64(123.45),
   412  							Negative: aws.Float64(123.45),
   413  							Neutral:  aws.Float64(123.45),
   414  							Positive: aws.Float64(123.45),
   415  						},
   416  					},
   417  				},
   418  			},
   419  			RequestAttributes: map[string]*string{
   420  				"a": aws.String("string value goes here"),
   421  				"b": aws.String("string value goes here"),
   422  				"c": aws.String("string value goes here"),
   423  			},
   424  			SessionId: aws.String("string value goes here"),
   425  			SessionState: &SessionState{
   426  				ActiveContexts: []*ActiveContext{
   427  					{
   428  						ContextAttributes: map[string]*string{
   429  							"a": aws.String("string value goes here"),
   430  							"b": aws.String("string value goes here"),
   431  							"c": aws.String("string value goes here"),
   432  						},
   433  						Name: aws.String("string value goes here"),
   434  						TimeToLive: &ActiveContextTimeToLive{
   435  							TimeToLiveInSeconds: aws.Int64(123),
   436  							TurnsToLive:         aws.Int64(123),
   437  						},
   438  					},
   439  					{
   440  						ContextAttributes: map[string]*string{
   441  							"a": aws.String("string value goes here"),
   442  							"b": aws.String("string value goes here"),
   443  							"c": aws.String("string value goes here"),
   444  						},
   445  						Name: aws.String("string value goes here"),
   446  						TimeToLive: &ActiveContextTimeToLive{
   447  							TimeToLiveInSeconds: aws.Int64(123),
   448  							TurnsToLive:         aws.Int64(123),
   449  						},
   450  					},
   451  					{
   452  						ContextAttributes: map[string]*string{
   453  							"a": aws.String("string value goes here"),
   454  							"b": aws.String("string value goes here"),
   455  							"c": aws.String("string value goes here"),
   456  						},
   457  						Name: aws.String("string value goes here"),
   458  						TimeToLive: &ActiveContextTimeToLive{
   459  							TimeToLiveInSeconds: aws.Int64(123),
   460  							TurnsToLive:         aws.Int64(123),
   461  						},
   462  					},
   463  				},
   464  				DialogAction: &DialogAction{
   465  					SlotToElicit: aws.String("string value goes here"),
   466  					Type:         aws.String("string value goes here"),
   467  				},
   468  				Intent: &Intent{
   469  					ConfirmationState: aws.String("string value goes here"),
   470  					Name:              aws.String("string value goes here"),
   471  					Slots: map[string]*Slot{
   472  						"a": {
   473  							Shape: aws.String("string value goes here"),
   474  							Value: &Value{
   475  								InterpretedValue: aws.String("string value goes here"),
   476  								OriginalValue:    aws.String("string value goes here"),
   477  								ResolvedValues: []*string{
   478  									aws.String("string value goes here"),
   479  									aws.String("string value goes here"),
   480  									aws.String("string value goes here"),
   481  								},
   482  							},
   483  							Values: []*Slot{},
   484  						},
   485  						"b": {
   486  							Shape: aws.String("string value goes here"),
   487  							Value: &Value{
   488  								InterpretedValue: aws.String("string value goes here"),
   489  								OriginalValue:    aws.String("string value goes here"),
   490  								ResolvedValues: []*string{
   491  									aws.String("string value goes here"),
   492  									aws.String("string value goes here"),
   493  									aws.String("string value goes here"),
   494  								},
   495  							},
   496  							Values: []*Slot{},
   497  						},
   498  						"c": {
   499  							Shape: aws.String("string value goes here"),
   500  							Value: &Value{
   501  								InterpretedValue: aws.String("string value goes here"),
   502  								OriginalValue:    aws.String("string value goes here"),
   503  								ResolvedValues: []*string{
   504  									aws.String("string value goes here"),
   505  									aws.String("string value goes here"),
   506  									aws.String("string value goes here"),
   507  								},
   508  							},
   509  							Values: []*Slot{},
   510  						},
   511  					},
   512  					State: aws.String("string value goes here"),
   513  				},
   514  				OriginatingRequestId: aws.String("string value goes here"),
   515  				SessionAttributes: map[string]*string{
   516  					"a": aws.String("string value goes here"),
   517  					"b": aws.String("string value goes here"),
   518  					"c": aws.String("string value goes here"),
   519  				},
   520  			},
   521  		},
   522  		&PlaybackInterruptionEvent{
   523  			CausedByEventId: aws.String("string value goes here"),
   524  			EventId:         aws.String("string value goes here"),
   525  			EventReason:     aws.String("string value goes here"),
   526  		},
   527  		&TextResponseEvent{
   528  			EventId: aws.String("string value goes here"),
   529  			Messages: []*Message{
   530  				{
   531  					Content:     aws.String("string value goes here"),
   532  					ContentType: aws.String("string value goes here"),
   533  					ImageResponseCard: &ImageResponseCard{
   534  						Buttons: []*Button{
   535  							{
   536  								Text:  aws.String("string value goes here"),
   537  								Value: aws.String("string value goes here"),
   538  							},
   539  							{
   540  								Text:  aws.String("string value goes here"),
   541  								Value: aws.String("string value goes here"),
   542  							},
   543  							{
   544  								Text:  aws.String("string value goes here"),
   545  								Value: aws.String("string value goes here"),
   546  							},
   547  						},
   548  						ImageUrl: aws.String("string value goes here"),
   549  						Subtitle: aws.String("string value goes here"),
   550  						Title:    aws.String("string value goes here"),
   551  					},
   552  				},
   553  				{
   554  					Content:     aws.String("string value goes here"),
   555  					ContentType: aws.String("string value goes here"),
   556  					ImageResponseCard: &ImageResponseCard{
   557  						Buttons: []*Button{
   558  							{
   559  								Text:  aws.String("string value goes here"),
   560  								Value: aws.String("string value goes here"),
   561  							},
   562  							{
   563  								Text:  aws.String("string value goes here"),
   564  								Value: aws.String("string value goes here"),
   565  							},
   566  							{
   567  								Text:  aws.String("string value goes here"),
   568  								Value: aws.String("string value goes here"),
   569  							},
   570  						},
   571  						ImageUrl: aws.String("string value goes here"),
   572  						Subtitle: aws.String("string value goes here"),
   573  						Title:    aws.String("string value goes here"),
   574  					},
   575  				},
   576  				{
   577  					Content:     aws.String("string value goes here"),
   578  					ContentType: aws.String("string value goes here"),
   579  					ImageResponseCard: &ImageResponseCard{
   580  						Buttons: []*Button{
   581  							{
   582  								Text:  aws.String("string value goes here"),
   583  								Value: aws.String("string value goes here"),
   584  							},
   585  							{
   586  								Text:  aws.String("string value goes here"),
   587  								Value: aws.String("string value goes here"),
   588  							},
   589  							{
   590  								Text:  aws.String("string value goes here"),
   591  								Value: aws.String("string value goes here"),
   592  							},
   593  						},
   594  						ImageUrl: aws.String("string value goes here"),
   595  						Subtitle: aws.String("string value goes here"),
   596  						Title:    aws.String("string value goes here"),
   597  					},
   598  				},
   599  			},
   600  		},
   601  		&TranscriptEvent{
   602  			EventId:    aws.String("string value goes here"),
   603  			Transcript: aws.String("string value goes here"),
   604  		},
   605  	}
   606  
   607  	var marshalers request.HandlerList
   608  	marshalers.PushBackNamed(restjson.BuildHandler)
   609  	payloadMarshaler := protocol.HandlerPayloadMarshal{
   610  		Marshalers: marshalers,
   611  	}
   612  	_ = payloadMarshaler
   613  
   614  	eventMsgs := []eventstream.Message{
   615  		{
   616  			Headers: eventstream.Headers{
   617  				eventstreamtest.EventMessageTypeHeader,
   618  				{
   619  					Name:  eventstreamapi.EventTypeHeader,
   620  					Value: eventstream.StringValue("AudioResponseEvent"),
   621  				},
   622  			},
   623  			Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[0]),
   624  		},
   625  		{
   626  			Headers: eventstream.Headers{
   627  				eventstreamtest.EventMessageTypeHeader,
   628  				{
   629  					Name:  eventstreamapi.EventTypeHeader,
   630  					Value: eventstream.StringValue("HeartbeatEvent"),
   631  				},
   632  			},
   633  			Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[1]),
   634  		},
   635  		{
   636  			Headers: eventstream.Headers{
   637  				eventstreamtest.EventMessageTypeHeader,
   638  				{
   639  					Name:  eventstreamapi.EventTypeHeader,
   640  					Value: eventstream.StringValue("IntentResultEvent"),
   641  				},
   642  			},
   643  			Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[2]),
   644  		},
   645  		{
   646  			Headers: eventstream.Headers{
   647  				eventstreamtest.EventMessageTypeHeader,
   648  				{
   649  					Name:  eventstreamapi.EventTypeHeader,
   650  					Value: eventstream.StringValue("PlaybackInterruptionEvent"),
   651  				},
   652  			},
   653  			Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[3]),
   654  		},
   655  		{
   656  			Headers: eventstream.Headers{
   657  				eventstreamtest.EventMessageTypeHeader,
   658  				{
   659  					Name:  eventstreamapi.EventTypeHeader,
   660  					Value: eventstream.StringValue("TextResponseEvent"),
   661  				},
   662  			},
   663  			Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[4]),
   664  		},
   665  		{
   666  			Headers: eventstream.Headers{
   667  				eventstreamtest.EventMessageTypeHeader,
   668  				{
   669  					Name:  eventstreamapi.EventTypeHeader,
   670  					Value: eventstream.StringValue("TranscriptEvent"),
   671  				},
   672  			},
   673  			Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[5]),
   674  		},
   675  	}
   676  
   677  	return expectEvents, eventMsgs
   678  }
   679  func TestStartConversation_ReadException(t *testing.T) {
   680  	expectEvents := []StartConversationResponseEventStreamEvent{
   681  		&AccessDeniedException{
   682  			RespMetadata: protocol.ResponseMetadata{
   683  				StatusCode: 200,
   684  			},
   685  			Message_: aws.String("string value goes here"),
   686  		},
   687  	}
   688  
   689  	var marshalers request.HandlerList
   690  	marshalers.PushBackNamed(restjson.BuildHandler)
   691  	payloadMarshaler := protocol.HandlerPayloadMarshal{
   692  		Marshalers: marshalers,
   693  	}
   694  
   695  	eventMsgs := []eventstream.Message{
   696  		{
   697  			Headers: eventstream.Headers{
   698  				eventstreamtest.EventExceptionTypeHeader,
   699  				{
   700  					Name:  eventstreamapi.ExceptionTypeHeader,
   701  					Value: eventstream.StringValue("AccessDeniedException"),
   702  				},
   703  			},
   704  			Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, expectEvents[0]),
   705  		},
   706  	}
   707  
   708  	sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
   709  		eventstreamtest.ServeEventStream{
   710  			T:      t,
   711  			Events: eventMsgs,
   712  		},
   713  		true,
   714  	)
   715  	if err != nil {
   716  		t.Fatalf("expect no error, %v", err)
   717  	}
   718  	defer cleanupFn()
   719  
   720  	svc := New(sess)
   721  	resp, err := svc.StartConversation(nil)
   722  	if err != nil {
   723  		t.Fatalf("expect no error got, %v", err)
   724  	}
   725  
   726  	defer resp.GetStream().Close()
   727  
   728  	<-resp.GetStream().Events()
   729  
   730  	err = resp.GetStream().Err()
   731  	if err == nil {
   732  		t.Fatalf("expect err, got none")
   733  	}
   734  
   735  	expectErr := &AccessDeniedException{
   736  		RespMetadata: protocol.ResponseMetadata{
   737  			StatusCode: 200,
   738  		},
   739  		Message_: aws.String("string value goes here"),
   740  	}
   741  	aerr, ok := err.(awserr.Error)
   742  	if !ok {
   743  		t.Errorf("expect exception, got %T, %#v", err, err)
   744  	}
   745  	if e, a := expectErr.Code(), aerr.Code(); e != a {
   746  		t.Errorf("expect %v, got %v", e, a)
   747  	}
   748  	if e, a := expectErr.Message(), aerr.Message(); e != a {
   749  		t.Errorf("expect %v, got %v", e, a)
   750  	}
   751  
   752  	if e, a := expectErr, aerr; !reflect.DeepEqual(e, a) {
   753  		t.Errorf("expect error %+#v, got %+#v", e, a)
   754  	}
   755  }
   756  
   757  var _ awserr.Error = (*AccessDeniedException)(nil)
   758  var _ awserr.Error = (*BadGatewayException)(nil)
   759  var _ awserr.Error = (*ConflictException)(nil)
   760  var _ awserr.Error = (*DependencyFailedException)(nil)
   761  var _ awserr.Error = (*InternalServerException)(nil)
   762  var _ awserr.Error = (*ResourceNotFoundException)(nil)
   763  var _ awserr.Error = (*ThrottlingException)(nil)
   764  var _ awserr.Error = (*ValidationException)(nil)
   765  
   766  type loopReader struct {
   767  	source *bytes.Reader
   768  }
   769  
   770  func (c *loopReader) Read(p []byte) (int, error) {
   771  	if c.source.Len() == 0 {
   772  		c.source.Seek(0, 0)
   773  	}
   774  
   775  	return c.source.Read(p)
   776  }
   777  
   778  func TestStartConversation_Write(t *testing.T) {
   779  	clientEvents, expectedClientEvents := mockStartConversationWriteEvents()
   780  
   781  	sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
   782  		&eventstreamtest.ServeEventStream{
   783  			T:             t,
   784  			ClientEvents:  expectedClientEvents,
   785  			BiDirectional: true,
   786  		},
   787  		true)
   788  	defer cleanupFn()
   789  
   790  	svc := New(sess)
   791  	resp, err := svc.StartConversation(nil)
   792  	if err != nil {
   793  		t.Fatalf("expect no error, got %v", err)
   794  	}
   795  
   796  	stream := resp.GetStream()
   797  
   798  	for _, event := range clientEvents {
   799  		err = stream.Send(context.Background(), event)
   800  		if err != nil {
   801  			t.Fatalf("expect no error, got %v", err)
   802  		}
   803  	}
   804  
   805  	if err := stream.Close(); err != nil {
   806  		t.Errorf("expect no error, got %v", err)
   807  	}
   808  }
   809  
   810  func TestStartConversation_WriteClose(t *testing.T) {
   811  	sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
   812  		eventstreamtest.ServeEventStream{T: t, BiDirectional: true},
   813  		true,
   814  	)
   815  	if err != nil {
   816  		t.Fatalf("expect no error, %v", err)
   817  	}
   818  	defer cleanupFn()
   819  
   820  	svc := New(sess)
   821  	resp, err := svc.StartConversation(nil)
   822  	if err != nil {
   823  		t.Fatalf("expect no error got, %v", err)
   824  	}
   825  
   826  	// Assert calling Err before close does not close the stream.
   827  	resp.GetStream().Err()
   828  
   829  	err = resp.GetStream().Send(context.Background(), &AudioInputEvent{})
   830  	if err != nil {
   831  		t.Fatalf("expect no error, got %v", err)
   832  	}
   833  
   834  	resp.GetStream().Close()
   835  
   836  	if err := resp.GetStream().Err(); err != nil {
   837  		t.Errorf("expect no error, %v", err)
   838  	}
   839  }
   840  
   841  func TestStartConversation_WriteError(t *testing.T) {
   842  	sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
   843  		eventstreamtest.ServeEventStream{
   844  			T:               t,
   845  			BiDirectional:   true,
   846  			ForceCloseAfter: time.Millisecond * 500,
   847  		},
   848  		true,
   849  	)
   850  	if err != nil {
   851  		t.Fatalf("expect no error, %v", err)
   852  	}
   853  	defer cleanupFn()
   854  
   855  	svc := New(sess)
   856  	resp, err := svc.StartConversation(nil)
   857  	if err != nil {
   858  		t.Fatalf("expect no error got, %v", err)
   859  	}
   860  
   861  	defer resp.GetStream().Close()
   862  
   863  	for {
   864  		err = resp.GetStream().Send(context.Background(), &AudioInputEvent{})
   865  		if err != nil {
   866  			if strings.Contains("unable to send event", err.Error()) {
   867  				t.Errorf("expected stream closed error, got %v", err)
   868  			}
   869  			break
   870  		}
   871  	}
   872  }
   873  
   874  func TestStartConversation_ReadWrite(t *testing.T) {
   875  	expectedServiceEvents, serviceEvents := mockStartConversationReadEvents()
   876  	clientEvents, expectedClientEvents := mockStartConversationWriteEvents()
   877  
   878  	sess, cleanupFn, err := eventstreamtest.SetupEventStreamSession(t,
   879  		&eventstreamtest.ServeEventStream{
   880  			T:             t,
   881  			ClientEvents:  expectedClientEvents,
   882  			Events:        serviceEvents,
   883  			BiDirectional: true,
   884  		},
   885  		true)
   886  	defer cleanupFn()
   887  
   888  	svc := New(sess)
   889  	resp, err := svc.StartConversation(nil)
   890  	if err != nil {
   891  		t.Fatalf("expect no error, got %v", err)
   892  	}
   893  
   894  	stream := resp.GetStream()
   895  	defer stream.Close()
   896  
   897  	var wg sync.WaitGroup
   898  
   899  	wg.Add(1)
   900  	go func() {
   901  		defer wg.Done()
   902  		var i int
   903  		for event := range resp.GetStream().Events() {
   904  			if event == nil {
   905  				t.Errorf("%d, expect event, got nil", i)
   906  			}
   907  			if e, a := expectedServiceEvents[i], event; !reflect.DeepEqual(e, a) {
   908  				t.Errorf("%d, expect %T %v, got %T %v", i, e, e, a, a)
   909  			}
   910  			i++
   911  		}
   912  	}()
   913  
   914  	for _, event := range clientEvents {
   915  		err = stream.Send(context.Background(), event)
   916  		if err != nil {
   917  			t.Errorf("expect no error, got %v", err)
   918  		}
   919  	}
   920  
   921  	resp.GetStream().Close()
   922  
   923  	wg.Wait()
   924  
   925  	if err := resp.GetStream().Err(); err != nil {
   926  		t.Errorf("expect no error, %v", err)
   927  	}
   928  }
   929  
   930  func mockStartConversationWriteEvents() (
   931  	[]StartConversationRequestEventStreamEvent,
   932  	[]eventstream.Message,
   933  ) {
   934  	inputEvents := []StartConversationRequestEventStreamEvent{
   935  		&AudioInputEvent{
   936  			AudioChunk:            []byte("blob value goes here"),
   937  			ClientTimestampMillis: aws.Int64(1234),
   938  			ContentType:           aws.String("string value goes here"),
   939  			EventId:               aws.String("string value goes here"),
   940  		},
   941  		&ConfigurationEvent{
   942  			ClientTimestampMillis: aws.Int64(1234),
   943  			DisablePlayback:       aws.Bool(true),
   944  			EventId:               aws.String("string value goes here"),
   945  			RequestAttributes: map[string]*string{
   946  				"a": aws.String("string value goes here"),
   947  				"b": aws.String("string value goes here"),
   948  				"c": aws.String("string value goes here"),
   949  			},
   950  			ResponseContentType: aws.String("string value goes here"),
   951  			SessionState: &SessionState{
   952  				ActiveContexts: []*ActiveContext{
   953  					{
   954  						ContextAttributes: map[string]*string{
   955  							"a": aws.String("string value goes here"),
   956  							"b": aws.String("string value goes here"),
   957  							"c": aws.String("string value goes here"),
   958  						},
   959  						Name: aws.String("string value goes here"),
   960  						TimeToLive: &ActiveContextTimeToLive{
   961  							TimeToLiveInSeconds: aws.Int64(123),
   962  							TurnsToLive:         aws.Int64(123),
   963  						},
   964  					},
   965  					{
   966  						ContextAttributes: map[string]*string{
   967  							"a": aws.String("string value goes here"),
   968  							"b": aws.String("string value goes here"),
   969  							"c": aws.String("string value goes here"),
   970  						},
   971  						Name: aws.String("string value goes here"),
   972  						TimeToLive: &ActiveContextTimeToLive{
   973  							TimeToLiveInSeconds: aws.Int64(123),
   974  							TurnsToLive:         aws.Int64(123),
   975  						},
   976  					},
   977  					{
   978  						ContextAttributes: map[string]*string{
   979  							"a": aws.String("string value goes here"),
   980  							"b": aws.String("string value goes here"),
   981  							"c": aws.String("string value goes here"),
   982  						},
   983  						Name: aws.String("string value goes here"),
   984  						TimeToLive: &ActiveContextTimeToLive{
   985  							TimeToLiveInSeconds: aws.Int64(123),
   986  							TurnsToLive:         aws.Int64(123),
   987  						},
   988  					},
   989  				},
   990  				DialogAction: &DialogAction{
   991  					SlotToElicit: aws.String("string value goes here"),
   992  					Type:         aws.String("string value goes here"),
   993  				},
   994  				Intent: &Intent{
   995  					ConfirmationState: aws.String("string value goes here"),
   996  					Name:              aws.String("string value goes here"),
   997  					Slots: map[string]*Slot{
   998  						"a": {
   999  							Shape: aws.String("string value goes here"),
  1000  							Value: &Value{
  1001  								InterpretedValue: aws.String("string value goes here"),
  1002  								OriginalValue:    aws.String("string value goes here"),
  1003  								ResolvedValues: []*string{
  1004  									aws.String("string value goes here"),
  1005  									aws.String("string value goes here"),
  1006  									aws.String("string value goes here"),
  1007  								},
  1008  							},
  1009  							Values: []*Slot{},
  1010  						},
  1011  						"b": {
  1012  							Shape: aws.String("string value goes here"),
  1013  							Value: &Value{
  1014  								InterpretedValue: aws.String("string value goes here"),
  1015  								OriginalValue:    aws.String("string value goes here"),
  1016  								ResolvedValues: []*string{
  1017  									aws.String("string value goes here"),
  1018  									aws.String("string value goes here"),
  1019  									aws.String("string value goes here"),
  1020  								},
  1021  							},
  1022  							Values: []*Slot{},
  1023  						},
  1024  						"c": {
  1025  							Shape: aws.String("string value goes here"),
  1026  							Value: &Value{
  1027  								InterpretedValue: aws.String("string value goes here"),
  1028  								OriginalValue:    aws.String("string value goes here"),
  1029  								ResolvedValues: []*string{
  1030  									aws.String("string value goes here"),
  1031  									aws.String("string value goes here"),
  1032  									aws.String("string value goes here"),
  1033  								},
  1034  							},
  1035  							Values: []*Slot{},
  1036  						},
  1037  					},
  1038  					State: aws.String("string value goes here"),
  1039  				},
  1040  				OriginatingRequestId: aws.String("string value goes here"),
  1041  				SessionAttributes: map[string]*string{
  1042  					"a": aws.String("string value goes here"),
  1043  					"b": aws.String("string value goes here"),
  1044  					"c": aws.String("string value goes here"),
  1045  				},
  1046  			},
  1047  			WelcomeMessages: []*Message{
  1048  				{
  1049  					Content:     aws.String("string value goes here"),
  1050  					ContentType: aws.String("string value goes here"),
  1051  					ImageResponseCard: &ImageResponseCard{
  1052  						Buttons: []*Button{
  1053  							{
  1054  								Text:  aws.String("string value goes here"),
  1055  								Value: aws.String("string value goes here"),
  1056  							},
  1057  							{
  1058  								Text:  aws.String("string value goes here"),
  1059  								Value: aws.String("string value goes here"),
  1060  							},
  1061  							{
  1062  								Text:  aws.String("string value goes here"),
  1063  								Value: aws.String("string value goes here"),
  1064  							},
  1065  						},
  1066  						ImageUrl: aws.String("string value goes here"),
  1067  						Subtitle: aws.String("string value goes here"),
  1068  						Title:    aws.String("string value goes here"),
  1069  					},
  1070  				},
  1071  				{
  1072  					Content:     aws.String("string value goes here"),
  1073  					ContentType: aws.String("string value goes here"),
  1074  					ImageResponseCard: &ImageResponseCard{
  1075  						Buttons: []*Button{
  1076  							{
  1077  								Text:  aws.String("string value goes here"),
  1078  								Value: aws.String("string value goes here"),
  1079  							},
  1080  							{
  1081  								Text:  aws.String("string value goes here"),
  1082  								Value: aws.String("string value goes here"),
  1083  							},
  1084  							{
  1085  								Text:  aws.String("string value goes here"),
  1086  								Value: aws.String("string value goes here"),
  1087  							},
  1088  						},
  1089  						ImageUrl: aws.String("string value goes here"),
  1090  						Subtitle: aws.String("string value goes here"),
  1091  						Title:    aws.String("string value goes here"),
  1092  					},
  1093  				},
  1094  				{
  1095  					Content:     aws.String("string value goes here"),
  1096  					ContentType: aws.String("string value goes here"),
  1097  					ImageResponseCard: &ImageResponseCard{
  1098  						Buttons: []*Button{
  1099  							{
  1100  								Text:  aws.String("string value goes here"),
  1101  								Value: aws.String("string value goes here"),
  1102  							},
  1103  							{
  1104  								Text:  aws.String("string value goes here"),
  1105  								Value: aws.String("string value goes here"),
  1106  							},
  1107  							{
  1108  								Text:  aws.String("string value goes here"),
  1109  								Value: aws.String("string value goes here"),
  1110  							},
  1111  						},
  1112  						ImageUrl: aws.String("string value goes here"),
  1113  						Subtitle: aws.String("string value goes here"),
  1114  						Title:    aws.String("string value goes here"),
  1115  					},
  1116  				},
  1117  			},
  1118  		},
  1119  		&DTMFInputEvent{
  1120  			ClientTimestampMillis: aws.Int64(1234),
  1121  			EventId:               aws.String("string value goes here"),
  1122  			InputCharacter:        aws.String("string value goes here"),
  1123  		},
  1124  		&DisconnectionEvent{
  1125  			ClientTimestampMillis: aws.Int64(1234),
  1126  			EventId:               aws.String("string value goes here"),
  1127  		},
  1128  		&PlaybackCompletionEvent{
  1129  			ClientTimestampMillis: aws.Int64(1234),
  1130  			EventId:               aws.String("string value goes here"),
  1131  		},
  1132  		&TextInputEvent{
  1133  			ClientTimestampMillis: aws.Int64(1234),
  1134  			EventId:               aws.String("string value goes here"),
  1135  			Text:                  aws.String("string value goes here"),
  1136  		},
  1137  	}
  1138  
  1139  	var marshalers request.HandlerList
  1140  	marshalers.PushBackNamed(restjson.BuildHandler)
  1141  	payloadMarshaler := protocol.HandlerPayloadMarshal{
  1142  		Marshalers: marshalers,
  1143  	}
  1144  	_ = payloadMarshaler
  1145  
  1146  	eventMsgs := []eventstream.Message{
  1147  		{
  1148  			Headers: eventstream.Headers{
  1149  				eventstreamtest.EventMessageTypeHeader,
  1150  				{
  1151  					Name:  eventstreamapi.EventTypeHeader,
  1152  					Value: eventstream.StringValue("AudioInputEvent"),
  1153  				},
  1154  			},
  1155  			Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, inputEvents[0]),
  1156  		},
  1157  		{
  1158  			Headers: eventstream.Headers{
  1159  				eventstreamtest.EventMessageTypeHeader,
  1160  				{
  1161  					Name:  eventstreamapi.EventTypeHeader,
  1162  					Value: eventstream.StringValue("ConfigurationEvent"),
  1163  				},
  1164  			},
  1165  			Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, inputEvents[1]),
  1166  		},
  1167  		{
  1168  			Headers: eventstream.Headers{
  1169  				eventstreamtest.EventMessageTypeHeader,
  1170  				{
  1171  					Name:  eventstreamapi.EventTypeHeader,
  1172  					Value: eventstream.StringValue("DTMFInputEvent"),
  1173  				},
  1174  			},
  1175  			Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, inputEvents[2]),
  1176  		},
  1177  		{
  1178  			Headers: eventstream.Headers{
  1179  				eventstreamtest.EventMessageTypeHeader,
  1180  				{
  1181  					Name:  eventstreamapi.EventTypeHeader,
  1182  					Value: eventstream.StringValue("DisconnectionEvent"),
  1183  				},
  1184  			},
  1185  			Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, inputEvents[3]),
  1186  		},
  1187  		{
  1188  			Headers: eventstream.Headers{
  1189  				eventstreamtest.EventMessageTypeHeader,
  1190  				{
  1191  					Name:  eventstreamapi.EventTypeHeader,
  1192  					Value: eventstream.StringValue("PlaybackCompletionEvent"),
  1193  				},
  1194  			},
  1195  			Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, inputEvents[4]),
  1196  		},
  1197  		{
  1198  			Headers: eventstream.Headers{
  1199  				eventstreamtest.EventMessageTypeHeader,
  1200  				{
  1201  					Name:  eventstreamapi.EventTypeHeader,
  1202  					Value: eventstream.StringValue("TextInputEvent"),
  1203  				},
  1204  			},
  1205  			Payload: eventstreamtest.MarshalEventPayload(payloadMarshaler, inputEvents[5]),
  1206  		},
  1207  	}
  1208  
  1209  	return inputEvents, eventMsgs
  1210  }