github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/core/chaincode/shim/shim_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package shim 18 19 import ( 20 "bytes" 21 "os" 22 "strconv" 23 "strings" 24 "testing" 25 "time" 26 27 mockpeer "github.com/hyperledger/fabric/common/mocks/peer" 28 "github.com/hyperledger/fabric/common/util" 29 lproto "github.com/hyperledger/fabric/protos/ledger/queryresult" 30 pb "github.com/hyperledger/fabric/protos/peer" 31 "github.com/hyperledger/fabric/protos/utils" 32 33 "github.com/hyperledger/fabric/common/flogging" 34 "github.com/op/go-logging" 35 "github.com/spf13/viper" 36 "github.com/stretchr/testify/assert" 37 ) 38 39 // shimTestCC example simple Chaincode implementation 40 type shimTestCC struct { 41 } 42 43 func (t *shimTestCC) Init(stub ChaincodeStubInterface) pb.Response { 44 _, args := stub.GetFunctionAndParameters() 45 var A, B string // Entities 46 var Aval, Bval int // Asset holdings 47 var err error 48 49 if len(args) != 4 { 50 return Error("Incorrect number of arguments. Expecting 4") 51 } 52 53 // Initialize the chaincode 54 A = args[0] 55 Aval, err = strconv.Atoi(args[1]) 56 if err != nil { 57 return Error("Expecting integer value for asset holding") 58 } 59 B = args[2] 60 Bval, err = strconv.Atoi(args[3]) 61 if err != nil { 62 return Error("Expecting integer value for asset holding") 63 } 64 65 // Write the state to the ledger 66 err = stub.PutState(A, []byte(strconv.Itoa(Aval))) 67 if err != nil { 68 return Error(err.Error()) 69 } 70 71 err = stub.PutState(B, []byte(strconv.Itoa(Bval))) 72 if err != nil { 73 return Error(err.Error()) 74 } 75 76 return Success(nil) 77 } 78 79 func (t *shimTestCC) Invoke(stub ChaincodeStubInterface) pb.Response { 80 function, args := stub.GetFunctionAndParameters() 81 if function == "invoke" { 82 // Make payment of X units from A to B 83 return t.invoke(stub, args) 84 } else if function == "delete" { 85 // Deletes an entity from its state 86 return t.delete(stub, args) 87 } else if function == "query" { 88 // the old "Query" is now implemtned in invoke 89 return t.query(stub, args) 90 } else if function == "cc2cc" { 91 return t.cc2cc(stub, args) 92 } else if function == "rangeq" { 93 return t.rangeq(stub, args) 94 } else if function == "historyq" { 95 return t.historyq(stub, args) 96 } else if function == "richq" { 97 return t.richq(stub, args) 98 } 99 100 return Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"") 101 } 102 103 // Transaction makes payment of X units from A to B 104 func (t *shimTestCC) invoke(stub ChaincodeStubInterface, args []string) pb.Response { 105 var A, B string // Entities 106 var Aval, Bval int // Asset holdings 107 var X int // Transaction value 108 var err error 109 110 if len(args) != 3 { 111 return Error("Incorrect number of arguments. Expecting 3") 112 } 113 114 A = args[0] 115 B = args[1] 116 117 // Get the state from the ledger 118 // TODO: will be nice to have a GetAllState call to ledger 119 Avalbytes, err := stub.GetState(A) 120 if err != nil { 121 return Error("Failed to get state") 122 } 123 if Avalbytes == nil { 124 return Error("Entity not found") 125 } 126 Aval, _ = strconv.Atoi(string(Avalbytes)) 127 128 Bvalbytes, err := stub.GetState(B) 129 if err != nil { 130 return Error("Failed to get state") 131 } 132 if Bvalbytes == nil { 133 return Error("Entity not found") 134 } 135 Bval, _ = strconv.Atoi(string(Bvalbytes)) 136 137 // Perform the execution 138 X, err = strconv.Atoi(args[2]) 139 if err != nil { 140 return Error("Invalid transaction amount, expecting a integer value") 141 } 142 Aval = Aval - X 143 Bval = Bval + X 144 145 // Write the state back to the ledger 146 err = stub.PutState(A, []byte(strconv.Itoa(Aval))) 147 if err != nil { 148 return Error(err.Error()) 149 } 150 151 err = stub.PutState(B, []byte(strconv.Itoa(Bval))) 152 if err != nil { 153 return Error(err.Error()) 154 } 155 156 return Success(nil) 157 } 158 159 // Deletes an entity from state 160 func (t *shimTestCC) delete(stub ChaincodeStubInterface, args []string) pb.Response { 161 if len(args) != 1 { 162 return Error("Incorrect number of arguments. Expecting 1") 163 } 164 165 A := args[0] 166 167 // Delete the key from the state in ledger 168 err := stub.DelState(A) 169 if err != nil { 170 return Error("Failed to delete state") 171 } 172 173 return Success(nil) 174 } 175 176 // query callback representing the query of a chaincode 177 func (t *shimTestCC) query(stub ChaincodeStubInterface, args []string) pb.Response { 178 var A string // Entities 179 var err error 180 181 if len(args) != 1 { 182 return Error("Incorrect number of arguments. Expecting name of the person to query") 183 } 184 185 A = args[0] 186 187 // Get the state from the ledger 188 Avalbytes, err := stub.GetState(A) 189 if err != nil { 190 jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}" 191 return Error(jsonResp) 192 } 193 194 if Avalbytes == nil { 195 jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}" 196 return Error(jsonResp) 197 } 198 199 return Success(Avalbytes) 200 } 201 202 // ccc2cc call 203 func (t *shimTestCC) cc2cc(stub ChaincodeStubInterface, args []string) pb.Response { 204 if len(args) < 1 { 205 return Error("Invalid number of args for cc2cc. expecting at least 1") 206 } 207 return stub.InvokeChaincode(args[0], util.ToChaincodeArgs(args...), "") 208 } 209 210 // rangeq calls range query 211 func (t *shimTestCC) rangeq(stub ChaincodeStubInterface, args []string) pb.Response { 212 if len(args) != 2 { 213 return Error("Incorrect number of arguments. Expecting keys for range query") 214 } 215 216 A := args[0] 217 B := args[0] 218 219 // Get the state from the ledger 220 resultsIterator, err := stub.GetStateByRange(A, B) 221 if err != nil { 222 return Error(err.Error()) 223 } 224 defer resultsIterator.Close() 225 226 // buffer is a JSON array containing QueryResults 227 var buffer bytes.Buffer 228 buffer.WriteString("[") 229 230 bArrayMemberAlreadyWritten := false 231 for resultsIterator.HasNext() { 232 queryResponse, err := resultsIterator.Next() 233 if err != nil { 234 return Error(err.Error()) 235 } 236 // Add a comma before array members, suppress it for the first array member 237 if bArrayMemberAlreadyWritten == true { 238 buffer.WriteString(",") 239 } 240 buffer.WriteString("{\"Key\":") 241 buffer.WriteString("\"") 242 buffer.WriteString(queryResponse.Key) 243 buffer.WriteString("\"") 244 245 buffer.WriteString(", \"Record\":") 246 // Record is a JSON object, so we write as-is 247 buffer.WriteString(string(queryResponse.Value)) 248 buffer.WriteString("}") 249 bArrayMemberAlreadyWritten = true 250 } 251 buffer.WriteString("]") 252 253 return Success(buffer.Bytes()) 254 } 255 256 // richq calls tichq query 257 func (t *shimTestCC) richq(stub ChaincodeStubInterface, args []string) pb.Response { 258 if len(args) != 1 { 259 return Error("Incorrect number of arguments. Expecting keys for range query") 260 } 261 262 query := args[0] 263 264 // Get the state from the ledger 265 resultsIterator, err := stub.GetQueryResult(query) 266 if err != nil { 267 return Error(err.Error()) 268 } 269 defer resultsIterator.Close() 270 271 // buffer is a JSON array containing QueryResults 272 var buffer bytes.Buffer 273 buffer.WriteString("[") 274 275 bArrayMemberAlreadyWritten := false 276 for resultsIterator.HasNext() { 277 queryResponse, err := resultsIterator.Next() 278 if err != nil { 279 return Error(err.Error()) 280 } 281 // Add a comma before array members, suppress it for the first array member 282 if bArrayMemberAlreadyWritten == true { 283 buffer.WriteString(",") 284 } 285 buffer.WriteString("{\"Key\":") 286 buffer.WriteString("\"") 287 buffer.WriteString(queryResponse.Key) 288 buffer.WriteString("\"") 289 290 buffer.WriteString(", \"Record\":") 291 // Record is a JSON object, so we write as-is 292 buffer.WriteString(string(queryResponse.Value)) 293 buffer.WriteString("}") 294 bArrayMemberAlreadyWritten = true 295 } 296 buffer.WriteString("]") 297 298 return Success(buffer.Bytes()) 299 } 300 301 // rangeq calls range query 302 func (t *shimTestCC) historyq(stub ChaincodeStubInterface, args []string) pb.Response { 303 if len(args) < 1 { 304 return Error("Incorrect number of arguments. Expecting 1") 305 } 306 307 key := args[0] 308 309 resultsIterator, err := stub.GetHistoryForKey(key) 310 if err != nil { 311 return Error(err.Error()) 312 } 313 defer resultsIterator.Close() 314 315 var buffer bytes.Buffer 316 buffer.WriteString("[") 317 318 bArrayMemberAlreadyWritten := false 319 for resultsIterator.HasNext() { 320 response, err := resultsIterator.Next() 321 if err != nil { 322 return Error(err.Error()) 323 } 324 // Add a comma before array members, suppress it for the first array member 325 if bArrayMemberAlreadyWritten == true { 326 buffer.WriteString(",") 327 } 328 buffer.WriteString("{\"TxId\":") 329 buffer.WriteString("\"") 330 buffer.WriteString(response.TxId) 331 buffer.WriteString("\"") 332 333 buffer.WriteString(", \"Value\":") 334 if response.IsDelete { 335 buffer.WriteString("null") 336 } else { 337 buffer.WriteString(string(response.Value)) 338 } 339 340 buffer.WriteString(", \"IsDelete\":") 341 buffer.WriteString("\"") 342 buffer.WriteString(strconv.FormatBool(response.IsDelete)) 343 buffer.WriteString("\"") 344 345 buffer.WriteString("}") 346 bArrayMemberAlreadyWritten = true 347 } 348 buffer.WriteString("]") 349 350 return Success(buffer.Bytes()) 351 } 352 353 // Test Go shim functionality that can be tested outside of a real chaincode 354 // context. 355 356 // TestShimLogging simply tests that the APIs are working. These tests test 357 // for correct control over the shim's logging object and the LogLevel 358 // function. 359 func TestShimLogging(t *testing.T) { 360 SetLoggingLevel(LogCritical) 361 if shimLoggingLevel != LogCritical { 362 t.Errorf("shimLoggingLevel is not LogCritical as expected") 363 } 364 if chaincodeLogger.IsEnabledFor(logging.DEBUG) { 365 t.Errorf("The chaincodeLogger should not be enabled for DEBUG") 366 } 367 if !chaincodeLogger.IsEnabledFor(logging.CRITICAL) { 368 t.Errorf("The chaincodeLogger should be enabled for CRITICAL") 369 } 370 var level LoggingLevel 371 var err error 372 level, err = LogLevel("debug") 373 if err != nil { 374 t.Errorf("LogLevel(debug) failed") 375 } 376 if level != LogDebug { 377 t.Errorf("LogLevel(debug) did not return LogDebug") 378 } 379 level, err = LogLevel("INFO") 380 if err != nil { 381 t.Errorf("LogLevel(INFO) failed") 382 } 383 if level != LogInfo { 384 t.Errorf("LogLevel(INFO) did not return LogInfo") 385 } 386 level, err = LogLevel("Notice") 387 if err != nil { 388 t.Errorf("LogLevel(Notice) failed") 389 } 390 if level != LogNotice { 391 t.Errorf("LogLevel(Notice) did not return LogNotice") 392 } 393 level, err = LogLevel("WaRnInG") 394 if err != nil { 395 t.Errorf("LogLevel(WaRnInG) failed") 396 } 397 if level != LogWarning { 398 t.Errorf("LogLevel(WaRnInG) did not return LogWarning") 399 } 400 level, err = LogLevel("ERRor") 401 if err != nil { 402 t.Errorf("LogLevel(ERRor) failed") 403 } 404 if level != LogError { 405 t.Errorf("LogLevel(ERRor) did not return LogError") 406 } 407 level, err = LogLevel("critiCAL") 408 if err != nil { 409 t.Errorf("LogLevel(critiCAL) failed") 410 } 411 if level != LogCritical { 412 t.Errorf("LogLevel(critiCAL) did not return LogCritical") 413 } 414 level, err = LogLevel("foo") 415 if err == nil { 416 t.Errorf("LogLevel(foo) did not fail") 417 } 418 if level != LogError { 419 t.Errorf("LogLevel(foo) did not return LogError") 420 } 421 } 422 423 // TestChaincodeLogging tests the logging APIs for chaincodes. 424 func TestChaincodeLogging(t *testing.T) { 425 426 // From start() - We can't call start() from this test 427 format := logging.MustStringFormatter("%{time:15:04:05.000} [%{module}] %{level:.4s} : %{message}") 428 backend := logging.NewLogBackend(os.Stderr, "", 0) 429 backendFormatter := logging.NewBackendFormatter(backend, format) 430 logging.SetBackend(backendFormatter).SetLevel(logging.Level(shimLoggingLevel), "shim") 431 432 foo := NewLogger("foo") 433 bar := NewLogger("bar") 434 435 foo.Debugf("Foo is debugging: %d", 10) 436 bar.Infof("Bar is informational? %s.", "Yes") 437 foo.Noticef("NOTE NOTE NOTE") 438 bar.Warningf("Danger, Danger %s %s", "Will", "Robinson!") 439 foo.Errorf("I'm sorry Dave, I'm afraid I can't do that.") 440 bar.Criticalf("PI is not equal to 3.14, we computed it as %.2f", 4.13) 441 442 bar.Debug("Foo is debugging:", 10) 443 foo.Info("Bar is informational?", "Yes.") 444 bar.Notice("NOTE NOTE NOTE") 445 foo.Warning("Danger, Danger", "Will", "Robinson!") 446 bar.Error("I'm sorry Dave, I'm afraid I can't do that.") 447 foo.Critical("PI is not equal to", 3.14, ", we computed it as", 4.13) 448 449 foo.SetLevel(LogWarning) 450 if foo.IsEnabledFor(LogDebug) { 451 t.Errorf("'foo' should not be enabled for LogDebug") 452 } 453 if !foo.IsEnabledFor(LogCritical) { 454 t.Errorf("'foo' should be enabled for LogCritical") 455 } 456 bar.SetLevel(LogCritical) 457 if bar.IsEnabledFor(LogDebug) { 458 t.Errorf("'bar' should not be enabled for LogDebug") 459 } 460 if !bar.IsEnabledFor(LogCritical) { 461 t.Errorf("'bar' should be enabled for LogCritical") 462 } 463 } 464 465 func TestNilEventName(t *testing.T) { 466 stub := ChaincodeStub{} 467 if err := stub.SetEvent("", []byte("event payload")); err == nil { 468 t.Error("Event name can not be nil string.") 469 } 470 471 } 472 473 type testCase struct { 474 name string 475 ccLogLevel string 476 shimLogLevel string 477 } 478 479 func TestSetupChaincodeLogging_shim(t *testing.T) { 480 var tc []testCase 481 482 tc = append(tc, 483 testCase{"ValidLevels", "debug", "warning"}, 484 testCase{"EmptyLevels", "", ""}, 485 testCase{"BadShimLevel", "debug", "war"}, 486 testCase{"BadCCLevel", "deb", "notice"}, 487 testCase{"EmptyShimLevel", "error", ""}, 488 testCase{"EmptyCCLevel", "", "critical"}, 489 ) 490 491 assert := assert.New(t) 492 493 for i := 0; i < len(tc); i++ { 494 t.Run(tc[i].name, func(t *testing.T) { 495 viper.Set("chaincode.logging.level", tc[i].ccLogLevel) 496 viper.Set("chaincode.logging.shim", tc[i].shimLogLevel) 497 498 SetupChaincodeLogging() 499 500 _, ccErr := logging.LogLevel(tc[i].ccLogLevel) 501 _, shimErr := logging.LogLevel(tc[i].shimLogLevel) 502 if ccErr == nil { 503 assert.Equal(strings.ToUpper(tc[i].ccLogLevel), flogging.GetModuleLevel("ccLogger"), "Test case '%s' failed", tc[i].name) 504 if shimErr == nil { 505 assert.Equal(strings.ToUpper(tc[i].shimLogLevel), flogging.GetModuleLevel("shim"), "Test case '%s' failed", tc[i].name) 506 } else { 507 assert.Equal(strings.ToUpper(tc[i].ccLogLevel), flogging.GetModuleLevel("shim"), "Test case '%s' failed", tc[i].name) 508 } 509 } else { 510 assert.Equal(flogging.DefaultLevel(), flogging.GetModuleLevel("ccLogger"), "Test case '%s' failed", tc[i].name) 511 if shimErr == nil { 512 assert.Equal(strings.ToUpper(tc[i].shimLogLevel), flogging.GetModuleLevel("shim"), "Test case '%s' failed", tc[i].name) 513 } else { 514 assert.Equal(flogging.DefaultLevel(), flogging.GetModuleLevel("shim"), "Test case '%s' failed", tc[i].name) 515 } 516 } 517 }) 518 } 519 } 520 521 //store the stream CC mappings here 522 var mockPeerCCSupport = mockpeer.NewMockPeerSupport() 523 524 func mockChaincodeStreamGetter(name string) (PeerChaincodeStream, error) { 525 return mockPeerCCSupport.GetCC(name) 526 } 527 528 func setupcc(name string, cc Chaincode) *mockpeer.MockCCComm { 529 viper.Set("chaincode.id.name", name) 530 send := make(chan *pb.ChaincodeMessage) 531 recv := make(chan *pb.ChaincodeMessage) 532 ccSide, _ := mockPeerCCSupport.AddCC(name, recv, send) 533 ccSide.SetPong(true) 534 return mockPeerCCSupport.GetCCMirror(name) 535 } 536 537 //assign this to done and failNow and keep using them 538 func setuperror() chan error { 539 return make(chan error) 540 } 541 542 func processDone(t *testing.T, done chan error, expecterr bool) { 543 err := <-done 544 if expecterr != (err != nil) { 545 if err == nil { 546 t.Fatalf("Expected error but got success") 547 } else { 548 t.Fatalf("Expected success but got error %s", err) 549 } 550 } 551 } 552 553 //TestInvoke tests init and invoke along with many of the stub functions 554 //such as get/put/del/range... 555 func TestInvoke(t *testing.T) { 556 streamGetter = mockChaincodeStreamGetter 557 cc := &shimTestCC{} 558 //viper.Set("chaincode.logging.shim", "debug") 559 var err error 560 ccname := "shimTestCC" 561 peerSide := setupcc(ccname, cc) 562 defer mockPeerCCSupport.RemoveCC(ccname) 563 //start the shim+chaincode 564 go func() { 565 err = Start(cc) 566 }() 567 568 done := setuperror() 569 570 errorFunc := func(ind int, err error) { 571 done <- err 572 } 573 574 //start the mock peer 575 go func() { 576 respSet := &mockpeer.MockResponseSet{errorFunc, nil, []*mockpeer.MockResponse{ 577 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTER}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTERED}}}} 578 peerSide.SetResponses(respSet) 579 peerSide.SetKeepAlive(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_KEEPALIVE}) 580 err = peerSide.Run() 581 }() 582 583 //wait for init 584 processDone(t, done, false) 585 586 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: "1"}) 587 588 ci := &pb.ChaincodeInput{[][]byte{[]byte("init"), []byte("A"), []byte("100"), []byte("B"), []byte("200")}} 589 payload := utils.MarshalOrPanic(ci) 590 respSet := &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 591 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2"}}, 592 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2"}}, 593 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "2"}, nil}}} 594 peerSide.SetResponses(respSet) 595 596 //use the payload computed from prev init 597 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INIT, Payload: payload, Txid: "2"}) 598 599 //wait for done 600 processDone(t, done, false) 601 602 //good invoke 603 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 604 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: []byte("100"), Txid: "3"}}, 605 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: []byte("200"), Txid: "3"}}, 606 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "3"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "3"}}, 607 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "3"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "3"}}, 608 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "3"}, nil}}} 609 peerSide.SetResponses(respSet) 610 611 ci = &pb.ChaincodeInput{[][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}} 612 payload = utils.MarshalOrPanic(ci) 613 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "3"}) 614 615 //wait for done 616 processDone(t, done, false) 617 618 //bad put 619 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 620 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3a"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: []byte("100"), Txid: "3a"}}, 621 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3a"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: []byte("200"), Txid: "3a"}}, 622 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "3a"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "3a"}}, 623 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "3a"}, nil}}} 624 peerSide.SetResponses(respSet) 625 626 ci = &pb.ChaincodeInput{[][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}} 627 payload = utils.MarshalOrPanic(ci) 628 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "3a"}) 629 630 //wait for done 631 processDone(t, done, false) 632 633 //bad get 634 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 635 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE, Txid: "3b"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "3b"}}, 636 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "3b"}, nil}}} 637 peerSide.SetResponses(respSet) 638 639 ci = &pb.ChaincodeInput{[][]byte{[]byte("invoke"), []byte("A"), []byte("B"), []byte("10")}} 640 payload = utils.MarshalOrPanic(ci) 641 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "3b"}) 642 643 //wait for done 644 processDone(t, done, false) 645 646 //bad delete 647 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 648 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_DEL_STATE, Txid: "4"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "4"}}, 649 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "4"}, nil}}} 650 peerSide.SetResponses(respSet) 651 652 ci = &pb.ChaincodeInput{[][]byte{[]byte("delete"), []byte("A")}} 653 payload = utils.MarshalOrPanic(ci) 654 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "4"}) 655 656 //wait for done 657 processDone(t, done, false) 658 659 //good delete 660 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 661 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_DEL_STATE, Txid: "4a"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "4a"}}, 662 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "4a"}, nil}}} 663 peerSide.SetResponses(respSet) 664 665 ci = &pb.ChaincodeInput{[][]byte{[]byte("delete"), []byte("A")}} 666 payload = utils.MarshalOrPanic(ci) 667 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "4a"}) 668 669 //wait for done 670 processDone(t, done, false) 671 672 //bad invoke 673 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 674 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "5"}, nil}}} 675 peerSide.SetResponses(respSet) 676 677 ci = &pb.ChaincodeInput{[][]byte{[]byte("badinvoke")}} 678 payload = utils.MarshalOrPanic(ci) 679 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "5"}) 680 681 //wait for done 682 processDone(t, done, false) 683 684 //range query 685 686 //create the response 687 rangeQueryResponse := &pb.QueryResponse{Results: []*pb.QueryResultBytes{ 688 &pb.QueryResultBytes{ResultBytes: utils.MarshalOrPanic(&lproto.KV{"getputcc", "A", []byte("100")})}, 689 &pb.QueryResultBytes{ResultBytes: utils.MarshalOrPanic(&lproto.KV{"getputcc", "B", []byte("200")})}}, 690 HasMore: true} 691 rangeQPayload := utils.MarshalOrPanic(rangeQueryResponse) 692 693 //create the next response 694 rangeQueryNext := &pb.QueryResponse{Results: nil, HasMore: false} 695 696 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 697 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Txid: "6"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: rangeQPayload, Txid: "6"}}, 698 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "6"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: utils.MarshalOrPanic(rangeQueryNext), Txid: "6"}}, 699 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "6"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "6"}}, 700 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "6"}, nil}}} 701 peerSide.SetResponses(respSet) 702 703 ci = &pb.ChaincodeInput{[][]byte{[]byte("rangeq"), []byte("A"), []byte("B")}} 704 payload = utils.MarshalOrPanic(ci) 705 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "6"}) 706 707 //wait for done 708 processDone(t, done, false) 709 710 //error range query 711 712 //create the response 713 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 714 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Txid: "6a"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: "6a"}}, 715 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "6a"}, nil}}} 716 peerSide.SetResponses(respSet) 717 718 ci = &pb.ChaincodeInput{[][]byte{[]byte("rangeq"), []byte("A"), []byte("B")}} 719 payload = utils.MarshalOrPanic(ci) 720 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "6a"}) 721 722 //wait for done 723 processDone(t, done, false) 724 725 //error range query next 726 727 //create the response 728 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 729 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Txid: "6b"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: rangeQPayload, Txid: "6b"}}, 730 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "6b"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "6b"}}, 731 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "6b"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "6b"}}, 732 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "6b"}, nil}}} 733 peerSide.SetResponses(respSet) 734 735 ci = &pb.ChaincodeInput{[][]byte{[]byte("rangeq"), []byte("A"), []byte("B")}} 736 payload = utils.MarshalOrPanic(ci) 737 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "6b"}) 738 739 //wait for done 740 processDone(t, done, false) 741 742 //error range query close 743 744 //create the response 745 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 746 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_STATE_BY_RANGE, Txid: "6c"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: rangeQPayload, Txid: "6c"}}, 747 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "6c"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "6c"}}, 748 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "6c"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Txid: "6c"}}, 749 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "6c"}, nil}}} 750 peerSide.SetResponses(respSet) 751 752 ci = &pb.ChaincodeInput{[][]byte{[]byte("rangeq"), []byte("A"), []byte("B")}} 753 payload = utils.MarshalOrPanic(ci) 754 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "6c"}) 755 756 //wait for done 757 processDone(t, done, false) 758 759 //history query 760 761 //create the response 762 historyQueryResponse := &pb.QueryResponse{Results: []*pb.QueryResultBytes{ 763 &pb.QueryResultBytes{ResultBytes: utils.MarshalOrPanic(&lproto.KeyModification{TxId: "6", Value: []byte("100")})}}, 764 HasMore: true} 765 payload = utils.MarshalOrPanic(historyQueryResponse) 766 767 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 768 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_HISTORY_FOR_KEY, Txid: "7"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payload, Txid: "7"}}, 769 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "7"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: utils.MarshalOrPanic(rangeQueryNext), Txid: "7"}}, 770 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "7"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "7"}}, 771 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "7"}, nil}}} 772 peerSide.SetResponses(respSet) 773 774 ci = &pb.ChaincodeInput{[][]byte{[]byte("historyq"), []byte("A")}} 775 payload = utils.MarshalOrPanic(ci) 776 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "7"}) 777 778 //wait for done 779 processDone(t, done, false) 780 781 //error history query 782 783 //create the response 784 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 785 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_HISTORY_FOR_KEY, Txid: "7a"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: "7a"}}, 786 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "7a"}, nil}}} 787 peerSide.SetResponses(respSet) 788 789 ci = &pb.ChaincodeInput{[][]byte{[]byte("historyq"), []byte("A")}} 790 payload = utils.MarshalOrPanic(ci) 791 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "7a"}) 792 793 //wait for done 794 processDone(t, done, false) 795 796 //query result 797 798 //create the response 799 getQRResp := &pb.QueryResponse{Results: []*pb.QueryResultBytes{ 800 &pb.QueryResultBytes{ResultBytes: utils.MarshalOrPanic(&lproto.KV{"getputcc", "A", []byte("100")})}, 801 &pb.QueryResultBytes{ResultBytes: utils.MarshalOrPanic(&lproto.KV{"getputcc", "B", []byte("200")})}}, 802 HasMore: true} 803 getQRRespPayload := utils.MarshalOrPanic(getQRResp) 804 805 //create the next response 806 rangeQueryNext = &pb.QueryResponse{Results: nil, HasMore: false} 807 808 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 809 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_QUERY_RESULT, Txid: "8"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: getQRRespPayload, Txid: "8"}}, 810 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Txid: "8"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: utils.MarshalOrPanic(rangeQueryNext), Txid: "8"}}, 811 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Txid: "8"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "8"}}, 812 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "8"}, nil}}} 813 peerSide.SetResponses(respSet) 814 815 ci = &pb.ChaincodeInput{[][]byte{[]byte("richq"), []byte("A")}} 816 payload = utils.MarshalOrPanic(ci) 817 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "8"}) 818 819 //wait for done 820 processDone(t, done, false) 821 822 //query result error 823 824 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 825 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_GET_QUERY_RESULT, Txid: "8a"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: nil, Txid: "8a"}}, 826 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "8a"}, nil}}} 827 peerSide.SetResponses(respSet) 828 829 ci = &pb.ChaincodeInput{[][]byte{[]byte("richq"), []byte("A")}} 830 payload = utils.MarshalOrPanic(ci) 831 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "8a"}) 832 833 //wait for done 834 processDone(t, done, false) 835 836 time.Sleep(1 * time.Second) 837 peerSide.Quit() 838 } 839 840 func TestStartInProc(t *testing.T) { 841 streamGetter = mockChaincodeStreamGetter 842 cc := &shimTestCC{} 843 var err error 844 ccname := "shimTestCC" 845 peerSide := setupcc(ccname, cc) 846 defer mockPeerCCSupport.RemoveCC(ccname) 847 848 done := setuperror() 849 850 doneFunc := func(ind int, err error) { 851 done <- err 852 } 853 854 //start the mock peer 855 go func() { 856 respSet := &mockpeer.MockResponseSet{doneFunc, nil, []*mockpeer.MockResponse{ 857 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTER}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTERED}}}} 858 peerSide.SetResponses(respSet) 859 peerSide.SetKeepAlive(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_KEEPALIVE}) 860 err = peerSide.Run() 861 }() 862 863 //start the shim+chaincode 864 go func() { 865 err = StartInProc([]string{"CORE_CHAINCODE_ID_NAME=shimTestCC", "CORE_CHAINCODE_LOGGING_SHIM=debug"}, nil, cc, peerSide.GetSendStream(), peerSide.GetRecvStream()) 866 }() 867 868 //wait for init 869 processDone(t, done, false) 870 871 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: "1"}) 872 873 time.Sleep(1 * time.Second) 874 peerSide.Quit() 875 } 876 877 func TestCC2CC(t *testing.T) { 878 streamGetter = mockChaincodeStreamGetter 879 cc := &shimTestCC{} 880 //viper.Set("chaincode.logging.shim", "debug") 881 var err error 882 ccname := "shimTestCC" 883 peerSide := setupcc(ccname, cc) 884 defer mockPeerCCSupport.RemoveCC(ccname) 885 //start the shim+chaincode 886 go func() { 887 err = Start(cc) 888 }() 889 890 done := setuperror() 891 892 errorFunc := func(ind int, err error) { 893 done <- err 894 } 895 896 //start the mock peer 897 go func() { 898 respSet := &mockpeer.MockResponseSet{errorFunc, nil, []*mockpeer.MockResponse{ 899 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTER}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_REGISTERED}}}} 900 peerSide.SetResponses(respSet) 901 peerSide.SetKeepAlive(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_KEEPALIVE}) 902 err = peerSide.Run() 903 }() 904 905 //wait for init 906 processDone(t, done, false) 907 908 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_READY, Txid: "1"}) 909 910 ci := &pb.ChaincodeInput{[][]byte{[]byte("init"), []byte("A"), []byte("100"), []byte("B"), []byte("200")}} 911 payload := utils.MarshalOrPanic(ci) 912 respSet := &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 913 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2"}}, 914 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_PUT_STATE, Txid: "2"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Txid: "2"}}, 915 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "2"}, nil}}} 916 peerSide.SetResponses(respSet) 917 918 //use the payload computed from prev init 919 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INIT, Payload: payload, Txid: "2"}) 920 921 //wait for done 922 processDone(t, done, false) 923 924 //cc2cc 925 innerResp := utils.MarshalOrPanic(&pb.Response{Status: OK, Payload: []byte("CC2CC rocks")}) 926 cc2ccresp := utils.MarshalOrPanic(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: innerResp}) 927 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 928 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Txid: "3"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: cc2ccresp, Txid: "3"}}, 929 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "3"}, nil}}} 930 peerSide.SetResponses(respSet) 931 932 ci = &pb.ChaincodeInput{[][]byte{[]byte("cc2cc"), []byte("othercc"), []byte("arg1"), []byte("arg2")}} 933 payload = utils.MarshalOrPanic(ci) 934 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "3"}) 935 936 //wait for done 937 processDone(t, done, false) 938 939 //error response cc2cc 940 respSet = &mockpeer.MockResponseSet{errorFunc, errorFunc, []*mockpeer.MockResponse{ 941 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_INVOKE_CHAINCODE, Txid: "4"}, &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: cc2ccresp, Txid: "4"}}, 942 &mockpeer.MockResponse{&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Txid: "4"}, nil}}} 943 peerSide.SetResponses(respSet) 944 945 peerSide.Send(&pb.ChaincodeMessage{Type: pb.ChaincodeMessage_TRANSACTION, Payload: payload, Txid: "4"}) 946 947 //wait for done 948 processDone(t, done, false) 949 950 time.Sleep(1 * time.Second) 951 peerSide.Quit() 952 } 953 954 func TestRealPeerStream(t *testing.T) { 955 viper.Set("peer.address", "127.0.0.1:12345") 956 _, err := userChaincodeStreamGetter("fake") 957 assert.Error(t, err) 958 }