Skip to content

Commit

Permalink
[FAB-1163] - prevent fabric network bounce
Browse files Browse the repository at this point in the history
- Also includes changes for FAB-1134
- Enable response checking as an explicit step
- Do not tear down fabric network between steps
- Split features to drive different chaincodes
- remove unnecessary 'deploy' feature that is implicitly covered in other features

Change-Id: Id466909ec1eac87330cb7aad47c8f336398daee6
Signed-off-by: nkl199@yahoo.co.uk <nkl199@yahoo.co.uk>
  • Loading branch information
nklincoln committed Feb 13, 2019
1 parent 57b683e commit 62106bd
Show file tree
Hide file tree
Showing 24 changed files with 815 additions and 207 deletions.
204 changes: 204 additions & 0 deletions test/scenario/chaincode/fabcar/go/fabcar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/

/*
* The sample smart contract for documentation topic:
* Writing Your First Blockchain Application
*/

package main

/* Imports
* 4 utility libraries for formatting, handling bytes, reading and writing JSON, and string manipulation
* 2 specific Hyperledger Fabric specific libraries for Smart Contracts
*/
import (
"bytes"
"encoding/json"
"fmt"
"strconv"

"github.com/hyperledger/fabric/core/chaincode/shim"
sc "github.com/hyperledger/fabric/protos/peer"
)

// Define the Smart Contract structure
type SmartContract struct {
}

// Define the car structure, with 4 properties. Structure tags are used by encoding/json library
type Car struct {
Make string `json:"make"`
Model string `json:"model"`
Colour string `json:"colour"`
Owner string `json:"owner"`
}

/*
* The Init method is called when the Smart Contract "fabcar" is instantiated by the blockchain network
* Best practice is to have any Ledger initialization in separate function -- see initLedger()
*/
func (s *SmartContract) Init(APIstub shim.ChaincodeStubInterface) sc.Response {
return shim.Success(nil)
}

/*
* The Invoke method is called as a result of an application request to run the Smart Contract "fabcar"
* The calling application program has also specified the particular smart contract function to be called, with arguments
*/
func (s *SmartContract) Invoke(APIstub shim.ChaincodeStubInterface) sc.Response {

// Retrieve the requested Smart Contract function and arguments
function, args := APIstub.GetFunctionAndParameters()
// Route to the appropriate handler function to interact with the ledger appropriately
if function == "queryCar" {
return s.queryCar(APIstub, args)
} else if function == "initLedger" {
return s.initLedger(APIstub)
} else if function == "createCar" {
return s.createCar(APIstub, args)
} else if function == "queryAllCars" {
return s.queryAllCars(APIstub)
} else if function == "changeCarOwner" {
return s.changeCarOwner(APIstub, args)
}

return shim.Error("Invalid Smart Contract function name.")
}

func (s *SmartContract) queryCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}

carAsBytes, _ := APIstub.GetState(args[0])
return shim.Success(carAsBytes)
}

func (s *SmartContract) initLedger(APIstub shim.ChaincodeStubInterface) sc.Response {
cars := []Car{
Car{Make: "Toyota", Model: "Prius", Colour: "blue", Owner: "Tomoko"},
Car{Make: "Ford", Model: "Mustang", Colour: "red", Owner: "Brad"},
Car{Make: "Hyundai", Model: "Tucson", Colour: "green", Owner: "Jin Soo"},
Car{Make: "Volkswagen", Model: "Passat", Colour: "yellow", Owner: "Max"},
Car{Make: "Tesla", Model: "S", Colour: "black", Owner: "Adriana"},
Car{Make: "Peugeot", Model: "205", Colour: "purple", Owner: "Michel"},
Car{Make: "Chery", Model: "S22L", Colour: "white", Owner: "Aarav"},
Car{Make: "Fiat", Model: "Punto", Colour: "violet", Owner: "Pari"},
Car{Make: "Tata", Model: "Nano", Colour: "indigo", Owner: "Valeria"},
Car{Make: "Holden", Model: "Barina", Colour: "brown", Owner: "Shotaro"},
}

i := 0
for i < len(cars) {
fmt.Println("i is ", i)
carAsBytes, _ := json.Marshal(cars[i])
APIstub.PutState("CAR"+strconv.Itoa(i), carAsBytes)
fmt.Println("Added", cars[i])
i = i + 1
}

return shim.Success(nil)
}

func (s *SmartContract) createCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

if len(args) != 5 {
return shim.Error("Incorrect number of arguments. Expecting 5")
}

var car = Car{Make: args[1], Model: args[2], Colour: args[3], Owner: args[4]}

carAsBytes, _ := json.Marshal(car)
APIstub.PutState(args[0], carAsBytes)

return shim.Success(nil)
}

