github.com/philippseith/signalr@v0.6.3/streamclient_test.go (about)

     1  package signalr
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  	"time"
     8  
     9  	. "github.com/onsi/ginkgo"
    10  	. "github.com/onsi/gomega"
    11  )
    12  
    13  type clientStreamHub struct {
    14  	Hub
    15  	ch chan string
    16  }
    17  
    18  func (c *clientStreamHub) SendResult(result string) {
    19  	if c.ch != nil {
    20  		c.ch <- result
    21  	}
    22  	c.Hub.Clients().All().Send("OnResult", result)
    23  }
    24  
    25  func (c *clientStreamHub) UploadStreamSmoke(upload1 <-chan int, factor float64, upload2 <-chan float64) {
    26  	ok1 := true
    27  	ok2 := true
    28  	u1 := 0
    29  	u2 := 0.0
    30  	c.SendResult(fmt.Sprintf("f: %v", factor))
    31  	for {
    32  		select {
    33  		case u1, ok1 = <-upload1:
    34  			if ok1 {
    35  				c.SendResult(fmt.Sprintf("u1: %v", u1))
    36  			}
    37  		case u2, ok2 = <-upload2:
    38  			if ok2 {
    39  				c.SendResult(fmt.Sprintf("u2: %v", u2))
    40  			}
    41  		case <-c.Hub.Context().Done():
    42  			return
    43  		}
    44  		if !ok1 && !ok2 {
    45  			c.SendResult("Finished")
    46  			return
    47  		}
    48  	}
    49  }
    50  
    51  //noinspection GoUnusedParameter
    52  func (c *clientStreamHub) UploadPanic(upload <-chan string) {
    53  	c.SendResult("Panic()")
    54  	panic("Don't panic!")
    55  }
    56  
    57  func (c *clientStreamHub) UploadInt(upload <-chan int) {
    58  	c.SendResult("UploadInt()")
    59  	for {
    60  		<-upload
    61  	}
    62  }
    63  
    64  //noinspection GoUnusedParameter
    65  func (c *clientStreamHub) UploadHang(upload <-chan int) {
    66  	c.SendResult("UploadHang()")
    67  	// wait forever
    68  	select {}
    69  }
    70  
    71  func (c *clientStreamHub) UploadParamTypes(
    72  	u1 <-chan int8, u2 <-chan int16, u3 <-chan int32, u4 <-chan int64,
    73  	u5 <-chan uint, u6 <-chan uint8, u7 <-chan uint16, u8 <-chan uint32, u9 <-chan uint64,
    74  	u10 <-chan float32, u11 <-chan float64,
    75  	u12 <-chan string) {
    76  	for count := 0; count < 12; {
    77  		select {
    78  		case <-u1:
    79  			count++
    80  		case <-u2:
    81  			count++
    82  		case <-u3:
    83  			count++
    84  		case <-u4:
    85  			count++
    86  		case <-u5:
    87  			count++
    88  		case <-u6:
    89  			count++
    90  		case <-u7:
    91  			count++
    92  		case <-u8:
    93  			count++
    94  		case <-u9:
    95  			count++
    96  		case <-u10:
    97  			count++
    98  		case <-u11:
    99  			count++
   100  		case <-u12:
   101  			count++
   102  		case <-time.After(100 * time.Millisecond):
   103  			c.SendResult("timed out")
   104  			return
   105  		}
   106  	}
   107  	c.SendResult("UPT finished")
   108  }
   109  
   110  func (c *clientStreamHub) UploadArray(u <-chan []int) {
   111  	for r := range u {
   112  		c.SendResult(fmt.Sprintf("received %v", r))
   113  	}
   114  	c.SendResult("UploadArray finished")
   115  }
   116  
   117  func (c *clientStreamHub) UploadError(u <-chan error) {
   118  	c.SendResult("UploadError start")
   119  	for range u {
   120  	}
   121  }
   122  
   123  func (c *clientStreamHub) UploadErrorArray(u <-chan []error) {
   124  	c.SendResult("UploadErrorArray start")
   125  	for range u {
   126  	}
   127  }
   128  
   129  type resultReceiver struct {
   130  	ch chan string
   131  }
   132  
   133  func (r *resultReceiver) OnResult(result string) {
   134  	r.ch <- result
   135  }
   136  
   137  func makeStreamingClientAndServer(options ...func(Party) error) (Client, *resultReceiver, context.CancelFunc) {
   138  	cliConn, srvConn := newClientServerConnections()
   139  	ctx, cancel := context.WithCancel(context.Background())
   140  	if options == nil {
   141  		options = make([]func(Party) error, 0)
   142  	}
   143  	options = append(options, SimpleHubFactory(&clientStreamHub{}), testLoggerOption())
   144  	server, _ := NewServer(ctx, options...)
   145  	go func() { _ = server.Serve(srvConn) }()
   146  	receiver := &resultReceiver{ch: make(chan string, 1)}
   147  	client, _ := NewClient(ctx, WithConnection(cliConn), WithReceiver(receiver), testLoggerOption())
   148  	client.Start()
   149  	return client, receiver, cancel
   150  }
   151  
   152  var _ = Describe("ClientStreaming", func() {
   153  
   154  	Describe("Simple stream invocation", func() {
   155  		Context("When invoked by the client with streamIds", func() {
   156  			It("should be invoked on the server, and receive stream items until the caller sends a completion", func(done Done) {
   157  				client, receiver, cancel := makeStreamingClientAndServer()
   158  				ch1 := make(chan int, 1)
   159  				ch2 := make(chan float64, 1)
   160  				client.PushStreams("UploadStreamSmoke", ch1, 5, ch2)
   161  				go func() {
   162  					go func() {
   163  						for i := 0; i < 10; i++ {
   164  							ch1 <- i
   165  							time.Sleep(100 * time.Millisecond)
   166  						}
   167  					}()
   168  					go func() {
   169  						for i := 5; i < 10; i++ {
   170  							ch2 <- float64(i) * 7.1
   171  							time.Sleep(200 * time.Millisecond)
   172  						}
   173  					}()
   174  				}()
   175  				u1 := 0
   176  				u2 := 5
   177  			loop:
   178  				for {
   179  					select {
   180  					case r := <-receiver.ch:
   181  						switch {
   182  						case strings.HasPrefix(r, "u1"):
   183  							Expect(r).To(Equal(fmt.Sprintf("u1: %v", u1)))
   184  							u1++
   185  							if u1 == 10 {
   186  								close(ch1)
   187  							}
   188  						case strings.HasPrefix(r, "u2"):
   189  							Expect(r).To(Equal(fmt.Sprintf("u2: %v", float64(u2)*7.1)))
   190  							u2++
   191  							if u2 == 10 {
   192  								close(ch2)
   193  							}
   194  						case r == "Finished":
   195  							break loop
   196  						}
   197  					}
   198  				}
   199  				cancel()
   200  				close(done)
   201  			}, 2.0)
   202  		})
   203  	})
   204  
   205  	Describe("Stream invocation", func() {
   206  		Context(" When stream item type that could not be converted to the receiving hub methods channel type is sent", func() {
   207  			for i := 0; i < 1; i++ {
   208  				j := i
   209  				It(fmt.Sprintf("should end the connection with an error %v", j), func(done Done) {
   210  					client, _, cancel := makeStreamingClientAndServer()
   211  					ch := make(chan string, 1)
   212  					client.PushStreams("UploadInt", ch)
   213  					ch <- fmt.Sprintf("ShouldBeInt %v", j)
   214  					<-client.WaitForState(context.Background(), ClientClosed)
   215  					Expect(client.Err()).To(HaveOccurred())
   216  					cancel()
   217  					close(done)
   218  				}, 2.0)
   219  			}
   220  		})
   221  	})
   222  
   223  	Describe("Stream invocation to the StreamBufferCapacity", func() {
   224  		Context(" When hub method is called as streaming receiver but does not handle channel input", func() {
   225  			It("should send a completion with error, but wait at least ChanReceiveTimeout", func(done Done) {
   226  				client, _, cancel := makeStreamingClientAndServer(ChanReceiveTimeout(500*time.Millisecond),
   227  					StreamBufferCapacity(5))
   228  				<-client.WaitForState(context.Background(), ClientConnected)
   229  				ch := make(chan int, 1)
   230  				client.PushStreams("UploadHang", ch)
   231  				// connect() sets StreamBufferCapacity to 5, so 6 messages should be send to make it hang
   232  				for i := 0; i < 6; i++ {
   233  					ch <- i
   234  				}
   235  				sent := time.Now()
   236  				<-client.WaitForState(context.Background(), ClientClosed)
   237  				Expect(client.Err()).To(HaveOccurred())
   238  				// ChanReceiveTimeout 200 ms should be over
   239  				Expect(time.Now().UnixNano()).To(BeNumerically(">", sent.Add(500*time.Millisecond).UnixNano()))
   240  				cancel()
   241  				close(done)
   242  			})
   243  		})
   244  	})
   245  
   246  	Describe("Stream invocation with wrong streamId", func() {
   247  		Context("When invoked by the client with streamIds", func() {
   248  			It("should be invoked on the server, and receive stream items until the caller sends a completion. Unknown streamIds should be ignored", func(done Done) {
   249  				hub := &clientStreamHub{ch: make(chan string, 20)}
   250  				server, err := NewServer(context.TODO(), HubFactory(func() HubInterface {
   251  					return hub
   252  				}), testLoggerOption())
   253  				Expect(err).NotTo(HaveOccurred())
   254  				conn := newTestingConnectionForServer()
   255  				go func() { _ = server.Serve(conn) }()
   256  
   257  				conn.ClientSend(fmt.Sprintf(
   258  					`{"type":1,"invocationId":"upstream","target":"uploadstreamsmoke","arguments":[%v],"streamIds":["123","456"]}`, 5))
   259  				Expect(<-hub.ch).To(Equal(fmt.Sprintf("f: %v", 5)))
   260  				// close the first stream
   261  				conn.ClientSend(`{"type":3,"invocationId":"123"}`)
   262  				// Send one with correct streamid
   263  				conn.ClientSend(fmt.Sprintf(`{"type":2,"invocationId":"456","item":%v}`, 7.1))
   264  				// close the second stream
   265  				conn.ClientSend(`{"type":3,"invocationId":"456"}`)
   266  			loop:
   267  				for {
   268  					select {
   269  					case <-hub.ch:
   270  						break loop
   271  					case <-time.After(500 * time.Millisecond):
   272  						Fail("timed out")
   273  					}
   274  				}
   275  				// Read finished value from queue
   276  				<-hub.ch
   277  				server.cancel()
   278  				close(done)
   279  			})
   280  		})
   281  	})
   282  	Describe("Stream invocation with wrong count of streamid", func() {
   283  
   284  		Context("When invoked by the client with to many streamIds", func() {
   285  			It("should end the connection with an error", func(done Done) {
   286  				server, conn := connect(&clientStreamHub{})
   287  				conn.ClientSend(fmt.Sprintf(`{"type":1,"invocationId":"upstream","target":"uploadstreamsmoke","arguments":[%v],"streamIds":["123","456","789"]}`, 5))
   288  				message := <-conn.received
   289  				Expect(message).To(BeAssignableToTypeOf(completionMessage{}))
   290  				completionMessage := message.(completionMessage)
   291  				Expect(completionMessage.Error).NotTo(BeNil())
   292  				server.cancel()
   293  				close(done)
   294  			}, 2.0)
   295  		})
   296  		Context("When invoked by the client with not enough streamIds", func() {
   297  			It("should end the connection with an error", func(done Done) {
   298  				server, conn := connect(&clientStreamHub{})
   299  				conn.ClientSend(fmt.Sprintf(`{"type":1,"invocationId":"upstream","target":"uploadstreamsmoke","arguments":[%v],"streamIds":["123"]}`, 5))
   300  				message := <-conn.received
   301  				Expect(message).To(BeAssignableToTypeOf(completionMessage{}))
   302  				completionMessage := message.(completionMessage)
   303  				Expect(completionMessage.Error).NotTo(BeNil())
   304  				server.cancel()
   305  				close(done)
   306  			}, 2.0)
   307  		})
   308  	})
   309  
   310  	Describe("Panic in invoked stream client func", func() {
   311  		Context("When a func is invoked by the client and panics", func() {
   312  			It("should return a completion with error", func(done Done) {
   313  				client, _, cancel := makeStreamingClientAndServer()
   314  				client.PushStreams("UploadPanic", make(chan int))
   315  				<-client.WaitForState(context.Background(), ClientClosed)
   316  				Expect(client.Err()).To(HaveOccurred())
   317  				cancel()
   318  				close(done)
   319  			})
   320  		})
   321  	})
   322  	Describe("Stream client with all numbertypes of channels", func() {
   323  		Context("When a func is invoked by the client with all number types of channels", func() {
   324  			It("should receive values on all of these types", func(done Done) {
   325  				u1 := make(chan int8, 1)
   326  				u2 := make(chan int16, 1)
   327  				u3 := make(chan int32, 1)
   328  				u4 := make(chan int64, 1)
   329  				u5 := make(chan uint, 1)
   330  				u6 := make(chan uint8, 1)
   331  				u7 := make(chan uint16, 1)
   332  				u8 := make(chan uint32, 1)
   333  				u9 := make(chan uint64, 1)
   334  				u10 := make(chan float32, 1)
   335  				u11 := make(chan float64, 1)
   336  				u12 := make(chan string, 1)
   337  				client, receiver, cancel := makeStreamingClientAndServer()
   338  				client.PushStreams("UploadParamTypes", u1, u2, u3, u4, u5, u6, u7, u8, u9, u10, u11, u12)
   339  				u1 <- 1
   340  				u2 <- 1
   341  				u3 <- 1
   342  				u4 <- 1
   343  				u5 <- 1
   344  				u6 <- 1
   345  				u7 <- 1
   346  				u8 <- 1
   347  				u9 <- 1
   348  				u10 <- 1.1
   349  				u11 <- 2.1
   350  				u12 <- "Some String"
   351  				Expect(<-receiver.ch).To(Equal("UPT finished"))
   352  				cancel()
   353  				close(done)
   354  			})
   355  		})
   356  	})
   357  
   358  	Describe("Stream client with array channel", func() {
   359  		Context("When a func with an array channel is invoked by the client and stream items are send", func() {
   360  			It("should receive values and end after that", func(done Done) {
   361  				client, receiver, cancel := makeStreamingClientAndServer()
   362  				ch := make(chan []int)
   363  				client.PushStreams("UploadArray", ch)
   364  				ch <- []int{1, 2}
   365  				Expect(<-receiver.ch).To(Equal("received [1 2]"))
   366  				close(ch)
   367  				Expect(<-receiver.ch).To(Equal("UploadArray finished"))
   368  				cancel()
   369  				close(done)
   370  			})
   371  		})
   372  	})
   373  
   374  	Describe("Client sending invalid streamitems", func() {
   375  		Context("When an invalid streamitem message with missing id and item is sent", func() {
   376  			It("should end the connection with an error", func(done Done) {
   377  				hub := &clientStreamHub{ch: make(chan string, 20)}
   378  				server, err := NewServer(context.TODO(), HubFactory(func() HubInterface {
   379  					return hub
   380  				}), testLoggerOption())
   381  				Expect(err).NotTo(HaveOccurred())
   382  				conn := newTestingConnectionForServer()
   383  				go func() { _ = server.Serve(conn) }()
   384  				conn.ClientSend(`{"type":1,"invocationId": "nnn","target":"uploadstreamsmoke","arguments":[5.0],"streamIds":["ff2","ggg"]}`)
   385  				<-hub.ch
   386  				<-conn.received
   387  				// Send invalid stream item message with missing id and item
   388  				conn.ClientSend(`{"type":2}`)
   389  				message := <-conn.received
   390  				Expect(message).To(BeAssignableToTypeOf(closeMessage{}))
   391  				Expect(message.(closeMessage).Error).NotTo(BeNil())
   392  				server.cancel()
   393  				close(done)
   394  			}, 2.0)
   395  		})
   396  		Context("When an invalid streamitem message with missing item is received", func() {
   397  			It("should end the connection with an error", func(done Done) {
   398  				hub := &clientStreamHub{ch: make(chan string, 20)}
   399  				server, err := NewServer(context.TODO(), HubFactory(func() HubInterface {
   400  					return hub
   401  				}), testLoggerOption())
   402  				Expect(err).NotTo(HaveOccurred())
   403  				conn := newTestingConnectionForServer()
   404  				go func() { _ = server.Serve(conn) }()
   405  				conn.ClientSend(`{"type":1,"invocationId": "nnn","target":"uploadstreamsmoke","arguments":[5.0],"streamIds":["ff3","ggg"]}`)
   406  				<-hub.ch
   407  				<-conn.received
   408  				// Send invalid stream item message with missing item
   409  				conn.ClientSend(`{"type":2,"InvocationId":"iii"}`)
   410  				message := <-conn.received
   411  				Expect(message).To(BeAssignableToTypeOf(closeMessage{}))
   412  				Expect(message.(closeMessage).Error).NotTo(BeNil())
   413  				server.cancel()
   414  				close(done)
   415  			}, 2.0)
   416  		})
   417  		Context("When an invalid streamitem message with wrong itemtype is received", func() {
   418  			It("should end the connection with an error", func(done Done) {
   419  				hub := &clientStreamHub{ch: make(chan string, 20)}
   420  				server, err := NewServer(context.TODO(), HubFactory(func() HubInterface {
   421  					return hub
   422  				}), testLoggerOption())
   423  				Expect(err).NotTo(HaveOccurred())
   424  				conn := newTestingConnectionForServer()
   425  				go func() { _ = server.Serve(conn) }()
   426  				conn.ClientSend(`{"type":1,"invocationId": "nnn","target":"uploadstreamsmoke","arguments":[5.0],"streamIds":["ff1","ggg"]}`)
   427  				<-hub.ch
   428  				<-conn.received
   429  				// Send invalid stream item message
   430  				conn.ClientSend(`{"type":2,"invocationId":"ff1","item":[42]}`)
   431  				message := <-conn.received
   432  				Expect(message).To(BeAssignableToTypeOf(closeMessage{}))
   433  				Expect(message.(closeMessage).Error).NotTo(BeNil())
   434  				server.cancel()
   435  				close(done)
   436  			}, 2.0)
   437  		})
   438  		Context("When an invalid stream item message with invalid invocation id is sent", func() {
   439  			It("should end the connection with an error", func(done Done) {
   440  				hub := &clientStreamHub{ch: make(chan string, 20)}
   441  				server, err := NewServer(context.TODO(), HubFactory(func() HubInterface {
   442  					return hub
   443  				}), testLoggerOption())
   444  				Expect(err).NotTo(HaveOccurred())
   445  				conn := newTestingConnectionForServer()
   446  				go func() { _ = server.Serve(conn) }()
   447  				conn.ClientSend(`{"type":1,"invocationId": "nnn","target":"uploadstreamsmoke","arguments":[5.0],"streamIds":["ff4","ggg"]}`)
   448  				<-hub.ch
   449  				<-conn.received
   450  				// Send invalid stream item message with invalid invocation id
   451  				conn.ClientSend(`{"type":2,"invocationId":1}`)
   452  				message := <-conn.received
   453  				Expect(message).To(BeAssignableToTypeOf(closeMessage{}))
   454  				Expect(message.(closeMessage).Error).NotTo(BeNil())
   455  				server.cancel()
   456  				close(done)
   457  			}, 2.0)
   458  		})
   459  	})
   460  
   461  	Describe("Client sending invalid completion", func() {
   462  		Context("When an invalid completion message with missing id is sent", func() {
   463  			It("should end the connection with an error", func(done Done) {
   464  				hub := &clientStreamHub{ch: make(chan string, 20)}
   465  				server, err := NewServer(context.TODO(), HubFactory(func() HubInterface {
   466  					return hub
   467  				}), testLoggerOption())
   468  				Expect(err).NotTo(HaveOccurred())
   469  				conn := newTestingConnectionForServer()
   470  				go func() { _ = server.Serve(conn) }()
   471  				conn.ClientSend(`{"type":1,"invocationId": "nnn","target":"uploadstreamsmoke","arguments":[5.0],"streamIds":["ff5","ggg"]}`)
   472  				<-hub.ch
   473  				<-conn.received
   474  				// Send invalid completion message with missing id
   475  				conn.ClientSend(`{"type":3}`)
   476  				message := <-conn.received
   477  				Expect(message).To(BeAssignableToTypeOf(closeMessage{}))
   478  				Expect(message.(closeMessage).Error).NotTo(BeNil())
   479  				server.cancel()
   480  				close(done)
   481  			}, 2.0)
   482  		})
   483  
   484  		Context("When an invalid completion message with unknown id is sent", func() {
   485  			It("should end the connection with an error", func(done Done) {
   486  				hub := &clientStreamHub{ch: make(chan string, 20)}
   487  				server, err := NewServer(context.TODO(), HubFactory(func() HubInterface {
   488  					return hub
   489  				}), testLoggerOption())
   490  				Expect(err).NotTo(HaveOccurred())
   491  				conn := newTestingConnectionForServer()
   492  				go func() { _ = server.Serve(conn) }()
   493  				conn.ClientSend(`{"type":1,"invocationId":"nnn","target":"uploadstreamsmoke","arguments":[5.0],"streamIds":["ff6","ggg"]}`)
   494  				<-hub.ch
   495  				<-conn.received
   496  				// Send invalid completion message with unknown id
   497  				conn.ClientSend(`{"type":3,"invocationId":"qqq"}`)
   498  				message := <-conn.received
   499  				Expect(message).To(BeAssignableToTypeOf(closeMessage{}))
   500  				Expect(message.(closeMessage).Error).NotTo(BeNil())
   501  				server.cancel()
   502  				close(done)
   503  			}, 2.0)
   504  		})
   505  
   506  		Context("When an completion message with an result is sent before any stream item was received", func() {
   507  			It("should take the result as stream item and consider the streaming as finished", func(done Done) {
   508  				hub := &clientStreamHub{ch: make(chan string, 20)}
   509  				server, err := NewServer(context.TODO(), HubFactory(func() HubInterface {
   510  					return hub
   511  				}), testLoggerOption())
   512  				Expect(err).NotTo(HaveOccurred())
   513  				conn := newTestingConnectionForServer()
   514  				go func() { _ = server.Serve(conn) }()
   515  				conn.ClientSend(`{"type":1,"invocationId":"UPA","target":"uploadarray","streamIds":["aaa"]}`)
   516  				conn.ClientSend(`{"type":3,"invocationId":"aaa","result":[1,2]}`)
   517  				Expect(<-hub.ch).To(Equal("received [1 2]"))
   518  				Expect(<-hub.ch).To(Equal("UploadArray finished"))
   519  				server.cancel()
   520  				close(done)
   521  			})
   522  		})
   523  
   524  		Context("When an invalid completion message is sent", func() {
   525  			It("should close the connection with an error", func(done Done) {
   526  				hub := &clientStreamHub{ch: make(chan string, 20)}
   527  				server, err := NewServer(context.TODO(), HubFactory(func() HubInterface {
   528  					return hub
   529  				}), testLoggerOption())
   530  				Expect(err).NotTo(HaveOccurred())
   531  				conn := newTestingConnectionForServer()
   532  				go func() { _ = server.Serve(conn) }()
   533  				conn.ClientSend(`{"type":1,"invocationId":"UPA","target":"uploadarray","streamIds":["aaa"]}`)
   534  				conn.ClientSend(`{"type":3,"invocationId":1}`)
   535  				message := <-conn.received
   536  				Expect(message).To(BeAssignableToTypeOf(closeMessage{}))
   537  				Expect(message.(closeMessage).Error).NotTo(BeNil())
   538  				server.cancel()
   539  				close(done)
   540  			}, 2.0)
   541  		})
   542  
   543  		Context("When an completion message with an result is sent after a stream item was received", func() {
   544  			It("should end the connection with an error", func(done Done) {
   545  				hub := &clientStreamHub{ch: make(chan string, 20)}
   546  				server, err := NewServer(context.TODO(), HubFactory(func() HubInterface {
   547  					return hub
   548  				}), testLoggerOption())
   549  				Expect(err).NotTo(HaveOccurred())
   550  				conn := newTestingConnectionForServer()
   551  				go func() { _ = server.Serve(conn) }()
   552  				conn.ClientSend(`{"type":1,"invocationId":"nnn","target":"uploadstreamsmoke","arguments":[5.0],"streamIds":["fff","ggg"]}`)
   553  				<-hub.ch
   554  				<-conn.received
   555  				// Send stream item
   556  				conn.ClientSend(`{"type":2,"invocationId":"fff","item":1}`)
   557  				<-hub.ch
   558  				<-conn.received
   559  				// Send completion message with result
   560  				conn.ClientSend(`{"type":3,"invocationId":"fff","result":1}`)
   561  				message := <-conn.received
   562  				Expect(message).To(BeAssignableToTypeOf(closeMessage{}))
   563  				Expect(message.(closeMessage).Error).NotTo(BeNil())
   564  				server.cancel()
   565  				close(done)
   566  			})
   567  		})
   568  
   569  		Context("When the stream item type could not converted to the hub methods receive channel type", func() {
   570  			It("should end the connection with an error", func(done Done) {
   571  				hub := &clientStreamHub{ch: make(chan string, 20)}
   572  				server, err := NewServer(context.TODO(), HubFactory(func() HubInterface {
   573  					return hub
   574  				}), testLoggerOption())
   575  				Expect(err).NotTo(HaveOccurred())
   576  				conn := newTestingConnectionForServer()
   577  				go func() { _ = server.Serve(conn) }()
   578  				conn.ClientSend(`{"type":1,"invocationId":"nnn","target":"uploaderror","streamIds":["eee"]}`)
   579  				<-hub.ch
   580  				<-conn.received
   581  				// Send stream item
   582  				conn.ClientSend(`{"type":2,"invocationId":"eee","item":1}`)
   583  				message := <-conn.received
   584  				Expect(message).To(BeAssignableToTypeOf(closeMessage{}))
   585  				Expect(message.(closeMessage).Error).NotTo(BeNil())
   586  				server.cancel()
   587  				close(done)
   588  			})
   589  		})
   590  
   591  		Context("When the stream item array type could not converted to the hub methods receive channel array type", func() {
   592  			It("should end the connection with an error", func(done Done) {
   593  				hub := &clientStreamHub{ch: make(chan string, 20)}
   594  				server, err := NewServer(context.TODO(), HubFactory(func() HubInterface {
   595  					return hub
   596  				}), testLoggerOption())
   597  				Expect(err).NotTo(HaveOccurred())
   598  				conn := newTestingConnectionForServer()
   599  				go func() { _ = server.Serve(conn) }()
   600  				conn.ClientSend(`{"type":1,"invocationId":"nnn","target":"uploaderrorarray","streamIds":["aeae"]}`)
   601  				<-hub.ch
   602  				<-conn.received
   603  				// Send stream item
   604  				conn.ClientSend(`{"type":2,"invocationId":"aeae","item":[7,8]}`)
   605  				message := <-conn.received
   606  				Expect(message).To(BeAssignableToTypeOf(closeMessage{}))
   607  				Expect(message.(closeMessage).Error).NotTo(BeNil())
   608  				server.cancel()
   609  				close(done)
   610  			})
   611  		})
   612  	})
   613  })