vitess.io/vitess@v0.16.2/go/vt/topo/topotests/replication_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  	"strings"
    22  	"testing"
    23  
    24  	"google.golang.org/protobuf/proto"
    25  
    26  	"vitess.io/vitess/go/vt/logutil"
    27  	"vitess.io/vitess/go/vt/topo"
    28  	"vitess.io/vitess/go/vt/topo/memorytopo"
    29  	"vitess.io/vitess/go/vt/topo/topoproto"
    30  
    31  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    32  )
    33  
    34  // This file contains tests for the replication.go file.
    35  
    36  func TestFixShardReplication(t *testing.T) {
    37  	cell := "cell1"
    38  	keyspace := "ks1"
    39  	shard := "shard1"
    40  	ctx := context.Background()
    41  	ts := memorytopo.NewServer(cell)
    42  
    43  	// Create a tablet.
    44  	alias := &topodatapb.TabletAlias{
    45  		Cell: cell,
    46  		Uid:  1,
    47  	}
    48  	tablet := &topodatapb.Tablet{
    49  		Keyspace: keyspace,
    50  		Shard:    shard,
    51  		Alias:    alias,
    52  	}
    53  	if err := ts.CreateTablet(ctx, tablet); err != nil {
    54  		t.Fatalf("CreateTablet failed: %v", err)
    55  	}
    56  
    57  	// Make sure it's in the ShardReplication.
    58  	sri, err := ts.GetShardReplication(ctx, cell, keyspace, shard)
    59  	if err != nil {
    60  		t.Fatalf("GetShardReplication failed: %v", err)
    61  	}
    62  	if len(sri.Nodes) != 1 || !proto.Equal(sri.Nodes[0].TabletAlias, alias) {
    63  		t.Errorf("Missing or wrong alias in ShardReplication: %v", sri)
    64  	}
    65  
    66  	// Run FixShardReplication, should do nothing.
    67  	logger := logutil.NewMemoryLogger()
    68  	problem, err := topo.FixShardReplication(ctx, ts, logger, cell, keyspace, shard)
    69  	if err != nil {
    70  		t.Errorf("FixShardReplication failed: %v", err)
    71  	}
    72  	if problem != nil {
    73  		t.Errorf("FixShardReplication should have found no issues, got %+v", problem)
    74  	}
    75  	sri, err = ts.GetShardReplication(ctx, cell, keyspace, shard)
    76  	if err != nil {
    77  		t.Fatalf("GetShardReplication failed: %v", err)
    78  	}
    79  	if len(sri.Nodes) != 1 || !proto.Equal(sri.Nodes[0].TabletAlias, alias) {
    80  		t.Errorf("Missing or wrong alias in ShardReplication: %v", sri)
    81  	}
    82  	if !strings.Contains(logger.String(), "All entries in replication graph are valid") {
    83  		t.Errorf("Wrong log: %v", logger.String())
    84  	}
    85  
    86  	bogusTablet := &topodatapb.Tablet{
    87  		Alias: &topodatapb.TabletAlias{
    88  			Cell: cell,
    89  			Uid:  2,
    90  		},
    91  	}
    92  
    93  	// Add a bogus entries: a non-existing tablet.
    94  	if err := ts.UpdateShardReplicationFields(ctx, cell, keyspace, shard, func(sr *topodatapb.ShardReplication) error {
    95  		sr.Nodes = append(sr.Nodes, &topodatapb.ShardReplication_Node{
    96  			TabletAlias: bogusTablet.Alias,
    97  		})
    98  		return nil
    99  	}); err != nil {
   100  		t.Fatalf("UpdateShardReplicationFields failed: %v", err)
   101  	}
   102  	logger.Clear()
   103  	problem, err = topo.FixShardReplication(ctx, ts, logger, cell, keyspace, shard)
   104  	if err != nil {
   105  		t.Errorf("FixShardReplication failed: %v", err)
   106  	}
   107  	if problem == nil {
   108  		t.Errorf("FixShardReplication should have found problem, but found none")
   109  	} else {
   110  		if problem.Type != topodatapb.ShardReplicationError_NOT_FOUND {
   111  			t.Errorf("FixShardReplication problem.Type mismatch: want %q got %q", topoproto.ShardReplicationErrorTypeString(topodatapb.ShardReplicationError_NOT_FOUND), topoproto.ShardReplicationErrorTypeString(problem.Type))
   112  		}
   113  
   114  		if !topoproto.TabletAliasEqual(problem.TabletAlias, bogusTablet.Alias) {
   115  			t.Errorf("FixShardReplication problem.TabletAlias mismatch: want %q got %q", topoproto.TabletAliasString(bogusTablet.Alias), topoproto.TabletAliasString(problem.TabletAlias))
   116  		}
   117  	}
   118  	sri, err = ts.GetShardReplication(ctx, cell, keyspace, shard)
   119  	if err != nil {
   120  		t.Fatalf("GetShardReplication failed: %v", err)
   121  	}
   122  	if len(sri.Nodes) != 1 || !proto.Equal(sri.Nodes[0].TabletAlias, alias) {
   123  		t.Errorf("Missing or wrong alias in ShardReplication: %v", sri)
   124  	}
   125  	if !strings.Contains(logger.String(), "but does not exist, removing it") {
   126  		t.Errorf("Wrong log: %v", logger.String())
   127  	}
   128  
   129  	// Add a bogus entries: a tablet with wrong keyspace.
   130  	bogusTablet = &topodatapb.Tablet{
   131  		Keyspace: "other" + keyspace,
   132  		Shard:    shard,
   133  		Alias: &topodatapb.TabletAlias{
   134  			Cell: cell,
   135  			Uid:  3,
   136  		},
   137  	}
   138  	if err := ts.CreateTablet(ctx, bogusTablet); err != nil {
   139  		t.Fatalf("CreateTablet failed: %v", err)
   140  	}
   141  	if err := ts.UpdateShardReplicationFields(ctx, cell, keyspace, shard, func(sr *topodatapb.ShardReplication) error {
   142  		sr.Nodes = append(sr.Nodes, &topodatapb.ShardReplication_Node{
   143  			TabletAlias: bogusTablet.Alias,
   144  		})
   145  		return nil
   146  	}); err != nil {
   147  		t.Fatalf("UpdateShardReplicationFields failed: %v", err)
   148  	}
   149  	logger.Clear()
   150  	problem, err = topo.FixShardReplication(ctx, ts, logger, cell, keyspace, shard)
   151  	if err != nil {
   152  		t.Errorf("FixShardReplication failed: %v", err)
   153  	}
   154  	if problem == nil {
   155  		t.Errorf("FixShardReplication should have found problem, but found none")
   156  	} else {
   157  		if problem.Type != topodatapb.ShardReplicationError_TOPOLOGY_MISMATCH {
   158  			t.Errorf("FixShardReplication problem.Type mismatch: want %q got %q", topoproto.ShardReplicationErrorTypeString(topodatapb.ShardReplicationError_TOPOLOGY_MISMATCH), topoproto.ShardReplicationErrorTypeString(problem.Type))
   159  		}
   160  
   161  		if !topoproto.TabletAliasEqual(problem.TabletAlias, bogusTablet.Alias) {
   162  			t.Errorf("FixShardReplication problem.TabletAlias mismatch: want %q got %q", topoproto.TabletAliasString(bogusTablet.Alias), topoproto.TabletAliasString(problem.TabletAlias))
   163  		}
   164  	}
   165  	sri, err = ts.GetShardReplication(ctx, cell, keyspace, shard)
   166  	if err != nil {
   167  		t.Fatalf("GetShardReplication failed: %v", err)
   168  	}
   169  	if len(sri.Nodes) != 1 || !proto.Equal(sri.Nodes[0].TabletAlias, alias) {
   170  		t.Errorf("Missing or wrong alias in ShardReplication: %v", sri)
   171  	}
   172  	if !strings.Contains(logger.String(), "but has wrong keyspace/shard/cell, removing it") {
   173  		t.Errorf("Wrong log: %v", logger.String())
   174  	}
   175  }