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

     1  package orm
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/assert"
     7  	"github.com/stretchr/testify/require"
     8  
     9  	errorsmod "cosmossdk.io/errors"
    10  	storetypes "cosmossdk.io/store/types"
    11  
    12  	"github.com/cosmos/cosmos-sdk/codec"
    13  	"github.com/cosmos/cosmos-sdk/codec/types"
    14  	"github.com/cosmos/cosmos-sdk/testutil/testdata"
    15  	"github.com/cosmos/cosmos-sdk/x/group/errors"
    16  )
    17  
    18  func TestPrimaryKeyTablePrefixScan(t *testing.T) {
    19  	interfaceRegistry := types.NewInterfaceRegistry()
    20  	cdc := codec.NewProtoCodec(interfaceRegistry)
    21  
    22  	tb, err := NewPrimaryKeyTable(PrimaryKeyTablePrefix, &testdata.TableModel{}, cdc)
    23  	require.NoError(t, err)
    24  
    25  	ctx := NewMockContext()
    26  	store := ctx.KVStore(storetypes.NewKVStoreKey("test"))
    27  
    28  	metadata := []byte("metadata")
    29  	t1 := testdata.TableModel{
    30  		Id:       1,
    31  		Name:     "my test 1",
    32  		Metadata: metadata,
    33  	}
    34  	t2 := testdata.TableModel{
    35  		Id:       2,
    36  		Name:     "my test 2",
    37  		Metadata: metadata,
    38  	}
    39  	t3 := testdata.TableModel{
    40  		Id:       3,
    41  		Name:     "my test 3",
    42  		Metadata: metadata,
    43  	}
    44  	for _, g := range []testdata.TableModel{t1, t2, t3} {
    45  		g := g
    46  		require.NoError(t, tb.Create(store, &g))
    47  	}
    48  
    49  	specs := map[string]struct {
    50  		start, end []byte
    51  		expResult  []testdata.TableModel
    52  		expRowIDs  []RowID
    53  		expError   *errorsmod.Error
    54  		method     func(store storetypes.KVStore, start, end []byte) (Iterator, error)
    55  	}{
    56  		"exact match with a single result": {
    57  			start:     EncodeSequence(1), // == PrimaryKey(&t1)
    58  			end:       EncodeSequence(2), // == PrimaryKey(&t2)
    59  			method:    tb.PrefixScan,
    60  			expResult: []testdata.TableModel{t1},
    61  			expRowIDs: []RowID{PrimaryKey(&t1)},
    62  		},
    63  		"one result by 1st byte": {
    64  			start:     []byte{0},
    65  			end:       EncodeSequence(2), // == PrimaryKey(&t2)
    66  			method:    tb.PrefixScan,
    67  			expResult: []testdata.TableModel{t1},
    68  			expRowIDs: []RowID{PrimaryKey(&t1)},
    69  		},
    70  		"open end query": {
    71  			start:     EncodeSequence(3),
    72  			end:       nil,
    73  			method:    tb.PrefixScan,
    74  			expResult: []testdata.TableModel{t3},
    75  			expRowIDs: []RowID{PrimaryKey(&t3)},
    76  		},
    77  		"open end query with all": {
    78  			start:     EncodeSequence(1),
    79  			end:       nil,
    80  			method:    tb.PrefixScan,
    81  			expResult: []testdata.TableModel{t1, t2, t3},
    82  			expRowIDs: []RowID{PrimaryKey(&t1), PrimaryKey(&t2), PrimaryKey(&t3)},
    83  		},
    84  		"open start query": {
    85  			start:     nil,
    86  			end:       EncodeSequence(3),
    87  			method:    tb.PrefixScan,
    88  			expResult: []testdata.TableModel{t1, t2},
    89  			expRowIDs: []RowID{PrimaryKey(&t1), PrimaryKey(&t2)},
    90  		},
    91  		"open start and end query": {
    92  			start:     nil,
    93  			end:       nil,
    94  			method:    tb.PrefixScan,
    95  			expResult: []testdata.TableModel{t1, t2, t3},
    96  			expRowIDs: []RowID{PrimaryKey(&t1), PrimaryKey(&t2), PrimaryKey(&t3)},
    97  		},
    98  		"all matching 1st byte": {
    99  			start:     []byte{0},
   100  			end:       nil,
   101  			method:    tb.PrefixScan,
   102  			expResult: []testdata.TableModel{t1, t2, t3},
   103  			expRowIDs: []RowID{PrimaryKey(&t1), PrimaryKey(&t2), PrimaryKey(&t3)},
   104  		},
   105  		"non matching 1st byte": {
   106  			start:     []byte{1},
   107  			end:       nil,
   108  			method:    tb.PrefixScan,
   109  			expResult: []testdata.TableModel{},
   110  		},
   111  		"start equals end": {
   112  			start:    EncodeSequence(1),
   113  			end:      EncodeSequence(1),
   114  			method:   tb.PrefixScan,
   115  			expError: errors.ErrORMInvalidArgument,
   116  		},
   117  		"start after end": {
   118  			start:    EncodeSequence(2),
   119  			end:      EncodeSequence(1),
   120  			method:   tb.PrefixScan,
   121  			expError: errors.ErrORMInvalidArgument,
   122  		},
   123  		"reverse: exact match with a single result": {
   124  			start:     EncodeSequence(1), // == PrimaryKey(&t1)
   125  			end:       EncodeSequence(2), // == PrimaryKey(&t2)
   126  			method:    tb.ReversePrefixScan,
   127  			expResult: []testdata.TableModel{t1},
   128  			expRowIDs: []RowID{PrimaryKey(&t1)},
   129  		},
   130  		"reverse: one result by 1st byte": {
   131  			start:     []byte{0},
   132  			end:       EncodeSequence(2), // == PrimaryKey(&t2)
   133  			method:    tb.ReversePrefixScan,
   134  			expResult: []testdata.TableModel{t1},
   135  			expRowIDs: []RowID{PrimaryKey(&t1)},
   136  		},
   137  		"reverse: open end query": {
   138  			start:     EncodeSequence(3),
   139  			end:       nil,
   140  			method:    tb.ReversePrefixScan,
   141  			expResult: []testdata.TableModel{t3},
   142  			expRowIDs: []RowID{PrimaryKey(&t3)},
   143  		},
   144  		"reverse: open end query with all": {
   145  			start:     EncodeSequence(1),
   146  			end:       nil,
   147  			method:    tb.ReversePrefixScan,
   148  			expResult: []testdata.TableModel{t3, t2, t1},
   149  			expRowIDs: []RowID{PrimaryKey(&t3), PrimaryKey(&t2), PrimaryKey(&t1)},
   150  		},
   151  		"reverse: open start query": {
   152  			start:     nil,
   153  			end:       EncodeSequence(3),
   154  			method:    tb.ReversePrefixScan,
   155  			expResult: []testdata.TableModel{t2, t1},
   156  			expRowIDs: []RowID{PrimaryKey(&t2), PrimaryKey(&t1)},
   157  		},
   158  		"reverse: open start and end query": {
   159  			start:     nil,
   160  			end:       nil,
   161  			method:    tb.ReversePrefixScan,
   162  			expResult: []testdata.TableModel{t3, t2, t1},
   163  			expRowIDs: []RowID{PrimaryKey(&t3), PrimaryKey(&t2), PrimaryKey(&t1)},
   164  		},
   165  		"reverse: all matching 1st byte": {
   166  			start:     []byte{0},
   167  			end:       nil,
   168  			method:    tb.ReversePrefixScan,
   169  			expResult: []testdata.TableModel{t3, t2, t1},
   170  			expRowIDs: []RowID{PrimaryKey(&t3), PrimaryKey(&t2), PrimaryKey(&t1)},
   171  		},
   172  		"reverse: non matching prefix": {
   173  			start:     []byte{1},
   174  			end:       nil,
   175  			method:    tb.ReversePrefixScan,
   176  			expResult: []testdata.TableModel{},
   177  		},
   178  		"reverse: start equals end": {
   179  			start:    EncodeSequence(1),
   180  			end:      EncodeSequence(1),
   181  			method:   tb.ReversePrefixScan,
   182  			expError: errors.ErrORMInvalidArgument,
   183  		},
   184  		"reverse: start after end": {
   185  			start:    EncodeSequence(2),
   186  			end:      EncodeSequence(1),
   187  			method:   tb.ReversePrefixScan,
   188  			expError: errors.ErrORMInvalidArgument,
   189  		},
   190  	}
   191  	for msg, spec := range specs {
   192  		t.Run(msg, func(t *testing.T) {
   193  			it, err := spec.method(store, spec.start, spec.end)
   194  			require.True(t, spec.expError.Is(err), "expected #+v but got #+v", spec.expError, err)
   195  			if spec.expError != nil {
   196  				return
   197  			}
   198  			var loaded []testdata.TableModel
   199  			rowIDs, err := ReadAll(it, &loaded)
   200  			require.NoError(t, err)
   201  			assert.Equal(t, spec.expResult, loaded)
   202  			assert.Equal(t, spec.expRowIDs, rowIDs)
   203  		})
   204  	}
   205  }
   206  
   207  func TestContains(t *testing.T) {
   208  	interfaceRegistry := types.NewInterfaceRegistry()
   209  	cdc := codec.NewProtoCodec(interfaceRegistry)
   210  
   211  	ctx := NewMockContext()
   212  	store := ctx.KVStore(storetypes.NewKVStoreKey("test"))
   213  
   214  	tb, err := NewPrimaryKeyTable(PrimaryKeyTablePrefix, &testdata.TableModel{}, cdc)
   215  	require.NoError(t, err)
   216  
   217  	obj := testdata.TableModel{
   218  		Id:   1,
   219  		Name: "Some name",
   220  	}
   221  	err = tb.Create(store, &obj)
   222  	require.NoError(t, err)
   223  
   224  	specs := map[string]struct {
   225  		src PrimaryKeyed
   226  		exp bool
   227  	}{
   228  		"same object": {src: &obj, exp: true},
   229  		"clone": {
   230  			src: &testdata.TableModel{
   231  				Id:   1,
   232  				Name: "Some name",
   233  			},
   234  			exp: true,
   235  		},
   236  		"different primary key": {
   237  			src: &testdata.TableModel{
   238  				Id:   2,
   239  				Name: "Some name",
   240  			},
   241  			exp: false,
   242  		},
   243  		"different type, same key": {
   244  			src: mockPrimaryKeyed{&obj},
   245  			exp: false,
   246  		},
   247  	}
   248  	for msg, spec := range specs {
   249  		t.Run(msg, func(t *testing.T) {
   250  			got := tb.Contains(store, spec.src)
   251  			assert.Equal(t, spec.exp, got)
   252  		})
   253  	}
   254  }
   255  
   256  type mockPrimaryKeyed struct {
   257  	*testdata.TableModel
   258  }