94 lines
3.0 KiB
Go
94 lines
3.0 KiB
Go
package ormkv_test
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"testing"
|
|
|
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
|
"gotest.tools/v3/assert"
|
|
"pgregory.net/rapid"
|
|
|
|
"github.com/cosmos/cosmos-sdk/orm/encoding/ormkv"
|
|
"github.com/cosmos/cosmos-sdk/orm/internal/testpb"
|
|
"github.com/cosmos/cosmos-sdk/orm/internal/testutil"
|
|
"github.com/cosmos/cosmos-sdk/orm/types/ormerrors"
|
|
)
|
|
|
|
func TestUniqueKeyCodec(t *testing.T) {
|
|
rapid.Check(t, func(t *rapid.T) {
|
|
keyCodec := testutil.TestKeyCodecGen(1, 5).Draw(t, "keyCodec").(testutil.TestKeyCodec)
|
|
pkCodec := testutil.TestKeyCodecGen(1, 5).Draw(t, "primaryKeyCodec").(testutil.TestKeyCodec)
|
|
|
|
// check if we have a trivial unique index where all of the fields
|
|
// in the primary key are in the unique key, we should expect an
|
|
// error in this case
|
|
isInPk := map[protoreflect.Name]bool{}
|
|
for _, spec := range pkCodec.KeySpecs {
|
|
isInPk[spec.FieldName] = true
|
|
}
|
|
numPkFields := 0
|
|
for _, spec := range keyCodec.KeySpecs {
|
|
if isInPk[spec.FieldName] {
|
|
numPkFields++
|
|
}
|
|
}
|
|
isTrivialUniqueKey := numPkFields == len(pkCodec.KeySpecs)
|
|
|
|
messageType := (&testpb.ExampleTable{}).ProtoReflect().Type()
|
|
uniqueKeyCdc, err := ormkv.NewUniqueKeyCodec(
|
|
keyCodec.Codec.Prefix(),
|
|
messageType,
|
|
keyCodec.Codec.GetFieldNames(),
|
|
pkCodec.Codec.GetFieldNames(),
|
|
)
|
|
|
|
if isTrivialUniqueKey {
|
|
assert.ErrorContains(t, err, "no new uniqueness constraint")
|
|
return
|
|
} else {
|
|
assert.NilError(t, err)
|
|
}
|
|
|
|
for i := 0; i < 100; i++ {
|
|
a := testutil.GenA.Draw(t, fmt.Sprintf("a%d", i)).(*testpb.ExampleTable)
|
|
key := keyCodec.Codec.GetKeyValues(a.ProtoReflect())
|
|
pk := pkCodec.Codec.GetKeyValues(a.ProtoReflect())
|
|
uniq1 := &ormkv.IndexKeyEntry{
|
|
TableName: messageType.Descriptor().FullName(),
|
|
Fields: keyCodec.Codec.GetFieldNames(),
|
|
IsUnique: true,
|
|
IndexValues: key,
|
|
PrimaryKey: pk,
|
|
}
|
|
k, v, err := uniqueKeyCdc.EncodeEntry(uniq1)
|
|
assert.NilError(t, err)
|
|
|
|
k2, v2, err := uniqueKeyCdc.EncodeKVFromMessage(a.ProtoReflect())
|
|
assert.NilError(t, err)
|
|
assert.Assert(t, bytes.Equal(k, k2))
|
|
assert.Assert(t, bytes.Equal(v, v2))
|
|
|
|
entry2, err := uniqueKeyCdc.DecodeEntry(k, v)
|
|
assert.NilError(t, err)
|
|
uniq2 := entry2.(*ormkv.IndexKeyEntry)
|
|
assert.Equal(t, 0, keyCodec.Codec.CompareKeys(uniq1.IndexValues, uniq2.IndexValues))
|
|
assert.Equal(t, 0, pkCodec.Codec.CompareKeys(uniq1.PrimaryKey, uniq2.PrimaryKey))
|
|
assert.Equal(t, true, uniq2.IsUnique)
|
|
assert.Equal(t, messageType.Descriptor().FullName(), uniq2.TableName)
|
|
assert.DeepEqual(t, uniq1.Fields, uniq2.Fields)
|
|
|
|
idxFields, pk2, err := uniqueKeyCdc.DecodeIndexKey(k, v)
|
|
assert.NilError(t, err)
|
|
assert.Equal(t, 0, keyCodec.Codec.CompareKeys(key, idxFields))
|
|
assert.Equal(t, 0, pkCodec.Codec.CompareKeys(pk, pk2))
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestTrivialUnique(t *testing.T) {
|
|
_, err := ormkv.NewUniqueKeyCodec(nil, (&testpb.ExampleTable{}).ProtoReflect().Type(),
|
|
[]protoreflect.Name{"u32", "str"}, []protoreflect.Name{"str", "u32"})
|
|
assert.ErrorIs(t, err, ormerrors.InvalidTableDefinition)
|
|
}
|