github.com/ewagmig/fabric@v2.1.1+incompatible/core/chaincode/lifecycle/ledger_shim_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package lifecycle_test 8 9 import ( 10 "fmt" 11 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/gomega" 14 15 "github.com/hyperledger/fabric-protos-go/ledger/queryresult" 16 "github.com/hyperledger/fabric/core/chaincode/lifecycle" 17 "github.com/hyperledger/fabric/core/chaincode/lifecycle/mock" 18 ) 19 20 var _ = Describe("LedgerShims", func() { 21 var ( 22 fakeStub *mock.ChaincodeStub 23 ) 24 25 BeforeEach(func() { 26 fakeStub = &mock.ChaincodeStub{} 27 }) 28 29 Describe("ChaincodePublicLedgerShim", func() { 30 var ( 31 cls *lifecycle.ChaincodePublicLedgerShim 32 fakeIterator *mock.StateIterator 33 ) 34 35 BeforeEach(func() { 36 fakeIterator = &mock.StateIterator{} 37 fakeIterator.HasNextReturnsOnCall(0, true) 38 fakeIterator.HasNextReturnsOnCall(1, false) 39 fakeIterator.NextReturns(&queryresult.KV{ 40 Key: "fake-prefix-key", 41 Value: []byte("fake-value"), 42 }, nil) 43 44 fakeStub.GetStateByRangeReturns(fakeIterator, nil) 45 46 cls = &lifecycle.ChaincodePublicLedgerShim{ 47 ChaincodeStubInterface: fakeStub, 48 } 49 }) 50 51 Describe("GetStateRange", func() { 52 It("passes through to the stub", func() { 53 res, err := cls.GetStateRange("fake-prefix") 54 Expect(err).NotTo(HaveOccurred()) 55 Expect(res).To(Equal(map[string][]byte{ 56 "fake-prefix-key": []byte("fake-value"), 57 })) 58 Expect(fakeStub.GetStateByRangeCallCount()).To(Equal(1)) 59 start, end := fakeStub.GetStateByRangeArgsForCall(0) 60 Expect(start).To(Equal("fake-prefix")) 61 Expect(end).To(Equal("fake-prefix\x7f")) 62 }) 63 64 Context("when the iterator cannot be retrieved", func() { 65 BeforeEach(func() { 66 fakeStub.GetStateByRangeReturns(nil, fmt.Errorf("error-by-range")) 67 }) 68 69 It("wraps and returns the error", func() { 70 _, err := cls.GetStateRange("fake-prefix") 71 Expect(err).To(MatchError("could not get state iterator: error-by-range")) 72 73 }) 74 }) 75 76 Context("when the iterator fails to iterate", func() { 77 BeforeEach(func() { 78 fakeIterator.NextReturns(nil, fmt.Errorf("fake-iterator-error")) 79 }) 80 81 It("wraps and returns the error", func() { 82 _, err := cls.GetStateRange("fake-prefix") 83 Expect(err).To(MatchError("could not iterate over range: fake-iterator-error")) 84 85 }) 86 }) 87 }) 88 }) 89 90 Describe("ChaincodePrivateLedgerShim", func() { 91 var ( 92 cls *lifecycle.ChaincodePrivateLedgerShim 93 ) 94 95 BeforeEach(func() { 96 cls = &lifecycle.ChaincodePrivateLedgerShim{ 97 Stub: fakeStub, 98 Collection: "fake-collection", 99 } 100 }) 101 102 Describe("GetStateRange", func() { 103 BeforeEach(func() { 104 fakeStub.GetPrivateDataByRangeReturns(&mock.StateIterator{}, nil) 105 }) 106 107 It("passes through to the stub private function", func() { 108 res, err := cls.GetStateRange("fake-key") 109 Expect(err).NotTo(HaveOccurred()) 110 Expect(res).To(BeEmpty()) 111 112 Expect(fakeStub.GetPrivateDataByRangeCallCount()).To(Equal(1)) 113 collection, start, end := fakeStub.GetPrivateDataByRangeArgsForCall(0) 114 Expect(collection).To(Equal("fake-collection")) 115 Expect(start).To(Equal("fake-key")) 116 Expect(end).To(Equal("fake-key\x7f")) 117 }) 118 119 Context("when getting the state iterator fails", func() { 120 BeforeEach(func() { 121 fakeStub.GetPrivateDataByRangeReturns(nil, fmt.Errorf("fake-range-error")) 122 }) 123 124 It("wraps and returns the error", func() { 125 _, err := cls.GetStateRange("fake-key") 126 Expect(err).To(MatchError("could not get state iterator: fake-range-error")) 127 }) 128 }) 129 }) 130 131 Describe("GetState", func() { 132 BeforeEach(func() { 133 fakeStub.GetPrivateDataReturns([]byte("fake-value"), fmt.Errorf("fake-getstate-error")) 134 }) 135 136 It("passes through to the stub private data implementation", func() { 137 res, err := cls.GetState("fake-key") 138 Expect(res).To(Equal([]byte("fake-value"))) 139 Expect(err).To(MatchError(fmt.Errorf("fake-getstate-error"))) 140 Expect(fakeStub.GetPrivateDataCallCount()).To(Equal(1)) 141 collection, key := fakeStub.GetPrivateDataArgsForCall(0) 142 Expect(collection).To(Equal("fake-collection")) 143 Expect(key).To(Equal("fake-key")) 144 }) 145 }) 146 147 Describe("GetStateHash", func() { 148 BeforeEach(func() { 149 fakeStub.GetPrivateDataHashReturns([]byte("fake-hash"), fmt.Errorf("fake-error")) 150 }) 151 152 It("passes through to the chaincode stub", func() { 153 res, err := cls.GetStateHash("fake-key") 154 Expect(res).To(Equal([]byte("fake-hash"))) 155 Expect(err).To(MatchError("fake-error")) 156 Expect(fakeStub.GetPrivateDataHashCallCount()).To(Equal(1)) 157 collection, key := fakeStub.GetPrivateDataHashArgsForCall(0) 158 Expect(collection).To(Equal("fake-collection")) 159 Expect(key).To(Equal("fake-key")) 160 }) 161 }) 162 163 Describe("PutState", func() { 164 BeforeEach(func() { 165 fakeStub.PutPrivateDataReturns(fmt.Errorf("fake-putstate-error")) 166 }) 167 168 It("passes through to the stub private data implementation", func() { 169 err := cls.PutState("fake-key", []byte("fake-value")) 170 Expect(err).To(MatchError(fmt.Errorf("fake-putstate-error"))) 171 Expect(fakeStub.PutPrivateDataCallCount()).To(Equal(1)) 172 collection, key, value := fakeStub.PutPrivateDataArgsForCall(0) 173 Expect(collection).To(Equal("fake-collection")) 174 Expect(key).To(Equal("fake-key")) 175 Expect(value).To(Equal([]byte("fake-value"))) 176 }) 177 }) 178 179 Describe("DelState", func() { 180 BeforeEach(func() { 181 fakeStub.DelPrivateDataReturns(fmt.Errorf("fake-delstate-error")) 182 }) 183 184 It("passes through to the stub private data implementation", func() { 185 err := cls.DelState("fake-key") 186 Expect(err).To(MatchError(fmt.Errorf("fake-delstate-error"))) 187 Expect(fakeStub.DelPrivateDataCallCount()).To(Equal(1)) 188 collection, key := fakeStub.DelPrivateDataArgsForCall(0) 189 Expect(collection).To(Equal("fake-collection")) 190 Expect(key).To(Equal("fake-key")) 191 }) 192 }) 193 }) 194 195 Describe("SimpleQueryExecutorShim", func() { 196 var ( 197 sqes *lifecycle.SimpleQueryExecutorShim 198 fakeSimpleQueryExecutor *mock.SimpleQueryExecutor 199 ) 200 201 BeforeEach(func() { 202 fakeSimpleQueryExecutor = &mock.SimpleQueryExecutor{} 203 sqes = &lifecycle.SimpleQueryExecutorShim{ 204 Namespace: "cc-namespace", 205 SimpleQueryExecutor: fakeSimpleQueryExecutor, 206 } 207 }) 208 209 Describe("GetState", func() { 210 BeforeEach(func() { 211 fakeSimpleQueryExecutor.GetStateReturns([]byte("fake-state"), fmt.Errorf("fake-error")) 212 }) 213 214 It("passes through to the query executor", func() { 215 res, err := sqes.GetState("fake-prefix") 216 Expect(res).To(Equal([]byte("fake-state"))) 217 Expect(err).To(MatchError("fake-error")) 218 }) 219 }) 220 221 Describe("GetStateRange", func() { 222 var ( 223 resItr *mock.ResultsIterator 224 ) 225 226 BeforeEach(func() { 227 resItr = &mock.ResultsIterator{} 228 resItr.NextReturnsOnCall(0, &queryresult.KV{ 229 Key: "fake-key", 230 Value: []byte("key-value"), 231 }, nil) 232 fakeSimpleQueryExecutor.GetStateRangeScanIteratorReturns(resItr, nil) 233 }) 234 235 It("passes through to the query executor", func() { 236 res, err := sqes.GetStateRange("fake-key") 237 Expect(err).NotTo(HaveOccurred()) 238 Expect(res).To(Equal(map[string][]byte{ 239 "fake-key": []byte("key-value"), 240 })) 241 242 Expect(fakeSimpleQueryExecutor.GetStateRangeScanIteratorCallCount()).To(Equal(1)) 243 namespace, start, end := fakeSimpleQueryExecutor.GetStateRangeScanIteratorArgsForCall(0) 244 Expect(namespace).To(Equal("cc-namespace")) 245 Expect(start).To(Equal("fake-key")) 246 Expect(end).To(Equal("fake-key\x7f")) 247 }) 248 249 Context("when the result iterator returns an error", func() { 250 BeforeEach(func() { 251 resItr.NextReturns(nil, fmt.Errorf("fake-error")) 252 }) 253 254 It("returns the error", func() { 255 _, err := sqes.GetStateRange("fake-key") 256 Expect(err).To(MatchError("could not iterate over range: fake-error")) 257 }) 258 }) 259 260 Context("when getting the state iterator fails", func() { 261 BeforeEach(func() { 262 fakeSimpleQueryExecutor.GetStateRangeScanIteratorReturns(nil, fmt.Errorf("fake-range-error")) 263 }) 264 265 It("wraps and returns the error", func() { 266 _, err := sqes.GetStateRange("fake-key") 267 Expect(err).To(MatchError("could not get state iterator: fake-range-error")) 268 }) 269 }) 270 }) 271 }) 272 273 Describe("PrivateQueryExecutorShim", func() { 274 var ( 275 pqes *lifecycle.PrivateQueryExecutorShim 276 fakeSimpleQueryExecutor *mock.SimpleQueryExecutor 277 ) 278 279 BeforeEach(func() { 280 fakeSimpleQueryExecutor = &mock.SimpleQueryExecutor{} 281 pqes = &lifecycle.PrivateQueryExecutorShim{ 282 Namespace: "cc-namespace", 283 Collection: "collection", 284 State: fakeSimpleQueryExecutor, 285 } 286 fakeSimpleQueryExecutor.GetPrivateDataHashReturns([]byte("hash"), fmt.Errorf("fake-error")) 287 }) 288 289 It("passes through to the underlying implementation", func() { 290 data, err := pqes.GetStateHash("key") 291 Expect(data).To(Equal([]byte("hash"))) 292 Expect(err).To(MatchError("fake-error")) 293 Expect(fakeSimpleQueryExecutor.GetPrivateDataHashCallCount()).To(Equal(1)) 294 namespace, collection, key := fakeSimpleQueryExecutor.GetPrivateDataHashArgsForCall(0) 295 Expect(namespace).To(Equal("cc-namespace")) 296 Expect(collection).To(Equal("collection")) 297 Expect(key).To(Equal("key")) 298 }) 299 }) 300 })