168 lines
3.6 KiB
Go
168 lines
3.6 KiB
Go
// Copyright 2021 PingCAP, Inc.
|
|
//
|
|
// 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,
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package executor_test
|
|
|
|
import (
|
|
. "github.com/pingcap/check"
|
|
"github.com/pingcap/tidb/executor"
|
|
"github.com/pingcap/tidb/kv"
|
|
)
|
|
|
|
var _ = Suite(&testUnionIterSuit{})
|
|
|
|
type testUnionIterSuit struct {
|
|
}
|
|
|
|
func (s *testUnionIterSuit) TestUnionIter(c *C) {
|
|
// test iter normal cases, snap iter become invalid before dirty iter
|
|
snapRecords := []*mockRecord{
|
|
r("k01", "v1"),
|
|
r("k03", "v3"),
|
|
r("k06", "v6"),
|
|
r("k10", "v10"),
|
|
r("k12", "v12"),
|
|
r("k15", "v15"),
|
|
r("k16", "v16"),
|
|
}
|
|
|
|
dirtyRecords := []*mockRecord{
|
|
r("k03", "x3"),
|
|
r("k05", "x5"),
|
|
r("k07", "x7"),
|
|
r("k08", "x8"),
|
|
}
|
|
|
|
assertUnionIter(c, dirtyRecords, snapRecords, []*mockRecord{
|
|
r("k01", "v1"),
|
|
r("k03", "x3"),
|
|
r("k05", "x5"),
|
|
r("k06", "v6"),
|
|
r("k07", "x7"),
|
|
r("k08", "x8"),
|
|
r("k10", "v10"),
|
|
r("k12", "v12"),
|
|
r("k15", "v15"),
|
|
r("k16", "v16"),
|
|
})
|
|
|
|
// test iter normal cases, dirty iter become invalid before snap iter
|
|
dirtyRecords = []*mockRecord{
|
|
r("k03", "x3"),
|
|
r("k05", "x5"),
|
|
r("k07", "x7"),
|
|
r("k08", "x8"),
|
|
r("k17", "x17"),
|
|
r("k18", "x18"),
|
|
}
|
|
|
|
assertUnionIter(c, dirtyRecords, snapRecords, []*mockRecord{
|
|
r("k01", "v1"),
|
|
r("k03", "x3"),
|
|
r("k05", "x5"),
|
|
r("k06", "v6"),
|
|
r("k07", "x7"),
|
|
r("k08", "x8"),
|
|
r("k10", "v10"),
|
|
r("k12", "v12"),
|
|
r("k15", "v15"),
|
|
r("k16", "v16"),
|
|
r("k17", "x17"),
|
|
r("k18", "x18"),
|
|
})
|
|
}
|
|
|
|
func assertUnionIter(c *C, dirtyRecords, snapRecords, expected []*mockRecord) {
|
|
iter, err := executor.NewUnionIter(newMockIter(dirtyRecords), newMockIter(snapRecords), false)
|
|
c.Assert(err, IsNil)
|
|
assertIter(c, iter, expected)
|
|
|
|
// assert reverse is true
|
|
iter, err = executor.NewUnionIter(newMockIter(reverseRecords(dirtyRecords)), newMockIter(reverseRecords(snapRecords)), true)
|
|
c.Assert(err, IsNil)
|
|
assertIter(c, iter, reverseRecords(expected))
|
|
}
|
|
|
|
func assertIter(c *C, iter kv.Iterator, expected []*mockRecord) {
|
|
records := make([]*mockRecord, 0, len(expected))
|
|
for iter.Valid() {
|
|
records = append(records, &mockRecord{iter.Key(), iter.Value()})
|
|
err := iter.Next()
|
|
c.Assert(err, IsNil)
|
|
}
|
|
c.Assert(len(records), Equals, len(expected))
|
|
for idx, record := range records {
|
|
c.Assert(record.key, BytesEquals, expected[idx].key)
|
|
c.Assert(record.value, BytesEquals, expected[idx].value)
|
|
}
|
|
}
|
|
|
|
func reverseRecords(records []*mockRecord) []*mockRecord {
|
|
reversed := make([]*mockRecord, 0)
|
|
for i := range records {
|
|
reversed = append(reversed, records[len(records)-i-1])
|
|
}
|
|
return reversed
|
|
}
|
|
|
|
type mockRecord struct {
|
|
key []byte
|
|
value []byte
|
|
}
|
|
|
|
func r(key, value string) *mockRecord {
|
|
bKey := []byte(key)
|
|
bValue := []byte(value)
|
|
if value == "nil" {
|
|
bValue = nil
|
|
}
|
|
|
|
return &mockRecord{bKey, bValue}
|
|
}
|
|
|
|
type mockIter struct {
|
|
data []*mockRecord
|
|
cur int
|
|
}
|
|
|
|
func newMockIter(records []*mockRecord) *mockIter {
|
|
return &mockIter{
|
|
records,
|
|
0,
|
|
}
|
|
}
|
|
|
|
func (m *mockIter) Valid() bool {
|
|
return m.cur >= 0 && m.cur < len(m.data)
|
|
}
|
|
|
|
func (m *mockIter) Key() kv.Key {
|
|
return m.data[m.cur].key
|
|
}
|
|
|
|
func (m *mockIter) Value() []byte {
|
|
return m.data[m.cur].value
|
|
}
|
|
|
|
func (m *mockIter) Next() error {
|
|
if m.Valid() {
|
|
m.cur += 1
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *mockIter) Close() {
|
|
m.cur = -1
|
|
}
|