github.com/s7techlab/cckit@v0.10.5/testing/pagination_test.go (about) 1 package testing_test 2 3 import ( 4 . "github.com/onsi/ginkgo" 5 . "github.com/onsi/gomega" 6 7 "fmt" 8 9 "github.com/hyperledger/fabric-chaincode-go/shim" 10 "github.com/hyperledger/fabric-protos-go/ledger/queryresult" 11 "github.com/hyperledger/fabric-protos-go/peer" 12 13 testcc "github.com/s7techlab/cckit/testing" 14 ) 15 16 var _ = Describe("MockStateRangePagedIterator", func() { 17 var ( 18 mockStub *testcc.MockStub 19 iter *testcc.MockStateRangeQueryPagedIterator 20 state []*queryresult.KV 21 ) 22 23 var _ = BeforeEach(func() { 24 mockStub = testcc.NewMockStub("test", nil) 25 state = []*queryresult.KV{ 26 {Key: "aa", Value: []byte{10}}, 27 {Key: "ab", Value: []byte{11}}, 28 {Key: "ac", Value: []byte{12}}, 29 {Key: "ad", Value: []byte{13}}, 30 {Key: "ae", Value: []byte{14}}, 31 {Key: "af", Value: []byte{15}}, 32 {Key: "ag", Value: []byte{16}}, 33 {Key: "ba", Value: []byte{20}}, 34 {Key: "bb", Value: []byte{21}}, 35 } 36 37 if err := populateState(mockStub, state); err != nil { 38 Fail(fmt.Sprintf("Couldn't populate state: %s", err.Error())) 39 } 40 }) 41 42 Context("without bookmark", func() { 43 It("should iterate over first 2 items", func() { 44 iter = testcc.NewMockStatesRangeQueryPagedIterator( 45 mockStub, "aa", "b", 2, "") 46 Expect(iter.Len()).To(Equal(int32(2))) 47 Expect(iter.NextBookmark()).To(Equal("ac")) 48 49 Expect(iter.HasNext()).To(Equal(true)) 50 kv, err := iter.Next() 51 Expect(err).NotTo(HaveOccurred()) 52 Expect(kv.Key).To(Equal("aa")) 53 Expect(kv.Value).To(Equal([]byte{10})) 54 55 Expect(iter.HasNext()).To(Equal(true)) 56 kv, err = iter.Next() 57 Expect(err).NotTo(HaveOccurred()) 58 Expect(kv.Key).To(Equal("ab")) 59 Expect(kv.Value).To(Equal([]byte{11})) 60 61 Expect(iter.HasNext()).To(Equal(false)) 62 }) 63 }) 64 65 Context("with bookmark", func() { 66 It("should iterate over 2 items from bookmark (inclusive)", func() { 67 iter = testcc.NewMockStatesRangeQueryPagedIterator( 68 mockStub, "aa", "b", 3, "ab") 69 Expect(iter.Len()).To(Equal(int32(3))) 70 Expect(iter.NextBookmark()).To(Equal("ae")) 71 72 Expect(iter.HasNext()).To(Equal(true)) 73 kv, err := iter.Next() 74 Expect(err).NotTo(HaveOccurred()) 75 Expect(kv.Key).To(Equal("ab")) 76 Expect(kv.Value).To(Equal([]byte{11})) 77 78 Expect(iter.HasNext()).To(Equal(true)) 79 kv, err = iter.Next() 80 Expect(err).NotTo(HaveOccurred()) 81 Expect(kv.Key).To(Equal("ac")) 82 Expect(kv.Value).To(Equal([]byte{12})) 83 84 Expect(iter.HasNext()).To(Equal(true)) 85 kv, err = iter.Next() 86 Expect(err).NotTo(HaveOccurred()) 87 Expect(kv.Key).To(Equal("ad")) 88 Expect(kv.Value).To(Equal([]byte{13})) 89 90 Expect(iter.HasNext()).To(Equal(false)) 91 }) 92 }) 93 94 Context("with bookmark less than startKey", func() { 95 It("should iterate over 2 items from startKey", func() { 96 iter = testcc.NewMockStatesRangeQueryPagedIterator( 97 mockStub, "ac", "bb", 2, "ab") 98 Expect(iter.Len()).To(Equal(int32(2))) 99 Expect(iter.NextBookmark()).To(Equal("ae")) 100 101 Expect(iter.HasNext()).To(Equal(true)) 102 kv, err := iter.Next() 103 Expect(err).NotTo(HaveOccurred()) 104 Expect(kv.Key).To(Equal("ac")) 105 Expect(kv.Value).To(Equal([]byte{12})) 106 107 Expect(iter.HasNext()).To(Equal(true)) 108 kv, err = iter.Next() 109 Expect(err).NotTo(HaveOccurred()) 110 Expect(kv.Key).To(Equal("ad")) 111 Expect(kv.Value).To(Equal([]byte{13})) 112 113 Expect(iter.HasNext()).To(Equal(false)) 114 }) 115 }) 116 117 Context("with bookmark greater than endKey", func() { 118 It("shouldn't contains elements", func() { 119 iter = testcc.NewMockStatesRangeQueryPagedIterator( 120 mockStub, "ac", "ae", 2, "ba") 121 122 Expect(iter.HasNext()).To(Equal(false)) 123 Expect(iter.Len()).To(Equal(int32(0))) 124 Expect(iter.NextBookmark()).To(Equal("")) 125 }) 126 }) 127 128 Context("with empty state", func() { 129 It("shouldn't contains elements", func() { 130 emptyStub := testcc.NewMockStub("test", nil) 131 iter = testcc.NewMockStatesRangeQueryPagedIterator(emptyStub, "", "", 10, "") 132 133 Expect(iter.Len()).To(Equal(int32(0))) 134 Expect(iter.HasNext()).To(Equal(false)) 135 Expect(iter.NextBookmark()).To(Equal("")) 136 }) 137 }) 138 139 Context("with unbound range", func() { 140 It("should contains upto pageSize elements", func() { 141 iter = testcc.NewMockStatesRangeQueryPagedIterator(mockStub, "", "", 6, "") 142 143 Expect(iter.Len()).To(Equal(int32(6))) 144 Expect(iter.HasNext()).To(Equal(true)) 145 Expect(iter.NextBookmark()).To(Equal("ag")) 146 }) 147 }) 148 149 Context("when iterate over last elements", func() { 150 It("shouldn't has next page", func() { 151 iter = testcc.NewMockStatesRangeQueryPagedIterator(mockStub, "", "", 6, "ae") 152 Expect(iter.Len()).To(Equal(int32(5))) 153 Expect(iter.HasNext()).To(Equal(true)) 154 Expect(iter.NextBookmark()).To(Equal("")) 155 }) 156 }) 157 }) 158 159 var _ = Describe("MockStub", func() { 160 Describe("GetStateByRangeWithPagination", func() { 161 var ( 162 mockStub *testcc.MockStub 163 state []*queryresult.KV 164 ) 165 166 var _ = BeforeEach(func() { 167 mockStub = testcc.NewMockStub("test", nil) 168 state = []*queryresult.KV{ 169 {Key: "aa", Value: []byte{10}}, 170 {Key: "ab", Value: []byte{11}}, 171 {Key: "ac", Value: []byte{12}}, 172 {Key: "ad", Value: []byte{13}}, 173 {Key: "ae", Value: []byte{14}}, 174 {Key: "af", Value: []byte{15}}, 175 {Key: "ag", Value: []byte{16}}, 176 {Key: "ba", Value: []byte{20}}, 177 {Key: "bb", Value: []byte{21}}, 178 } 179 if err := populateState(mockStub, state); err != nil { 180 Fail(fmt.Sprintf("Couldn't populate state: %s", err.Error())) 181 } 182 }) 183 184 It("should return first 5 elements in range", func() { 185 iter, md, err := mockStub.GetStateByRangeWithPagination("aa", "ba", 5, "") 186 187 Expect(err).NotTo(HaveOccurred()) 188 Expect(md.Bookmark).To(Equal("af")) 189 Expect(md.FetchedRecordsCount).To(Equal(int32(5))) 190 191 for _, expect := range state[0:5] { 192 kv, err := iter.Next() 193 Expect(err).NotTo(HaveOccurred()) 194 Expect(kv).To(Equal(expect)) 195 } 196 197 Expect(iter.HasNext()).To(Equal(false)) 198 }) 199 200 It("should return 3 elements after bookmark(inclusive)", func() { 201 iter, md, err := mockStub.GetStateByRangeWithPagination("aa", "ba", 3, "ad") 202 203 Expect(err).NotTo(HaveOccurred()) 204 Expect(md.Bookmark).To(Equal("ag")) 205 Expect(md.FetchedRecordsCount).To(Equal(int32(3))) 206 207 for _, expect := range state[3:6] { 208 kv, err := iter.Next() 209 Expect(err).NotTo(HaveOccurred()) 210 Expect(kv).To(Equal(expect)) 211 } 212 213 Expect(iter.HasNext()).To(Equal(false)) 214 }) 215 216 It("should return last 2 elements", func() { 217 iter, md, err := mockStub.GetStateByRangeWithPagination("aa", "ba", 3, "ag") 218 219 Expect(err).NotTo(HaveOccurred()) 220 Expect(md.Bookmark).To(Equal("")) 221 Expect(md.FetchedRecordsCount).To(Equal(int32(1))) 222 223 for _, expect := range state[6:7] { 224 kv, err := iter.Next() 225 Expect(err).NotTo(HaveOccurred()) 226 Expect(kv).To(Equal(expect)) 227 } 228 229 Expect(iter.HasNext()).To(Equal(false)) 230 }) 231 232 It("should be empty when bookmark equal to endKey", func() { 233 iter, md, err := mockStub.GetStateByRangeWithPagination("aa", "ba", 3, "ba") 234 235 Expect(err).NotTo(HaveOccurred()) 236 Expect(md.Bookmark).To(Equal("")) 237 Expect(md.FetchedRecordsCount).To(Equal(int32(0))) 238 239 Expect(iter.HasNext()).To(Equal(false)) 240 }) 241 242 It("should return items in range when bookmark equal to startKey", func() { 243 iter, md, err := mockStub.GetStateByRangeWithPagination("aa", "ba", 3, "aa") 244 245 Expect(err).NotTo(HaveOccurred()) 246 Expect(md.Bookmark).To(Equal("ad")) 247 Expect(md.FetchedRecordsCount).To(Equal(int32(3))) 248 249 for _, expect := range state[0:3] { 250 kv, err := iter.Next() 251 Expect(err).NotTo(HaveOccurred()) 252 Expect(kv).To(Equal(expect)) 253 } 254 255 Expect(iter.HasNext()).To(Equal(false)) 256 }) 257 258 It("should returns items in range when bookmark is less than startKey", func() { 259 iter, md, err := mockStub.GetStateByRangeWithPagination("af", "ba", 3, "ab") 260 261 Expect(err).NotTo(HaveOccurred()) 262 Expect(md.Bookmark).To(Equal("")) 263 Expect(md.FetchedRecordsCount).To(Equal(int32(2))) 264 265 for _, expect := range state[5:7] { 266 kv, err := iter.Next() 267 Expect(err).NotTo(HaveOccurred()) 268 Expect(kv).To(Equal(expect)) 269 } 270 271 Expect(iter.HasNext()).To(Equal(false)) 272 }) 273 }) 274 275 Describe("GetStateByPartialCompositeKeyWithPagination", func() { 276 var ( 277 mockStub *testcc.MockStub 278 state []*queryresult.KV 279 ) 280 281 var _ = BeforeEach(func() { 282 mockStub = testcc.NewMockStub("test", nil) 283 k := keyComposer(mockStub) 284 state = []*queryresult.KV{ 285 {Key: k("test/Foo", "a"), Value: []byte{10}}, 286 {Key: k("test/Foo", "b"), Value: []byte{11}}, 287 {Key: k("test/Foo", "c"), Value: []byte{12}}, 288 {Key: k("test/Foo", "d"), Value: []byte{13}}, 289 {Key: k("test/Foo", "e"), Value: []byte{14}}, 290 {Key: k("test/Foo", "f"), Value: []byte{15}}, 291 {Key: k("test/Zoo", "a"), Value: []byte{20}}, 292 {Key: k("test/Zoo", "b"), Value: []byte{21}}, 293 {Key: k("test/Zoo", "c"), Value: []byte{22}}, 294 } 295 if err := populateState(mockStub, state); err != nil { 296 Fail(fmt.Sprintf("Couldn't populate state: %s", err.Error())) 297 } 298 }) 299 300 It("should returns single element", func() { 301 iter, md, err := mockStub.GetStateByPartialCompositeKeyWithPagination( 302 "test/Foo", []string{"b"}, 10, "") 303 Expect(err).NotTo(HaveOccurred()) 304 Expect(md.FetchedRecordsCount).To(Equal(int32(1))) 305 Expect(md.Bookmark).To(Equal("")) 306 Expect(iter.HasNext()).To(Equal(true)) 307 308 kv, err := iter.Next() 309 Expect(err).NotTo(HaveOccurred()) 310 Expect(kv).To(Equal(state[1])) 311 312 Expect(iter.HasNext()).To(Equal(false)) 313 }) 314 315 It("should returns bookmark to next page when matched elements more than page size", func() { 316 iter, md, err := mockStub.GetStateByPartialCompositeKeyWithPagination("test/Foo", nil, 3, "") 317 Expect(err).NotTo(HaveOccurred()) 318 Expect(md.Bookmark).To(Equal(state[3].Key)) 319 Expect(md.FetchedRecordsCount).To(Equal(int32(3))) 320 321 for _, expect := range state[0:3] { 322 Expect(iter.HasNext()).To(Equal(true)) 323 kv, err := iter.Next() 324 Expect(err).NotTo(HaveOccurred()) 325 Expect(kv).To(Equal(expect)) 326 } 327 328 Expect(iter.HasNext()).To(Equal(false)) 329 }) 330 331 It("should return elements after bookmark", func() { 332 iter, md, err := mockStub.GetStateByPartialCompositeKeyWithPagination("test/Foo", nil, 3, state[4].Key) 333 Expect(err).NotTo(HaveOccurred()) 334 Expect(md.Bookmark).To(Equal("")) 335 Expect(md.FetchedRecordsCount).To(Equal(int32(2))) 336 337 for _, expect := range state[4:6] { 338 Expect(iter.HasNext()).To(Equal(true)) 339 kv, err := iter.Next() 340 Expect(err).NotTo(HaveOccurred()) 341 Expect(kv).To(Equal(expect)) 342 } 343 344 Expect(iter.HasNext()).To(Equal(false)) 345 }) 346 347 It("should returns empty result for incorrect bookmark", func() { 348 iter, md, err := mockStub.GetStateByPartialCompositeKeyWithPagination("test/Foo", nil, 3, state[7].Key) 349 350 Expect(err).NotTo(HaveOccurred()) 351 Expect(md.Bookmark).To(Equal("")) 352 Expect(md.FetchedRecordsCount).To(Equal(int32(0))) 353 Expect(iter.HasNext()).To(Equal(false)) 354 }) 355 }) 356 }) 357 358 // keyComposer returns wrapper upon mockStub.CreateCompositeKey function 359 func keyComposer(mockStub *testcc.MockStub) func(objectType string, attrs ...string) string { 360 return func(objectType string, attrs ...string) string { 361 key, err := mockStub.CreateCompositeKey(objectType, attrs) 362 if err != nil { 363 Fail(fmt.Sprintf("Couldn't compose key: %s", err.Error())) 364 } 365 return key 366 } 367 } 368 369 // populateState populate mock stub state with given key - value pairs 370 func populateState(mockStub *testcc.MockStub, values []*queryresult.KV) error { 371 mockStub.MockTransactionStart("init") 372 for _, kv := range values { 373 if err := mockStub.PutState(kv.Key, kv.Value); err != nil { 374 return err 375 } 376 } 377 // workaround 378 mockStub.TxResult = peer.Response{ 379 Status: shim.OK, 380 Message: "", 381 Payload: nil, 382 } 383 mockStub.MockTransactionEnd("init") 384 385 return nil 386 }