github.com/XiaoMi/Gaea@v1.2.5/models/namespace_test.go (about)

     1  // Copyright 2019 The Gaea Authors. All Rights Reserved.
     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  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  package models
    15  
    16  import (
    17  	"encoding/json"
    18  	"fmt"
    19  	"testing"
    20  )
    21  
    22  func defaultNamespace() *Namespace {
    23  	n := &Namespace{
    24  		IsEncrypt:        false,
    25  		Name:             "default",
    26  		Online:           true,
    27  		ReadOnly:         true,
    28  		AllowedDBS:       make(map[string]bool),
    29  		DefaultPhyDBS:    make(map[string]string),
    30  		SlowSQLTime:      "",
    31  		BlackSQL:         nil,
    32  		AllowedIP:        nil,
    33  		Slices:           make([]*Slice, 0),
    34  		ShardRules:       make([]*Shard, 0),
    35  		Users:            make([]*User, 0),
    36  		DefaultSlice:     "",
    37  		GlobalSequences:  nil,
    38  		DefaultCharset:   "",
    39  		DefaultCollation: "",
    40  	}
    41  	return n
    42  }
    43  
    44  func TestNamespaceEncode(t *testing.T) {
    45  	var namespace = &Namespace{Name: "gaea_namespace_1", Online: true, ReadOnly: true, AllowedDBS: make(map[string]bool), Slices: make([]*Slice, 0), ShardRules: make([]*Shard, 0), Users: make([]*User, 0), DefaultSlice: "slice-0"}
    46  
    47  	slice0 := &Slice{Name: "slice-0", UserName: "root", Password: "root", Master: "127.0.0.1:3306", Slaves: []string{"127.0.0.1:3306", "127.0.0.1:3306"}, Capacity: 128, MaxCapacity: 128, IdleTimeout: 120}
    48  	slice1 := &Slice{Name: "slice-1", UserName: "root", Password: "root", Master: "127.0.0.1:3306", Slaves: []string{"127.0.0.1:3306", "127.0.0.1:3306"}, Capacity: 128, MaxCapacity: 128, IdleTimeout: 120}
    49  	namespace.Slices = append(namespace.Slices, slice0)
    50  	namespace.Slices = append(namespace.Slices, slice1)
    51  
    52  	namespace.AllowedDBS["db1"] = true
    53  	namespace.AllowedDBS["db2"] = true
    54  
    55  	shard1 := &Shard{DB: "gaea", Table: "test_shard_hash", Type: "hash", Key: "id", Locations: []int{1, 1}, Slices: []string{"slice-0", "slice-1"}}
    56  	shard2 := &Shard{DB: "gaea", Table: "test_shard_range", Type: "range", Key: "id", Locations: []int{1, 1}, Slices: []string{"slice-0", "slice-1"}, TableRowLimit: 10000}
    57  	namespace.ShardRules = append(namespace.ShardRules, shard1)
    58  	namespace.ShardRules = append(namespace.ShardRules, shard2)
    59  
    60  	user1 := &User{UserName: "test1", Password: "test1", Namespace: "gaea_namespace_1", RWFlag: 2, RWSplit: 1}
    61  	namespace.Users = append(namespace.Users, user1)
    62  
    63  	t.Logf(string(namespace.Encode()))
    64  }
    65  
    66  func TestEncrypt(t *testing.T) {
    67  	key := "1234abcd5678efg*"
    68  	var namespace = &Namespace{Name: "gaea_namespace_1", Online: true, ReadOnly: true, AllowedDBS: make(map[string]bool), Slices: make([]*Slice, 0), ShardRules: make([]*Shard, 0), Users: make([]*User, 0), DefaultSlice: "slice-0"}
    69  	slice0 := &Slice{Name: "slice-0", UserName: "test1", Password: "fdsafdsa23423sx*123", Master: "127.0.0.1:3306", Slaves: []string{"127.0.0.1:3306", "127.0.0.1:3306"}, Capacity: 128, MaxCapacity: 128, IdleTimeout: 120}
    70  	slice1 := &Slice{Name: "slice-1", UserName: "test2", Password: "fasd14-43828284s*", Master: "127.0.0.1:3306", Slaves: []string{"127.0.0.1:3306", "127.0.0.1:3306"}, Capacity: 128, MaxCapacity: 128, IdleTimeout: 120}
    71  	namespace.Slices = append(namespace.Slices, slice0)
    72  	namespace.Slices = append(namespace.Slices, slice1)
    73  	user1 := &User{UserName: "test1", Password: "testfadsfafdsla234231", Namespace: "gaea_namespace_1", RWFlag: 2, RWSplit: 1}
    74  	user2 := &User{UserName: "test2", Password: "test2fdsafw5r3234", Namespace: "gaea_namespace_1", RWFlag: 2, RWSplit: 1}
    75  	namespace.Users = append(namespace.Users, user1)
    76  	namespace.Users = append(namespace.Users, user2)
    77  	err := namespace.Encrypt(key)
    78  	if err != nil {
    79  		t.Errorf("test namespace encrypt failed, %v", err)
    80  	}
    81  	err = namespace.Decrypt(key)
    82  	if err != nil {
    83  		t.Errorf("test namespace failed, %v", err)
    84  	}
    85  	t.Logf(string(namespace.Encode()))
    86  }
    87  
    88  func TestVerifyName_Success(t *testing.T) {
    89  	n := defaultNamespace()
    90  	if err := n.verifyName(); err != nil {
    91  		t.Errorf("test verifyName failed, %v", err)
    92  	}
    93  }
    94  
    95  func TestVerifyName_Error(t *testing.T) {
    96  	nf := defaultNamespace()
    97  	nf.Name = ""
    98  	if err := nf.verifyName(); err == nil {
    99  		t.Errorf("test verifyName should fail but pass, name: %v", nf.Name)
   100  	}
   101  }
   102  
   103  func TestVerifyAllowDBS_Success(t *testing.T) {
   104  	n := defaultNamespace()
   105  	n.AllowedDBS["db1"] = true
   106  	if err := n.verifyAllowDBS(); err != nil {
   107  		t.Errorf("test verifyAllowDBS failed, %v", err)
   108  	}
   109  
   110  }
   111  func TestVerifyAllowDBS_Error(t *testing.T) {
   112  	nf := defaultNamespace()
   113  	if err := nf.verifyAllowDBS(); err == nil {
   114  		t.Errorf("test verifyAllowDBS should fail but pass, name: %v", nf.Name)
   115  	}
   116  }
   117  
   118  func TestVerifyUsers_Success(t *testing.T) {
   119  	n := defaultNamespace()
   120  	u1 := &User{UserName: "u1", Namespace: n.Name, Password: "pw1", RWFlag: ReadOnly, RWSplit: NoReadWriteSplit, OtherProperty: 0}
   121  	u2 := &User{UserName: "u2", Namespace: n.Name, Password: "pw2", RWFlag: ReadWrite, RWSplit: ReadWriteSplit, OtherProperty: StatisticUser}
   122  	n.Users = append(n.Users, u1)
   123  	n.Users = append(n.Users, u2)
   124  
   125  	if err := n.verifyUsers(); err != nil {
   126  		t.Errorf("test verifyUsers failed, %v", err)
   127  	}
   128  }
   129  
   130  func TestVerifyUsers_Error(t *testing.T) {
   131  	nf := defaultNamespace()
   132  	uf1 := &User{UserName: "u1", Namespace: "someone", Password: "pw1", RWFlag: -1, RWSplit: -1, OtherProperty: -1}
   133  	uf2 := &User{UserName: "u1", Namespace: nf.Name, Password: "pw2", RWFlag: -1, RWSplit: -1, OtherProperty: -1}
   134  	uf3 := &User{UserName: "", Namespace: "", Password: "", RWFlag: -1, RWSplit: -1, OtherProperty: -1}
   135  	nf.Users = append(nf.Users, uf1)
   136  	nf.Users = append(nf.Users, uf2)
   137  	nf.Users = append(nf.Users, uf3)
   138  
   139  	if err := nf.verifyUsers(); err == nil {
   140  		t.Errorf("test verifyUsers should fail but pass, users: %s", JSONEncode(nf.Users))
   141  	}
   142  }
   143  
   144  func TestVerifySlowSQLTime_Success(t *testing.T) {
   145  	n := defaultNamespace()
   146  	ssts := []string{"", "10"}
   147  	for _, sst := range ssts {
   148  		n.SlowSQLTime = sst
   149  		if err := n.verifySlowSQLTime(); err != nil {
   150  			t.Errorf("test verifySlowSQLTime failed, %v", err)
   151  		}
   152  	}
   153  }
   154  
   155  func TestVerifySlowSQLTime_Error(t *testing.T) {
   156  	nf := defaultNamespace()
   157  	sstfs := []string{"-1", "10.0", "test"}
   158  	for _, sst := range sstfs {
   159  		nf.SlowSQLTime = sst
   160  		if err := nf.verifySlowSQLTime(); err == nil {
   161  			t.Errorf("test verifySlowSQLTime should fail but pass, sst: %v", nf.SlowSQLTime)
   162  		}
   163  	}
   164  }
   165  
   166  func TestVerifyDBs_Success(t *testing.T) {
   167  	n := defaultNamespace()
   168  	// no logic database mode
   169  	if err := n.verifyDBs(); err != nil {
   170  		t.Errorf("test verifyDBs failed, %v", err)
   171  	}
   172  
   173  	// logic database mode
   174  	n.AllowedDBS["test1"] = true
   175  	n.DefaultPhyDBS["test1"] = ""
   176  	if err := n.verifyDBs(); err != nil {
   177  		t.Errorf("test verifyDBs failed, %v", err)
   178  	}
   179  }
   180  
   181  func TestVerifyDBs_Error(t *testing.T) {
   182  	nf := defaultNamespace()
   183  	// logic database mode
   184  	nf.AllowedDBS["test1"] = true
   185  	nf.DefaultPhyDBS["test2"] = ""
   186  	if err := nf.verifyDBs(); err == nil {
   187  		t.Errorf("test verifyDBs should fail but pass, allowedDBS: %v, defaultPhyDBS: %v", nf.AllowedDBS, nf.DefaultPhyDBS)
   188  	}
   189  }
   190  
   191  func TestVerifyAllowIps_Success(t *testing.T) {
   192  	n := defaultNamespace()
   193  	n.AllowedIP = append(n.AllowedIP, "  ")
   194  	n.AllowedIP = append(n.AllowedIP, "10.221.163.82")
   195  	if err := n.verifyAllowIps(); err != nil {
   196  		t.Errorf("test verifyAllowIps failed, %v", err)
   197  	}
   198  }
   199  
   200  func TestVerifyAllowIps_Error(t *testing.T) {
   201  	nf := defaultNamespace()
   202  	var ipfs = []string{"test", "1.1.1"}
   203  	for _, ipf := range ipfs {
   204  		nf.AllowedIP = []string{ipf}
   205  		if err := nf.verifyAllowIps(); err == nil {
   206  			t.Errorf("test verifyAllowIps should fail but pass, %v", nf.AllowedIP)
   207  		}
   208  	}
   209  }
   210  
   211  func TestVerifyCharset_Success(t *testing.T) {
   212  	n := defaultNamespace()
   213  	var ccs = [][]string{[]string{"", ""}, []string{"big5", ""}, []string{"big5", "big5_chinese_ci"}}
   214  	for _, cc := range ccs {
   215  		n.DefaultCharset = cc[0]
   216  		n.DefaultCollation = cc[1]
   217  		if err := n.verifyCharset(); err != nil {
   218  			t.Errorf("test verifyCharset failed, %v", err)
   219  		}
   220  	}
   221  }
   222  
   223  func TestVerifyCharset_Error(t *testing.T) {
   224  	nf := defaultNamespace()
   225  	var ccfs = [][]string{[]string{"", "test"}, []string{"test", ""}, []string{"big5", "test"}, []string{"big5", "latin2_czech_cs"}}
   226  	for _, ccf := range ccfs {
   227  		nf.DefaultCharset = ccf[0]
   228  		nf.DefaultCollation = ccf[1]
   229  		if err := nf.verifyCharset(); err == nil {
   230  			t.Errorf("test verifyCharset should fail but pass, charset: %s, collation: %s", nf.DefaultCharset, nf.DefaultCollation)
   231  		}
   232  	}
   233  }
   234  
   235  func TestVerifySlices_Success(t *testing.T) {
   236  	n := defaultNamespace()
   237  	var slice1 = &Slice{Name: "slice1", UserName: "user", Password: "", Master: "1.1.1.1:1", Slaves: []string{"1.1.1.1:2"}, Capacity: 1, MaxCapacity: 1, IdleTimeout: 100}
   238  	var slice2 = &Slice{Name: "slice2", UserName: "user", Password: "", Master: "1.1.1.1:1", Slaves: []string{"1.1.1.1:2"}, Capacity: 1, MaxCapacity: 1, IdleTimeout: 100}
   239  	n.Slices = append(n.Slices, slice1)
   240  	n.Slices = append(n.Slices, slice2)
   241  	if err := n.verifySlices(); err != nil {
   242  		t.Errorf("test verifySlices failed, %v", err)
   243  	}
   244  }
   245  
   246  func TestVerifySlices_Error(t *testing.T) {
   247  	nf := defaultNamespace()
   248  	var slice1 = &Slice{Name: "slice1", UserName: "user", Password: "", Master: "1.1.1.1:1", Slaves: []string{"1.1.1.1:2"}, Capacity: 1, MaxCapacity: 1, IdleTimeout: 100}
   249  	var slicefs = []*Slice{
   250  		&Slice{Name: "", UserName: "user", Password: "", Master: "1.1.1.1:1", Slaves: []string{"1.1.1.1:2"}, Capacity: 1, MaxCapacity: 1, IdleTimeout: 100},
   251  		&Slice{Name: "slice1", UserName: "user", Password: "", Master: "1.1.1.1:1", Slaves: []string{"1.1.1.1:2"}, Capacity: 1, MaxCapacity: 1, IdleTimeout: 100},
   252  		&Slice{Name: "slice1", UserName: "", Password: "", Master: "1.1.1.1:1", Slaves: []string{"1.1.1.1:2"}, Capacity: 1, MaxCapacity: 1, IdleTimeout: 100},
   253  		&Slice{Name: "slice1", UserName: "user", Password: "", Master: "", Slaves: []string{}, Capacity: 1, MaxCapacity: 1, IdleTimeout: 100},
   254  		&Slice{Name: "slice1", UserName: "user", Password: "", Master: "", Slaves: []string{""}, Capacity: 1, MaxCapacity: 1, IdleTimeout: 100},
   255  		&Slice{Name: "slice1", UserName: "user", Password: "", Master: "1.1.1.1:1", Slaves: []string{"1.1.1.1:2"}, Capacity: 0, MaxCapacity: 1, IdleTimeout: 100},
   256  		&Slice{Name: "slice1", UserName: "user", Password: "", Master: "1.1.1.1:1", Slaves: []string{"1.1.1.1:2"}, Capacity: 1, MaxCapacity: 0, IdleTimeout: 100},
   257  	}
   258  	for _, slicef := range slicefs {
   259  		nf.Slices = append(nf.Slices, slice1)
   260  		nf.Slices = append(nf.Slices, slicef)
   261  		if err := nf.verifySlices(); err == nil {
   262  			t.Errorf("test verifySlices should fail but pass, slices: %s", JSONEncode(nf.Slices))
   263  		}
   264  	}
   265  }
   266  
   267  func TestVerifyDefaultSlice_Success(t *testing.T) {
   268  	n := defaultNamespace()
   269  	n.Slices = append(n.Slices, &Slice{Name: "slice1"})
   270  	var dss = []string{"", "slice1"}
   271  	for _, ds := range dss {
   272  		n.DefaultSlice = ds
   273  		if err := n.verifyDefaultSlice(); err != nil {
   274  			t.Errorf("test verifyDefaultSlice failed, %v", err)
   275  		}
   276  	}
   277  }
   278  
   279  func TestVerifyDefaultSlice_Error(t *testing.T) {
   280  	nf := defaultNamespace()
   281  	nf.Slices = append(nf.Slices, &Slice{Name: "slice1"})
   282  	nf.DefaultSlice = "slice2"
   283  	if err := nf.verifyDefaultSlice(); err == nil {
   284  		t.Errorf("test verifyDefaultSlice should fail but pass, defaultSlice: %s", nf.DefaultSlice)
   285  	}
   286  }
   287  
   288  func TestVerifyShardRules_Success(t *testing.T) {
   289  	n := defaultNamespace()
   290  	n.Slices = []*Slice{
   291  		&Slice{Name: "slice-0", UserName: "root", Password: "root", Master: "127.0.0.1:3306", Capacity: 64, MaxCapacity: 128, IdleTimeout: 3600},
   292  		&Slice{Name: "slice-1", UserName: "root", Password: "root", Master: "127.0.0.1:3307", Capacity: 64, MaxCapacity: 128, IdleTimeout: 3600},
   293  	}
   294  	n.ShardRules = []*Shard{
   295  		&Shard{DB: "db_ks", Table: "tbl_ks", Type: "mod", Key: "id", Locations: []int{2, 2}, Slices: []string{"slice-0", "slice-1"}},
   296  		&Shard{DB: "db_ks", Table: "tbl_ks_child", Type: "linked", Key: "id", ParentTable: "tbl_ks"},
   297  		&Shard{DB: "db_ks", Table: "tbl_ks_user_child", Type: "linked", Key: "user_id", ParentTable: "tbl_ks"},
   298  		&Shard{DB: "db_ks", Table: "tbl_ks_global_one", Type: "global", Locations: []int{2, 2}, Slices: []string{"slice-0", "slice-1"}},
   299  		&Shard{DB: "db_ks", Table: "tbl_ks_global_two", Type: "global", Locations: []int{2, 2}, Slices: []string{"slice-0", "slice-1"}},
   300  		&Shard{DB: "db_ks", Table: "tbl_ks_range", Type: "range", Key: "id", Locations: []int{2, 2}, Slices: []string{"slice-0", "slice-1"}, TableRowLimit: 100},
   301  		&Shard{DB: "db_ks", Table: "tbl_ks_year", Type: "date_year", Key: "create_time", Slices: []string{"slice-0", "slice-1"}, DateRange: []string{"2014-2017", "2018-2019"}},
   302  		&Shard{DB: "db_ks", Table: "tbl_ks_month", Type: "date_month", Key: "create_time", Slices: []string{"slice-0", "slice-1"}, DateRange: []string{"201405-201406", "201408-201409"}},
   303  		&Shard{DB: "db_ks", Table: "tbl_ks_day", Type: "date_day", Key: "create_time", Slices: []string{"slice-0", "slice-1"}, DateRange: []string{"20140901-20140905", "20140907-20140908"}},
   304  		&Shard{DB: "db_mycat", Table: "tbl_mycat", Type: "mycat_mod", Key: "id", Locations: []int{2, 2}, Slices: []string{"slice-0", "slice-1"}, Databases: []string{"db_mycat_[0-3]"}},
   305  		&Shard{DB: "db_mycat", Table: "tbl_mycat_child", Type: "linked", ParentTable: "tbl_mycat", Key: "id"},
   306  		&Shard{DB: "db_mycat", Table: "tbl_mycat_user_child", Type: "linked", ParentTable: "tbl_mycat", Key: "user_id"},
   307  		&Shard{DB: "db_mycat", Table: "tbl_mycat_murmur", Type: "mycat_murmur", Key: "id", Locations: []int{2, 2}, Slices: []string{"slice-0", "slice-1"}, Databases: []string{"db_mycat_0", "db_mycat_1", "db_mycat_2", "db_mycat_3"}, Seed: "0", VirtualBucketTimes: "160"},
   308  		&Shard{DB: "db_mycat", Table: "tbl_mycat_long", Type: "mycat_long", Key: "id", Locations: []int{2, 2}, Slices: []string{"slice-0", "slice-1"}, Databases: []string{"db_mycat_[0-3]"}, PartitionCount: "4", PartitionLength: "256"},
   309  		&Shard{DB: "db_mycat", Table: "tbl_mycat_global_one", Type: "global", Locations: []int{2, 2}, Slices: []string{"slice-0", "slice-1"}, Databases: []string{"db_mycat_[0-3]"}},
   310  		&Shard{DB: "db_mycat", Table: "tbl_mycat_global_two", Type: "global", Locations: []int{2, 2}, Slices: []string{"slice-0", "slice-1"}, Databases: []string{"db_mycat_[0-3]"}},
   311  		&Shard{DB: "db_mycat", Table: "tbl_mycat_string", Type: "mycat_string", Key: "id", Locations: []int{2, 2}, Slices: []string{"slice-0", "slice-1"}, Databases: []string{"db_mycat_[0-3]"}, PartitionCount: "4", PartitionLength: "256", HashSlice: "20"},
   312  	}
   313  	if err := n.verifyShardRules(); err != nil {
   314  		t.Errorf("test verifyShardRules failed, %v", err)
   315  	}
   316  }
   317  
   318  func TestVerifyShardRule_Error_common(t *testing.T) {
   319  	nf := defaultNamespace()
   320  	// slices not match
   321  	nf.ShardRules = []*Shard{&Shard{Slices: []string{"slice"}}}
   322  	if err := nf.verifyShardRules(); err == nil {
   323  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   324  	}
   325  
   326  	// db duplicate
   327  	nf.ShardRules = []*Shard{
   328  		&Shard{DB: "db", Table: "table", Type: ShardMod},
   329  		&Shard{DB: "db", Table: "table", Type: ShardMod},
   330  	}
   331  	if err := nf.verifyShardRules(); err == nil {
   332  		t.Errorf("test verifyShardRules should fail but pass, shardRule: %s", JSONEncode(nf.ShardRules))
   333  	}
   334  }
   335  
   336  func TestVerifyShardRules_Error_ShardDefault(t *testing.T) {
   337  	nf := defaultNamespace()
   338  	nf.ShardRules = []*Shard{&Shard{Type: ShardDefault}}
   339  	if err := nf.verifyShardRules(); err == nil {
   340  		t.Errorf("test verifyShardRules should fail but pass, shardRule: %s", JSONEncode(nf.ShardRules))
   341  	}
   342  }
   343  
   344  func TestVerifyShardRules_Error_ShardLinked(t *testing.T) {
   345  	nf := defaultNamespace()
   346  	// without parent rules
   347  	nf.ShardRules = []*Shard{
   348  		&Shard{Type: ShardLinked, DB: "db1", Table: "table1", ParentTable: "table2"},
   349  	}
   350  	if err := nf.verifyShardRules(); err == nil {
   351  		t.Errorf("test verifyShardRules should fail but pass, shardRule: %s", JSONEncode(nf.ShardRules))
   352  	}
   353  
   354  	// link to another linkedRule
   355  	nf.ShardRules = []*Shard{
   356  		&Shard{Type: ShardLinked, DB: "db1", Table: "table1", ParentTable: "table2"},
   357  		&Shard{Type: ShardLinked, DB: "db1", Table: "table2", ParentTable: "table2"},
   358  	}
   359  	if err := nf.verifyShardRules(); err == nil {
   360  		t.Errorf("test verifyShardRules should fail but pass, shardRule: %s", JSONEncode(nf.ShardRules))
   361  	}
   362  }
   363  
   364  func TestVerifyShardRules_Error_ShardHash(t *testing.T) {
   365  	nf := defaultNamespace()
   366  	// locations count is not equal
   367  	nf.ShardRules = []*Shard{&Shard{Type: ShardHash, Locations: []int{1}, Slices: []string{}}}
   368  	if err := nf.verifyShardRules(); err == nil {
   369  		t.Errorf("test verifyShardRules should fail but pass, shardRule: %s", JSONEncode(nf.ShardRules))
   370  	}
   371  }
   372  
   373  func TestVerifyShardRules_Error_ShardMod(t *testing.T) {
   374  	nf := defaultNamespace()
   375  	// locations count is not equal
   376  	nf.ShardRules = []*Shard{&Shard{Type: ShardMod, Locations: []int{1}, Slices: []string{}}}
   377  	if err := nf.verifyShardRules(); err == nil {
   378  		t.Errorf("test verifyShardRules should fail but pass, shardRule: %s", JSONEncode(nf.ShardRules))
   379  	}
   380  }
   381  
   382  func TestVerifyShardRules_Error_ShardRange(t *testing.T) {
   383  	nf := defaultNamespace()
   384  	// locations count is not equal
   385  	nf.ShardRules = []*Shard{&Shard{Type: ShardRange, Locations: []int{1}, Slices: []string{}}}
   386  	if err := nf.verifyShardRules(); err == nil {
   387  		t.Errorf("test verifyShardRules should fail but pass, shardRule: %s", JSONEncode(nf.ShardRules))
   388  	}
   389  }
   390  
   391  func TestVerifyShardRules_Error_ShardDay(t *testing.T) {
   392  	nf := defaultNamespace()
   393  	nf.Slices = []*Slice{&Slice{Name: "slice1"}}
   394  	// dateRange count is not equal
   395  	nf.ShardRules = []*Shard{&Shard{Type: ShardDay, DateRange: []string{"1"}, Slices: []string{}}}
   396  	if err := nf.verifyShardRules(); err == nil {
   397  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   398  	}
   399  	// dateRange not match
   400  	nf.ShardRules = []*Shard{&Shard{Type: ShardDay, DateRange: []string{"1"}, Slices: []string{"slice1"}}}
   401  	if err := nf.verifyShardRules(); err == nil {
   402  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   403  	}
   404  	nf.ShardRules = []*Shard{&Shard{Type: ShardDay, DateRange: []string{"abc"}, Slices: []string{"slice1"}}}
   405  	if err := nf.verifyShardRules(); err == nil {
   406  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   407  	}
   408  	nf.ShardRules = []*Shard{&Shard{Type: ShardDay, DateRange: []string{"22222222"}, Slices: []string{"slice1"}}}
   409  	if err := nf.verifyShardRules(); err == nil {
   410  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   411  	}
   412  	nf.ShardRules = []*Shard{&Shard{Type: ShardDay, DateRange: []string{"201910301-2019103"}, Slices: []string{"slice1"}}}
   413  	if err := nf.verifyShardRules(); err == nil {
   414  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   415  	}
   416  	nf.ShardRules = []*Shard{&Shard{Type: ShardDay, DateRange: []string{"22222222-33333333"}, Slices: []string{"slice1"}}}
   417  	if err := nf.verifyShardRules(); err == nil {
   418  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   419  	}
   420  	nf.ShardRules = []*Shard{&Shard{Type: ShardDay, DateRange: []string{"11111111-22222222"}, Slices: []string{"slice1"}}}
   421  	if err := nf.verifyShardRules(); err == nil {
   422  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   423  	}
   424  	// date range overlapped
   425  	nf.Slices = []*Slice{&Slice{Name: "slice1"}, &Slice{Name: "slice2"}}
   426  	nf.ShardRules = []*Shard{&Shard{Type: ShardDay, DateRange: []string{"20181030", "20181001"}, Slices: []string{"slice1", "slice2"}}}
   427  	if err := nf.verifyShardRules(); err == nil {
   428  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   429  	}
   430  }
   431  
   432  func TestVerifyShardRules_Error_ShardMonth(t *testing.T) {
   433  	nf := defaultNamespace()
   434  	nf.Slices = []*Slice{&Slice{Name: "slice1"}}
   435  	// dateRange count is not equal
   436  	nf.ShardRules = []*Shard{&Shard{Type: ShardMonth, DateRange: []string{"1"}, Slices: []string{}}}
   437  	if err := nf.verifyShardRules(); err == nil {
   438  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   439  	}
   440  	// dateRange not match
   441  	nf.ShardRules = []*Shard{&Shard{Type: ShardMonth, DateRange: []string{"1"}, Slices: []string{"slice1"}}}
   442  	if err := nf.verifyShardRules(); err == nil {
   443  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   444  	}
   445  	nf.ShardRules = []*Shard{&Shard{Type: ShardMonth, DateRange: []string{"abc"}, Slices: []string{"slice1"}}}
   446  	if err := nf.verifyShardRules(); err == nil {
   447  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   448  	}
   449  	nf.ShardRules = []*Shard{&Shard{Type: ShardMonth, DateRange: []string{"222222"}, Slices: []string{"slice1"}}}
   450  	if err := nf.verifyShardRules(); err == nil {
   451  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   452  	}
   453  	nf.ShardRules = []*Shard{&Shard{Type: ShardMonth, DateRange: []string{"2019101-20191"}, Slices: []string{"slice1"}}}
   454  	if err := nf.verifyShardRules(); err == nil {
   455  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   456  	}
   457  	nf.ShardRules = []*Shard{&Shard{Type: ShardMonth, DateRange: []string{"222222-333333"}, Slices: []string{"slice1"}}}
   458  	if err := nf.verifyShardRules(); err == nil {
   459  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   460  	}
   461  	nf.ShardRules = []*Shard{&Shard{Type: ShardMonth, DateRange: []string{"111111-222222"}, Slices: []string{"slice1"}}}
   462  	if err := nf.verifyShardRules(); err == nil {
   463  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   464  	}
   465  	// date range overlapped
   466  	nf.Slices = []*Slice{&Slice{Name: "slice1"}, &Slice{Name: "slice2"}}
   467  	nf.ShardRules = []*Shard{&Shard{Type: ShardMonth, DateRange: []string{"201810", "201809"}, Slices: []string{"slice1", "slice2"}}}
   468  	if err := nf.verifyShardRules(); err == nil {
   469  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   470  	}
   471  }
   472  
   473  func TestVerifyShardRules_Error_ShardYear(t *testing.T) {
   474  	nf := defaultNamespace()
   475  	nf.Slices = []*Slice{&Slice{Name: "slice1"}}
   476  	// dateRange count is not equal
   477  	nf.ShardRules = []*Shard{&Shard{Type: ShardYear, DateRange: []string{"1"}, Slices: []string{}}}
   478  	if err := nf.verifyShardRules(); err == nil {
   479  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   480  	}
   481  	// dateRange not match
   482  	nf.ShardRules = []*Shard{&Shard{Type: ShardYear, DateRange: []string{"1"}, Slices: []string{"slice1"}}}
   483  	if err := nf.verifyShardRules(); err == nil {
   484  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   485  	}
   486  	nf.ShardRules = []*Shard{&Shard{Type: ShardYear, DateRange: []string{"abc"}, Slices: []string{"slice1"}}}
   487  	if err := nf.verifyShardRules(); err == nil {
   488  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   489  	}
   490  	nf.ShardRules = []*Shard{&Shard{Type: ShardYear, DateRange: []string{"20191-201"}, Slices: []string{"slice1"}}}
   491  	if err := nf.verifyShardRules(); err == nil {
   492  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   493  	}
   494  	// date range overlapped
   495  	nf.Slices = []*Slice{&Slice{Name: "slice1"}, &Slice{Name: "slice2"}}
   496  	nf.ShardRules = []*Shard{&Shard{Type: ShardYear, DateRange: []string{"2018", "2017"}, Slices: []string{"slice1", "slice2"}}}
   497  	if err := nf.verifyShardRules(); err == nil {
   498  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   499  	}
   500  }
   501  
   502  func TestVerifyShardRules_Error_ShardMycatMod(t *testing.T) {
   503  	if err := testVerifyShardRules_Error_ShardMycatMod(ShardMycatMod); err != nil {
   504  		t.Error(err)
   505  	}
   506  }
   507  
   508  func testVerifyShardRules_Error_ShardMycatMod(t string) error {
   509  	nf := defaultNamespace()
   510  	nf.Slices = []*Slice{&Slice{Name: "slice1"}}
   511  	// location count is not equal of slice
   512  	nf.ShardRules = []*Shard{&Shard{Type: t, Locations: []int{1}, Slices: []string{}, Databases: []string{""}}}
   513  	if err := nf.verifyShardRules(); err == nil {
   514  		return fmt.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   515  	}
   516  	// db bound value invalid
   517  	nf.ShardRules = []*Shard{&Shard{Type: t, Locations: []int{1}, Slices: []string{"slice1"}, Databases: []string{"db[1-1]"}}}
   518  	if err := nf.verifyShardRules(); err == nil {
   519  		return fmt.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   520  	}
   521  	// location count is not equal of db
   522  	nf.ShardRules = []*Shard{&Shard{Type: t, Locations: []int{1}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}}}
   523  	if err := nf.verifyShardRules(); err == nil {
   524  		return fmt.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   525  	}
   526  	return nil
   527  }
   528  
   529  func TestVerifyShardRules_Error_ShardMycatLong(t *testing.T) {
   530  	if err := testVerifyShardRules_Error_ShardMycatMod(ShardMycatLong); err != nil {
   531  		t.Error(err)
   532  	}
   533  
   534  	if err := testVerifyShardRules_Error_ShardMycatLong(ShardMycatLong); err != nil {
   535  		t.Error(err)
   536  	}
   537  }
   538  
   539  func testVerifyShardRules_Error_ShardMycatLong(t string) error {
   540  	nf := defaultNamespace()
   541  	nf.Slices = []*Slice{&Slice{Name: "slice1"}}
   542  	// patitionCount to int array
   543  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatLong, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PartitionCount: "test", PartitionLength: ""}}
   544  	if err := nf.verifyShardRules(); err == nil {
   545  		return fmt.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   546  	}
   547  	// patitionLength to int array
   548  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatLong, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PartitionCount: "4", PartitionLength: "test"}}
   549  	if err := nf.verifyShardRules(); err == nil {
   550  		return fmt.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   551  	}
   552  	// partitionScope not match
   553  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatLong, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PartitionCount: "2", PartitionLength: "256"}}
   554  	if err := nf.verifyShardRules(); err == nil {
   555  		return fmt.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   556  	}
   557  	return nil
   558  }
   559  
   560  func TestVerifyShardRules_Error_ShardMycatString(t *testing.T) {
   561  	if err := testVerifyShardRules_Error_ShardMycatMod(ShardMycatString); err != nil {
   562  		t.Error(err)
   563  	}
   564  
   565  	if err := testVerifyShardRules_Error_ShardMycatLong(ShardMycatString); err != nil {
   566  		t.Error(err)
   567  	}
   568  
   569  	nf := defaultNamespace()
   570  	nf.Slices = []*Slice{&Slice{Name: "slice1"}}
   571  	// verify hashSlice
   572  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatString, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PartitionCount: "2", PartitionLength: "512", HashSlice: "test"}}
   573  	if err := nf.verifyShardRules(); err == nil {
   574  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   575  	}
   576  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatString, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PartitionCount: "2", PartitionLength: "512", HashSlice: "test:"}}
   577  	if err := nf.verifyShardRules(); err == nil {
   578  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   579  	}
   580  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatString, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PartitionCount: "2", PartitionLength: "512", HashSlice: ":test"}}
   581  	if err := nf.verifyShardRules(); err == nil {
   582  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   583  	}
   584  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatString, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PartitionCount: "2", PartitionLength: "512", HashSlice: "a:b:c"}}
   585  	if err := nf.verifyShardRules(); err == nil {
   586  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   587  	}
   588  }
   589  
   590  func TestVerifyShardRules_Error_ShardMycatMURMUR(t *testing.T) {
   591  	if err := testVerifyShardRules_Error_ShardMycatMod(ShardMycatMURMUR); err != nil {
   592  		t.Error(err)
   593  	}
   594  
   595  	nf := defaultNamespace()
   596  	nf.Slices = []*Slice{&Slice{Name: "slice1"}}
   597  	// verify seed and virtualBucketTimes
   598  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatMURMUR, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, Seed: "test", VirtualBucketTimes: ""}}
   599  	if err := nf.verifyShardRules(); err == nil {
   600  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   601  	}
   602  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatMURMUR, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, Seed: "5", VirtualBucketTimes: "test"}}
   603  	if err := nf.verifyShardRules(); err == nil {
   604  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   605  	}
   606  }
   607  
   608  func TestVerifyShardRules_Error_ShardMycatPaddingMod(t *testing.T) {
   609  	if err := testVerifyShardRules_Error_ShardMycatMod(ShardMycatPaddingMod); err != nil {
   610  		t.Error(err)
   611  	}
   612  
   613  	nf := defaultNamespace()
   614  	nf.Slices = []*Slice{&Slice{Name: "slice1"}}
   615  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatPaddingMod, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PadFrom: "test", PadLength: "", ModBegin: "", ModEnd: ""}}
   616  	if err := nf.verifyShardRules(); err == nil {
   617  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   618  	}
   619  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatPaddingMod, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PadFrom: "1", PadLength: "test", ModBegin: "", ModEnd: ""}}
   620  	if err := nf.verifyShardRules(); err == nil {
   621  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   622  	}
   623  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatPaddingMod, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PadFrom: "1", PadLength: "1", ModBegin: "test", ModEnd: ""}}
   624  	if err := nf.verifyShardRules(); err == nil {
   625  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   626  	}
   627  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatPaddingMod, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PadFrom: "1", PadLength: "1", ModBegin: "1", ModEnd: "test"}}
   628  	if err := nf.verifyShardRules(); err == nil {
   629  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   630  	}
   631  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatPaddingMod, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PadFrom: "2", PadLength: "1", ModBegin: "1", ModEnd: "1"}}
   632  	if err := nf.verifyShardRules(); err == nil {
   633  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   634  	}
   635  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatPaddingMod, Locations: []int{1}, Slices: []string{"slice1"}, Databases: []string{"db0"}, PadFrom: "1", PadLength: "1", ModBegin: "1", ModEnd: "1"}}
   636  	if err := nf.verifyShardRules(); err == nil {
   637  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   638  	}
   639  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatPaddingMod, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PadFrom: "1", PadLength: "1", ModBegin: "-1", ModEnd: "4"}}
   640  	if err := nf.verifyShardRules(); err == nil {
   641  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   642  	}
   643  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatPaddingMod, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PadFrom: "1", PadLength: "1", ModBegin: "4", ModEnd: "4"}}
   644  	if err := nf.verifyShardRules(); err == nil {
   645  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   646  	}
   647  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatPaddingMod, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PadFrom: "1", PadLength: "0", ModBegin: "0", ModEnd: "4"}}
   648  	if err := nf.verifyShardRules(); err == nil {
   649  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   650  	}
   651  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatPaddingMod, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PadFrom: "1", PadLength: "-1", ModBegin: "0", ModEnd: "4"}}
   652  	if err := nf.verifyShardRules(); err == nil {
   653  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   654  	}
   655  	nf.ShardRules = []*Shard{&Shard{Type: ShardMycatPaddingMod, Locations: []int{2}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}, PadFrom: "1", PadLength: "2", ModBegin: "0", ModEnd: "4"}}
   656  	if err := nf.verifyShardRules(); err == nil {
   657  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   658  	}
   659  }
   660  
   661  func TestVerifyShardRules_Error_ShardGlobal(t *testing.T) {
   662  	nf := defaultNamespace()
   663  	nf.Slices = []*Slice{&Slice{Name: "slice1"}}
   664  	// location count is not equal of slice
   665  	nf.ShardRules = []*Shard{&Shard{Type: ShardGlobal, Locations: []int{1}, Slices: []string{}, Databases: []string{""}}}
   666  	if err := nf.verifyShardRules(); err == nil {
   667  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   668  	}
   669  	// db bound value invalid
   670  	nf.ShardRules = []*Shard{&Shard{Type: ShardGlobal, Locations: []int{1}, Slices: []string{"slice1"}, Databases: []string{"db[1-1]"}}}
   671  	if err := nf.verifyShardRules(); err == nil {
   672  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   673  	}
   674  	// location count is not equal of db
   675  	nf.ShardRules = []*Shard{&Shard{Type: ShardGlobal, Locations: []int{1}, Slices: []string{"slice1"}, Databases: []string{"db[0-1]"}}}
   676  	if err := nf.verifyShardRules(); err == nil {
   677  		t.Errorf("test verifyShardRules should fail but pass, slices: %s, shardRule: %s", JSONEncode(nf.Slices), JSONEncode(nf.ShardRules))
   678  	}
   679  }
   680  
   681  func TestNamespace_Verify(t *testing.T) {
   682  	nsStr := `
   683  {
   684      "name": "gaea_namespace_1",
   685      "online": true,
   686      "read_only": true,
   687      "allowed_dbs": {
   688          "db_ks": true,
   689          "db_mycat": true
   690      },
   691      "default_phy_dbs": {
   692          "db_ks": "db_ks",
   693          "db_mycat": "db_mycat_0"
   694      },
   695      "slices": [
   696          {
   697              "name": "slice-0",
   698              "user_name": "root",
   699              "password": "root",
   700              "master": "127.0.0.1:3306",
   701              "capacity": 64,
   702              "max_capacity": 128,
   703              "idle_timeout": 3600
   704          },
   705          {
   706              "name": "slice-1",
   707              "user_name": "root",
   708              "password": "root",
   709              "master": "127.0.0.1:3307",
   710              "capacity": 64,
   711              "max_capacity": 128,
   712              "idle_timeout": 3600
   713          }
   714      ],
   715      "shard_rules": [
   716          {
   717              "db": "db_ks",
   718              "table": "tbl_ks",
   719              "type": "mod",
   720              "key": "id",
   721              "locations": [
   722                  2,
   723                  2
   724              ],
   725              "slices": [
   726                  "slice-0",
   727                  "slice-1"
   728              ]
   729          },
   730          {
   731              "db": "db_ks",
   732              "table": "tbl_ks_child",
   733              "type": "linked",
   734              "key": "id",
   735              "parent_table": "tbl_ks"
   736          },
   737          {
   738              "db": "db_ks",
   739              "table": "tbl_ks_user_child",
   740              "type": "linked",
   741              "key": "user_id",
   742              "parent_table": "tbl_ks"
   743          },
   744  		{
   745              "db": "db_ks",
   746              "table": "tbl_ks_global_one",
   747              "type": "global",
   748              "locations": [
   749                  2,
   750                  2
   751              ],
   752              "slices": [
   753                  "slice-0",
   754                  "slice-1"
   755              ]
   756          },
   757  		{
   758              "db": "db_ks",
   759              "table": "tbl_ks_global_two",
   760              "type": "global",
   761              "locations": [
   762                  2,
   763                  2
   764              ],
   765              "slices": [
   766                  "slice-0",
   767                  "slice-1"
   768              ]
   769          },
   770  		{
   771  			"db": "db_ks",
   772              "table": "tbl_ks_range",
   773              "type": "range",
   774  			"key": "id",
   775              "locations": [
   776                  2,
   777                  2
   778              ],
   779              "slices": [
   780                  "slice-0",
   781                  "slice-1"
   782              ],
   783  			"table_row_limit": 100
   784  		},
   785  		{
   786  			"db": "db_ks",
   787              "table": "tbl_ks_year",
   788              "type": "date_year",
   789  			"key": "create_time",
   790              "slices": [
   791                  "slice-0",
   792                  "slice-1"
   793              ],
   794  			"date_range": [
   795  				"2014-2017",
   796  				"2018-2019"
   797  			]
   798  		},
   799  		{
   800  			"db": "db_ks",
   801              "table": "tbl_ks_month",
   802              "type": "date_month",
   803  			"key": "create_time",
   804              "slices": [
   805                  "slice-0",
   806                  "slice-1"
   807              ],
   808  			"date_range": [
   809  				"201405-201406",
   810  				"201408-201409"
   811  			]
   812  		},
   813  		{
   814  			"db": "db_ks",
   815              "table": "tbl_ks_day",
   816              "type": "date_day",
   817  			"key": "create_time",
   818              "slices": [
   819                  "slice-0",
   820                  "slice-1"
   821              ],
   822  			"date_range": [
   823  				"20140901-20140905",
   824  				"20140907-20140908"
   825  			]
   826  		},
   827          {
   828              "db": "db_mycat",
   829              "table": "tbl_mycat",
   830              "type": "mycat_mod",
   831              "key": "id",
   832              "locations": [
   833                  2,
   834                  2
   835              ],
   836              "slices": [
   837                  "slice-0",
   838                  "slice-1"
   839              ],
   840              "databases": [
   841                  "db_mycat_[0-3]"
   842              ]
   843          },
   844          {
   845              "db": "db_mycat",
   846              "table": "tbl_mycat_child",
   847              "type": "linked",
   848              "parent_table": "tbl_mycat",
   849              "key": "id"
   850          },
   851          {
   852              "db": "db_mycat",
   853              "table": "tbl_mycat_user_child",
   854              "type": "linked",
   855              "parent_table": "tbl_mycat",
   856              "key": "user_id"
   857          },
   858          {
   859              "db": "db_mycat",
   860              "table": "tbl_mycat_murmur",
   861              "type": "mycat_murmur",
   862              "key": "id",
   863              "locations": [
   864                  2,
   865                  2
   866              ],
   867              "slices": [
   868                  "slice-0",
   869                  "slice-1"
   870              ],
   871              "databases": [
   872                  "db_mycat_0","db_mycat_1","db_mycat_2","db_mycat_3"
   873              ],
   874  			"seed": "0",
   875  			"virtual_bucket_times": "160"
   876          },
   877          {
   878              "db": "db_mycat",
   879              "table": "tbl_mycat_long",
   880              "type": "mycat_long",
   881              "key": "id",
   882              "locations": [
   883                  2,
   884                  2
   885              ],
   886              "slices": [
   887                  "slice-0",
   888                  "slice-1"
   889              ],
   890              "databases": [
   891                  "db_mycat_[0-3]"
   892              ],
   893  			"partition_count": "4",
   894  			"partition_length": "256"
   895          },
   896  		{
   897              "db": "db_mycat",
   898              "table": "tbl_mycat_global_one",
   899              "type": "global",
   900              "locations": [
   901                  2,
   902                  2
   903              ],
   904              "slices": [
   905                  "slice-0",
   906                  "slice-1"
   907              ],
   908              "databases": [
   909                  "db_mycat_[0-3]"
   910              ]
   911          },
   912  		{
   913              "db": "db_mycat",
   914              "table": "tbl_mycat_global_two",
   915              "type": "global",
   916              "locations": [
   917                  2,
   918                  2
   919              ],
   920              "slices": [
   921                  "slice-0",
   922                  "slice-1"
   923              ],
   924              "databases": [
   925                  "db_mycat_[0-3]"
   926              ]
   927          },
   928          {
   929              "db": "db_mycat",
   930              "table": "tbl_mycat_string",
   931              "type": "mycat_string",
   932              "key": "id",
   933              "locations": [
   934                  2,
   935                  2
   936              ],
   937              "slices": [
   938                  "slice-0",
   939                  "slice-1"
   940              ],
   941              "databases": [
   942                  "db_mycat_[0-3]"
   943              ],
   944  			"partition_count": "4",
   945  			"partition_length": "256",
   946  			"hash_slice": "20"
   947          }
   948      ],
   949  	"global_sequences": [
   950  		{
   951  			"db": "db_mycat",
   952  			"table": "tbl_mycat",
   953  			"type": "test",
   954  			"pk_name": "id"
   955  		},
   956  		{
   957  			"db": "db_ks",
   958  			"table": "tbl_ks",
   959  			"type": "test",
   960  			"pk_name": "user_id"
   961  		}
   962  	],
   963      "users": [
   964          {
   965              "user_name": "test_shard_hash",
   966              "password": "test_shard_hash",
   967              "namespace": "gaea_namespace_1",
   968              "rw_flag": 2,
   969              "rw_split": 1
   970          }
   971      ],
   972      "default_slice": "slice-0"
   973  }`
   974  	ns := &Namespace{}
   975  	if err := json.Unmarshal([]byte(nsStr), ns); err != nil {
   976  		t.Errorf("namespace unmarshal failed, err: %v", err)
   977  	}
   978  
   979  	if err := ns.Verify(); err != nil {
   980  		t.Errorf("namespace verify failed, err: %v", err)
   981  	}
   982  }