github.com/philippseith/signalr@v0.6.3/streaminvocation_test.go (about) 1 package signalr 2 3 import ( 4 "time" 5 6 . "github.com/onsi/ginkgo" 7 . "github.com/onsi/gomega" 8 ) 9 10 var streamInvocationQueue = make(chan string, 20) 11 12 type streamHub struct { 13 Hub 14 } 15 16 func (s *streamHub) SimpleStream() <-chan int { 17 r := make(chan int) 18 go func() { 19 defer close(r) 20 for i := 1; i < 4; i++ { 21 r <- i 22 } 23 }() 24 streamInvocationQueue <- "SimpleStream()" 25 return r 26 } 27 28 func (s *streamHub) EndlessStream() <-chan int { 29 r := make(chan int) 30 go func() { 31 defer close(r) 32 for i := 1; ; i++ { 33 r <- i 34 } 35 }() 36 streamInvocationQueue <- "EndlessStream()" 37 return r 38 } 39 40 func (s *streamHub) SliceStream() <-chan []int { 41 r := make(chan []int) 42 go func() { 43 defer close(r) 44 for i := 1; i < 4; i++ { 45 s := make([]int, 2) 46 s[0] = i 47 s[1] = i * 2 48 r <- s 49 } 50 }() 51 streamInvocationQueue <- "SliceStream()" 52 return r 53 } 54 55 func (s *streamHub) SimpleInt() int { 56 streamInvocationQueue <- "SimpleInt()" 57 return -1 58 } 59 60 var _ = Describe("StreamInvocation", func() { 61 62 Describe("Simple stream invocation", func() { 63 var server Server 64 var conn *testingConnection 65 BeforeEach(func(done Done) { 66 server, conn = connect(&streamHub{}) 67 close(done) 68 }) 69 AfterEach(func(done Done) { 70 server.cancel() 71 close(done) 72 }) 73 Context("When invoked by the client", func() { 74 It("should be invoked on the server, return stream items and a final completion without result", func(done Done) { 75 p := &jsonHubProtocol{dbg: testLogger()} 76 conn.ClientSend(`{"type":4,"invocationId": "zzz","target":"simplestream"}`) 77 Expect(<-streamInvocationQueue).To(Equal("SimpleStream()")) 78 for i := 1; i < 4; i++ { 79 recv := (<-conn.received).(streamItemMessage) 80 Expect(recv).NotTo(BeNil()) 81 Expect(recv.InvocationID).To(Equal("zzz")) 82 var f float64 83 Expect(p.UnmarshalArgument(recv.Item, &f)).NotTo(HaveOccurred()) 84 Expect(f).To(Equal(float64(i))) 85 } 86 recv := (<-conn.received).(completionMessage) 87 Expect(recv).NotTo(BeNil()) 88 Expect(recv.InvocationID).To(Equal("zzz")) 89 Expect(recv.Result).To(BeNil()) 90 Expect(recv.Error).To(Equal("")) 91 close(done) 92 }) 93 }) 94 }) 95 96 Describe("Slice stream invocation", func() { 97 var server Server 98 var conn *testingConnection 99 BeforeEach(func(done Done) { 100 server, conn = connect(&streamHub{}) 101 close(done) 102 }) 103 AfterEach(func(done Done) { 104 server.cancel() 105 close(done) 106 }) 107 Context("When invoked by the client", func() { 108 It("should be invoked on the server, return stream items and a final completion without result", func(done Done) { 109 protocol := jsonHubProtocol{dbg: testLogger()} 110 conn.ClientSend(`{"type":4,"invocationId": "slice","target":"slicestream"}`) 111 Expect(<-streamInvocationQueue).To(Equal("SliceStream()")) 112 for i := 1; i < 4; i++ { 113 recv := (<-conn.received).(streamItemMessage) 114 Expect(recv).NotTo(BeNil()) 115 Expect(recv.InvocationID).To(Equal("slice")) 116 exp := make([]int, 0, 2) 117 exp = append(exp, i) 118 exp = append(exp, i*2) 119 var got []int 120 Expect(protocol.UnmarshalArgument(recv.Item, &got)).NotTo(HaveOccurred()) 121 Expect(got).To(Equal(exp)) 122 } 123 recv := (<-conn.received).(completionMessage) 124 Expect(recv).NotTo(BeNil()) 125 Expect(recv.InvocationID).To(Equal("slice")) 126 Expect(recv.Result).To(BeNil()) 127 Expect(recv.Error).To(Equal("")) 128 close(done) 129 }) 130 }) 131 }) 132 133 Describe("Stop simple stream invocation", func() { 134 var server Server 135 var conn *testingConnection 136 BeforeEach(func(done Done) { 137 server, conn = connect(&streamHub{}) 138 close(done) 139 }) 140 AfterEach(func(done Done) { 141 server.cancel() 142 close(done) 143 }) 144 Context("When invoked by the client and stop after one result", func() { 145 It("should be invoked on the server, return stream one item and a final completion without result", func(done Done) { 146 protocol := jsonHubProtocol{dbg: testLogger()} 147 conn.ClientSend(`{"type":4,"invocationId": "xxx","target":"endlessstream"}`) 148 Expect(<-streamInvocationQueue).To(Equal("EndlessStream()")) 149 recv := (<-conn.received).(streamItemMessage) 150 Expect(recv).NotTo(BeNil()) 151 Expect(recv.InvocationID).To(Equal("xxx")) 152 var got int 153 Expect(protocol.UnmarshalArgument(recv.Item, &got)).NotTo(HaveOccurred()) 154 Expect(got).To(Equal(1)) 155 // stop it 156 conn.ClientSend(`{"type":5,"invocationId": "xxx"}`) 157 loop: 158 for { 159 recv := <-conn.received 160 Expect(recv).NotTo(BeNil()) 161 switch recv := recv.(type) { 162 case streamItemMessage: 163 Expect(recv.InvocationID).To(Equal("xxx")) 164 case completionMessage: 165 Expect(recv.InvocationID).To(Equal("xxx")) 166 Expect(recv.Result).To(BeNil()) 167 Expect(recv.Error).To(Equal("")) 168 break loop 169 } 170 } 171 close(done) 172 }) 173 }) 174 }) 175 176 Describe("Invalid CancelInvocation", func() { 177 var server Server 178 var conn *testingConnection 179 BeforeEach(func(done Done) { 180 server, conn = connect(&streamHub{}) 181 close(done) 182 }) 183 AfterEach(func(done Done) { 184 server.cancel() 185 close(done) 186 }) 187 Context("When invoked by the client and receiving an invalid CancelInvocation", func() { 188 It("should close the connection with an error", func(done Done) { 189 protocol := &jsonHubProtocol{dbg: testLogger()} 190 conn.ClientSend(`{"type":4,"invocationId": "xyz","target":"endlessstream"}`) 191 Expect(<-streamInvocationQueue).To(Equal("EndlessStream()")) 192 recv := (<-conn.received).(streamItemMessage) 193 Expect(recv).NotTo(BeNil()) 194 Expect(recv.InvocationID).To(Equal("xyz")) 195 var got int 196 Expect(protocol.UnmarshalArgument(recv.Item, &got)).NotTo(HaveOccurred()) 197 Expect(got).To(Equal(1)) 198 // try to stop it, but do not get it right 199 conn.ClientSend(`{"type":5,"invocationId":1}`) 200 loop: 201 for { 202 message := <-conn.received 203 switch message := message.(type) { 204 case closeMessage: 205 Expect(message.Error).NotTo(BeNil()) 206 break loop 207 default: 208 } 209 } 210 close(done) 211 }) 212 }) 213 }) 214 215 Describe("Stream invocation of method with no stream result", func() { 216 var server Server 217 var conn *testingConnection 218 BeforeEach(func(done Done) { 219 server, conn = connect(&streamHub{}) 220 close(done) 221 }) 222 AfterEach(func(done Done) { 223 server.cancel() 224 close(done) 225 }) 226 Context("When invoked by the client", func() { 227 It("should be invoked on the server, return one stream item with the \"no stream\" result and a final completion without result", func(done Done) { 228 protocol := &jsonHubProtocol{dbg: testLogger()} 229 conn.ClientSend(`{"type":4,"invocationId": "yyy","target":"simpleint"}`) 230 Expect(<-streamInvocationQueue).To(Equal("SimpleInt()")) 231 sRecv := (<-conn.received).(streamItemMessage) 232 Expect(sRecv).NotTo(BeNil()) 233 Expect(sRecv.InvocationID).To(Equal("yyy")) 234 var got int 235 Expect(protocol.UnmarshalArgument(sRecv.Item, &got)).NotTo(HaveOccurred()) 236 Expect(got).To(Equal(-1)) 237 cRecv := (<-conn.received).(completionMessage) 238 Expect(cRecv).NotTo(BeNil()) 239 Expect(cRecv.InvocationID).To(Equal("yyy")) 240 Expect(cRecv.Result).To(BeNil()) 241 Expect(cRecv.Error).To(Equal("")) 242 close(done) 243 }) 244 }) 245 }) 246 247 Describe("invalid messages", func() { 248 var server Server 249 var conn *testingConnection 250 BeforeEach(func(done Done) { 251 server, conn = connect(&streamHub{}) 252 close(done) 253 }) 254 AfterEach(func(done Done) { 255 server.cancel() 256 close(done) 257 }) 258 Context("When an invalid stream invocation message is sent", func() { 259 It("should return a completion with error", func(done Done) { 260 conn.ClientSend(`{"type":4}`) 261 select { 262 case message := <-conn.received: 263 completionMessage := message.(completionMessage) 264 Expect(completionMessage).NotTo(BeNil()) 265 Expect(completionMessage.Error).NotTo(BeNil()) 266 case <-time.After(100 * time.Millisecond): 267 } 268 close(done) 269 }) 270 }) 271 }) 272 273 })