@@ -9,9 +9,11 @@ import (
9
9
"io"
10
10
"net/http"
11
11
"net/http/httptest"
12
+ "sync"
12
13
"testing"
13
14
"time"
14
15
16
+ "github.com/cespare/xxhash/v2"
15
17
"github.com/stretchr/testify/assert"
16
18
"github.com/stretchr/testify/require"
17
19
@@ -7996,10 +7998,70 @@ var errSubscriptionClientFail = errors.New("subscription client fail error")
7996
7998
7997
7999
type FailingSubscriptionClient struct {}
7998
8000
7999
- func (f FailingSubscriptionClient ) Subscribe (_ * resolve.Context , _ GraphQLSubscriptionOptions , _ chan <- [] byte ) error {
8001
+ func (f * FailingSubscriptionClient ) Subscribe (ctx * resolve.Context , options GraphQLSubscriptionOptions , updater resolve. SubscriptionUpdater ) error {
8000
8002
return errSubscriptionClientFail
8001
8003
}
8002
8004
8005
+ func (f * FailingSubscriptionClient ) UniqueRequestID (ctx * resolve.Context , options GraphQLSubscriptionOptions , hash * xxhash.Digest ) (err error ) {
8006
+ return errSubscriptionClientFail
8007
+ }
8008
+
8009
+ type testSubscriptionUpdater struct {
8010
+ updates []string
8011
+ done bool
8012
+ mux sync.Mutex
8013
+ }
8014
+
8015
+ func (t * testSubscriptionUpdater ) AwaitUpdates (tt * testing.T , timeout time.Duration , count int ) {
8016
+ ticker := time .NewTicker (timeout )
8017
+ defer ticker .Stop ()
8018
+ for {
8019
+ time .Sleep (10 * time .Millisecond )
8020
+ select {
8021
+ case <- ticker .C :
8022
+ tt .Fatalf ("timed out waiting for updates" )
8023
+ default :
8024
+ t .mux .Lock ()
8025
+ if len (t .updates ) == count {
8026
+ t .mux .Unlock ()
8027
+ return
8028
+ }
8029
+ t .mux .Unlock ()
8030
+ }
8031
+ }
8032
+ }
8033
+
8034
+ func (t * testSubscriptionUpdater ) AwaitDone (tt * testing.T , timeout time.Duration ) {
8035
+ ticker := time .NewTicker (timeout )
8036
+ defer ticker .Stop ()
8037
+ for {
8038
+ time .Sleep (10 * time .Millisecond )
8039
+ select {
8040
+ case <- ticker .C :
8041
+ tt .Fatalf ("timed out waiting for done" )
8042
+ default :
8043
+ t .mux .Lock ()
8044
+ if t .done {
8045
+ t .mux .Unlock ()
8046
+ return
8047
+ }
8048
+ t .mux .Unlock ()
8049
+ }
8050
+ }
8051
+ }
8052
+
8053
+ func (t * testSubscriptionUpdater ) Update (data []byte ) {
8054
+ t .mux .Lock ()
8055
+ defer t .mux .Unlock ()
8056
+ t .updates = append (t .updates , string (data ))
8057
+ }
8058
+
8059
+ func (t * testSubscriptionUpdater ) Done () {
8060
+ t .mux .Lock ()
8061
+ defer t .mux .Unlock ()
8062
+ t .done = true
8063
+ }
8064
+
8003
8065
func TestSubscriptionSource_Start (t * testing.T ) {
8004
8066
chatServer := httptest .NewServer (subscriptiontesting .ChatGraphQLEndpointHandler ())
8005
8067
defer chatServer .Close ()
@@ -8042,84 +8104,86 @@ func TestSubscriptionSource_Start(t *testing.T) {
8042
8104
}
8043
8105
8044
8106
t .Run ("should return error when input is invalid" , func (t * testing.T ) {
8045
- source := SubscriptionSource {client : FailingSubscriptionClient {}}
8107
+ source := SubscriptionSource {client : & FailingSubscriptionClient {}}
8046
8108
err := source .Start (resolve .NewContext (context .Background ()), []byte (`{"url": "", "body": "", "header": null}` ), nil )
8047
8109
assert .Error (t , err )
8048
8110
})
8049
8111
8050
8112
t .Run ("should return error when subscription client returns an error" , func (t * testing.T ) {
8051
- source := SubscriptionSource {client : FailingSubscriptionClient {}}
8113
+ source := SubscriptionSource {client : & FailingSubscriptionClient {}}
8052
8114
err := source .Start (resolve .NewContext (context .Background ()), []byte (`{"url": "", "body": {}, "header": null}` ), nil )
8053
8115
assert .Error (t , err )
8054
8116
assert .Equal (t , resolve .ErrUnableToResolve , err )
8055
8117
})
8056
8118
8057
8119
t .Run ("invalid json: should stop before sending to upstream" , func (t * testing.T ) {
8058
- next := make (chan []byte )
8059
8120
ctx := resolve .NewContext (context .Background ())
8060
8121
defer ctx .Context ().Done ()
8061
8122
8123
+ updater := & testSubscriptionUpdater {}
8124
+
8062
8125
source := newSubscriptionSource (ctx .Context ())
8063
8126
chatSubscriptionOptions := chatServerSubscriptionOptions (t , `{"variables": {}, "extensions": {}, "operationName": "LiveMessages", "query": "subscription LiveMessages { messageAdded(roomName: "#test") { text createdBy } }"}` )
8064
- err := source .Start (ctx , chatSubscriptionOptions , next )
8127
+ err := source .Start (ctx , chatSubscriptionOptions , updater )
8065
8128
require .ErrorIs (t , err , resolve .ErrUnableToResolve )
8066
8129
})
8067
8130
8068
8131
t .Run ("invalid syntax (roomNam)" , func (t * testing.T ) {
8069
- next := make (chan []byte )
8070
8132
ctx := resolve .NewContext (context .Background ())
8071
8133
defer ctx .Context ().Done ()
8072
8134
8135
+ updater := & testSubscriptionUpdater {}
8136
+
8073
8137
source := newSubscriptionSource (ctx .Context ())
8074
8138
chatSubscriptionOptions := chatServerSubscriptionOptions (t , `{"variables": {}, "extensions": {}, "operationName": "LiveMessages", "query": "subscription LiveMessages { messageAdded(roomNam: \"#test\") { text createdBy } }"}` )
8075
- err := source .Start (ctx , chatSubscriptionOptions , next )
8139
+ err := source .Start (ctx , chatSubscriptionOptions , updater )
8076
8140
require .NoError (t , err )
8077
-
8078
- msg , ok := <- next
8079
- assert .True (t , ok )
8080
- assert .Equal (t , `{"errors":[{"message":"Unknown argument \"roomNam\" on field \"Subscription.messageAdded\". Did you mean \"roomName\"?","locations":[{"line":1,"column":29}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Field \"messageAdded\" argument \"roomName\" of type \"String!\" is required, but it was not provided.","locations":[{"line":1,"column":29}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}]}` , string (msg ))
8081
- _ , ok = <- next
8082
- assert .False (t , ok )
8141
+ updater .AwaitUpdates (t , time .Second , 1 )
8142
+ assert .Len (t , updater .updates , 1 )
8143
+ assert .Equal (t , `{"errors":[{"message":"Unknown argument \"roomNam\" on field \"Subscription.messageAdded\". Did you mean \"roomName\"?","locations":[{"line":1,"column":29}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Field \"messageAdded\" argument \"roomName\" of type \"String!\" is required, but it was not provided.","locations":[{"line":1,"column":29}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}]}` , updater .updates [0 ])
8144
+ assert .Equal (t , true , updater .done )
8083
8145
})
8084
8146
8085
8147
t .Run ("should close connection on stop message" , func (t * testing.T ) {
8086
- next := make (chan []byte )
8087
8148
subscriptionLifecycle , cancelSubscription := context .WithCancel (context .Background ())
8088
8149
resolverLifecycle , cancelResolver := context .WithCancel (context .Background ())
8089
8150
defer cancelResolver ()
8090
8151
8152
+ updater := & testSubscriptionUpdater {}
8153
+
8091
8154
source := newSubscriptionSource (resolverLifecycle )
8092
8155
chatSubscriptionOptions := chatServerSubscriptionOptions (t , `{"variables": {}, "extensions": {}, "operationName": "LiveMessages", "query": "subscription LiveMessages { messageAdded(roomName: \"#test\") { text createdBy } }"}` )
8093
- err := source .Start (resolve .NewContext (subscriptionLifecycle ), chatSubscriptionOptions , next )
8156
+ err := source .Start (resolve .NewContext (subscriptionLifecycle ), chatSubscriptionOptions , updater )
8094
8157
require .NoError (t , err )
8095
8158
8096
8159
username := "myuser"
8097
8160
message := "hello world!"
8098
8161
go sendChatMessage (t , username , message )
8099
8162
8100
- nextBytes := <- next
8101
- assert .Equal (t , `{"data":{"messageAdded":{"text":"hello world!","createdBy":"myuser"}}}` , string (nextBytes ))
8163
+ updater .AwaitUpdates (t , time .Second , 1 )
8102
8164
cancelSubscription ()
8103
- _ , ok := <- next
8104
- assert .False (t , ok )
8165
+ updater .AwaitDone (t , time .Second * 5 )
8166
+ assert .Len (t , updater .updates , 1 )
8167
+ assert .Equal (t , `{"data":{"messageAdded":{"text":"hello world!","createdBy":"myuser"}}}` , updater .updates [0 ])
8105
8168
})
8106
8169
8107
8170
t .Run ("should successfully subscribe with chat example" , func (t * testing.T ) {
8108
- next := make (chan []byte )
8109
8171
ctx := resolve .NewContext (context .Background ())
8110
8172
defer ctx .Context ().Done ()
8111
8173
8174
+ updater := & testSubscriptionUpdater {}
8175
+
8112
8176
source := newSubscriptionSource (ctx .Context ())
8113
8177
chatSubscriptionOptions := chatServerSubscriptionOptions (t , `{"variables": {}, "extensions": {}, "operationName": "LiveMessages", "query": "subscription LiveMessages { messageAdded(roomName: \"#test\") { text createdBy } }"}` )
8114
- err := source .Start (ctx , chatSubscriptionOptions , next )
8178
+ err := source .Start (ctx , chatSubscriptionOptions , updater )
8115
8179
require .NoError (t , err )
8116
8180
8117
8181
username := "myuser"
8118
8182
message := "hello world!"
8119
8183
go sendChatMessage (t , username , message )
8120
-
8121
- nextBytes := <- next
8122
- assert .Equal (t , `{"data":{"messageAdded":{"text":"hello world!","createdBy":"myuser"}}}` , string ( nextBytes ) )
8184
+ updater . AwaitUpdates ( t , time . Second , 1 )
8185
+ assert . Len ( t , updater . updates , 1 )
8186
+ assert .Equal (t , `{"data":{"messageAdded":{"text":"hello world!","createdBy":"myuser"}}}` , updater . updates [ 0 ] )
8123
8187
})
8124
8188
}
8125
8189
@@ -8167,60 +8231,65 @@ func TestSubscription_GTWS_SubProtocol(t *testing.T) {
8167
8231
}
8168
8232
8169
8233
t .Run ("invalid syntax (roomNam)" , func (t * testing.T ) {
8170
- next := make (chan []byte )
8171
8234
ctx := resolve .NewContext (context .Background ())
8172
8235
defer ctx .Context ().Done ()
8173
8236
8237
+ updater := & testSubscriptionUpdater {}
8238
+
8174
8239
source := newSubscriptionSource (ctx .Context ())
8175
8240
chatSubscriptionOptions := chatServerSubscriptionOptions (t , `{"variables": {}, "extensions": {}, "operationName": "LiveMessages", "query": "subscription LiveMessages { messageAdded(roomNam: \"#test\") { text createdBy } }"}` )
8176
- err := source .Start (ctx , chatSubscriptionOptions , next )
8241
+ err := source .Start (ctx , chatSubscriptionOptions , updater )
8177
8242
require .NoError (t , err )
8178
8243
8179
- msg , ok := <- next
8180
- assert .True (t , ok )
8181
- assert .Equal (t , `{"errors":[{"message":"Unknown argument \"roomNam\" on field \"Subscription.messageAdded\". Did you mean \"roomName\"?","locations":[{"line":1,"column":29}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Field \"messageAdded\" argument \"roomName\" of type \"String!\" is required, but it was not provided.","locations":[{"line":1,"column":29}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}]}` , string ( msg ) )
8182
- _ , ok = <- next
8183
- assert .False (t , ok )
8244
+ updater . AwaitUpdates ( t , time . Second , 1 )
8245
+ assert .Len (t , updater . updates , 1 )
8246
+ assert .Equal (t , `{"errors":[{"message":"Unknown argument \"roomNam\" on field \"Subscription.messageAdded\". Did you mean \"roomName\"?","locations":[{"line":1,"column":29}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Field \"messageAdded\" argument \"roomName\" of type \"String!\" is required, but it was not provided.","locations":[{"line":1,"column":29}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}]}` , updater . updates [ 0 ] )
8247
+ updater . AwaitDone ( t , time . Second )
8248
+ assert .Equal (t , true , updater . done )
8184
8249
})
8185
8250
8186
8251
t .Run ("should close connection on stop message" , func (t * testing.T ) {
8187
- next := make (chan []byte )
8188
8252
subscriptionLifecycle , cancelSubscription := context .WithCancel (context .Background ())
8189
8253
resolverLifecycle , cancelResolver := context .WithCancel (context .Background ())
8190
8254
defer cancelResolver ()
8191
8255
8256
+ updater := & testSubscriptionUpdater {}
8257
+
8192
8258
source := newSubscriptionSource (resolverLifecycle )
8193
8259
chatSubscriptionOptions := chatServerSubscriptionOptions (t , `{"variables": {}, "extensions": {}, "operationName": "LiveMessages", "query": "subscription LiveMessages { messageAdded(roomName: \"#test\") { text createdBy } }"}` )
8194
- err := source .Start (resolve .NewContext (subscriptionLifecycle ), chatSubscriptionOptions , next )
8260
+ err := source .Start (resolve .NewContext (subscriptionLifecycle ), chatSubscriptionOptions , updater )
8195
8261
require .NoError (t , err )
8196
8262
8197
8263
username := "myuser"
8198
8264
message := "hello world!"
8199
8265
go sendChatMessage (t , username , message )
8200
8266
8201
- nextBytes := <- next
8202
- assert .Equal (t , `{"data":{"messageAdded":{"text":"hello world!","createdBy":"myuser"}}}` , string (nextBytes ))
8267
+ updater .AwaitUpdates (t , time .Second , 1 )
8268
+ assert .Len (t , updater .updates , 1 )
8269
+ assert .Equal (t , `{"data":{"messageAdded":{"text":"hello world!","createdBy":"myuser"}}}` , updater .updates [0 ])
8203
8270
cancelSubscription ()
8204
- _ , ok := <- next
8205
- assert .False (t , ok )
8271
+ updater . AwaitDone ( t , time . Second * 5 )
8272
+ assert .Equal (t , true , updater . done )
8206
8273
})
8207
8274
8208
8275
t .Run ("should successfully subscribe with chat example" , func (t * testing.T ) {
8209
- next := make (chan []byte )
8210
8276
ctx := resolve .NewContext (context .Background ())
8211
8277
defer ctx .Context ().Done ()
8212
8278
8279
+ updater := & testSubscriptionUpdater {}
8280
+
8213
8281
source := newSubscriptionSource (ctx .Context ())
8214
8282
chatSubscriptionOptions := chatServerSubscriptionOptions (t , `{"variables": {}, "extensions": {}, "operationName": "LiveMessages", "query": "subscription LiveMessages { messageAdded(roomName: \"#test\") { text createdBy } }"}` )
8215
- err := source .Start (ctx , chatSubscriptionOptions , next )
8283
+ err := source .Start (ctx , chatSubscriptionOptions , updater )
8216
8284
require .NoError (t , err )
8217
8285
8218
8286
username := "myuser"
8219
8287
message := "hello world!"
8220
8288
go sendChatMessage (t , username , message )
8221
8289
8222
- nextBytes := <- next
8223
- assert .Equal (t , `{"data":{"messageAdded":{"text":"hello world!","createdBy":"myuser"}}}` , string (nextBytes ))
8290
+ updater .AwaitUpdates (t , time .Second , 1 )
8291
+ assert .Len (t , updater .updates , 1 )
8292
+ assert .Equal (t , `{"data":{"messageAdded":{"text":"hello world!","createdBy":"myuser"}}}` , updater .updates [0 ])
8224
8293
})
8225
8294
}
8226
8295
0 commit comments