etcd/server/storage/wal/version_test.go
Piotr Tabor 9abc895122 Goimports: Apply automated fixing to test files as well.
Signed-off-by: Piotr Tabor <ptab@google.com>
2022-12-29 13:04:45 +01:00

288 lines
7.3 KiB
Go

// Copyright 2021 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package wal
import (
"fmt"
"testing"
"github.com/coreos/go-semver/semver"
"github.com/golang/protobuf/proto"
"github.com/stretchr/testify/assert"
"google.golang.org/protobuf/reflect/protoreflect"
"go.etcd.io/etcd/api/v3/etcdserverpb"
"go.etcd.io/etcd/api/v3/membershippb"
"go.etcd.io/etcd/api/v3/version"
"go.etcd.io/etcd/pkg/v3/pbutil"
"go.etcd.io/raft/v3/raftpb"
)
func TestEtcdVersionFromEntry(t *testing.T) {
raftReq := etcdserverpb.InternalRaftRequest{Header: &etcdserverpb.RequestHeader{AuthRevision: 1}}
normalRequestData := pbutil.MustMarshal(&raftReq)
clusterVersionV3_6Req := etcdserverpb.InternalRaftRequest{ClusterVersionSet: &membershippb.ClusterVersionSetRequest{Ver: "3.6.0"}}
clusterVersionV3_6Data := pbutil.MustMarshal(&clusterVersionV3_6Req)
confChange := raftpb.ConfChange{Type: raftpb.ConfChangeAddLearnerNode}
confChangeData := pbutil.MustMarshal(&confChange)
confChangeV2 := raftpb.ConfChangeV2{Transition: raftpb.ConfChangeTransitionJointExplicit}
confChangeV2Data := pbutil.MustMarshal(&confChangeV2)
tcs := []struct {
name string
input raftpb.Entry
expect *semver.Version
}{
{
name: "Using RequestHeader AuthRevision in NormalEntry implies v3.1",
input: raftpb.Entry{
Term: 1,
Index: 2,
Type: raftpb.EntryNormal,
Data: normalRequestData,
},
expect: &version.V3_1,
},
{
name: "Setting cluster version implies version within",
input: raftpb.Entry{
Term: 1,
Index: 2,
Type: raftpb.EntryNormal,
Data: clusterVersionV3_6Data,
},
expect: &version.V3_6,
},
{
name: "Using ConfigChange implies v3.0",
input: raftpb.Entry{
Term: 1,
Index: 2,
Type: raftpb.EntryConfChange,
Data: confChangeData,
},
expect: &version.V3_0,
},
{
name: "Using ConfigChangeV2 implies v3.4",
input: raftpb.Entry{
Term: 1,
Index: 2,
Type: raftpb.EntryConfChangeV2,
Data: confChangeV2Data,
},
expect: &version.V3_4,
},
}
for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
var maxVer *semver.Version
err := visitEntry(tc.input, func(path protoreflect.FullName, ver *semver.Version) error {
maxVer = maxVersion(maxVer, ver)
return nil
})
assert.NoError(t, err)
assert.Equal(t, tc.expect, maxVer)
})
}
}
func TestEtcdVersionFromMessage(t *testing.T) {
tcs := []struct {
name string
input proto.Message
expect *semver.Version
}{
{
name: "Empty RequestHeader impies v3.0",
input: &etcdserverpb.RequestHeader{},
expect: &version.V3_0,
},
{
name: "RequestHeader AuthRevision field set implies v3.5",
input: &etcdserverpb.RequestHeader{AuthRevision: 1},
expect: &version.V3_1,
},
{
name: "RequestHeader Username set implies v3.0",
input: &etcdserverpb.RequestHeader{Username: "Alice"},
expect: &version.V3_0,
},
{
name: "When two fields are set take higher version",
input: &etcdserverpb.RequestHeader{AuthRevision: 1, Username: "Alice"},
expect: &version.V3_1,
},
{
name: "Setting a RequestHeader AuthRevision in subfield implies v3.1",
input: &etcdserverpb.InternalRaftRequest{Header: &etcdserverpb.RequestHeader{AuthRevision: 1}},
expect: &version.V3_1,
},
{
name: "Setting a DowngradeInfoSetRequest implies v3.5",
input: &etcdserverpb.InternalRaftRequest{DowngradeInfoSet: &membershippb.DowngradeInfoSetRequest{}},
expect: &version.V3_5,
},
{
name: "Enum CompareResult set to EQUAL implies v3.0",
input: &etcdserverpb.Compare{Result: etcdserverpb.Compare_EQUAL},
expect: &version.V3_0,
},
{
name: "Enum CompareResult set to NOT_EQUAL implies v3.1",
input: &etcdserverpb.Compare{Result: etcdserverpb.Compare_NOT_EQUAL},
expect: &version.V3_1,
},
{
name: "Oneof Compare version set implies v3.1",
input: &etcdserverpb.Compare{TargetUnion: &etcdserverpb.Compare_Version{}},
expect: &version.V3_0,
},
{
name: "Oneof Compare lease set implies v3.3",
input: &etcdserverpb.Compare{TargetUnion: &etcdserverpb.Compare_Lease{}},
expect: &version.V3_3,
},
}
for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
var maxVer *semver.Version
err := visitMessage(proto.MessageReflect(tc.input), func(path protoreflect.FullName, ver *semver.Version) error {
maxVer = maxVersion(maxVer, ver)
return nil
})
assert.NoError(t, err)
assert.Equal(t, tc.expect, maxVer)
})
}
}
func TestEtcdVersionFromFieldOptionsString(t *testing.T) {
tcs := []struct {
input string
expect *semver.Version
}{
{
input: "65001:0",
},
{
input: `65001:0 65004:"NodeID"`,
},
{
input: `[versionpb.XXX]:"3.5"`,
},
{
input: `[versionpb.etcd_version_msg]:"3.5"`,
expect: &version.V3_5,
},
{
input: `[versionpb.etcd_version_enum]:"3.5"`,
expect: &version.V3_5,
},
{
input: `[versionpb.etcd_version_field]:"3.5"`,
expect: &version.V3_5,
},
{
input: `[versionpb.etcd_version_enum_value]:"3.5"`,
expect: &version.V3_5,
},
{
input: `65001:0 [versionpb.etcd_version_msg]:"3.5"`,
expect: &version.V3_5,
},
{
input: `65004:"NodeID" [versionpb.etcd_version_msg]:"3.5"`,
expect: &version.V3_5,
},
{
input: `65004:"NodeID" [versionpb.etcd_version_enum]:"3.5"`,
expect: &version.V3_5,
},
{
input: `[versionpb.other_field]:"NodeID" [versionpb.etcd_version_msg]:"3.5"`,
expect: &version.V3_5,
},
{
input: `[versionpb.etcd_version_msg]:"3.5" 65001:0`,
expect: &version.V3_5,
},
{
input: `[versionpb.etcd_version_msg]:"3.5" 65004:"NodeID"`,
expect: &version.V3_5,
},
{
input: `[versionpb.etcd_version_msg]:"3.5" [versionpb.other_field]:"NodeID"`,
expect: &version.V3_5,
},
{
input: `[versionpb.other_field]:"NodeID" [versionpb.etcd_version_msg]:"3.5" [versionpb.another_field]:"NodeID"`,
expect: &version.V3_5,
},
{
input: `65001:0 [versionpb.etcd_version_msg]:"3.5" 65001:0"`,
expect: &version.V3_5,
},
}
for _, tc := range tcs {
t.Run(tc.input, func(t *testing.T) {
ver, err := etcdVersionFromOptionsString(tc.input)
assert.NoError(t, err)
assert.Equal(t, ver, tc.expect)
})
}
}
func TestMaxVersion(t *testing.T) {
tcs := []struct {
a, b, expect *semver.Version
}{
{
a: nil,
b: nil,
expect: nil,
},
{
a: &version.V3_5,
b: nil,
expect: &version.V3_5,
},
{
a: nil,
b: &version.V3_5,
expect: &version.V3_5,
},
{
a: &version.V3_6,
b: &version.V3_5,
expect: &version.V3_6,
},
{
a: &version.V3_5,
b: &version.V3_6,
expect: &version.V3_6,
},
}
for _, tc := range tcs {
t.Run(fmt.Sprintf("%v %v %v", tc.a, tc.b, tc.expect), func(t *testing.T) {
got := maxVersion(tc.a, tc.b)
assert.Equal(t, got, tc.expect)
})
}
}