github.com/XiaoMi/Gaea@v1.2.5/parser/model/model_test.go (about)

     1  // Copyright 2015 PingCAP, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package model
    15  
    16  import (
    17  	"encoding/json"
    18  	"fmt"
    19  	"testing"
    20  	"time"
    21  
    22  	. "github.com/pingcap/check"
    23  
    24  	"github.com/XiaoMi/Gaea/mysql"
    25  	"github.com/XiaoMi/Gaea/parser/types"
    26  )
    27  
    28  func TestT(t *testing.T) {
    29  	CustomVerboseFlag = true
    30  	TestingT(t)
    31  }
    32  
    33  var _ = Suite(&testModelSuite{})
    34  
    35  type testModelSuite struct {
    36  }
    37  
    38  func (*testModelSuite) TestT(c *C) {
    39  	abc := NewCIStr("aBC")
    40  	c.Assert(abc.O, Equals, "aBC")
    41  	c.Assert(abc.L, Equals, "abc")
    42  	c.Assert(abc.String(), Equals, "aBC")
    43  }
    44  
    45  func (*testModelSuite) TestModelBasic(c *C) {
    46  	column := &ColumnInfo{
    47  		ID:           1,
    48  		Name:         NewCIStr("c"),
    49  		Offset:       0,
    50  		DefaultValue: 0,
    51  		FieldType:    *types.NewFieldType(0),
    52  	}
    53  	column.Flag |= mysql.PriKeyFlag
    54  
    55  	index := &IndexInfo{
    56  		Name:  NewCIStr("key"),
    57  		Table: NewCIStr("t"),
    58  		Columns: []*IndexColumn{
    59  			{
    60  				Name:   NewCIStr("c"),
    61  				Offset: 0,
    62  				Length: 10,
    63  			}},
    64  		Unique:  true,
    65  		Primary: true,
    66  	}
    67  
    68  	fk := &FKInfo{
    69  		RefCols: []CIStr{NewCIStr("a")},
    70  		Cols:    []CIStr{NewCIStr("a")},
    71  	}
    72  
    73  	table := &TableInfo{
    74  		ID:          1,
    75  		Name:        NewCIStr("t"),
    76  		Charset:     "utf8",
    77  		Collate:     "utf8_bin",
    78  		Columns:     []*ColumnInfo{column},
    79  		Indices:     []*IndexInfo{index},
    80  		ForeignKeys: []*FKInfo{fk},
    81  		PKIsHandle:  true,
    82  	}
    83  
    84  	dbInfo := &DBInfo{
    85  		ID:      1,
    86  		Name:    NewCIStr("test"),
    87  		Charset: "utf8",
    88  		Collate: "utf8_bin",
    89  		Tables:  []*TableInfo{table},
    90  	}
    91  
    92  	n := dbInfo.Clone()
    93  	c.Assert(n, DeepEquals, dbInfo)
    94  
    95  	pkName := table.GetPkName()
    96  	c.Assert(pkName, Equals, NewCIStr("c"))
    97  	newColumn := table.GetPkColInfo()
    98  	c.Assert(newColumn, DeepEquals, column)
    99  	inIdx := table.ColumnIsInIndex(column)
   100  	c.Assert(inIdx, Equals, true)
   101  	tp := IndexTypeBtree
   102  	c.Assert(tp.String(), Equals, "BTREE")
   103  	tp = IndexTypeHash
   104  	c.Assert(tp.String(), Equals, "HASH")
   105  	tp = 1E5
   106  	c.Assert(tp.String(), Equals, "")
   107  	has := index.HasPrefixIndex()
   108  	c.Assert(has, Equals, true)
   109  	t := table.GetUpdateTime()
   110  	c.Assert(t, Equals, TSConvert2Time(table.UpdateTS))
   111  
   112  	// Corner cases
   113  	column.Flag ^= mysql.PriKeyFlag
   114  	pkName = table.GetPkName()
   115  	c.Assert(pkName, Equals, NewCIStr(""))
   116  	newColumn = table.GetPkColInfo()
   117  	c.Assert(newColumn, IsNil)
   118  	anCol := &ColumnInfo{
   119  		Name: NewCIStr("d"),
   120  	}
   121  	exIdx := table.ColumnIsInIndex(anCol)
   122  	c.Assert(exIdx, Equals, false)
   123  	anIndex := &IndexInfo{
   124  		Columns: []*IndexColumn{},
   125  	}
   126  	no := anIndex.HasPrefixIndex()
   127  	c.Assert(no, Equals, false)
   128  }
   129  
   130  func (*testModelSuite) TestJobStartTime(c *C) {
   131  	job := &Job{
   132  		ID:         123,
   133  		BinlogInfo: &HistoryInfo{},
   134  	}
   135  	t := time.Unix(0, 0)
   136  	c.Assert(t, Equals, TSConvert2Time(job.StartTS))
   137  	ret := fmt.Sprintf("%s", job)
   138  	c.Assert(job.String(), Equals, ret)
   139  }
   140  
   141  func (*testModelSuite) TestJobCodec(c *C) {
   142  	type A struct {
   143  		Name string
   144  	}
   145  	job := &Job{
   146  		ID:         1,
   147  		TableID:    2,
   148  		SchemaID:   1,
   149  		BinlogInfo: &HistoryInfo{},
   150  		Args:       []interface{}{NewCIStr("a"), A{Name: "abc"}},
   151  	}
   152  	job.BinlogInfo.AddDBInfo(123, &DBInfo{ID: 1, Name: NewCIStr("test_history_db")})
   153  	job.BinlogInfo.AddTableInfo(123, &TableInfo{ID: 1, Name: NewCIStr("test_history_tbl")})
   154  
   155  	// Test IsDependentOn.
   156  	// job: table ID is 2
   157  	// job1: table ID is 2
   158  	var err error
   159  	job1 := &Job{
   160  		ID:         2,
   161  		TableID:    2,
   162  		SchemaID:   1,
   163  		Type:       ActionRenameTable,
   164  		BinlogInfo: &HistoryInfo{},
   165  		Args:       []interface{}{int64(3), NewCIStr("new_table_name")},
   166  	}
   167  	job1.RawArgs, err = json.Marshal(job1.Args)
   168  	c.Assert(err, IsNil)
   169  	isDependent, err := job.IsDependentOn(job1)
   170  	c.Assert(err, IsNil)
   171  	c.Assert(isDependent, IsTrue)
   172  	// job1: rename table, old schema ID is 3
   173  	// job2: create schema, schema ID is 3
   174  	job2 := &Job{
   175  		ID:         3,
   176  		TableID:    3,
   177  		SchemaID:   3,
   178  		Type:       ActionCreateSchema,
   179  		BinlogInfo: &HistoryInfo{},
   180  	}
   181  	isDependent, err = job2.IsDependentOn(job1)
   182  	c.Assert(err, IsNil)
   183  	c.Assert(isDependent, IsTrue)
   184  
   185  	c.Assert(job.IsCancelled(), Equals, false)
   186  	b, err := job.Encode(false)
   187  	c.Assert(err, IsNil)
   188  	newJob := &Job{}
   189  	err = newJob.Decode(b)
   190  	c.Assert(err, IsNil)
   191  	c.Assert(newJob.BinlogInfo, DeepEquals, job.BinlogInfo)
   192  	name := CIStr{}
   193  	a := A{}
   194  	err = newJob.DecodeArgs(&name, &a)
   195  	c.Assert(err, IsNil)
   196  	c.Assert(name, DeepEquals, NewCIStr(""))
   197  	c.Assert(a, DeepEquals, A{Name: ""})
   198  	c.Assert(len(newJob.String()), Greater, 0)
   199  
   200  	job.BinlogInfo.Clean()
   201  	b1, err := job.Encode(true)
   202  	c.Assert(err, IsNil)
   203  	newJob = &Job{}
   204  	err = newJob.Decode(b1)
   205  	c.Assert(err, IsNil)
   206  	c.Assert(newJob.BinlogInfo, DeepEquals, &HistoryInfo{})
   207  	name = CIStr{}
   208  	a = A{}
   209  	err = newJob.DecodeArgs(&name, &a)
   210  	c.Assert(err, IsNil)
   211  	c.Assert(name, DeepEquals, NewCIStr("a"))
   212  	c.Assert(a, DeepEquals, A{Name: "abc"})
   213  	c.Assert(len(newJob.String()), Greater, 0)
   214  
   215  	b2, err := job.Encode(true)
   216  	c.Assert(err, IsNil)
   217  	newJob = &Job{}
   218  	err = newJob.Decode(b2)
   219  	c.Assert(err, IsNil)
   220  	name = CIStr{}
   221  	// Don't decode to a here.
   222  	err = newJob.DecodeArgs(&name)
   223  	c.Assert(err, IsNil)
   224  	c.Assert(name, DeepEquals, NewCIStr("a"))
   225  	c.Assert(len(newJob.String()), Greater, 0)
   226  
   227  	job.State = JobStateDone
   228  	c.Assert(job.IsDone(), IsTrue)
   229  	c.Assert(job.IsFinished(), IsTrue)
   230  	c.Assert(job.IsRunning(), IsFalse)
   231  	c.Assert(job.IsSynced(), IsFalse)
   232  	c.Assert(job.IsRollbackDone(), IsFalse)
   233  	job.SetRowCount(3)
   234  	c.Assert(job.GetRowCount(), Equals, int64(3))
   235  }
   236  
   237  func (testModelSuite) TestState(c *C) {
   238  	schemaTbl := []SchemaState{
   239  		StateDeleteOnly,
   240  		StateWriteOnly,
   241  		StateWriteReorganization,
   242  		StateDeleteReorganization,
   243  		StatePublic,
   244  	}
   245  
   246  	for _, state := range schemaTbl {
   247  		c.Assert(len(state.String()), Greater, 0)
   248  	}
   249  
   250  	jobTbl := []JobState{
   251  		JobStateRunning,
   252  		JobStateDone,
   253  		JobStateCancelled,
   254  		JobStateRollingback,
   255  		JobStateRollbackDone,
   256  		JobStateSynced,
   257  	}
   258  
   259  	for _, state := range jobTbl {
   260  		c.Assert(len(state.String()), Greater, 0)
   261  	}
   262  }
   263  
   264  func (testModelSuite) TestString(c *C) {
   265  	acts := []struct {
   266  		act    ActionType
   267  		result string
   268  	}{
   269  		{ActionNone, "none"},
   270  		{ActionAddForeignKey, "add foreign key"},
   271  		{ActionDropForeignKey, "drop foreign key"},
   272  		{ActionTruncateTable, "truncate table"},
   273  		{ActionModifyColumn, "modify column"},
   274  		{ActionRenameTable, "rename table"},
   275  		{ActionSetDefaultValue, "set default value"},
   276  		{ActionCreateSchema, "create schema"},
   277  		{ActionDropSchema, "drop schema"},
   278  		{ActionCreateTable, "create table"},
   279  		{ActionDropTable, "drop table"},
   280  		{ActionAddIndex, "add index"},
   281  		{ActionDropIndex, "drop index"},
   282  		{ActionAddColumn, "add column"},
   283  		{ActionDropColumn, "drop column"},
   284  	}
   285  
   286  	for _, v := range acts {
   287  		str := v.act.String()
   288  		c.Assert(str, Equals, v.result)
   289  	}
   290  }
   291  
   292  func (testModelSuite) TestUnmarshalCIStr(c *C) {
   293  	var ci CIStr
   294  
   295  	// Test unmarshal CIStr from a single string.
   296  	str := "aaBB"
   297  	buf, err := json.Marshal(str)
   298  	c.Assert(err, IsNil)
   299  	ci.UnmarshalJSON(buf)
   300  	c.Assert(ci.O, Equals, str)
   301  	c.Assert(ci.L, Equals, "aabb")
   302  
   303  	buf, err = json.Marshal(ci)
   304  	c.Assert(string(buf), Equals, `{"O":"aaBB","L":"aabb"}`)
   305  	ci.UnmarshalJSON(buf)
   306  	c.Assert(ci.O, Equals, str)
   307  	c.Assert(ci.L, Equals, "aabb")
   308  }