Implement GTID and GTIDSet for MySQL 5.6.

This commit is contained in:
Anthony Yeh 2015-05-01 17:27:39 -07:00
Родитель 57290ce3d4
Коммит 1cd37f7ca0
4 изменённых файлов: 760 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,85 @@
// Copyright 2015, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package proto
import (
"encoding/hex"
"fmt"
)
const mysql56FlavorID = "MySQL56"
// SID is the 16-byte unique ID of a MySQL 5.6 server.
type SID [16]byte
// String prints an SID in the form used by MySQL 5.6.
func (sid SID) String() string {
dst := []byte("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
hex.Encode(dst, sid[:4])
hex.Encode(dst[9:], sid[4:6])
hex.Encode(dst[14:], sid[6:8])
hex.Encode(dst[19:], sid[8:10])
hex.Encode(dst[24:], sid[10:16])
return string(dst)
}
// ParseSID parses an SID in the form used by MySQL 5.6.
func ParseSID(s string) (sid SID, err error) {
if len(s) != 36 || s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
return sid, fmt.Errorf("invalid MySQL 5.6 SID %q", s)
}
// Drop the dashes so we can just check the error of Decode once.
b := make([]byte, 0, 32)
b = append(b, s[:8]...)
b = append(b, s[9:13]...)
b = append(b, s[14:18]...)
b = append(b, s[19:23]...)
b = append(b, s[24:]...)
if _, err := hex.Decode(sid[:], b); err != nil {
return sid, fmt.Errorf("invalid MySQL 5.6 SID %q: %v", s, err)
}
return sid, nil
}
// Mysql56GTID implements GTID
type Mysql56GTID struct {
// Server is the SID of the server that originally committed the transaction.
Server SID
// Sequence is the sequence number of the transaction within a given Server's
// scope.
Sequence int64
}
// String implements GTID.String().
func (gtid Mysql56GTID) String() string {
return fmt.Sprintf("%s:%d", gtid.Server, gtid.Sequence)
}
// Flavor implements GTID.Flavor().
func (gtid Mysql56GTID) Flavor() string {
return mysql56FlavorID
}
// SequenceDomain implements GTID.SequenceDomain().
func (gtid Mysql56GTID) SequenceDomain() interface{} {
return nil
}
// SourceServer implements GTID.SourceServer().
func (gtid Mysql56GTID) SourceServer() interface{} {
return gtid.Server
}
// SequenceNumber implements GTID.SequenceNumber().
func (gtid Mysql56GTID) SequenceNumber() interface{} {
return gtid.Sequence
}
// GTIDSet implements GTID.GTIDSet().
func (gtid Mysql56GTID) GTIDSet() GTIDSet {
return Mysql56GTIDSet{}.AddGTID(gtid)
}

Просмотреть файл

