-
Notifications
You must be signed in to change notification settings - Fork 516
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This is the main happy path test that connects all the individual v1.0 APIs together to ensure the return values and parameters are properly constructed and designed to allow applications to use the SDK to implement complete flows. The change also includes corresponding README.md updates for instructions to set up the target environment and drive the tests. fixes in response to comments: - ESLint warnings Change-Id: Id523f479434de3588ba9ba345c500c5d0519e7f9 Signed-off-by: Jim Zhang <jzhang@us.ibm.com>
- Loading branch information
1 parent
9731107
commit 21473c4
Showing
8 changed files
with
388 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
/* | ||
Copyright IBM Corp. 2016 All Rights Reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package main | ||
|
||
// A copy of fabric/examples/chaincode/go/chaincode_example02/chaincode_example02.go | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"strconv" | ||
|
||
"github.com/hyperledger/fabric/core/chaincode/shim" | ||
) | ||
|
||
// SimpleChaincode example simple Chaincode implementation | ||
type SimpleChaincode struct { | ||
} | ||
|
||
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) ([]byte, error) { | ||
_, args := stub.GetFunctionAndParameters() | ||
var A, B string // Entities | ||
var Aval, Bval int // Asset holdings | ||
var err error | ||
|
||
if len(args) != 4 { | ||
return nil, errors.New("Incorrect number of arguments. Expecting 4") | ||
} | ||
|
||
// Initialize the chaincode | ||
A = args[0] | ||
Aval, err = strconv.Atoi(args[1]) | ||
if err != nil { | ||
return nil, errors.New("Expecting integer value for asset holding") | ||
} | ||
B = args[2] | ||
Bval, err = strconv.Atoi(args[3]) | ||
if err != nil { | ||
return nil, errors.New("Expecting integer value for asset holding") | ||
} | ||
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval) | ||
|
||
// Write the state to the ledger | ||
err = stub.PutState(A, []byte(strconv.Itoa(Aval))) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
err = stub.PutState(B, []byte(strconv.Itoa(Bval))) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return nil, nil | ||
} | ||
|
||
// Transaction makes payment of X units from A to B | ||
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) ([]byte, error) { | ||
function, args := stub.GetFunctionAndParameters() | ||
if function == "delete" { | ||
// Deletes an entity from its state | ||
return t.delete(stub, args) | ||
} | ||
|
||
var A, B string // Entities | ||
var Aval, Bval int // Asset holdings | ||
var X int // Transaction value | ||
var err error | ||
|
||
if len(args) != 3 { | ||
return nil, errors.New("Incorrect number of arguments. Expecting 3") | ||
} | ||
|
||
A = args[0] | ||
B = args[1] | ||
|
||
// Get the state from the ledger | ||
// TODO: will be nice to have a GetAllState call to ledger | ||
Avalbytes, err := stub.GetState(A) | ||
if err != nil { | ||
return nil, errors.New("Failed to get state") | ||
} | ||
if Avalbytes == nil { | ||
return nil, errors.New("Entity not found") | ||
} | ||
Aval, _ = strconv.Atoi(string(Avalbytes)) | ||
|
||
Bvalbytes, err := stub.GetState(B) | ||
if err != nil { | ||
return nil, errors.New("Failed to get state") | ||
} | ||
if Bvalbytes == nil { | ||
return nil, errors.New("Entity not found") | ||
} | ||
Bval, _ = strconv.Atoi(string(Bvalbytes)) | ||
|
||
// Perform the execution | ||
X, err = strconv.Atoi(args[2]) | ||
if err != nil { | ||
return nil, errors.New("Invalid transaction amount, expecting a integer value") | ||
} | ||
Aval = Aval - X | ||
Bval = Bval + X | ||
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval) | ||
|
||
// Write the state back to the ledger | ||
err = stub.PutState(A, []byte(strconv.Itoa(Aval))) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
err = stub.PutState(B, []byte(strconv.Itoa(Bval))) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return nil, nil | ||
} | ||
|
||
// Deletes an entity from state | ||
func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { | ||
if len(args) != 1 { | ||
return nil, errors.New("Incorrect number of arguments. Expecting 1") | ||
} | ||
|
||
A := args[0] | ||
|
||
// Delete the key from the state in ledger | ||
err := stub.DelState(A) | ||
if err != nil { | ||
return nil, errors.New("Failed to delete state") | ||
} | ||
|
||
return nil, nil | ||
} | ||
|
||
// Query callback representing the query of a chaincode | ||
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface) ([]byte, error) { | ||
function, args := stub.GetFunctionAndParameters() | ||
if function != "query" { | ||
return nil, errors.New("Invalid query function name. Expecting \"query\"") | ||
} | ||
var A string // Entities | ||
var err error | ||
|
||
if len(args) != 1 { | ||
return nil, errors.New("Incorrect number of arguments. Expecting name of the person to query") | ||
} | ||
|
||
A = args[0] | ||
|
||
// Get the state from the ledger | ||
Avalbytes, err := stub.GetState(A) | ||
if err != nil { | ||
jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}" | ||
return nil, errors.New(jsonResp) | ||
} | ||
|
||
if Avalbytes == nil { | ||
jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}" | ||
return nil, errors.New(jsonResp) | ||
} | ||
|
||
jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}" | ||
fmt.Printf("Query Response:%s\n", jsonResp) | ||
return Avalbytes, nil | ||
} | ||
|
||
func main() { | ||
err := shim.Start(new(SimpleChaincode)) | ||
if err != nil { | ||
fmt.Printf("Error starting Simple chaincode: %s", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// This is an end-to-end test that focuses on exercising all parts of the fabric APIs | ||
// in a happy-path scenario | ||
var tape = require('tape'); | ||
var _test = require('tape-promise'); | ||
var test = _test(tape); | ||
|
||
var path = require('path'); | ||
|
||
var hfc = require('../..'); | ||
var util = require('util'); | ||
var grpc = require('grpc'); | ||
var testUtil = require('./util.js'); | ||
|
||
var _fabricProto = grpc.load(path.join(__dirname,'../../lib/protos/fabric_next.proto')).protos; | ||
|
||
var chain = hfc.newChain('testChain'); | ||
var webUser; | ||
|
||
testUtil.setupChaincodeDeploy(); | ||
|
||
chain.setKeyValueStore(hfc.newKeyValueStore({ | ||
path: '/tmp/kvs-hfc-e2e' | ||
})); | ||
|
||
chain.setMemberServicesUrl('grpc://localhost:7054'); | ||
chain.setOrderer('grpc://localhost:5151'); | ||
|
||
test('End-to-end flow of chaincode deploy, transaction invocation, and query', function(t) { | ||
chain.enroll('admin', 'Xurw3yU9zI0l') | ||
.then( | ||
function(admin) { | ||
t.pass('Successfully enrolled user \'admin\''); | ||
webUser = admin; | ||
|
||
// send proposal to endorser | ||
var request = { | ||
endorserUrl: 'grpc://localhost:7051', | ||
chaincodePath: testUtil.CHAINCODE_PATH, | ||
fcn: 'init', | ||
args: ['a', '100', 'b', '200'] | ||
}; | ||
|
||
return admin.sendDeploymentProposal(request); | ||
}, | ||
function(err) { | ||
t.fail('Failed to enroll user \'admin\'. ' + err); | ||
t.end(); | ||
} | ||
).then( | ||
function(response) { | ||
if (response && response.response && response.response.status === 200) { | ||
t.pass(util.format('Successfully sent Proposal and received ProposalResponse: Status - %s, message - "%s", metadata - "%s", endorsement signature: %s', response.response.status, response.response.message, response.response.payload, response.endorsement.signature)); | ||
|
||
var tx = new _fabricProto.Transaction2(); | ||
tx.setEndorsedActions([{ | ||
actionBytes: response.actionBytes, | ||
endorsements: response.response.endorsement | ||
}]); | ||
|
||
return webUser.sendTransaction(tx.toBuffer()); | ||
|
||
} else { | ||
t.fail('Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...'); | ||
t.end(); | ||
} | ||
}, | ||
function(err) { | ||
t.fail('Failed to send deployment proposal due to error: ' + err.stack ? err.stack : err); | ||
t.end(); | ||
} | ||
).then( | ||
function(data) { | ||
t.pass(util.format('Response from orderer: %j', data)); | ||
|
||
t.end(); | ||
} | ||
).catch( | ||
function(err) { | ||
t.fail('Failed to send deployment proposal. ' + err.stack ? err.stack : err); | ||
t.end(); | ||
} | ||
); | ||
}); |
Oops, something went wrong.