github.com/s7techlab/cckit@v0.10.5/gateway/chaincode_service_test.go (about) 1 package gateway_test 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/gogo/protobuf/proto" 8 "github.com/golang/protobuf/jsonpb" 9 "github.com/golang/protobuf/ptypes/empty" 10 . "github.com/onsi/ginkgo" 11 . "github.com/onsi/gomega" 12 13 "github.com/s7techlab/cckit/convert" 14 cpservice "github.com/s7techlab/cckit/examples/cpaper_asservice" 15 "github.com/s7techlab/cckit/examples/cpaper_asservice/testdata" 16 "github.com/s7techlab/cckit/extensions/encryption" 17 enctest "github.com/s7techlab/cckit/extensions/encryption/testing" 18 "github.com/s7techlab/cckit/gateway" 19 idtestdata "github.com/s7techlab/cckit/identity/testdata" 20 testcc "github.com/s7techlab/cckit/testing" 21 "github.com/s7techlab/cckit/testing/gomega" 22 ) 23 24 func TestService(t *testing.T) { 25 RegisterFailHandler(Fail) 26 RunSpecs(t, "Gateway suite") 27 } 28 29 const ( 30 Channel = `my_channel` 31 ChaincodeName = `commercial_paper` 32 ) 33 34 var ( 35 ctx = gateway.ContextWithSigner( 36 context.Background(), 37 idtestdata.Certificates[0].MustIdentity(idtestdata.DefaultMSP), 38 ) 39 ) 40 41 var _ = Describe(`Gateway`, func() { 42 43 Context(`Chaincode service without options`, func() { 44 45 var ( 46 ccService *gateway.ChaincodeService 47 ccInstanceService *gateway.ChaincodeInstanceService 48 cPaperGateway *cpservice.CPaperServiceGateway 49 mockStub *testcc.MockStub 50 ) 51 52 It("Init", func() { 53 ccImpl, err := cpservice.NewCC() 54 Expect(err).NotTo(HaveOccurred()) 55 56 mockStub = testcc.NewMockStub(ChaincodeName, ccImpl) 57 peer := testcc.NewPeer().WithChannel(Channel, mockStub) 58 59 ccService = gateway.NewChaincodeService(peer) 60 ccInstanceService = ccService.InstanceService( 61 &gateway.ChaincodeLocator{Channel: Channel, Chaincode: ChaincodeName}, 62 gateway.WithEventResolver(cpservice.EventMappings)) 63 64 // "sdk" for deal with cpaper chaincode 65 cPaperGateway = cpservice.NewCPaperServiceGateway(peer, Channel, ChaincodeName) 66 }) 67 68 Context(`Direct calls`, func() { 69 70 It("Require to provide chaincode locator", func() { 71 _, err := ccService.Query(ctx, &gateway.ChaincodeQueryRequest{ 72 Input: &gateway.ChaincodeInput{ 73 Args: [][]byte{[]byte(`List`), {}}, 74 }, 75 }) 76 77 Expect(err).To(HaveOccurred()) 78 Expect(err.Error()).To(ContainSubstring(`invalid field Locator: message must exist`)) 79 }) 80 }) 81 82 Context(`Chaincode gateway`, func() { 83 84 It("Allow to get empty commercial paper list", func() { 85 pp, err := cPaperGateway.List(ctx, &empty.Empty{}) 86 Expect(err).NotTo(HaveOccurred()) 87 Expect(pp.Items).To(HaveLen(0)) 88 }) 89 90 It("Invoke chaincode with 'tx waiter' in context", func() { 91 ctx = gateway.ContextWithTxWaiter(ctx, "all") 92 _, err := cPaperGateway.Issue(ctx, testdata.Issue1) 93 Expect(err).NotTo(HaveOccurred()) 94 }) 95 96 It("Invoke chaincode with custom identity in context", func() { 97 signer := idtestdata.Certificates[1].MustIdentity(idtestdata.DefaultMSP) 98 ctx = gateway.ContextWithDefaultSigner(ctx, signer) 99 100 _, err := cPaperGateway.Delete(ctx, testdata.Id1) 101 Expect(err).NotTo(HaveOccurred()) 102 }) 103 }) 104 105 Context(`Events`, func() { 106 107 It(`allow to get events as LIST (by default from block 0 to current channel height) `, func(done Done) { 108 events, err := ccInstanceService.Events(ctx, &gateway.ChaincodeInstanceEventsRequest{}) 109 110 Expect(err).NotTo(HaveOccurred()) 111 Expect(events.Items).To(HaveLen(1)) // 1 event on issue 112 113 e := events.Items[0] 114 var ( 115 eventObj interface{} 116 eventJson string 117 ) 118 eventObj, err = convert.FromBytes(e.Event.Payload, &cpservice.IssueCommercialPaper{}) 119 Expect(err).NotTo(HaveOccurred()) 120 121 eventJson, err = (&jsonpb.Marshaler{EmitDefaults: true, OrigName: true}). 122 MarshalToString(eventObj.(proto.Message)) 123 Expect(err).NotTo(HaveOccurred()) 124 Expect(e.Event.EventName).To(Equal(`IssueCommercialPaper`)) 125 Expect(e.Payload).NotTo(BeNil()) 126 Expect(e.Payload.Value).To(Equal([]byte(eventJson))) // check event resolving 127 close(done) 128 }) 129 130 It(`allow to get 0 events as LIST from chaincode with incorrect event name filter`, func(done Done) { 131 events, err := ccInstanceService.Events(ctx, &gateway.ChaincodeInstanceEventsRequest{ 132 EventName: []string{`________IssueCommercialPaper______`}, 133 }) 134 135 Expect(err).NotTo(HaveOccurred()) 136 Expect(events.Items).To(HaveLen(0)) // 1 event on issue 137 138 close(done) 139 }) 140 141 It(`allow to get events from block 0 to current channel height AS STREAM`, func(done Done) { 142 ctxWithCancel, cancel := context.WithCancel(ctx) 143 stream := gateway.NewChaincodeEventServerStream(ctxWithCancel) 144 145 go func() { 146 req := &gateway.ChaincodeEventsStreamRequest{ 147 Locator: &gateway.ChaincodeLocator{ 148 Channel: Channel, 149 Chaincode: ChaincodeName, 150 }, 151 FromBlock: &gateway.BlockLimit{Num: 0}, 152 ToBlock: &gateway.BlockLimit{Num: 0}, 153 } 154 155 err := ccService.EventsStream(req, &gateway.ChaincodeEventsServer{ServerStream: stream}) 156 157 Expect(err).NotTo(HaveOccurred()) 158 }() 159 160 var e *gateway.ChaincodeEvent 161 err := stream.Recv(e) 162 Expect(err).NotTo(HaveOccurred()) 163 cancel() 164 close(done) 165 }, 1) 166 }) 167 168 }) 169 170 Context(`Chaincode service with encrypted chaincode`, func() { 171 172 var ( 173 ccService *gateway.ChaincodeService 174 ccInstance *gateway.ChaincodeInstanceService 175 176 cPaperGateway *cpservice.CPaperServiceGateway 177 cPaperGatewayWithoutEncryption *cpservice.CPaperServiceGateway 178 179 encMockStub *enctest.MockStub 180 181 encryptOpts []gateway.Opt 182 ) 183 184 It("Init", func() { 185 ccImpl, err := cpservice.NewCCEncrypted() 186 Expect(err).NotTo(HaveOccurred()) 187 188 encMockStub = enctest.NewMockStub(testcc.NewMockStub(ChaincodeName, ccImpl)) 189 190 encryptOpts = []gateway.Opt{ 191 gateway.WithEncryption(encMockStub.EncKey), 192 // Event resolver should be AFTER encryption / decryption middleware 193 gateway.WithEventResolver(cpservice.EventMappings), 194 } 195 196 // "sdk" for deal with cpaper chaincode 197 peer := testcc.NewPeer().WithChannel(Channel, encMockStub.MockStub) 198 ccService = gateway.NewChaincodeService(peer) 199 200 locator := &gateway.ChaincodeLocator{ 201 Channel: Channel, 202 Chaincode: ChaincodeName, 203 } 204 205 ccInstance = ccService.InstanceService(locator, encryptOpts...) 206 207 cPaperGateway = cpservice.NewCPaperServiceGateway(peer, Channel, ChaincodeName, encryptOpts...) 208 cPaperGatewayWithoutEncryption = cpservice.NewCPaperServiceGateway( 209 peer, Channel, ChaincodeName, 210 gateway.WithEventResolver(cpservice.EventMappings)) 211 }) 212 213 Context(`Chaincode gateway`, func() { 214 215 It("Disallow to query chaincode without encryption data", func() { 216 _, err := cPaperGatewayWithoutEncryption.List(ctx, &empty.Empty{}) 217 Expect(err).To(gomega.ErrorIs(encryption.ErrKeyNotDefinedInTransientMap)) 218 219 }) 220 221 It("Allow to get empty commercial paper list", func() { 222 pp, err := cPaperGateway.List(ctx, &empty.Empty{}) 223 Expect(err).NotTo(HaveOccurred()) 224 Expect(pp.Items).To(HaveLen(0)) 225 }) 226 227 It("Invoke chaincode", func() { 228 issued, err := cPaperGateway.Issue(ctx, testdata.Issue1) 229 Expect(err).NotTo(HaveOccurred()) 230 Expect(issued.Issuer).To(Equal(testdata.Issue1.Issuer)) 231 }) 232 233 It("Query chaincode", func() { 234 issued, err := cPaperGateway.Get(ctx, testdata.Id1) 235 Expect(err).NotTo(HaveOccurred()) 236 Expect(issued.Issuer).To(Equal(testdata.Issue1.Issuer)) 237 }) 238 239 }) 240 241 Context(`Events`, func() { 242 243 It(`allow to get encrypted events as LIST (by default from block 0 to current channel height) `, func(done Done) { 244 events, err := ccInstance.Events(ctx, &gateway.ChaincodeInstanceEventsRequest{}) 245 246 Expect(err).NotTo(HaveOccurred()) 247 Expect(events.Items).To(HaveLen(1)) // 1 event on issue 248 249 e := events.Items[0] 250 var ( 251 eventObj interface{} 252 eventJson string 253 ) 254 eventObj, err = convert.FromBytes(e.Event.Payload, &cpservice.IssueCommercialPaper{}) 255 Expect(err).NotTo(HaveOccurred()) 256 257 eventJson, err = (&jsonpb.Marshaler{EmitDefaults: true, OrigName: true}). 258 MarshalToString(eventObj.(proto.Message)) 259 Expect(err).NotTo(HaveOccurred()) 260 Expect(e.Event.EventName).To(Equal(`IssueCommercialPaper`)) 261 262 Expect(e.Payload.Value).To(Equal([]byte(eventJson))) // check event resolving 263 close(done) 264 }) 265 266 It(`allow to get encrypted events from block 0 to current channel height AS STREAM`, func(done Done) { 267 ctxWithCancel, cancel := context.WithCancel(ctx) 268 stream := gateway.NewChaincodeEventServerStream(ctxWithCancel) 269 270 go func() { 271 req := &gateway.ChaincodeInstanceEventsStreamRequest{ 272 FromBlock: &gateway.BlockLimit{Num: 0}, 273 ToBlock: &gateway.BlockLimit{Num: 0}, 274 } 275 276 err := ccInstance.EventsStream(req, &gateway.ChaincodeEventsServer{ServerStream: stream}) 277 278 Expect(err).NotTo(HaveOccurred()) 279 }() 280 281 var e *gateway.ChaincodeEvent 282 err := stream.Recv(e) 283 Expect(err).NotTo(HaveOccurred()) 284 cancel() 285 close(done) 286 }, 1) 287 288 }) 289 290 }) 291 Context(`Chaincode instance service`, func() { 292 293 var ( 294 ccInstanceService *gateway.ChaincodeInstanceService 295 ) 296 297 It("Init", func() { 298 ccImpl, err := cpservice.NewCC() 299 Expect(err).NotTo(HaveOccurred()) 300 301 // peer imitation 302 peer := testcc.NewPeer().WithChannel(Channel, testcc.NewMockStub(ChaincodeName, ccImpl)) 303 ccInstanceService = gateway.NewChaincodeInstanceService(peer, &gateway.ChaincodeLocator{ 304 Channel: Channel, 305 Chaincode: ChaincodeName, 306 }) 307 }) 308 309 Context(`Direct calls`, func() { 310 311 It("Allow to get empty commercial paper list", func() { 312 resp, err := ccInstanceService.Query(ctx, &gateway.ChaincodeInstanceQueryRequest{ 313 Input: &gateway.ChaincodeInput{ 314 Args: [][]byte{[]byte(`List`), {}}, 315 }, 316 }) 317 318 Expect(err).NotTo(HaveOccurred()) 319 cPaperList := testcc.MustProtoUnmarshal(resp.Payload, &cpservice.CommercialPaperList{}).(*cpservice.CommercialPaperList) 320 Expect(cPaperList.Items).To(HaveLen(0)) 321 }) 322 323 It("Invoke chaincode", func() { 324 325 _, err := ccInstanceService.Invoke(ctx, &gateway.ChaincodeInstanceInvokeRequest{ 326 Input: &gateway.ChaincodeInput{ 327 Args: [][]byte{[]byte(`Issue`), testcc.MustProtoMarshal(testdata.Issue1)}, 328 }}) 329 Expect(err).NotTo(HaveOccurred()) 330 }) 331 332 }) 333 334 Context(`Events delivery`, func() { 335 336 //It(`allow to get events as LIST from chaincode instance service (by default from block 0 to current channel height) `, func(done Done) { 337 // events, err := ccInstanceService.Events(ctx, &gateway.ChaincodeInstanceEventsRequest{ 338 // EventName: []string{`IssueCommercialPaper`}, 339 // }) 340 // 341 // Expect(err).NotTo(HaveOccurred()) 342 // Expect(events.Items).To(HaveLen(1)) // 1 event on issue 343 // 344 // close(done) 345 //}) 346 347 It(`allow to get events as chan from chaincode instance service (by default from block 0 to current channel height) `, func(done Done) { 348 events, closer, err := ccInstanceService.EventsChan(ctx, &gateway.ChaincodeInstanceEventsStreamRequest{ 349 EventName: []string{`IssueCommercialPaper`}, 350 FromBlock: &gateway.BlockLimit{Num: 0}, 351 }) 352 353 Expect(err).NotTo(HaveOccurred()) 354 355 event := <-events 356 Expect(event.Event.EventName).To(Equal(`IssueCommercialPaper`)) 357 358 _ = closer() 359 close(done) 360 }) 361 }) 362 }) 363 364 })