@ -0,0 +1,251 @@
// Copyright 2015, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package proto
import (
"bytes"
"encoding/binary"
"sort"
"strconv"
)
type interval struct {
start, end int64
}
func (iv interval) contains(other interval) bool {
return iv.start <= other.start && other.end <= iv.end
}
// Mysql56GTIDSet implements GTIDSet for MySQL 5.6.
type Mysql56GTIDSet map[SID][]interval
// SIDs returns a sorted list of SIDs in the set.
func (set Mysql56GTIDSet) SIDs() []SID {
sids := make([]SID, 0, len(set))
for sid := range set {
sids = append(sids, sid)
}
sort.Sort(sidList(sids))
return sids
}
// Len implements sort.Interface.
type sidList []SID
func (s sidList) Len() int { return len(s) }
// Less implements sort.Interface.
func (s sidList) Less(i, j int) bool { return bytes.Compare(s[i][:], s[j][:]) < 0 }
// Swap implements sort.Interface.
func (s sidList) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// String implements GTIDSet.
func (set Mysql56GTIDSet) String() string {
buf := &bytes.Buffer{}
for i, sid := range set.SIDs() {
if i != 0 {
buf.WriteByte(',')
}
buf.WriteString(sid.String())
for _, interval := range set[sid] {
buf.WriteByte(':')
buf.WriteString(strconv.FormatInt(interval.start, 10))
if interval.end != interval.start {
buf.WriteByte('-')
buf.WriteString(strconv.FormatInt(interval.end, 10))
}
}
}
return buf.String()
}
// Flavor implements GTIDSet.
func (Mysql56GTIDSet) Flavor() string { return mysql56FlavorID }
// ContainsGTID implements GTIDSet.
func (set Mysql56GTIDSet) ContainsGTID(gtid GTID) bool {
gtid56, ok := gtid.(Mysql56GTID)
if !ok {
return false
}
for _, iv := range set[gtid56.Server] {
if iv.start > gtid56.Sequence {
// We assume intervals are sorted, so we can skip the rest.
return false
}
if gtid56.Sequence <= iv.end {
// Now we know that: start <= Sequence <= end.
return true
}
}
// Server wasn't in the set, or no interval contained gtid.
return false
}
// Contains implements GTIDSet.
func (set Mysql56GTIDSet) Contains(other GTIDSet) bool {
other56, ok := other.(Mysql56GTIDSet)
if !ok {
return false
}
// Check each SID in the other set.
for sid, otherIntervals := range other56 {
i := 0
intervals := set[sid]
count := len(intervals)
// Check each interval for this SID in the other set.
for _, iv := range otherIntervals {
// Check that interval against each of our intervals.
// Intervals are monotonically increasing,
// so we don't need to reset the index each time.
for {
if i >= count {
// We ran out of intervals to check against.
return false
}
if intervals[i].contains(iv) {
// Yes it's covered. Go on to the next one.
break
}
i++
}
}
}
// No uncovered intervals were found.
return true
}
// Equal implements GTIDSet.
func (set Mysql56GTIDSet) Equal(other GTIDSet) bool {
other56, ok := other.(Mysql56GTIDSet)
if !ok {
return false
}
// Check for same number of SIDs.
if len(set) != len(other56) {
return false
}
// Compare each SID.
for sid, intervals := range set {
otherIntervals := other56[sid]
// Check for same number of intervals.
if len(intervals) != len(otherIntervals) {
return false
}
// Compare each interval.
// Since intervals are sorted, they have to be in the same order.
for i, iv := range intervals {
if iv != otherIntervals[i] {
return false
}
}
}
// No discrepancies were found.
return true
}
// AddGTID implements GTIDSet.
func (set Mysql56GTIDSet) AddGTID(gtid GTID) GTIDSet {
gtid56, ok := gtid.(Mysql56GTID)
if !ok {
return set
}
// Make a copy and add the new GTID in the proper place.
// This function is not supposed to modify the original set.
newSet := make(Mysql56GTIDSet)
added := false
for sid, intervals := range set {
newIntervals := make([]interval, 0, len(intervals))
if sid == gtid56.Server {
// Look for the right place to add this GTID.
for _, iv := range intervals {
if !added {
switch {
case gtid56.Sequence == iv.start-1:
// Expand the interval at the beginning.
iv.start = gtid56.Sequence
added = true
case gtid56.Sequence == iv.end+1:
// Expand the interval at the end.
iv.end = gtid56.Sequence
added = true
case gtid56.Sequence < iv.start-1:
// The next interval is beyond the new GTID, but it can't
// be expanded, so we have to insert a new interval.
newIntervals = append(newIntervals, interval{start: gtid56.Sequence, end: gtid56.Sequence})
added = true
}
}
// Check if this interval can be merged with the previous one.
count := len(newIntervals)
if count != 0 && iv.start == newIntervals[count-1].end+1 {
// Merge instead of appending.
newIntervals[count-1].end = iv.end
} else {
// Can't be merged.
newIntervals = append(newIntervals, iv)
}
}
} else {
// Just copy everything.
newIntervals = append(newIntervals, intervals...)
}
newSet[sid] = newIntervals
}
if !added {
// There wasn't any place to insert the new GTID, so just append it
// as a new interval.
newSet[gtid56.Server] = append(newSet[gtid56.Server], interval{start: gtid56.Sequence, end: gtid56.Sequence})
}
return newSet
}
// SIDBlock returns the binary encoding of a MySQL 5.6 GTID set as expected
// by internal commands that refer to an "SID block".
//
// e.g. https://dev.mysql.com/doc/internals/en/com-binlog-dump-gtid.html
func (set Mysql56GTIDSet) SIDBlock() []byte {
buf := &bytes.Buffer{}
// Number of SIDs.
binary.Write(buf, binary.LittleEndian, uint64(len(set)))
for _, sid := range set.SIDs() {
buf.Write(sid[:])
// Number of intervals.
intervals := set[sid]
binary.Write(buf, binary.LittleEndian, uint64(len(intervals)))
for _, iv := range intervals {
binary.Write(buf, binary.LittleEndian, iv.start)
binary.Write(buf, binary.LittleEndian, iv.end)
}
}
return buf.Bytes()
}

