170 lines
4.9 KiB
Go
170 lines
4.9 KiB
Go
// Copyright 2020 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,
|
|
// 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 cdclog
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/pingcap/check"
|
|
"github.com/pingcap/tidb/parser/mysql"
|
|
)
|
|
|
|
func Test(t *testing.T) { check.TestingT(t) }
|
|
|
|
type batchSuite struct {
|
|
ddlEvents []*MessageDDL
|
|
ddlDecodeItem []*SortItem
|
|
|
|
rowEvents []*MessageRow
|
|
rowDecodeItem []*SortItem
|
|
}
|
|
|
|
var updateCols = map[string]Column{
|
|
// json.Number
|
|
"id": {Type: 1, Value: "1"},
|
|
"name": {Type: 2, Value: "test"},
|
|
}
|
|
|
|
var _ = check.Suite(&batchSuite{
|
|
ddlEvents: []*MessageDDL{
|
|
{"drop table event", 4},
|
|
{"create table event", 3},
|
|
{"drop table event", 5},
|
|
},
|
|
ddlDecodeItem: []*SortItem{
|
|
{ItemType: DDL, Schema: "test", Table: "event", TS: 1, Data: MessageDDL{"drop table event", 4}},
|
|
{ItemType: DDL, Schema: "test", Table: "event", TS: 1, Data: MessageDDL{"create table event", 3}},
|
|
{ItemType: DDL, Schema: "test", Table: "event", TS: 1, Data: MessageDDL{"drop table event", 5}},
|
|
},
|
|
|
|
rowEvents: []*MessageRow{
|
|
{Update: updateCols},
|
|
{PreColumns: updateCols},
|
|
{Delete: updateCols},
|
|
},
|
|
rowDecodeItem: []*SortItem{
|
|
{ItemType: RowChanged, Schema: "test", Table: "event", TS: 1, RowID: 0, Data: MessageRow{Update: updateCols}},
|
|
{ItemType: RowChanged, Schema: "test", Table: "event", TS: 1, RowID: 1, Data: MessageRow{PreColumns: updateCols}},
|
|
{ItemType: RowChanged, Schema: "test", Table: "event", TS: 1, RowID: 2, Data: MessageRow{Delete: updateCols}},
|
|
},
|
|
})
|
|
|
|
func buildEncodeRowData(events []*MessageRow) []byte {
|
|
var versionByte [8]byte
|
|
binary.BigEndian.PutUint64(versionByte[:], BatchVersion1)
|
|
data := append(make([]byte, 0), versionByte[:]...)
|
|
key := messageKey{
|
|
TS: 1,
|
|
Schema: "test",
|
|
Table: "event",
|
|
}
|
|
var LenByte [8]byte
|
|
for i := 0; i < len(events); i++ {
|
|
key.RowID = int64(i)
|
|
keyBytes, _ := key.Encode()
|
|
binary.BigEndian.PutUint64(LenByte[:], uint64(len(keyBytes)))
|
|
data = append(data, LenByte[:]...)
|
|
data = append(data, keyBytes...)
|
|
eventBytes, _ := events[i].Encode()
|
|
binary.BigEndian.PutUint64(LenByte[:], uint64(len(eventBytes)))
|
|
data = append(data, LenByte[:]...)
|
|
data = append(data, eventBytes...)
|
|
}
|
|
return data
|
|
}
|
|
|
|
func buildEncodeDDLData(events []*MessageDDL) []byte {
|
|
var versionByte [8]byte
|
|
binary.BigEndian.PutUint64(versionByte[:], BatchVersion1)
|
|
data := append(make([]byte, 0), versionByte[:]...)
|
|
key := messageKey{
|
|
TS: 1,
|
|
Schema: "test",
|
|
Table: "event",
|
|
}
|
|
var LenByte [8]byte
|
|
for i := 0; i < len(events); i++ {
|
|
keyBytes, _ := key.Encode()
|
|
binary.BigEndian.PutUint64(LenByte[:], uint64(len(keyBytes)))
|
|
data = append(data, LenByte[:]...)
|
|
data = append(data, keyBytes...)
|
|
eventBytes, _ := events[i].Encode()
|
|
binary.BigEndian.PutUint64(LenByte[:], uint64(len(eventBytes)))
|
|
data = append(data, LenByte[:]...)
|
|
data = append(data, eventBytes...)
|
|
}
|
|
return data
|
|
}
|
|
|
|
func (s *batchSuite) TestDecoder(c *check.C) {
|
|
var item *SortItem
|
|
|
|
data := buildEncodeDDLData(s.ddlEvents)
|
|
decoder, err := NewJSONEventBatchDecoder(data)
|
|
c.Assert(err, check.IsNil)
|
|
index := 0
|
|
for {
|
|
hasNext := decoder.HasNext()
|
|
if !hasNext {
|
|
break
|
|
}
|
|
item, err = decoder.NextEvent(DDL)
|
|
c.Assert(err, check.IsNil)
|
|
c.Assert(item.Data.(*MessageDDL), check.DeepEquals, s.ddlEvents[index])
|
|
index++
|
|
}
|
|
|
|
data = buildEncodeRowData(s.rowEvents)
|
|
decoder, err = NewJSONEventBatchDecoder(data)
|
|
c.Assert(err, check.IsNil)
|
|
index = 0
|
|
for {
|
|
hasNext := decoder.HasNext()
|
|
if !hasNext {
|
|
break
|
|
}
|
|
item, err = decoder.NextEvent(RowChanged)
|
|
c.Assert(err, check.IsNil)
|
|
c.Assert(item.Data.(*MessageRow), check.DeepEquals, s.rowEvents[index])
|
|
c.Assert(item.RowID, check.Equals, int64(index))
|
|
index++
|
|
}
|
|
}
|
|
|
|
func (s *batchSuite) TestColumn(c *check.C) {
|
|
// test varbinary columns (same type with varchar 15)
|
|
col1 := Column{Type: mysql.TypeVarchar, Flag: BinaryFlag, Value: "\\x00\\x01"}
|
|
col1 = formatColumnVal(col1)
|
|
dat, err := col1.ToDatum()
|
|
c.Assert(err, check.IsNil)
|
|
c.Assert(dat.GetString(), check.Equals, "\x00\x01")
|
|
|
|
// test binary columns (same type with varchar 254)
|
|
col2 := Column{Type: mysql.TypeString, Flag: BinaryFlag, Value: "test\\ttest"}
|
|
col2 = formatColumnVal(col2)
|
|
dat, err = col2.ToDatum()
|
|
c.Assert(err, check.IsNil)
|
|
c.Assert(dat.GetString(), check.Equals, "test\ttest")
|
|
|
|
// test year columns
|
|
val := json.Number("2020")
|
|
colYear := Column{Type: mysql.TypeYear, Value: val}
|
|
dat, err = colYear.ToDatum()
|
|
c.Assert(err, check.IsNil)
|
|
c.Assert(dat.GetInt64(), check.Equals, int64(2020))
|
|
}
|