vitess-gh/go/mysql/binlog_event_make_test.go

401 строка
10 KiB
Go

/*
Copyright 2019 The Vitess 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 mysql
import (
"reflect"
"testing"
binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata"
)
// TestFormatDescriptionEvent tests both MySQL 5.6 and MariaDB 10.0
// FormatDescriptionEvent is working properly.
func TestFormatDescriptionEvent(t *testing.T) {
// MySQL 5.6
f := NewMySQL56BinlogFormat()
s := NewFakeBinlogStream()
event := NewFormatDescriptionEvent(f, s)
if !event.IsValid() {
t.Fatalf("IsValid() returned false")
}
if !event.IsFormatDescription() {
t.Fatalf("IsFormatDescription returned false")
}
gotF, err := event.Format()
if err != nil {
t.Fatalf("Format failed: %v", err)
}
if !reflect.DeepEqual(gotF, f) {
t.Fatalf("Parsed BinlogFormat doesn't match, got:\n%v\nexpected:\n%v", gotF, f)
}
// MariaDB
f = NewMariaDBBinlogFormat()
s = NewFakeBinlogStream()
event = NewFormatDescriptionEvent(f, s)
if !event.IsValid() {
t.Fatalf("IsValid() returned false")
}
if !event.IsFormatDescription() {
t.Fatalf("IsFormatDescription returned false")
}
gotF, err = event.Format()
if err != nil {
t.Fatalf("Format failed: %v", err)
}
if !reflect.DeepEqual(gotF, f) {
t.Fatalf("Parsed BinlogFormat doesn't match, got:\n%v\nexpected:\n%v", gotF, f)
}
}
func TestQueryEvent(t *testing.T) {
f := NewMySQL56BinlogFormat()
s := NewFakeBinlogStream()
q := Query{
Database: "my database",
SQL: "my query",
Charset: &binlogdatapb.Charset{
Client: 0x1234,
Conn: 0x5678,
Server: 0x9abc,
},
}
event := NewQueryEvent(f, s, q)
if !event.IsValid() {
t.Fatalf("NewQueryEvent returned an invalid event")
}
if !event.IsQuery() {
t.Fatalf("NewQueryEvent returned a non-query event: %v", event)
}
event, _, err := event.StripChecksum(f)
if err != nil {
t.Fatalf("StripChecksum failed: %v", err)
}
gotQ, err := event.Query(f)
if err != nil {
t.Fatalf("event.Query() failed: %v", err)
}
if !reflect.DeepEqual(gotQ, q) {
t.Fatalf("event.Query() returned %v was expecting %v", gotQ, q)
}
}
func TestXIDEvent(t *testing.T) {
f := NewMySQL56BinlogFormat()
s := NewFakeBinlogStream()
event := NewXIDEvent(f, s)
if !event.IsValid() {
t.Fatalf("NewXIDEvent().IsValid() is false")
}
if !event.IsXID() {
t.Fatalf("NewXIDEvent().IsXID() is false")
}
}
func TestIntVarEvent(t *testing.T) {
f := NewMySQL56BinlogFormat()
s := NewFakeBinlogStream()
event := NewIntVarEvent(f, s, IntVarLastInsertID, 0x123456789abcdef0)
if !event.IsValid() {
t.Fatalf("NewIntVarEvent().IsValid() is false")
}
if !event.IsIntVar() {
t.Fatalf("NewIntVarEvent().IsIntVar() is false")
}
name, value, err := event.IntVar(f)
if name != IntVarLastInsertID || value != 0x123456789abcdef0 || err != nil {
t.Fatalf("IntVar() returned %v/%v/%v", name, value, err)
}
event = NewIntVarEvent(f, s, IntVarInvalidInt, 0x123456789abcdef0)
if !event.IsValid() {
t.Fatalf("NewIntVarEvent().IsValid() is false")
}
if !event.IsIntVar() {
t.Fatalf("NewIntVarEvent().IsIntVar() is false")
}
name, value, err = event.IntVar(f)
if err == nil {
t.Fatalf("IntVar(invalid) returned %v/%v/%v", name, value, err)
}
}
func TestInvalidEvents(t *testing.T) {
f := NewMySQL56BinlogFormat()
s := NewFakeBinlogStream()
// InvalidEvent
event := NewInvalidEvent()
if event.IsValid() {
t.Fatalf("NewInvalidEvent().IsValid() is true")
}
// InvalidFormatDescriptionEvent
event = NewInvalidFormatDescriptionEvent(f, s)
if !event.IsValid() {
t.Fatalf("NewInvalidFormatDescriptionEvent().IsValid() is false")
}
if !event.IsFormatDescription() {
t.Fatalf("NewInvalidFormatDescriptionEvent().IsFormatDescription() is false")
}
if _, err := event.Format(); err == nil {
t.Fatalf("NewInvalidFormatDescriptionEvent().Format() returned err=nil")
}
// InvalidQueryEvent
event = NewInvalidQueryEvent(f, s)
if !event.IsValid() {
t.Fatalf("NewInvalidQueryEvent().IsValid() is false")
}
if !event.IsQuery() {
t.Fatalf("NewInvalidQueryEvent().IsQuery() is false")
}
if _, err := event.Query(f); err == nil {
t.Fatalf("NewInvalidQueryEvent().Query() returned err=nil")
}
}
func TestMariadDBGTIDEVent(t *testing.T) {
f := NewMySQL56BinlogFormat()
s := NewFakeBinlogStream()
s.ServerID = 0x87654321
// With built-in begin.
event := NewMariaDBGTIDEvent(f, s, MariadbGTID{Domain: 0, Sequence: 0x123456789abcdef0}, true)
if !event.IsValid() {
t.Fatalf("NewMariaDBGTIDEvent().IsValid() is false")
}
if !event.IsGTID() {
t.Fatalf("NewMariaDBGTIDEvent().IsGTID() if false")
}
event, _, err := event.StripChecksum(f)
if err != nil {
t.Fatalf("StripChecksum failed: %v", err)
}
gtid, hasBegin, err := event.GTID(f)
if err != nil {
t.Fatalf("NewMariaDBGTIDEvent().GTID() returned error: %v", err)
}
if !hasBegin {
t.Fatalf("NewMariaDBGTIDEvent() didn't store hasBegin properly.")
}
mgtid, ok := gtid.(MariadbGTID)
if !ok {
t.Fatalf("NewMariaDBGTIDEvent().GTID() returned a non-MariaDBGTID GTID")
}
if mgtid.Domain != 0 || mgtid.Server != 0x87654321 || mgtid.Sequence != 0x123456789abcdef0 {
t.Fatalf("NewMariaDBGTIDEvent().GTID() returned invalid GITD: %v", mgtid)
}
// Without built-in begin.
event = NewMariaDBGTIDEvent(f, s, MariadbGTID{Domain: 0, Sequence: 0x123456789abcdef0}, false)
if !event.IsValid() {
t.Fatalf("NewMariaDBGTIDEvent().IsValid() is false")
}
if !event.IsGTID() {
t.Fatalf("NewMariaDBGTIDEvent().IsGTID() if false")
}
event, _, err = event.StripChecksum(f)
if err != nil {
t.Fatalf("StripChecksum failed: %v", err)
}
gtid, hasBegin, err = event.GTID(f)
if err != nil {
t.Fatalf("NewMariaDBGTIDEvent().GTID() returned error: %v", err)
}
if hasBegin {
t.Fatalf("NewMariaDBGTIDEvent() didn't store hasBegin properly.")
}
mgtid, ok = gtid.(MariadbGTID)
if !ok {
t.Fatalf("NewMariaDBGTIDEvent().GTID() returned a non-MariaDBGTID GTID")
}
if mgtid.Domain != 0 || mgtid.Server != 0x87654321 || mgtid.Sequence != 0x123456789abcdef0 {
t.Fatalf("NewMariaDBGTIDEvent().GTID() returned invalid GITD: %v", mgtid)
}
}
func TestTableMapEvent(t *testing.T) {
f := NewMySQL56BinlogFormat()
s := NewFakeBinlogStream()
tm := &TableMap{
Flags: 0x8090,
Database: "my_database",
Name: "my_table",
Types: []byte{
TypeLongLong,
TypeLongLong,
TypeLongLong,
TypeLongLong,
TypeLongLong,
TypeTime,
TypeLongLong,
TypeLongLong,
TypeLongLong,
TypeVarchar,
},
CanBeNull: NewServerBitmap(10),
Metadata: []uint16{
0,
0,
0,
0,
0,
0,
0,
0,
0,
384, // Length of the varchar field.
},
}
tm.CanBeNull.Set(1, true)
tm.CanBeNull.Set(2, true)
tm.CanBeNull.Set(5, true)
tm.CanBeNull.Set(9, true)
event := NewTableMapEvent(f, s, 0x102030405060, tm)
if !event.IsValid() {
t.Fatalf("NewTableMapEvent().IsValid() is false")
}
if !event.IsTableMap() {
t.Fatalf("NewTableMapEvent().IsTableMap() if false")
}
event, _, err := event.StripChecksum(f)
if err != nil {
t.Fatalf("StripChecksum failed: %v", err)
}
tableID := event.TableID(f)
if tableID != 0x102030405060 {
t.Fatalf("NewTableMapEvent().ID returned %x", tableID)
}
gotTm, err := event.TableMap(f)
if err != nil {
t.Fatalf("NewTableMapEvent().TableMapEvent() returned error: %v", err)
}
if !reflect.DeepEqual(gotTm, tm) {
t.Fatalf("NewTableMapEvent().TableMapEvent() got TableMap:\n%v\nexpected:\n%v", gotTm, tm)
}
}
func TestRowsEvent(t *testing.T) {
f := NewMySQL56BinlogFormat()
s := NewFakeBinlogStream()
/*
Reason for nolint
Used in line 384 to 387
tableID = event.ID(f)
if tableID != 0x102030405060 {
t.Fatalf("NewRowsEvent().ID returned %x", tableID)
}
*/
tableID := uint64(0x102030405060) //nolint
tm := &TableMap{
Flags: 0x8090,
Database: "my_database",
Name: "my_table",
Types: []byte{
TypeLong,
TypeVarchar,
},
CanBeNull: NewServerBitmap(2),
Metadata: []uint16{
0,
384,
},
}
tm.CanBeNull.Set(1, true)
// Do an update packet with all fields set.
rows := Rows{
Flags: 0x1234,
IdentifyColumns: NewServerBitmap(2),
DataColumns: NewServerBitmap(2),
Rows: []Row{
{
NullIdentifyColumns: NewServerBitmap(2),
NullColumns: NewServerBitmap(2),
Identify: []byte{
0x10, 0x20, 0x30, 0x40, // long
0x03, 0x00, // len('abc')
'a', 'b', 'c', // 'abc'
},
Data: []byte{
0x10, 0x20, 0x30, 0x40, // long
0x04, 0x00, // len('abcd')
'a', 'b', 'c', 'd', // 'abcd'
},
},
},
}
// All rows are included, none are NULL.
rows.IdentifyColumns.Set(0, true)
rows.IdentifyColumns.Set(1, true)
rows.DataColumns.Set(0, true)
rows.DataColumns.Set(1, true)
// Test the Rows we just created, to be sure.
// 1076895760 is 0x40302010.
identifies, _ := rows.StringIdentifiesForTests(tm, 0)
if expected := []string{"1076895760", "abc"}; !reflect.DeepEqual(identifies, expected) {
t.Fatalf("bad Rows identify, got %v expected %v", identifies, expected)
}
values, _ := rows.StringValuesForTests(tm, 0)
if expected := []string{"1076895760", "abcd"}; !reflect.DeepEqual(values, expected) {
t.Fatalf("bad Rows data, got %v expected %v", values, expected)
}
event := NewUpdateRowsEvent(f, s, 0x102030405060, rows)
if !event.IsValid() {
t.Fatalf("NewRowsEvent().IsValid() is false")
}
if !event.IsUpdateRows() {
t.Fatalf("NewRowsEvent().IsUpdateRows() if false")
}
event, _, err := event.StripChecksum(f)
if err != nil {
t.Fatalf("StripChecksum failed: %v", err)
}
tableID = event.TableID(f)
if tableID != 0x102030405060 {
t.Fatalf("NewRowsEvent().ID returned %x", tableID)
}
gotRows, err := event.Rows(f, tm)
if err != nil {
t.Fatalf("NewRowsEvent().Rows() returned error: %v", err)
}
if !reflect.DeepEqual(gotRows, rows) {
t.Fatalf("NewRowsEvent().Rows() got Rows:\n%v\nexpected:\n%v", gotRows, rows)
}
}