Просмотреть файл

@ -0,0 +1,321 @@
// Copyright 2015, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package proto
import (
"reflect"
"strings"
"testing"
)
func TestMysql56GTIDSetString(t *testing.T) {
sid1 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
sid2 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 255}
table := map[string]Mysql56GTIDSet{
// Simple case
"00010203-0405-0607-0809-0a0b0c0d0e0f:1-5": Mysql56GTIDSet{
sid1: []interval{{1, 5}},
},
// Interval with same start and end
"00010203-0405-0607-0809-0a0b0c0d0e0f:12": Mysql56GTIDSet{
sid1: []interval{{12, 12}},
},
// Multiple intervals
"00010203-0405-0607-0809-0a0b0c0d0e0f:1-5:10-20": Mysql56GTIDSet{
sid1: []interval{{1, 5}, {10, 20}},
},
// Multiple SIDs
"00010203-0405-0607-0809-0a0b0c0d0e0f:1-5:10-20,00010203-0405-0607-0809-0a0b0c0d0eff:1-5:50": Mysql56GTIDSet{
sid1: []interval{{1, 5}, {10, 20}},
sid2: []interval{{1, 5}, {50, 50}},
},
}
for want, input := range table {
got := strings.ToLower(input.String())
if got != want {
t.Errorf("%#v.String() = %#v, want %#v", input, got, want)
}
}
}
func TestMysql56GTIDSetFlavor(t *testing.T) {
input := Mysql56GTIDSet{}
if got, want := input.Flavor(), "MySQL56"; got != want {
t.Errorf("%#v.Flavor() = %#v, want %#v", input, got, want)
}
}
func TestMysql56GTIDSetContainsGTID(t *testing.T) {
sid1 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
sid2 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16}
sid3 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17}
set := Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 40}},
sid2: []interval{{1, 5}, {50, 50}},
}
table := map[GTID]bool{
fakeGTID{}: false,
Mysql56GTID{sid1, 1}: false,
Mysql56GTID{sid1, 19}: false,
Mysql56GTID{sid1, 20}: true,
Mysql56GTID{sid1, 23}: true,
Mysql56GTID{sid1, 30}: true,
Mysql56GTID{sid1, 31}: false,
Mysql56GTID{sid2, 1}: true,
Mysql56GTID{sid2, 10}: false,
Mysql56GTID{sid2, 50}: true,
Mysql56GTID{sid2, 51}: false,
Mysql56GTID{sid3, 1}: false,
}
for input, want := range table {
if got := set.ContainsGTID(input); got != want {
t.Errorf("ContainsGTID(%#v) = %#v, want %#v", input, got, want)
}
}
}
func TestMysql56GTIDSetContains(t *testing.T) {
sid1 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
sid2 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16}
sid3 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17}
// The set to test against.
set := Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 40}},
sid2: []interval{{1, 5}, {50, 50}, {60, 70}},
}
// Test cases that should return Contains() = true.
contained := []Mysql56GTIDSet{
// The set should contain itself.
set,
// Every set contains the empty set.
Mysql56GTIDSet{},
// Simple case
Mysql56GTIDSet{sid1: []interval{{25, 30}}},
// Multiple intervals
Mysql56GTIDSet{sid2: []interval{{1, 2}, {4, 5}, {60, 70}}},
// Multiple SIDs
Mysql56GTIDSet{
sid1: []interval{{25, 30}, {35, 37}},
sid2: []interval{{1, 5}},
},
}
for _, other := range contained {
if !set.Contains(other) {
t.Errorf("Contains(%#v) = false, want true", other)
}
}
// Test cases that should return Contains() = false.
notContained := []GTIDSet{
// Wrong flavor is not contained.
fakeGTID{},
// Simple cases
Mysql56GTIDSet{sid1: []interval{{1, 5}}},
Mysql56GTIDSet{sid1: []interval{{10, 19}}},
// Overlapping intervals
Mysql56GTIDSet{sid1: []interval{{10, 20}}},
Mysql56GTIDSet{sid1: []interval{{10, 25}}},
Mysql56GTIDSet{sid1: []interval{{25, 31}}},
Mysql56GTIDSet{sid1: []interval{{30, 31}}},
// Multiple intervals
Mysql56GTIDSet{sid1: []interval{{20, 30}, {34, 34}}},
// Multiple SIDs
Mysql56GTIDSet{
sid1: []interval{{20, 30}, {36, 36}},
sid2: []interval{{3, 5}, {55, 60}},
},
// SID is missing entirely
Mysql56GTIDSet{sid3: []interval{{1, 5}}},
}
for _, other := range notContained {
if set.Contains(other) {
t.Errorf("Contains(%#v) = true, want false", other)
}
}
}
func TestMysql56GTIDSetEqual(t *testing.T) {
sid1 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
sid2 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16}
sid3 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17}
// The set to test against.
set := Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 40}},
sid2: []interval{{1, 5}, {50, 50}, {60, 70}},
}
// Test cases that should return Equal() = true.
equal := []Mysql56GTIDSet{
// Same underlying map instance
set,
// Different instance, same data
Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 40}},
sid2: []interval{{1, 5}, {50, 50}, {60, 70}},
},
}
for _, other := range equal {
if !set.Equal(other) {
t.Errorf("Equal(%#v) = false, want true", other)
}
}
// Test cases that should return Equal() = false.
notEqual := []GTIDSet{
// Wrong flavor is not equal.
fakeGTID{},
// Empty set
Mysql56GTIDSet{},
// Interval changed
Mysql56GTIDSet{
sid1: []interval{{20, 31}, {35, 40}},
sid2: []interval{{1, 5}, {50, 50}, {60, 70}},
},
// Interval added
Mysql56GTIDSet{
sid1: []interval{{20, 30}, {32, 33}, {35, 40}},
sid2: []interval{{1, 5}, {50, 50}, {60, 70}},
},
// Interval removed
Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 40}},
sid2: []interval{{1, 5}, {60, 70}},
},
// Different SID, same intervals
Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 40}},
sid3: []interval{{1, 5}, {50, 50}, {60, 70}},
},
// SID added
Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 40}},
sid2: []interval{{1, 5}, {50, 50}, {60, 70}},
sid3: []interval{{1, 5}},
},
// SID removed
Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 40}},
},
}
for _, other := range notEqual {
if set.Equal(other) {
t.Errorf("Equal(%#v) = true, want false", other)
}
}
}
func TestMysql56GTIDSetAddGTID(t *testing.T) {
sid1 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
sid2 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16}
sid3 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17}
// The set to test against.
set := Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 40}, {42, 45}},
sid2: []interval{{1, 5}, {50, 50}, {60, 70}},
}
table := map[GTID]Mysql56GTIDSet{
// Adding wrong flavor is a no-op.
fakeGTID{}: set,
// New interval beginning
Mysql56GTID{Server: sid1, Sequence: 1}: Mysql56GTIDSet{
sid1: []interval{{1, 1}, {20, 30}, {35, 40}, {42, 45}},
sid2: []interval{{1, 5}, {50, 50}, {60, 70}},
},
// New interval middle
Mysql56GTID{Server: sid1, Sequence: 32}: Mysql56GTIDSet{
sid1: []interval{{20, 30}, {32, 32}, {35, 40}, {42, 45}},
sid2: []interval{{1, 5}, {50, 50}, {60, 70}},
},
// New interval end
Mysql56GTID{Server: sid1, Sequence: 50}: Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 40}, {42, 45}, {50, 50}},
sid2: []interval{{1, 5}, {50, 50}, {60, 70}},
},
// Extend interval start
Mysql56GTID{Server: sid2, Sequence: 49}: Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 40}, {42, 45}},
sid2: []interval{{1, 5}, {49, 50}, {60, 70}},
},
// Extend interval end
Mysql56GTID{Server: sid2, Sequence: 51}: Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 40}, {42, 45}},
sid2: []interval{{1, 5}, {50, 51}, {60, 70}},
},
// Merge intervals
Mysql56GTID{Server: sid1, Sequence: 41}: Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 45}},
sid2: []interval{{1, 5}, {50, 50}, {60, 70}},
},
// Different SID
Mysql56GTID{Server: sid3, Sequence: 1}: Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 40}, {42, 45}},
sid2: []interval{{1, 5}, {50, 50}, {60, 70}},
sid3: []interval{{1, 1}},
},
}
for input, want := range table {
if got := set.AddGTID(input); !got.Equal(want) {
t.Errorf("AddGTID(%#v) = %#v, want %#v", input, got, want)
}
}
}
func TestMysql56GTIDSetSIDBlock(t *testing.T) {
sid1 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
sid2 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16}
input := Mysql56GTIDSet{
sid1: []interval{{20, 30}, {35, 40}},
sid2: []interval{{1, 5}},
}
want := []byte{
// n_sids
2, 0, 0, 0, 0, 0, 0, 0,
// sid1
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
// sid1: n_intervals
2, 0, 0, 0, 0, 0, 0, 0,
// sid1: interval 1 start
20, 0, 0, 0, 0, 0, 0, 0,
// sid1: interval 1 end
30, 0, 0, 0, 0, 0, 0, 0,
// sid1: interval 2 start
35, 0, 0, 0, 0, 0, 0, 0,
// sid1: interval 2 end
40, 0, 0, 0, 0, 0, 0, 0,
// sid2
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16,
// sid2: n_intervals
1, 0, 0, 0, 0, 0, 0, 0,
// sid2: interval 1 start
1, 0, 0, 0, 0, 0, 0, 0,
// sid2: interval 1 end
5, 0, 0, 0, 0, 0, 0, 0,
}
if got := input.SIDBlock(); !reflect.DeepEqual(got, want) {
t.Errorf("%#v.SIDBlock() = %#v, want %#v", input, got, want)
}
}

