vitess.io/vitess@v0.16.2/go/vt/topo/topotests/wildcards_test.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package topotests
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"vitess.io/vitess/go/vt/topo"
    24  	"vitess.io/vitess/go/vt/topo/memorytopo"
    25  
    26  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    27  )
    28  
    29  type topoLayout struct {
    30  	keyspaces []string
    31  	shards    map[string][]string
    32  }
    33  
    34  func (l *topoLayout) initTopo(t *testing.T, ts *topo.Server) {
    35  	ctx := context.Background()
    36  	for _, keyspace := range l.keyspaces {
    37  		if err := ts.CreateKeyspace(ctx, keyspace, &topodatapb.Keyspace{}); err != nil {
    38  			t.Fatalf("CreateKeyspace(%v) failed: %v", keyspace, err)
    39  		}
    40  	}
    41  
    42  	for keyspace, shards := range l.shards {
    43  		for _, shard := range shards {
    44  			if err := ts.CreateShard(ctx, keyspace, shard); err != nil {
    45  				t.Fatalf("CreateShard(%v, %v) failed: %v", keyspace, shard, err)
    46  			}
    47  		}
    48  	}
    49  }
    50  
    51  func validateKeyspaceWildcard(t *testing.T, l *topoLayout, param string, expected []string) {
    52  	ts := memorytopo.NewServer()
    53  	l.initTopo(t, ts)
    54  
    55  	ctx := context.Background()
    56  	r, err := ts.ResolveKeyspaceWildcard(ctx, param)
    57  	if err != nil {
    58  		if expected != nil {
    59  			t.Errorf("was not expecting an error but got: %v", err)
    60  		}
    61  		return
    62  	}
    63  
    64  	if len(r) != len(expected) {
    65  		t.Errorf("got wrong result: %v", r)
    66  		return
    67  	}
    68  	for i, e := range expected {
    69  		if r[i] != e {
    70  			t.Errorf("got wrong result[%v]: %v", i, r)
    71  		}
    72  	}
    73  }
    74  
    75  func TestResolveKeyspaceWildcard(t *testing.T) {
    76  	l := &topoLayout{
    77  		keyspaces: []string{"aaaaa", "aabbb", "bbbbb"},
    78  	}
    79  	validateKeyspaceWildcard(t, l, "*", []string{"aaaaa", "aabbb", "bbbbb"})
    80  	validateKeyspaceWildcard(t, l, "aa*", []string{"aaaaa", "aabbb"})
    81  	validateKeyspaceWildcard(t, l, "??b??", []string{"aabbb", "bbbbb"})
    82  	validateKeyspaceWildcard(t, l, "ccc", []string{"ccc"})
    83  
    84  	validateKeyspaceWildcard(t, l, "ccc\\", nil)
    85  }
    86  
    87  func validateShardWildcard(t *testing.T, l *topoLayout, param string, expected []topo.KeyspaceShard) {
    88  	ts := memorytopo.NewServer()
    89  	l.initTopo(t, ts)
    90  
    91  	ctx := context.Background()
    92  	r, err := ts.ResolveShardWildcard(ctx, param)
    93  	if err != nil {
    94  		if expected != nil {
    95  			t.Errorf("was not expecting an error but got: %v", err)
    96  		}
    97  		return
    98  	}
    99  
   100  	if len(r) != len(expected) {
   101  		t.Errorf("got wrong result: %v", r)
   102  		return
   103  	}
   104  	for i, e := range expected {
   105  		if r[i] != e {
   106  			t.Errorf("got wrong result[%v]: %v", i, r)
   107  		}
   108  	}
   109  }
   110  
   111  func TestResolveShardWildcard(t *testing.T) {
   112  	l := &topoLayout{
   113  		keyspaces: []string{"aaaaa", "bbbbb"},
   114  		shards: map[string][]string{
   115  			"aaaaa": {"s0", "s1"},
   116  			"bbbbb": {"-40", "40-80", "80-c0", "c0-"},
   117  		},
   118  	}
   119  	validateShardWildcard(t, l, "*/*", []topo.KeyspaceShard{
   120  		{Keyspace: "aaaaa", Shard: "s0"},
   121  		{Keyspace: "aaaaa", Shard: "s1"},
   122  		{Keyspace: "bbbbb", Shard: "-40"},
   123  		{Keyspace: "bbbbb", Shard: "40-80"},
   124  		{Keyspace: "bbbbb", Shard: "80-c0"},
   125  		{Keyspace: "bbbbb", Shard: "c0-"},
   126  	})
   127  	validateShardWildcard(t, l, "aaaaa/*", []topo.KeyspaceShard{
   128  		{Keyspace: "aaaaa", Shard: "s0"},
   129  		{Keyspace: "aaaaa", Shard: "s1"},
   130  	})
   131  	validateShardWildcard(t, l, "*/s1", []topo.KeyspaceShard{
   132  		{Keyspace: "aaaaa", Shard: "s1"},
   133  	})
   134  	validateShardWildcard(t, l, "*/*0*", []topo.KeyspaceShard{
   135  		{Keyspace: "aaaaa", Shard: "s0"},
   136  		{Keyspace: "bbbbb", Shard: "-40"},
   137  		{Keyspace: "bbbbb", Shard: "40-80"},
   138  		{Keyspace: "bbbbb", Shard: "80-c0"},
   139  		{Keyspace: "bbbbb", Shard: "c0-"},
   140  	})
   141  	validateShardWildcard(t, l, "aaaaa/ccccc", []topo.KeyspaceShard{
   142  		{Keyspace: "aaaaa", Shard: "ccccc"},
   143  	})
   144  	validateShardWildcard(t, l, "ccccc/s0", []topo.KeyspaceShard{
   145  		{Keyspace: "ccccc", Shard: "s0"},
   146  	})
   147  	validateShardWildcard(t, l, "bbbbb/C0-", []topo.KeyspaceShard{
   148  		{Keyspace: "bbbbb", Shard: "c0-"},
   149  	})
   150  
   151  	// error cases
   152  	l = &topoLayout{
   153  		keyspaces: []string{"aaaaa", "bbbbb"},
   154  		shards: map[string][]string{
   155  			"aaaaa": nil,
   156  		},
   157  	}
   158  
   159  	// these two will return an error as GetShardNames("aaaaa")
   160  	// will return an error.
   161  	validateShardWildcard(t, l, "aaaaa/bbbb*", nil)
   162  	validateShardWildcard(t, l, "aaaa*/bbbb*", nil)
   163  
   164  	// GetShardNames("bbbbb") will return ErrNoNode, so we get empty lists
   165  	// in this case, as the keyspace is a wildcard.
   166  	validateShardWildcard(t, l, "bbbb*/cccc*", []topo.KeyspaceShard{})
   167  
   168  	// GetShardNames("bbbbb") returns ErrNoNode, so we get an error
   169  	// in this case, as keyspace is not a wildcard.
   170  	validateShardWildcard(t, l, "bbbbb/cccc*", nil)
   171  
   172  	// GetKeyspaces() will fail hard in this one, so we get an error
   173  	l = &topoLayout{}
   174  	validateShardWildcard(t, l, "*/s1", nil)
   175  
   176  	// GetKeyspaces() will return an empty list, so no error, no result
   177  	l = &topoLayout{
   178  		keyspaces: []string{},
   179  	}
   180  	validateShardWildcard(t, l, "*/s1", []topo.KeyspaceShard{})
   181  }
   182  
   183  func validateWildcards(t *testing.T, l *topoLayout, param string, expected []string) {
   184  	ts := memorytopo.NewServer()
   185  	l.initTopo(t, ts)
   186  
   187  	ctx := context.Background()
   188  	r, err := ts.ResolveWildcards(ctx, topo.GlobalCell, []string{param})
   189  	if err != nil {
   190  		if expected != nil {
   191  			t.Errorf("was not expecting an error but got: %v", err)
   192  		}
   193  		return
   194  	}
   195  
   196  	if len(r) != len(expected) {
   197  		t.Errorf("got wrong result: %v\nexpected: %v", r, expected)
   198  		return
   199  	}
   200  	for i, e := range expected {
   201  		if r[i] != e {
   202  			t.Errorf("got wrong result[%v]: %v", i, r)
   203  		}
   204  	}
   205  }
   206  
   207  func TestResolveWildcards(t *testing.T) {
   208  	l := &topoLayout{
   209  		keyspaces: []string{"aaaaa", "bbbbb"},
   210  		shards: map[string][]string{
   211  			"aaaaa": {"s0", "s1"},
   212  			"bbbbb": {"-40", "40-80", "80-c0", "c0-"},
   213  		},
   214  	}
   215  	// The end path is a wildcard.
   216  	validateWildcards(t, l, "/keyspaces/*", []string{
   217  		"/keyspaces/aaaaa",
   218  		"/keyspaces/bbbbb",
   219  	})
   220  	// The end path is a directory.
   221  	validateWildcards(t, l, "/keyspaces/*/shards", []string{
   222  		"/keyspaces/aaaaa/shards",
   223  		"/keyspaces/bbbbb/shards",
   224  	})
   225  	// The end path is a file.
   226  	validateWildcards(t, l, "/keyspaces/*/Keyspace", []string{
   227  		"/keyspaces/aaaaa/Keyspace",
   228  		"/keyspaces/bbbbb/Keyspace",
   229  	})
   230  	// Double wildcards.
   231  	validateWildcards(t, l, "/keyspaces/*/shards/*", []string{
   232  		"/keyspaces/aaaaa/shards/s0",
   233  		"/keyspaces/aaaaa/shards/s1",
   234  		"/keyspaces/bbbbb/shards/-40",
   235  		"/keyspaces/bbbbb/shards/40-80",
   236  		"/keyspaces/bbbbb/shards/80-c0",
   237  		"/keyspaces/bbbbb/shards/c0-",
   238  	})
   239  	// Double wildcards, subset of matches.
   240  	validateWildcards(t, l, "/keyspaces/*/shards/s*", []string{
   241  		"/keyspaces/aaaaa/shards/s0",
   242  		"/keyspaces/aaaaa/shards/s1",
   243  	})
   244  }