cosmos-sdk/orm/encoding/ormfield/codec_test.go
Aaron Craelius 1486a669b7
fix(orm): add additional checks on invalid tables (#11387)
## Description

Adds checks for two types of errors in table definitions
* defining a key on an `optional` field (haven't found a way to test unfortunately because a test case will break the code generator)
* defining a trivial unique key, essentially a unique key which contains all the fields in the primary key and is redundant



---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed 
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
2022-04-05 19:48:58 +00:00

172 lines
4.8 KiB
Go

package ormfield_test
import (
"bytes"
"fmt"
"testing"
"github.com/cosmos/cosmos-sdk/orm/encoding/ormfield"
"google.golang.org/protobuf/reflect/protoreflect"
"gotest.tools/v3/assert"
"pgregory.net/rapid"
"github.com/cosmos/cosmos-sdk/orm/types/ormerrors"
"github.com/cosmos/cosmos-sdk/orm/internal/testutil"
)
func TestCodec(t *testing.T) {
for _, ks := range testutil.TestFieldSpecs {
testCodec(t, ks)
}
}
func testCodec(t *testing.T, spec testutil.TestFieldSpec) {
t.Run(fmt.Sprintf("%s %v", spec.FieldName, false), func(t *testing.T) {
testCodecNT(t, spec.FieldName, spec.Gen, false)
})
t.Run(fmt.Sprintf("%s %v", spec.FieldName, true), func(t *testing.T) {
testCodecNT(t, spec.FieldName, spec.Gen, true)
})
}
func testCodecNT(t *testing.T, fname protoreflect.Name, generator *rapid.Generator, nonTerminal bool) {
cdc, err := testutil.MakeTestCodec(fname, nonTerminal)
assert.NilError(t, err)
rapid.Check(t, func(t *rapid.T) {
x := protoreflect.ValueOf(generator.Draw(t, string(fname)))
bz1 := checkEncodeDecodeSize(t, x, cdc)
if cdc.IsOrdered() {
y := protoreflect.ValueOf(generator.Draw(t, fmt.Sprintf("%s 2", fname)))
bz2 := checkEncodeDecodeSize(t, y, cdc)
assert.Equal(t, cdc.Compare(x, y), bytes.Compare(bz1, bz2))
}
})
}
func checkEncodeDecodeSize(t *rapid.T, x protoreflect.Value, cdc ormfield.Codec) []byte {
buf := &bytes.Buffer{}
err := cdc.Encode(x, buf)
assert.NilError(t, err)
bz := buf.Bytes()
size, err := cdc.ComputeBufferSize(x)
assert.NilError(t, err)
assert.Assert(t, size >= len(bz))
fixedSize := cdc.FixedBufferSize()
if fixedSize > 0 {
assert.Equal(t, fixedSize, size)
}
y, err := cdc.Decode(bytes.NewReader(bz))
assert.NilError(t, err)
assert.Equal(t, 0, cdc.Compare(x, y))
return bz
}
func TestUnsupportedFields(t *testing.T) {
_, err := ormfield.GetCodec(nil, false)
assert.ErrorContains(t, err, ormerrors.InvalidKeyField.Error())
_, err = ormfield.GetCodec(testutil.GetTestField("repeated"), false)
assert.ErrorContains(t, err, ormerrors.InvalidKeyField.Error())
_, err = ormfield.GetCodec(testutil.GetTestField("map"), false)
assert.ErrorContains(t, err, ormerrors.InvalidKeyField.Error())
_, err = ormfield.GetCodec(testutil.GetTestField("msg"), false)
assert.ErrorContains(t, err, ormerrors.InvalidKeyField.Error())
_, err = ormfield.GetCodec(testutil.GetTestField("oneof"), false)
assert.ErrorContains(t, err, ormerrors.InvalidKeyField.Error())
}
func TestCompactUInt32(t *testing.T) {
var lastBz []byte
testEncodeDecode := func(x uint32, expectedLen int) {
bz := ormfield.EncodeCompactUint32(x)
assert.Equal(t, expectedLen, len(bz))
y, err := ormfield.DecodeCompactUint32(bytes.NewReader(bz))
assert.NilError(t, err)
assert.Equal(t, x, y)
assert.Assert(t, bytes.Compare(lastBz, bz) < 0)
lastBz = bz
}
testEncodeDecode(64, 2)
testEncodeDecode(16383, 2)
testEncodeDecode(16384, 3)
testEncodeDecode(4194303, 3)
testEncodeDecode(4194304, 4)
testEncodeDecode(1073741823, 4)
testEncodeDecode(1073741824, 5)
// randomized tests
rapid.Check(t, func(t *rapid.T) {
x := rapid.Uint32().Draw(t, "x").(uint32)
y := rapid.Uint32().Draw(t, "y").(uint32)
bx := ormfield.EncodeCompactUint32(x)
by := ormfield.EncodeCompactUint32(y)
cmp := bytes.Compare(bx, by)
if x < y {
assert.Equal(t, -1, cmp)
} else if x == y {
assert.Equal(t, 0, cmp)
} else {
assert.Equal(t, 1, cmp)
}
x2, err := ormfield.DecodeCompactUint32(bytes.NewReader(bx))
assert.NilError(t, err)
assert.Equal(t, x, x2)
y2, err := ormfield.DecodeCompactUint32(bytes.NewReader(by))
assert.NilError(t, err)
assert.Equal(t, y, y2)
})
}
func TestCompactUInt64(t *testing.T) {
var lastBz []byte
testEncodeDecode := func(x uint64, expectedLen int) {
bz := ormfield.EncodeCompactUint64(x)
assert.Equal(t, expectedLen, len(bz))
y, err := ormfield.DecodeCompactUint64(bytes.NewReader(bz))
assert.NilError(t, err)
assert.Equal(t, x, y)
assert.Assert(t, bytes.Compare(lastBz, bz) < 0)
lastBz = bz
}
testEncodeDecode(64, 2)
testEncodeDecode(16383, 2)
testEncodeDecode(16384, 4)
testEncodeDecode(4194303, 4)
testEncodeDecode(4194304, 4)
testEncodeDecode(1073741823, 4)
testEncodeDecode(1073741824, 6)
testEncodeDecode(70368744177663, 6)
testEncodeDecode(70368744177664, 9)
// randomized tests
rapid.Check(t, func(t *rapid.T) {
x := rapid.Uint64().Draw(t, "x").(uint64)
y := rapid.Uint64().Draw(t, "y").(uint64)
bx := ormfield.EncodeCompactUint64(x)
by := ormfield.EncodeCompactUint64(y)
cmp := bytes.Compare(bx, by)
if x < y {
assert.Equal(t, -1, cmp)
} else if x == y {
assert.Equal(t, 0, cmp)
} else {
assert.Equal(t, 1, cmp)
}
x2, err := ormfield.DecodeCompactUint64(bytes.NewReader(bx))
assert.NilError(t, err)
assert.Equal(t, x, x2)
y2, err := ormfield.DecodeCompactUint64(bytes.NewReader(by))
assert.NilError(t, err)
assert.Equal(t, y, y2)
})
}