github.com/cosmos/cosmos-sdk@v0.50.10/x/group/internal/orm/iterator_property_test.go (about)

     1  package orm
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/cosmos/gogoproto/proto"
     7  	"github.com/stretchr/testify/require"
     8  	"pgregory.net/rapid"
     9  
    10  	errorsmod "cosmossdk.io/errors"
    11  
    12  	"github.com/cosmos/cosmos-sdk/testutil/testdata"
    13  	"github.com/cosmos/cosmos-sdk/types/query"
    14  	"github.com/cosmos/cosmos-sdk/x/group/errors"
    15  )
    16  
    17  func TestPaginationProperty(t *testing.T) {
    18  	t.Run("TestPagination", rapid.MakeCheck(func(t *rapid.T) {
    19  		// Create a slice of group members
    20  		tableModels := rapid.SliceOf(genTableModel).Draw(t, "tableModels")
    21  
    22  		// Choose a random limit for paging
    23  		upperLimit := uint64(len(tableModels))
    24  		if upperLimit == 0 {
    25  			upperLimit = 1
    26  		}
    27  		limit := rapid.Uint64Range(1, upperLimit).Draw(t, "limit")
    28  
    29  		// Reconstruct the slice from offset pages
    30  		reconstructedTableModels := make([]*testdata.TableModel, 0, len(tableModels))
    31  		for offset := uint64(0); offset < uint64(len(tableModels)); offset += limit {
    32  			pageRequest := &query.PageRequest{
    33  				Key:        nil,
    34  				Offset:     offset,
    35  				Limit:      limit,
    36  				CountTotal: false,
    37  				Reverse:    false,
    38  			}
    39  			end := offset + limit
    40  			if end > uint64(len(tableModels)) {
    41  				end = uint64(len(tableModels))
    42  			}
    43  			dest := reconstructedTableModels[offset:end]
    44  			tableModelsIt := testTableModelIterator(tableModels, nil)
    45  			Paginate(tableModelsIt, pageRequest, &dest)
    46  			reconstructedTableModels = append(reconstructedTableModels, dest...)
    47  		}
    48  
    49  		// Should be the same slice
    50  		require.Equal(t, len(tableModels), len(reconstructedTableModels))
    51  		for i, gm := range tableModels {
    52  			require.Equal(t, *gm, *reconstructedTableModels[i])
    53  		}
    54  
    55  		// Reconstruct the slice from keyed pages
    56  		reconstructedTableModels = make([]*testdata.TableModel, 0, len(tableModels))
    57  		var start uint64
    58  		key := EncodeSequence(0)
    59  		for key != nil {
    60  			pageRequest := &query.PageRequest{
    61  				Key:        key,
    62  				Offset:     0,
    63  				Limit:      limit,
    64  				CountTotal: false,
    65  				Reverse:    false,
    66  			}
    67  
    68  			end := start + limit
    69  			if end > uint64(len(tableModels)) {
    70  				end = uint64(len(tableModels))
    71  			}
    72  
    73  			dest := reconstructedTableModels[start:end]
    74  			tableModelsIt := testTableModelIterator(tableModels, key)
    75  
    76  			resp, err := Paginate(tableModelsIt, pageRequest, &dest)
    77  			require.NoError(t, err)
    78  			key = resp.NextKey
    79  
    80  			reconstructedTableModels = append(reconstructedTableModels, dest...)
    81  
    82  			start += limit
    83  		}
    84  
    85  		// Should be the same slice
    86  		require.Equal(t, len(tableModels), len(reconstructedTableModels))
    87  		for i, gm := range tableModels {
    88  			require.Equal(t, *gm, *reconstructedTableModels[i])
    89  		}
    90  	}))
    91  }
    92  
    93  func testTableModelIterator(tms []*testdata.TableModel, key RowID) Iterator {
    94  	var closed bool
    95  	var index int
    96  	if key != nil {
    97  		index = int(DecodeSequence(key))
    98  	}
    99  	return IteratorFunc(func(dest proto.Message) (RowID, error) {
   100  		if dest == nil {
   101  			return nil, errorsmod.Wrap(errors.ErrORMInvalidArgument, "destination object must not be nil")
   102  		}
   103  
   104  		if index == len(tms) {
   105  			closed = true
   106  		}
   107  
   108  		if closed {
   109  			return nil, errors.ErrORMIteratorDone
   110  		}
   111  
   112  		rowID := EncodeSequence(uint64(index))
   113  
   114  		bytes, err := tms[index].Marshal()
   115  		if err != nil {
   116  			return nil, err
   117  		}
   118  
   119  		index++
   120  
   121  		return rowID, proto.Unmarshal(bytes, dest)
   122  	})
   123  }