func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response {

startKey := "CAR0"
endKey := "CAR999"

resultsIterator, err := APIstub.GetStateByRange(startKey, endKey)
if err != nil {
return shim.Error(err.Error())
}
defer resultsIterator.Close()

// buffer is a JSON array containing QueryResults
var buffer bytes.Buffer
buffer.WriteString("[")

bArrayMemberAlreadyWritten := false
for resultsIterator.HasNext() {
queryResponse, err := resultsIterator.Next()
if err != nil {
return shim.Error(err.Error())
}
// Add a comma before array members, suppress it for the first array member
if bArrayMemberAlreadyWritten == true {
buffer.WriteString(",")
}
buffer.WriteString("{\"Key\":")
buffer.WriteString("\"")
buffer.WriteString(queryResponse.Key)
buffer.WriteString("\"")

buffer.WriteString(", \"Record\":")
// Record is a JSON object, so we write as-is
buffer.WriteString(string(queryResponse.Value))
buffer.WriteString("}")
bArrayMemberAlreadyWritten = true
}
buffer.WriteString("]")

fmt.Printf("- queryAllCars:\n%s\n", buffer.String())

return shim.Success(buffer.Bytes())
}

func (s *SmartContract) changeCarOwner(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

if len(args) != 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}

carAsBytes, _ := APIstub.GetState(args[0])
car := Car{}

json.Unmarshal(carAsBytes, &car)
car.Owner = args[1]

carAsBytes, _ = json.Marshal(car)
APIstub.PutState(args[0], carAsBytes)

return shim.Success(nil)
}

// The main function is only relevant in unit test mode. Only included here for completeness.
func main() {

// Create a new Smart Contract
err := shim.Start(new(SmartContract))
if err != nil {
fmt.Printf("Error creating new Smart Contract: %s", err)
}
}
10 changes: 10 additions & 0 deletions test/scenario/chaincode/fabcar/node/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/

'use strict';

const FabCar = require('./lib/fabcar');

module.exports.FabCar = FabCar;
module.exports.contracts = [FabCar];
155 changes: 155 additions & 0 deletions test/scenario/chaincode/fabcar/node/lib/fabcar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/

'use strict';

const {Contract} = require('fabric-contract-api');

class FabCar extends Contract {

async initLedger(ctx) {
console.info('============= START : Initialize Ledger ===========');
const cars = [
{
color: 'blue',
make: 'Toyota',
model: 'Prius',
owner: 'Tomoko',
},
{
color: 'red',
make: 'Ford',
model: 'Mustang',
owner: 'Brad',
},
{
color: 'green',
make: 'Hyundai',
model: 'Tucson',
owner: 'Jin Soo',
},
{
color: 'yellow',
make: 'Volkswagen',
model: 'Passat',
owner: 'Max',
},
{
color: 'black',
make: 'Tesla',
model: 'S',
owner: 'Adriana',
},
{
color: 'purple',
make: 'Peugeot',
model: '205',
owner: 'Michel',
},
{
color: 'white',
make: 'Chery',
model: 'S22L',
owner: 'Aarav',
},
{
color: 'violet',
make: 'Fiat',
model: 'Punto',
owner: 'Pari',
},
{
color: 'indigo',
make: 'Tata',
model: 'Nano',
owner: 'Valeria',
},
{
color: 'brown',
make: 'Holden',
model: 'Barina',
owner: 'Shotaro',
},
];

for (let i = 0; i < cars.length; i++) {
cars[i].docType = 'car';
await ctx.stub.putState('CAR' + i, Buffer.from(JSON.stringify(cars[i])));
console.info('Added <--> ', cars[i]);
}
console.info('============= END : Initialize Ledger ===========');
}

async queryCar(ctx, carNumber) {
const carAsBytes = await ctx.stub.getState(carNumber); // get the car from chaincode state
if (!carAsBytes || carAsBytes.length === 0) {
throw new Error(`${carNumber} does not exist`);
}
console.log(carAsBytes.toString());
return carAsBytes.toString();
}

async createCar(ctx, carNumber, make, model, color, owner) {
console.info('============= START : Create Car ===========');

const car = {
color,
docType: 'car',
make,
model,
owner,
};

await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car)));
console.info('============= END : Create Car ===========');
}

async queryAllCars(ctx) {
const startKey = 'CAR0';
const endKey = 'CAR999';

const iterator = await ctx.stub.getStateByRange(startKey, endKey);

const allResults = [];
let collect = true;
while (collect) {
const res = await iterator.next();

if (res.value && res.value.value.toString()) {

const Key = res.value.key;
let Record;
try {
Record = JSON.parse(res.value.value.toString('utf8'));
} catch (err) {
console.log(err);
Record = res.value.value.toString('utf8');
}
allResults.push({Key, Record});
}
if (res.done) {
await iterator.close();
collect = false;
}
}
return JSON.stringify(allResults);
}

async changeCarOwner(ctx, carNumber, newOwner) {
console.info('============= START : changeCarOwner ===========');

const carAsBytes = await ctx.stub.getState(carNumber); // get the car from chaincode state
if (!carAsBytes || carAsBytes.length === 0) {
throw new Error(`${carNumber} does not exist`);
}
const car = JSON.parse(carAsBytes.toString());
car.owner = newOwner;

await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car)));
console.info('============= END : changeCarOwner ===========');
}

}

module.exports = FabCar;
Empty file.
Loading

0 comments on commit 62106bd

Please sign in to comment.