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 }