mirror of
https://github.com/talent-plan/tinykv.git
synced 2025-01-13 13:50:43 +08:00
15838152aa
* fix invalid order of expected and actual in tests Co-authored-by: Connor <zbk602423539@gmail.com>
194 lines
6.5 KiB
Go
194 lines
6.5 KiB
Go
package util
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/pingcap-incubator/tinykv/proto/pkg/eraftpb"
|
|
"github.com/pingcap-incubator/tinykv/proto/pkg/metapb"
|
|
"github.com/pingcap-incubator/tinykv/proto/pkg/raft_cmdpb"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestCheckKeyInRegion(t *testing.T) {
|
|
type Case struct {
|
|
Key []byte
|
|
StartKey []byte
|
|
EndKey []byte
|
|
IsInRegion bool
|
|
Inclusive bool
|
|
Exclusive bool
|
|
}
|
|
test_cases := []Case{
|
|
{Key: []byte{}, StartKey: []byte{}, EndKey: []byte{}, IsInRegion: true, Inclusive: true, Exclusive: false},
|
|
{Key: []byte{}, StartKey: []byte{}, EndKey: []byte{6}, IsInRegion: true, Inclusive: true, Exclusive: false},
|
|
{Key: []byte{}, StartKey: []byte{3}, EndKey: []byte{6}, IsInRegion: false, Inclusive: false, Exclusive: false},
|
|
{Key: []byte{4}, StartKey: []byte{3}, EndKey: []byte{6}, IsInRegion: true, Inclusive: true, Exclusive: true},
|
|
{Key: []byte{4}, StartKey: []byte{3}, EndKey: []byte{}, IsInRegion: true, Inclusive: true, Exclusive: true},
|
|
{Key: []byte{3}, StartKey: []byte{3}, EndKey: []byte{}, IsInRegion: true, Inclusive: true, Exclusive: false},
|
|
{Key: []byte{2}, StartKey: []byte{3}, EndKey: []byte{6}, IsInRegion: false, Inclusive: false, Exclusive: false},
|
|
{Key: []byte{}, StartKey: []byte{3}, EndKey: []byte{6}, IsInRegion: false, Inclusive: false, Exclusive: false},
|
|
{Key: []byte{}, StartKey: []byte{3}, EndKey: []byte{}, IsInRegion: false, Inclusive: false, Exclusive: false},
|
|
{Key: []byte{6}, StartKey: []byte{3}, EndKey: []byte{6}, IsInRegion: false, Inclusive: true, Exclusive: false},
|
|
}
|
|
for _, c := range test_cases {
|
|
region := new(metapb.Region)
|
|
region.StartKey = c.StartKey
|
|
region.EndKey = c.EndKey
|
|
result := CheckKeyInRegion(c.Key, region)
|
|
assert.Equal(t, c.IsInRegion, result == nil)
|
|
result = CheckKeyInRegionInclusive(c.Key, region)
|
|
assert.Equal(t, c.Inclusive, result == nil)
|
|
result = CheckKeyInRegionExclusive(c.Key, region)
|
|
assert.Equal(t, c.Exclusive, result == nil)
|
|
}
|
|
}
|
|
|
|
func TestIsInitialMsg(t *testing.T) {
|
|
type MsgInfo struct {
|
|
MessageType eraftpb.MessageType
|
|
Commit uint64
|
|
IsInitialMsg bool
|
|
}
|
|
tbl := []MsgInfo{
|
|
{MessageType: eraftpb.MessageType_MsgRequestVote, Commit: RaftInvalidIndex, IsInitialMsg: true},
|
|
{MessageType: eraftpb.MessageType_MsgHeartbeat, Commit: RaftInvalidIndex, IsInitialMsg: true},
|
|
{MessageType: eraftpb.MessageType_MsgHeartbeat, Commit: 100, IsInitialMsg: false},
|
|
{MessageType: eraftpb.MessageType_MsgAppend, Commit: 100, IsInitialMsg: false},
|
|
}
|
|
for _, m := range tbl {
|
|
msg := new(eraftpb.Message)
|
|
msg.MsgType = m.MessageType
|
|
msg.Commit = m.Commit
|
|
assert.Equal(t, m.IsInitialMsg, IsInitialMsg(msg))
|
|
}
|
|
}
|
|
|
|
func TestEpochStale(t *testing.T) {
|
|
epoch := new(metapb.RegionEpoch)
|
|
epoch.Version = 10
|
|
epoch.ConfVer = 10
|
|
|
|
type Ep struct {
|
|
Version uint64
|
|
ConfVer uint64
|
|
IsStale bool
|
|
}
|
|
tbl := []Ep{
|
|
{Version: 11, ConfVer: 10, IsStale: true},
|
|
{Version: 10, ConfVer: 11, IsStale: true},
|
|
{Version: 10, ConfVer: 10, IsStale: false},
|
|
{Version: 10, ConfVer: 9, IsStale: false},
|
|
}
|
|
for _, e := range tbl {
|
|
checkEpoch := new(metapb.RegionEpoch)
|
|
checkEpoch.Version = e.Version
|
|
checkEpoch.ConfVer = e.ConfVer
|
|
assert.Equal(t, e.IsStale, IsEpochStale(epoch, checkEpoch))
|
|
}
|
|
}
|
|
|
|
func TestCheckRegionEpoch(t *testing.T) {
|
|
epoch := new(metapb.RegionEpoch)
|
|
epoch.ConfVer = 2
|
|
epoch.Version = 2
|
|
region := new(metapb.Region)
|
|
region.RegionEpoch = epoch
|
|
|
|
// Epoch is required for most requests even if it's empty.
|
|
emptyReq := new(raft_cmdpb.RaftCmdRequest)
|
|
assert.NotNil(t, CheckRegionEpoch(emptyReq, region, false))
|
|
|
|
// These admin commands do not require epoch.
|
|
tys := []raft_cmdpb.AdminCmdType{
|
|
raft_cmdpb.AdminCmdType_CompactLog,
|
|
raft_cmdpb.AdminCmdType_InvalidAdmin,
|
|
}
|
|
for _, ty := range tys {
|
|
admin := new(raft_cmdpb.AdminRequest)
|
|
admin.CmdType = ty
|
|
req := new(raft_cmdpb.RaftCmdRequest)
|
|
req.AdminRequest = admin
|
|
|
|
// It is Okay if req does not have region epoch.
|
|
assert.Nil(t, CheckRegionEpoch(req, region, false))
|
|
|
|
req.Header = new(raft_cmdpb.RaftRequestHeader)
|
|
req.Header.RegionEpoch = epoch
|
|
assert.Nil(t, CheckRegionEpoch(req, region, true))
|
|
assert.Nil(t, CheckRegionEpoch(req, region, false))
|
|
}
|
|
|
|
// These admin commands requires epoch.version.
|
|
tys = []raft_cmdpb.AdminCmdType{
|
|
raft_cmdpb.AdminCmdType_Split,
|
|
raft_cmdpb.AdminCmdType_TransferLeader,
|
|
}
|
|
for _, ty := range tys {
|
|
admin := new(raft_cmdpb.AdminRequest)
|
|
admin.CmdType = ty
|
|
req := new(raft_cmdpb.RaftCmdRequest)
|
|
req.AdminRequest = admin
|
|
|
|
// Error if req does not have region epoch.
|
|
assert.NotNil(t, CheckRegionEpoch(req, region, false))
|
|
|
|
staleVersionEpoch := *epoch
|
|
staleVersionEpoch.Version = 1
|
|
staleRegion := new(metapb.Region)
|
|
staleVersionEpochCloned := staleVersionEpoch
|
|
staleRegion.RegionEpoch = &staleVersionEpochCloned
|
|
staleVersionEpochCloned2 := staleVersionEpoch
|
|
req.Header = new(raft_cmdpb.RaftRequestHeader)
|
|
req.Header.RegionEpoch = &staleVersionEpochCloned2
|
|
assert.Nil(t, CheckRegionEpoch(req, staleRegion, false))
|
|
|
|
latestVersionEpoch := *epoch
|
|
latestVersionEpoch.Version = 3
|
|
|
|
for _, e := range []metapb.RegionEpoch{staleVersionEpoch, latestVersionEpoch} {
|
|
eCloned := e
|
|
req.Header.RegionEpoch = &eCloned
|
|
assert.NotNil(t, CheckRegionEpoch(req, region, false))
|
|
assert.NotNil(t, CheckRegionEpoch(req, region, true))
|
|
}
|
|
}
|
|
|
|
// These admin commands requires epoch.conf_version.
|
|
for _, ty := range []raft_cmdpb.AdminCmdType{
|
|
raft_cmdpb.AdminCmdType_Split,
|
|
raft_cmdpb.AdminCmdType_ChangePeer,
|
|
raft_cmdpb.AdminCmdType_TransferLeader,
|
|
} {
|
|
admin := new(raft_cmdpb.AdminRequest)
|
|
admin.CmdType = ty
|
|
req := new(raft_cmdpb.RaftCmdRequest)
|
|
req.AdminRequest = admin
|
|
req.Header = new(raft_cmdpb.RaftRequestHeader)
|
|
|
|
// Error if req does not have region epoch.
|
|
assert.NotNil(t, CheckRegionEpoch(req, region, false))
|
|
|
|
staleConfEpoch := cloneEpoch(epoch)
|
|
staleConfEpoch.ConfVer = 1
|
|
staleRegion := new(metapb.Region)
|
|
staleRegion.RegionEpoch = cloneEpoch(staleConfEpoch)
|
|
req.Header.RegionEpoch = cloneEpoch(staleConfEpoch)
|
|
assert.Nil(t, CheckRegionEpoch(req, staleRegion, false))
|
|
|
|
latestConfEpoch := cloneEpoch(epoch)
|
|
latestConfEpoch.ConfVer = 3
|
|
for _, e := range []*metapb.RegionEpoch{staleConfEpoch, latestConfEpoch} {
|
|
req.Header.RegionEpoch = cloneEpoch(e)
|
|
assert.NotNil(t, CheckRegionEpoch(req, region, false))
|
|
assert.NotNil(t, CheckRegionEpoch(req, region, true))
|
|
}
|
|
}
|
|
}
|
|
|
|
func cloneEpoch(epoch *metapb.RegionEpoch) *metapb.RegionEpoch {
|
|
return &metapb.RegionEpoch{
|
|
ConfVer: epoch.ConfVer,
|
|
Version: epoch.Version,
|
|
}
|
|
}
|