github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/core/chaincode/shim/mockstub_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 "encoding/json" 21 "fmt" 22 "reflect" 23 "testing" 24 25 "github.com/hyperledger/fabric/common/flogging" 26 "github.com/spf13/viper" 27 ) 28 29 func TestMockStateRangeQueryIterator(t *testing.T) { 30 stub := NewMockStub("rangeTest", nil) 31 stub.MockTransactionStart("init") 32 stub.PutState("1", []byte{61}) 33 stub.PutState("0", []byte{62}) 34 stub.PutState("5", []byte{65}) 35 stub.PutState("3", []byte{63}) 36 stub.PutState("4", []byte{64}) 37 stub.PutState("6", []byte{66}) 38 stub.MockTransactionEnd("init") 39 40 expectKeys := []string{"3", "4"} 41 expectValues := [][]byte{{63}, {64}} 42 43 rqi := NewMockStateRangeQueryIterator(stub, "2", "4") 44 45 fmt.Println("Running loop") 46 for i := 0; i < 2; i++ { 47 response, err := rqi.Next() 48 fmt.Println("Loop", i, "got", response.Key, response.Value, err) 49 if expectKeys[i] != response.Key { 50 fmt.Println("Expected key", expectKeys[i], "got", response.Key) 51 t.FailNow() 52 } 53 if expectValues[i][0] != response.Value[0] { 54 fmt.Println("Expected value", expectValues[i], "got", response.Value) 55 } 56 } 57 } 58 59 // TestMockStateRangeQueryIterator_openEnded tests running an open-ended query 60 // for all keys on the MockStateRangeQueryIterator 61 func TestMockStateRangeQueryIterator_openEnded(t *testing.T) { 62 stub := NewMockStub("rangeTest", nil) 63 stub.MockTransactionStart("init") 64 stub.PutState("1", []byte{61}) 65 stub.PutState("0", []byte{62}) 66 stub.PutState("5", []byte{65}) 67 stub.PutState("3", []byte{63}) 68 stub.PutState("4", []byte{64}) 69 stub.PutState("6", []byte{66}) 70 stub.MockTransactionEnd("init") 71 72 rqi := NewMockStateRangeQueryIterator(stub, "", "") 73 74 count := 0 75 for rqi.HasNext() { 76 rqi.Next() 77 count++ 78 } 79 80 if count != rqi.Stub.Keys.Len() { 81 t.FailNow() 82 } 83 } 84 85 // TestSetupChaincodeLogging uses the utlity function defined in chaincode.go to 86 // set the chaincodeLogger's logging format and level 87 func TestSetupChaincodeLogging_blankLevel(t *testing.T) { 88 // set log level to a non-default level 89 testLogLevelString := "" 90 testLogFormat := "%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}" 91 92 viper.Set("chaincode.logging.level", testLogLevelString) 93 viper.Set("chaincode.logging.format", testLogFormat) 94 95 SetupChaincodeLogging() 96 97 if !IsEnabledForLogLevel(flogging.DefaultLevel()) { 98 t.FailNow() 99 } 100 } 101 102 // TestSetupChaincodeLogging uses the utlity function defined in chaincode.go to 103 // set the chaincodeLogger's logging format and level 104 func TestSetupChaincodeLogging(t *testing.T) { 105 // set log level to a non-default level 106 testLogLevel := "debug" 107 testShimLogLevel := "warning" 108 testLogFormat := "%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}" 109 110 viper.Set("chaincode.logging.level", testLogLevel) 111 viper.Set("chaincode.logging.format", testLogFormat) 112 viper.Set("chaincode.logging.shim", testShimLogLevel) 113 114 SetupChaincodeLogging() 115 116 if !IsEnabledForLogLevel(testShimLogLevel) { 117 t.FailNow() 118 } 119 } 120 121 type Marble struct { 122 ObjectType string `json:"docType"` //docType is used to distinguish the various types of objects in state database 123 Name string `json:"name"` //the fieldtags are needed to keep case from bouncing around 124 Color string `json:"color"` 125 Size int `json:"size"` 126 Owner string `json:"owner"` 127 } 128 129 // JSONBytesEqual compares the JSON in two byte slices. 130 func jsonBytesEqual(expected []byte, actual []byte) bool { 131 var infExpected, infActual interface{} 132 if err := json.Unmarshal(expected, &infExpected); err != nil { 133 return false 134 } 135 if err := json.Unmarshal(actual, &infActual); err != nil { 136 return false 137 } 138 return reflect.DeepEqual(infActual, infExpected) 139 } 140 141 func TestGetStateByPartialCompositeKey(t *testing.T) { 142 stub := NewMockStub("GetStateByPartialCompositeKeyTest", nil) 143 stub.MockTransactionStart("init") 144 145 marble1 := &Marble{"marble", "set-1", "red", 5, "tom"} 146 // Convert marble1 to JSON with Color and Name as composite key 147 compositeKey1, _ := stub.CreateCompositeKey(marble1.ObjectType, []string{marble1.Name, marble1.Color}) 148 marbleJSONBytes1, _ := json.Marshal(marble1) 149 // Add marble1 JSON to state 150 stub.PutState(compositeKey1, marbleJSONBytes1) 151 152 marble2 := &Marble{"marble", "set-1", "blue", 5, "jerry"} 153 compositeKey2, _ := stub.CreateCompositeKey(marble2.ObjectType, []string{marble2.Name, marble2.Color}) 154 marbleJSONBytes2, _ := json.Marshal(marble2) 155 stub.PutState(compositeKey2, marbleJSONBytes2) 156 157 marble3 := &Marble{"marble", "set-2", "red", 5, "tom-jerry"} 158 compositeKey3, _ := stub.CreateCompositeKey(marble3.ObjectType, []string{marble3.Name, marble3.Color}) 159 marbleJSONBytes3, _ := json.Marshal(marble3) 160 stub.PutState(compositeKey3, marbleJSONBytes3) 161 162 stub.MockTransactionEnd("init") 163 // should return in sorted order of attributes 164 expectKeys := []string{compositeKey2, compositeKey1} 165 expectKeysAttributes := [][]string{{"set-1", "blue"}, {"set-1", "red"}} 166 expectValues := [][]byte{marbleJSONBytes2, marbleJSONBytes1} 167 168 rqi, _ := stub.GetStateByPartialCompositeKey("marble", []string{"set-1"}) 169 fmt.Println("Running loop") 170 for i := 0; i < 2; i++ { 171 response, err := rqi.Next() 172 fmt.Println("Loop", i, "got", response.Key, response.Value, err) 173 if expectKeys[i] != response.Key { 174 fmt.Println("Expected key", expectKeys[i], "got", response.Key) 175 t.FailNow() 176 } 177 objectType, attributes, _ := stub.SplitCompositeKey(response.Key) 178 if objectType != "marble" { 179 fmt.Println("Expected objectType", "marble", "got", objectType) 180 t.FailNow() 181 } 182 fmt.Println(attributes) 183 for index, attr := range attributes { 184 if expectKeysAttributes[i][index] != attr { 185 fmt.Println("Expected keys attribute", expectKeysAttributes[index][i], "got", attr) 186 t.FailNow() 187 } 188 } 189 if jsonBytesEqual(expectValues[i], response.Value) != true { 190 fmt.Println("Expected value", expectValues[i], "got", response.Value) 191 t.FailNow() 192 } 193 } 194 } 195 196 func TestGetStateByPartialCompositeKeyCollision(t *testing.T) { 197 stub := NewMockStub("GetStateByPartialCompositeKeyCollisionTest", nil) 198 stub.MockTransactionStart("init") 199 200 vehicle1Bytes := []byte("vehicle1") 201 compositeKeyVehicle1, _ := stub.CreateCompositeKey("Vehicle", []string{"VIN_1234"}) 202 stub.PutState(compositeKeyVehicle1, vehicle1Bytes) 203 204 vehicleListing1Bytes := []byte("vehicleListing1") 205 compositeKeyVehicleListing1, _ := stub.CreateCompositeKey("VehicleListing", []string{"LIST_1234"}) 206 stub.PutState(compositeKeyVehicleListing1, vehicleListing1Bytes) 207 208 stub.MockTransactionEnd("init") 209 210 // Only the single "Vehicle" object should be returned, not the "VehicleListing" object 211 rqi, _ := stub.GetStateByPartialCompositeKey("Vehicle", []string{}) 212 i := 0 213 fmt.Println("Running loop") 214 for rqi.HasNext() { 215 i++ 216 response, err := rqi.Next() 217 fmt.Println("Loop", i, "got", response.Key, response.Value, err) 218 } 219 // Only the single "Vehicle" object should be returned, not the "VehicleListing" object 220 if i != 1 { 221 fmt.Println("Expected 1, got", i) 222 t.FailNow() 223 } 224 } 225 226 func TestGetTxTimestamp(t *testing.T) { 227 stub := NewMockStub("GetTxTimestamp", nil) 228 stub.MockTransactionStart("init") 229 230 timestamp, err := stub.GetTxTimestamp() 231 if timestamp == nil || err != nil { 232 t.FailNow() 233 } 234 235 stub.MockTransactionEnd("init") 236 } 237 238 //TestMockMock clearly cheating for coverage... but not. Mock should 239 //be tucked away under common/mocks package which is not 240 //included for coverage. Moving mockstub to another package 241 //will cause upheaval in other code best dealt with separately 242 //For now, call all the methods to get mock covered in this 243 //package 244 func TestMockMock(t *testing.T) { 245 stub := NewMockStub("MOCKMOCK", &shimTestCC{}) 246 stub.args = [][]byte{[]byte("a"), []byte("b")} 247 stub.MockInit("id", nil) 248 stub.GetArgs() 249 stub.GetStringArgs() 250 stub.GetFunctionAndParameters() 251 stub.GetTxID() 252 stub.MockInvoke("id", nil) 253 stub.MockInvokeWithSignedProposal("id", nil, nil) 254 stub.DelState("dummy") 255 stub.GetStateByRange("start", "end") 256 stub.GetQueryResult("q") 257 stub2 := NewMockStub("othercc", &shimTestCC{}) 258 stub.MockPeerChaincode("othercc/mychan", stub2) 259 stub.InvokeChaincode("othercc", nil, "mychan") 260 stub.GetCreator() 261 stub.GetTransient() 262 stub.GetBinding() 263 stub.GetSignedProposal() 264 stub.GetArgsSlice() 265 stub.SetEvent("e", nil) 266 stub.GetHistoryForKey("k") 267 iter := &MockStateRangeQueryIterator{} 268 iter.HasNext() 269 iter.Close() 270 getBytes("f", []string{"a", "b"}) 271 getFuncArgs([][]byte{[]byte("a")}) 272 }