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  }