[#103] proto: Test end-to-end scenario

Test the generated code, do not write yet another marshaling routine in
tests.

Before:
```
ok      git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto      0.003s  coverage: 55.6% of statements
```

After:
```
ok      git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto      0.003s  coverage: 80.0% of statements
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
Evgenii Stratonikov 2024-08-09 10:44:14 +03:00
parent 19247e8941
commit 47a48969b0
3 changed files with 138 additions and 798 deletions

View file

@ -71,6 +71,17 @@ protoc:
--go-grpc_out=. --go-grpc_opt=paths=source_relative $$f; \ --go-grpc_out=. --go-grpc_opt=paths=source_relative $$f; \
done done
protogen:
@go build -v -trimpath \
-o $(BIN)/protogen \
./util/protogen
protoc-test: protoc protogen
@$(PROTOC_DIR)/bin/protoc \
--plugin=protoc-gen-go-frostfs=$(abspath $(BIN)/protogen) \
--go-frostfs_out=. --go-frostfs_opt=paths=source_relative \
./util/proto/test/test.proto
# Run Unit Test with go test # Run Unit Test with go test
test: GOFLAGS ?= "-count=1" test: GOFLAGS ?= "-count=1"
test: test:

View file

@ -1,826 +1,155 @@
package proto_test package proto_test
import ( import (
"encoding/binary"
"math" "math"
"math/rand"
"testing" "testing"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto/test" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"google.golang.org/protobuf/encoding/protowire"
goproto "google.golang.org/protobuf/proto" goproto "google.golang.org/protobuf/proto"
) )
type SomeEnum int32 type protoInt interface {
~int32 | ~uint32 | ~int64 | ~uint64
type stablePrimitives struct {
FieldA []byte
FieldB string
FieldC bool
FieldD int32
FieldE uint32
FieldF int64
FieldG uint64
FieldH SomeEnum
FieldI uint64 // fixed64
FieldJ float64
FieldK uint32 // fixed32
} }
type stableRepPrimitives struct { func nonZero[T protoInt]() T {
FieldA [][]byte var r T
FieldB []string for r == 0 {
FieldC []int32 r = T(rand.Uint64())
FieldD []uint32 }
FieldE []int64 return r
FieldF []uint64
FieldFu []uint64
} }
const ( func TestStableMarshalSingle(t *testing.T) {
ENUM_UNKNOWN SomeEnum = 0
ENUM_POSITIVE SomeEnum = 1
ENUM_NEGATIVE SomeEnum = -1
)
func (s *stablePrimitives) stableMarshal(buf []byte, wrongField bool) ([]byte, error) {
if s == nil {
return []byte{}, nil
}
if buf == nil {
buf = make([]byte, s.stableSize())
}
var i, offset, fieldNum int
fieldNum = 1
if wrongField {
fieldNum++
}
i += proto.BytesMarshal(fieldNum, buf, s.FieldA)
fieldNum = 2
if wrongField {
fieldNum++
}
i += proto.StringMarshal(fieldNum, buf, s.FieldB)
fieldNum = 200
if wrongField {
fieldNum++
}
i += proto.BoolMarshal(fieldNum, buf, s.FieldC)
fieldNum = 201
if wrongField {
fieldNum++
}
i += proto.Int32Marshal(fieldNum, buf, s.FieldD)
fieldNum = 202
if wrongField {
fieldNum++
}
i += proto.UInt32Marshal(fieldNum, buf, s.FieldE)
fieldNum = 203
if wrongField {
fieldNum++
}
i += proto.Int64Marshal(fieldNum, buf, s.FieldF)
fieldNum = 204
if wrongField {
fieldNum++
}
i += proto.UInt64Marshal(fieldNum, buf, s.FieldG)
fieldNum = 205
if wrongField {
fieldNum++
}
i += proto.Fixed64Marshal(fieldNum, buf, s.FieldI)
fieldNum = 206
if wrongField {
fieldNum++
}
i += proto.Float64Marshal(fieldNum, buf, s.FieldJ)
fieldNum = 207
if wrongField {
fieldNum++
}
offset = proto.Fixed32Marshal(fieldNum, buf, s.FieldK)
i += offset
fieldNum = 300
if wrongField {
fieldNum++
}
i += proto.EnumMarshal(fieldNum, buf, int32(s.FieldH))
return buf, nil
}
func (s *stablePrimitives) stableSize() int {
return proto.BytesSize(1, s.FieldA) +
proto.StringSize(2, s.FieldB) +
proto.BoolSize(200, s.FieldC) +
proto.Int32Size(201, s.FieldD) +
proto.UInt32Size(202, s.FieldE) +
proto.Int64Size(203, s.FieldF) +
proto.UInt64Size(204, s.FieldG) +
proto.Fixed64Size(205, s.FieldI) +
proto.Float64Size(206, s.FieldJ) +
proto.Fixed32Size(207, s.FieldK) +
proto.EnumSize(300, int32(s.FieldH))
}
func (s *stableRepPrimitives) stableMarshal(buf []byte, wrongField bool) ([]byte, error) {
if s == nil {
return []byte{}, nil
}
if buf == nil {
buf = make([]byte, s.stableSize())
}
var i, fieldNum int
fieldNum = 1
if wrongField {
fieldNum++
}
i += proto.RepeatedBytesMarshal(fieldNum, buf, s.FieldA)
fieldNum = 2
if wrongField {
fieldNum++
}
i += proto.RepeatedStringMarshal(fieldNum, buf, s.FieldB)
fieldNum = 3
if wrongField {
fieldNum++
}
i += proto.RepeatedInt32Marshal(fieldNum, buf, s.FieldC)
fieldNum = 4
if wrongField {
fieldNum++
}
i += proto.RepeatedUInt32Marshal(fieldNum, buf, s.FieldD)
fieldNum = 5
if wrongField {
fieldNum++
}
i += proto.RepeatedInt64Marshal(fieldNum, buf, s.FieldE)
fieldNum = 6
if wrongField {
fieldNum++
}
i += proto.RepeatedUInt64Marshal(fieldNum, buf, s.FieldF)
fieldNum = 7
if wrongField {
fieldNum++
}
for j := range s.FieldFu {
{
prefix := protowire.EncodeTag(
protowire.Number(fieldNum),
protowire.VarintType)
i += binary.PutUvarint(buf[i:], uint64(prefix))
i += binary.PutUvarint(buf[i:], s.FieldFu[j])
}
}
return buf, nil
}
func (s *stableRepPrimitives) stableSize() int {
f1 := proto.RepeatedBytesSize(1, s.FieldA)
f2 := proto.RepeatedStringSize(2, s.FieldB)
f3, _ := proto.RepeatedInt32Size(3, s.FieldC)
f4, _ := proto.RepeatedUInt32Size(4, s.FieldD)
f5, _ := proto.RepeatedInt64Size(5, s.FieldE)
f6, _ := proto.RepeatedUInt64Size(6, s.FieldF)
var f7 int
for i := range s.FieldFu {
f7 += protowire.SizeGroup(protowire.Number(7), protowire.SizeVarint(s.FieldFu[i]))
}
return f1 + f2 + f3 + f4 + f5 + f6 + f7
}
func TestBytesMarshal(t *testing.T) {
t.Run("not empty", func(t *testing.T) {
data := []byte("Hello World")
testBytesMarshal(t, data, false)
testBytesMarshal(t, data, true)
})
t.Run("empty", func(t *testing.T) { t.Run("empty", func(t *testing.T) {
testBytesMarshal(t, []byte{}, false) input := &test.Primitives{}
require.Zero(t, input.StableSize())
r := input.StableMarshal(nil)
require.Empty(t, r)
}) })
t.Run("nil", func(t *testing.T) { marshalCases := []struct {
testBytesMarshal(t, nil, false) name string
}) input *test.Primitives
}{
{name: "bytes", input: &test.Primitives{FieldA: []byte{1, 2, 3}}},
{name: "string", input: &test.Primitives{FieldB: "123"}},
{name: "bool", input: &test.Primitives{FieldC: true}},
{name: "int32", input: &test.Primitives{FieldD: nonZero[int32]()}},
{name: "uint32", input: &test.Primitives{FieldE: nonZero[uint32]()}},
{name: "int64", input: &test.Primitives{FieldF: nonZero[int64]()}},
{name: "uint64", input: &test.Primitives{FieldG: nonZero[uint64]()}},
{name: "uint64", input: &test.Primitives{FieldI: nonZero[uint64]()}},
{name: "float64", input: &test.Primitives{FieldJ: math.Float64frombits(12345677890)}},
{name: "fixed32", input: &test.Primitives{FieldK: nonZero[uint32]()}},
{name: "enum, positive", input: &test.Primitives{FieldH: test.Primitives_POSITIVE}},
{name: "enum, negative", input: &test.Primitives{FieldH: test.Primitives_NEGATIVE}},
}
for _, tc := range marshalCases {
t.Run(tc.name, func(t *testing.T) {
r := tc.input.StableMarshal(nil)
require.Equal(t, len(r), tc.input.StableSize())
require.NotEmpty(t, r)
var actual test.Primitives
require.NoError(t, goproto.Unmarshal(r, &actual))
// Compare each field directly, because proto-generated code has private fields.
require.Equal(t, tc.input.FieldA, actual.FieldA)
require.Equal(t, tc.input.FieldB, actual.FieldB)
require.Equal(t, tc.input.FieldC, actual.FieldC)
require.Equal(t, tc.input.FieldD, actual.FieldD)
require.Equal(t, tc.input.FieldE, actual.FieldE)
require.Equal(t, tc.input.FieldF, actual.FieldF)
require.Equal(t, tc.input.FieldG, actual.FieldG)
require.Equal(t, tc.input.FieldI, actual.FieldI)
require.Equal(t, tc.input.FieldJ, actual.FieldJ)
require.Equal(t, tc.input.FieldK, actual.FieldK)
require.Equal(t, tc.input.FieldH, actual.FieldH)
})
}
} }
func TestStringMarshal(t *testing.T) { func randIntSlice[T protoInt](n int, includeZero bool) []T {
t.Run("not empty", func(t *testing.T) { r := make([]T, n)
data := "Hello World" if n == 0 {
testStringMarshal(t, data, false) return r
testStringMarshal(t, data, true) }
}) for i := range r {
r[i] = T(rand.Uint64())
}
if includeZero {
r[0] = 0
}
return r
}
func TestStableMarshalRep(t *testing.T) {
t.Run("empty", func(t *testing.T) { t.Run("empty", func(t *testing.T) {
testStringMarshal(t, "", false) marshalCases := []struct {
}) name string
} input *test.RepPrimitives
}{
func TestBoolMarshal(t *testing.T) { {name: "default", input: &test.RepPrimitives{}},
t.Run("true", func(t *testing.T) { {name: "bytes", input: &test.RepPrimitives{FieldA: [][]byte{}}},
testBoolMarshal(t, true, false) {name: "string", input: &test.RepPrimitives{FieldB: []string{}}},
testBoolMarshal(t, true, true) {name: "int32", input: &test.RepPrimitives{FieldC: []int32{}}},
}) {name: "uint32", input: &test.RepPrimitives{FieldD: []uint32{}}},
{name: "int64", input: &test.RepPrimitives{FieldE: []int64{}}},
t.Run("false", func(t *testing.T) { {name: "uint64", input: &test.RepPrimitives{FieldF: []uint64{}}},
testBoolMarshal(t, false, false) {name: "uint64", input: &test.RepPrimitives{FieldFu: []uint64{}}},
})
}
func TestInt32Marshal(t *testing.T) {
t.Run("zero", func(t *testing.T) {
testInt32Marshal(t, 0, false)
})
t.Run("positive", func(t *testing.T) {
testInt32Marshal(t, math.MaxInt32, false)
testInt32Marshal(t, math.MaxInt32, true)
})
t.Run("negative", func(t *testing.T) {
testInt32Marshal(t, math.MinInt32, false)
testInt32Marshal(t, math.MinInt32, true)
})
}
func TestUInt32Marshal(t *testing.T) {
t.Run("zero", func(t *testing.T) {
testUInt32Marshal(t, 0, false)
})
t.Run("non zero", func(t *testing.T) {
testUInt32Marshal(t, math.MaxUint32, false)
testUInt32Marshal(t, math.MaxUint32, true)
})
}
func TestInt64Marshal(t *testing.T) {
t.Run("zero", func(t *testing.T) {
testInt32Marshal(t, 0, false)
})
t.Run("positive", func(t *testing.T) {
testInt64Marshal(t, math.MaxInt64, false)
testInt64Marshal(t, math.MaxInt64, true)
})
t.Run("negative", func(t *testing.T) {
testInt64Marshal(t, math.MinInt64, false)
testInt64Marshal(t, math.MinInt64, true)
})
}
func TestUInt64Marshal(t *testing.T) {
t.Run("zero", func(t *testing.T) {
testUInt64Marshal(t, 0, false)
})
t.Run("non zero", func(t *testing.T) {
testUInt64Marshal(t, math.MaxUint64, false)
testUInt64Marshal(t, math.MaxUint64, true)
})
}
func TestEnumMarshal(t *testing.T) {
testEnumMarshal(t, ENUM_UNKNOWN, false)
testEnumMarshal(t, ENUM_POSITIVE, false)
testEnumMarshal(t, ENUM_POSITIVE, true)
testEnumMarshal(t, ENUM_NEGATIVE, false)
testEnumMarshal(t, ENUM_NEGATIVE, true)
}
func TestRepeatedBytesMarshal(t *testing.T) {
t.Run("not empty", func(t *testing.T) {
data := [][]byte{[]byte("One"), []byte("Two"), []byte("Three")}
testRepeatedBytesMarshal(t, data, false)
testRepeatedBytesMarshal(t, data, true)
})
t.Run("empty", func(t *testing.T) {
testRepeatedBytesMarshal(t, [][]byte{}, false)
})
t.Run("empty element", func(t *testing.T) {
testRepeatedBytesMarshal(t, [][]byte{{1}, {}}, false)
})
t.Run("nil", func(t *testing.T) {
testRepeatedBytesMarshal(t, nil, false)
})
}
func TestRepeatedStringMarshal(t *testing.T) {
t.Run("not empty", func(t *testing.T) {
data := []string{"One", "Two", "Three"}
testRepeatedStringMarshal(t, data, false)
testRepeatedStringMarshal(t, data, true)
})
t.Run("empty element", func(t *testing.T) {
testRepeatedStringMarshal(t, []string{""}, false)
})
t.Run("empty", func(t *testing.T) {
testRepeatedStringMarshal(t, []string{}, false)
})
t.Run("nil", func(t *testing.T) {
testRepeatedStringMarshal(t, nil, false)
})
}
func TestRepeatedInt32Marshal(t *testing.T) {
t.Run("not empty", func(t *testing.T) {
data := []int32{-1, 0, 1, 2, 3, 4, 5}
testRepeatedInt32Marshal(t, data, false)
testRepeatedInt32Marshal(t, data, true)
})
t.Run("empty", func(t *testing.T) {
testRepeatedInt32Marshal(t, []int32{}, false)
})
t.Run("nil", func(t *testing.T) {
testRepeatedInt32Marshal(t, nil, false)
})
}
func TestRepeatedUInt32Marshal(t *testing.T) {
t.Run("not empty", func(t *testing.T) {
data := []uint32{0, 1, 2, 3, 4, 5}
testRepeatedUInt32Marshal(t, data, false)
testRepeatedUInt32Marshal(t, data, true)
})
t.Run("empty", func(t *testing.T) {
testRepeatedUInt32Marshal(t, []uint32{}, false)
})
t.Run("nil", func(t *testing.T) {
testRepeatedUInt32Marshal(t, nil, false)
})
}
func TestRepeatedInt64Marshal(t *testing.T) {
t.Run("not empty", func(t *testing.T) {
data := []int64{-1, 0, 1, 2, 3, 4, 5}
testRepeatedInt64Marshal(t, data, false)
testRepeatedInt64Marshal(t, data, true)
})
t.Run("empty", func(t *testing.T) {
testRepeatedInt64Marshal(t, []int64{}, false)
})
t.Run("nil", func(t *testing.T) {
testRepeatedInt64Marshal(t, nil, false)
})
}
func TestRepeatedUInt64Marshal(t *testing.T) {
t.Run("not empty", func(t *testing.T) {
data := []uint64{0, 1, 2, 3, 4, 5}
testRepeatedUInt64Marshal(t, data, false)
testRepeatedUInt64Marshal(t, data, true)
})
t.Run("empty", func(t *testing.T) {
testRepeatedUInt64Marshal(t, []uint64{}, false)
})
t.Run("nil", func(t *testing.T) {
testRepeatedUInt64Marshal(t, nil, false)
})
}
func TestRepeatedUInt64MarshalUnpacked(t *testing.T) {
t.Run("not empty", func(t *testing.T) {
data := []uint64{0, 1, 2, 3, 4, 5}
testRepeatedUInt64MarshalUnpacked(t, data, false)
testRepeatedUInt64MarshalUnpacked(t, data, true)
})
t.Run("empty", func(t *testing.T) {
testRepeatedUInt64MarshalUnpacked(t, []uint64{}, false)
})
t.Run("nil", func(t *testing.T) {
testRepeatedUInt64MarshalUnpacked(t, nil, false)
})
}
func TestFixed64Marshal(t *testing.T) {
t.Run("zero", func(t *testing.T) {
testFixed64Marshal(t, 0, false)
})
t.Run("non zero", func(t *testing.T) {
testFixed64Marshal(t, math.MaxUint64, false)
testFixed64Marshal(t, math.MaxUint64, true)
})
}
func TestFloat64Marshal(t *testing.T) {
t.Run("zero", func(t *testing.T) {
testFloat64Marshal(t, 0, false)
})
t.Run("non zero", func(t *testing.T) {
f := math.Float64frombits(12345677890)
testFloat64Marshal(t, f, false)
testFloat64Marshal(t, f, true)
})
}
func TestFixed32Marshal(t *testing.T) {
t.Run("zero", func(t *testing.T) {
testFixed32Marshal(t, 0, false)
})
t.Run("non zero", func(t *testing.T) {
testFixed32Marshal(t, math.MaxUint32, false)
testFixed32Marshal(t, math.MaxUint32, true)
})
}
func testMarshal(t *testing.T, c stablePrimitives, tr *test.Primitives, wrongField bool) *test.Primitives {
var (
wire []byte
err error
)
wire, err = c.stableMarshal(nil, wrongField)
require.NoError(t, err)
wireGen, err := goproto.Marshal(tr)
require.NoError(t, err)
if !wrongField {
// we can check equality because single field cannot be unstable marshalled
require.Equal(t, wireGen, wire)
} else {
require.NotEqual(t, wireGen, wire)
}
result := new(test.Primitives)
err = goproto.Unmarshal(wire, result)
require.NoError(t, err)
return result
}
func testBytesMarshal(t *testing.T, data []byte, wrongField bool) {
var (
custom = stablePrimitives{FieldA: data}
transport = test.Primitives{FieldA: data}
)
result := testMarshal(t, custom, &transport, wrongField)
if !wrongField {
require.Len(t, result.FieldA, len(data))
if len(data) > 0 {
require.Equal(t, data, result.FieldA)
} }
} else {
require.Len(t, result.FieldA, 0)
}
}
func testStringMarshal(t *testing.T, s string, wrongField bool) { for _, tc := range marshalCases {
var ( require.Zero(t, tc.input.StableSize())
custom = stablePrimitives{FieldB: s}
transport = test.Primitives{FieldB: s}
)
result := testMarshal(t, custom, &transport, wrongField) r := tc.input.StableMarshal(nil)
require.Empty(t, r)
if !wrongField {
require.Len(t, result.FieldB, len(s))
if len(s) > 0 {
require.Equal(t, s, result.FieldB)
} }
} else { })
require.Len(t, result.FieldB, 0)
} marshalCases := []struct {
} name string
input *test.RepPrimitives
func testBoolMarshal(t *testing.T, b bool, wrongField bool) { }{
var ( {name: "bytes", input: &test.RepPrimitives{FieldA: [][]byte{{1, 2, 3}}}},
custom = stablePrimitives{FieldC: b} {name: "string", input: &test.RepPrimitives{FieldB: []string{"123"}}},
transport = test.Primitives{FieldC: b} {name: "int32", input: &test.RepPrimitives{FieldC: randIntSlice[int32](1, true)}},
) {name: "int32", input: &test.RepPrimitives{FieldC: randIntSlice[int32](2, true)}},
{name: "int32", input: &test.RepPrimitives{FieldC: randIntSlice[int32](2, false)}},
result := testMarshal(t, custom, &transport, wrongField) {name: "uint32", input: &test.RepPrimitives{FieldD: randIntSlice[uint32](1, true)}},
{name: "uint32", input: &test.RepPrimitives{FieldD: randIntSlice[uint32](2, true)}},
if !wrongField { {name: "uint32", input: &test.RepPrimitives{FieldD: randIntSlice[uint32](2, false)}},
require.Equal(t, b, result.FieldC) {name: "int64", input: &test.RepPrimitives{FieldE: randIntSlice[int64](1, true)}},
} else { {name: "int64", input: &test.RepPrimitives{FieldE: randIntSlice[int64](2, true)}},
require.False(t, false, result.FieldC) {name: "int64", input: &test.RepPrimitives{FieldE: randIntSlice[int64](2, false)}},
} {name: "uint64", input: &test.RepPrimitives{FieldF: randIntSlice[uint64](1, true)}},
} {name: "uint64", input: &test.RepPrimitives{FieldF: randIntSlice[uint64](2, true)}},
{name: "uint64", input: &test.RepPrimitives{FieldF: randIntSlice[uint64](2, false)}},
func testInt32Marshal(t *testing.T, n int32, wrongField bool) { {name: "uint64", input: &test.RepPrimitives{FieldFu: randIntSlice[uint64](1, true)}},
var ( {name: "uint64", input: &test.RepPrimitives{FieldFu: randIntSlice[uint64](2, true)}},
custom = stablePrimitives{FieldD: n} {name: "uint64", input: &test.RepPrimitives{FieldFu: randIntSlice[uint64](2, false)}},
transport = test.Primitives{FieldD: n} }
) for _, tc := range marshalCases {
t.Run(tc.name, func(t *testing.T) {
result := testMarshal(t, custom, &transport, wrongField) r := tc.input.StableMarshal(nil)
require.Equal(t, len(r), tc.input.StableSize())
if !wrongField { require.NotEmpty(t, r)
require.Equal(t, n, result.FieldD)
} else { var actual test.RepPrimitives
require.EqualValues(t, 0, result.FieldD) require.NoError(t, goproto.Unmarshal(r, &actual))
}
} // Compare each field directly, because proto-generated code has private fields.
require.Equal(t, tc.input.FieldA, actual.FieldA)
func testUInt32Marshal(t *testing.T, n uint32, wrongField bool) { require.Equal(t, tc.input.FieldB, actual.FieldB)
var ( require.Equal(t, tc.input.FieldC, actual.FieldC)
custom = stablePrimitives{FieldE: n} require.Equal(t, tc.input.FieldD, actual.FieldD)
transport = test.Primitives{FieldE: n} require.Equal(t, tc.input.FieldE, actual.FieldE)
) require.Equal(t, tc.input.FieldF, actual.FieldF)
require.Equal(t, tc.input.FieldFu, actual.FieldFu)
result := testMarshal(t, custom, &transport, wrongField) })
if !wrongField {
require.Equal(t, n, result.FieldE)
} else {
require.EqualValues(t, 0, result.FieldE)
}
}
func testInt64Marshal(t *testing.T, n int64, wrongField bool) {
var (
custom = stablePrimitives{FieldF: n}
transport = test.Primitives{FieldF: n}
)
result := testMarshal(t, custom, &transport, wrongField)
if !wrongField {
require.Equal(t, n, result.FieldF)
} else {
require.EqualValues(t, 0, result.FieldF)
}
}
func testUInt64Marshal(t *testing.T, n uint64, wrongField bool) {
var (
custom = stablePrimitives{FieldG: n}
transport = test.Primitives{FieldG: n}
)
result := testMarshal(t, custom, &transport, wrongField)
if !wrongField {
require.Equal(t, n, result.FieldG)
} else {
require.EqualValues(t, 0, result.FieldG)
}
}
func testFloat64Marshal(t *testing.T, n float64, wrongField bool) {
var (
custom = stablePrimitives{FieldJ: n}
transport = test.Primitives{FieldJ: n}
)
result := testMarshal(t, custom, &transport, wrongField)
if !wrongField {
require.Equal(t, n, result.FieldJ)
} else {
require.EqualValues(t, 0, result.FieldJ)
}
}
func testEnumMarshal(t *testing.T, e SomeEnum, wrongField bool) {
var (
custom = stablePrimitives{FieldH: e}
transport = test.Primitives{FieldH: test.Primitives_SomeEnum(e)}
)
result := testMarshal(t, custom, &transport, wrongField)
if !wrongField {
require.EqualValues(t, custom.FieldH, result.FieldH)
} else {
require.EqualValues(t, 0, result.FieldH)
}
}
func testRepMarshal(t *testing.T, c stableRepPrimitives, tr *test.RepPrimitives, wrongField bool) *test.RepPrimitives {
var (
wire []byte
err error
)
wire, err = c.stableMarshal(nil, wrongField)
require.NoError(t, err)
wireGen, err := goproto.Marshal(tr)
require.NoError(t, err)
if !wrongField {
// we can check equality because single field cannot be unstable marshalled
require.Equal(t, wireGen, wire)
} else {
require.NotEqual(t, wireGen, wire)
}
result := new(test.RepPrimitives)
err = goproto.Unmarshal(wire, result)
require.NoError(t, err)
return result
}
func testRepeatedBytesMarshal(t *testing.T, data [][]byte, wrongField bool) {
var (
custom = stableRepPrimitives{FieldA: data}
transport = test.RepPrimitives{FieldA: data}
)
result := testRepMarshal(t, custom, &transport, wrongField)
if !wrongField {
require.Len(t, result.FieldA, len(data))
if len(data) > 0 {
require.Equal(t, data, result.FieldA)
}
} else {
require.Len(t, result.FieldA, 0)
}
}
func testRepeatedStringMarshal(t *testing.T, s []string, wrongField bool) {
var (
custom = stableRepPrimitives{FieldB: s}
transport = test.RepPrimitives{FieldB: s}
)
result := testRepMarshal(t, custom, &transport, wrongField)
if !wrongField {
require.Len(t, result.FieldB, len(s))
if len(s) > 0 {
require.Equal(t, s, result.FieldB)
}
} else {
require.Len(t, result.FieldB, 0)
}
}
func testRepeatedInt32Marshal(t *testing.T, n []int32, wrongField bool) {
var (
custom = stableRepPrimitives{FieldC: n}
transport = test.RepPrimitives{FieldC: n}
)
result := testRepMarshal(t, custom, &transport, wrongField)
if !wrongField {
require.Len(t, result.FieldC, len(n))
if len(n) > 0 {
require.Equal(t, n, result.FieldC)
}
} else {
require.Len(t, result.FieldC, 0)
}
}
func testRepeatedUInt32Marshal(t *testing.T, n []uint32, wrongField bool) {
var (
custom = stableRepPrimitives{FieldD: n}
transport = test.RepPrimitives{FieldD: n}
)
result := testRepMarshal(t, custom, &transport, wrongField)
if !wrongField {
require.Len(t, result.FieldD, len(n))
if len(n) > 0 {
require.Equal(t, n, result.FieldD)
}
} else {
require.Len(t, result.FieldD, 0)
}
}
func testRepeatedInt64Marshal(t *testing.T, n []int64, wrongField bool) {
var (
custom = stableRepPrimitives{FieldE: n}
transport = test.RepPrimitives{FieldE: n}
)
result := testRepMarshal(t, custom, &transport, wrongField)
if !wrongField {
require.Len(t, result.FieldE, len(n))
if len(n) > 0 {
require.Equal(t, n, result.FieldE)
}
} else {
require.Len(t, result.FieldE, 0)
}
}
func testRepeatedUInt64Marshal(t *testing.T, n []uint64, wrongField bool) {
var (
custom = stableRepPrimitives{FieldF: n}
transport = test.RepPrimitives{FieldF: n}
)
result := testRepMarshal(t, custom, &transport, wrongField)
if !wrongField {
require.Len(t, result.FieldF, len(n))
if len(n) > 0 {
require.Equal(t, n, result.FieldF)
}
} else {
require.Len(t, result.FieldF, 0)
}
}
func testRepeatedUInt64MarshalUnpacked(t *testing.T, n []uint64, wrongField bool) {
var (
custom = stableRepPrimitives{FieldFu: n}
transport = test.RepPrimitives{FieldFu: n}
)
result := testRepMarshal(t, custom, &transport, wrongField)
if !wrongField {
require.Len(t, result.FieldFu, len(n))
if len(n) > 0 {
require.Equal(t, n, result.FieldFu)
}
} else {
require.Len(t, result.FieldFu, 0)
}
}
func testFixed64Marshal(t *testing.T, n uint64, wrongField bool) {
var (
custom = stablePrimitives{FieldI: n}
transport = test.Primitives{FieldI: n}
)
result := testMarshal(t, custom, &transport, wrongField)
if !wrongField {
require.Equal(t, n, result.FieldI)
} else {
require.EqualValues(t, 0, result.FieldI)
}
}
func testFixed32Marshal(t *testing.T, n uint32, wrongField bool) {
var (
custom = stablePrimitives{FieldK: n}
transport = test.Primitives{FieldK: n}
)
result := testMarshal(t, custom, &transport, wrongField)
if !wrongField {
require.Equal(t, n, result.FieldK)
} else {
require.EqualValues(t, 0, result.FieldK)
} }
} }

BIN
util/proto/test/test_frostfs.pb.go generated Normal file

Binary file not shown.