Просмотреть файл

@ -0,0 +1,103 @@
// Copyright 2015, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package proto
import (
"strings"
"testing"
)
func TestSIDString(t *testing.T) {
input := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
want := "00010203-0405-0607-0809-0a0b0c0d0e0f"
if got := strings.ToLower(input.String()); got != want {
t.Errorf("%#v.String() = %#v, want %#v", input, got, want)
}
}
func TestParseSID(t *testing.T) {
input := "00010203-0405-0607-0809-0A0B0C0D0E0F"
want := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
got, err := ParseSID(input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got != want {
t.Errorf("ParseSID(%#v) = %#v, want %#v", input, got, want)
}
}
func TestParseSIDInvalid(t *testing.T) {
table := []string{
"123",
"x",
"00010203-0405-0607-0809-0A0B0C0D0E0x",
"00010203-0405-0607-080900A0B0C0D0E0F",
}
for _, input := range table {
_, err := ParseSID(input)
if err == nil {
t.Errorf("ParseSID(%#v): expected error, got none", input)
}
}
}
func TestMysql56GTIDString(t *testing.T) {
input := Mysql56GTID{
Server: SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
Sequence: 12345,
}
want := "00010203-0405-0607-0809-0a0b0c0d0e0f:12345"
if got := strings.ToLower(input.String()); got != want {
t.Errorf("%#v.String() = %#v, want %#v", input, got, want)
}
}
func TestMysql56GTIDFlavor(t *testing.T) {
input := Mysql56GTID{}
if got, want := input.Flavor(), "MySQL56"; got != want {
t.Errorf("%#v.Flavor() = %#v, want %#v", input, got, want)
}
}
func TestMysql56SequenceDomain(t *testing.T) {
input := Mysql56GTID{}
if got, want := input.SequenceDomain(), interface{}(nil); got != want {
t.Errorf("%#v.SequenceDomain() = %#v, want %#v", input, got, want)
}
}
func TestMysql56SourceServer(t *testing.T) {
input := Mysql56GTID{
Server: SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
}
want := interface{}(SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15})
if got := input.SourceServer(); got != want {
t.Errorf("%#v.SourceServer() = %#v, want %#v", input, got, want)
}
}
func TestMysql56SequenceNumber(t *testing.T) {
input := Mysql56GTID{
Server: SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
Sequence: 5432,
}
want := interface{}(int64(5432))
if got := input.SequenceNumber(); got != want {
t.Errorf("%#v.SequenceNumber() = %#v, want %#v", input, got, want)
}
}
func TestMysql56GTIDGTIDSet(t *testing.T) {
sid1 := SID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
input := Mysql56GTID{Server: sid1, Sequence: 5432}
want := Mysql56GTIDSet{sid1: []interval{{5432, 5432}}}
if got := input.GTIDSet(); !got.Equal(want) {
t.Errorf("%#v.GTIDSet() = %#v, want %#v", input, got, want)
}
}