vitess.io/vitess@v0.16.2/go/vt/vtctl/reparentutil/durability_funcs_test.go (about)

     1  /*
     2  Copyright 2022 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 reparentutil
    18  
    19  import (
    20  	"fmt"
    21  	"testing"
    22  
    23  	"github.com/stretchr/testify/require"
    24  
    25  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    26  )
    27  
    28  var (
    29  	primaryTablet = &topodatapb.Tablet{
    30  		Alias: &topodatapb.TabletAlias{
    31  			Cell: "zone-1",
    32  			Uid:  1,
    33  		},
    34  		Type: topodatapb.TabletType_PRIMARY,
    35  	}
    36  	replicaTablet = &topodatapb.Tablet{
    37  		Alias: &topodatapb.TabletAlias{
    38  			Cell: "zone-1",
    39  			Uid:  2,
    40  		},
    41  		Type: topodatapb.TabletType_REPLICA,
    42  	}
    43  	rdonlyTablet = &topodatapb.Tablet{
    44  		Alias: &topodatapb.TabletAlias{
    45  			Cell: "zone-1",
    46  			Uid:  3,
    47  		},
    48  		Type: topodatapb.TabletType_RDONLY,
    49  	}
    50  	replicaCrossCellTablet = &topodatapb.Tablet{
    51  		Alias: &topodatapb.TabletAlias{
    52  			Cell: "zone-2",
    53  			Uid:  2,
    54  		},
    55  		Type: topodatapb.TabletType_REPLICA,
    56  	}
    57  	rdonlyCrossCellTablet = &topodatapb.Tablet{
    58  		Alias: &topodatapb.TabletAlias{
    59  			Cell: "zone-2",
    60  			Uid:  3,
    61  		},
    62  		Type: topodatapb.TabletType_RDONLY,
    63  	}
    64  )
    65  
    66  func TestSemiSyncAckersForPrimary(t *testing.T) {
    67  	tests := []struct {
    68  		name               string
    69  		durabilityPolicy   string
    70  		primary            *topodatapb.Tablet
    71  		allTablets         []*topodatapb.Tablet
    72  		wantSemiSyncAckers []*topodatapb.Tablet
    73  	}{
    74  		{
    75  			name:               "no other tablets",
    76  			durabilityPolicy:   "none",
    77  			primary:            primaryTablet,
    78  			allTablets:         []*topodatapb.Tablet{primaryTablet},
    79  			wantSemiSyncAckers: nil,
    80  		}, {
    81  			name:               "'none' durability policy",
    82  			durabilityPolicy:   "none",
    83  			primary:            primaryTablet,
    84  			allTablets:         []*topodatapb.Tablet{primaryTablet, replicaTablet, rdonlyTablet, replicaCrossCellTablet, rdonlyCrossCellTablet},
    85  			wantSemiSyncAckers: nil,
    86  		}, {
    87  			name:               "'semi_sync' durability policy",
    88  			durabilityPolicy:   "semi_sync",
    89  			primary:            primaryTablet,
    90  			allTablets:         []*topodatapb.Tablet{primaryTablet, replicaTablet, rdonlyTablet, replicaCrossCellTablet, rdonlyCrossCellTablet},
    91  			wantSemiSyncAckers: []*topodatapb.Tablet{replicaTablet, replicaCrossCellTablet},
    92  		}, {
    93  			name:               "'cross_cell' durability policy",
    94  			durabilityPolicy:   "cross_cell",
    95  			primary:            primaryTablet,
    96  			allTablets:         []*topodatapb.Tablet{primaryTablet, replicaTablet, rdonlyTablet, replicaCrossCellTablet, rdonlyCrossCellTablet},
    97  			wantSemiSyncAckers: []*topodatapb.Tablet{replicaCrossCellTablet},
    98  		},
    99  	}
   100  	for _, tt := range tests {
   101  		t.Run(tt.name, func(t *testing.T) {
   102  			durability, err := GetDurabilityPolicy(tt.durabilityPolicy)
   103  			require.NoError(t, err, "error setting durability policy")
   104  			semiSyncAckers := SemiSyncAckersForPrimary(durability, tt.primary, tt.allTablets)
   105  			require.Equal(t, tt.wantSemiSyncAckers, semiSyncAckers)
   106  		})
   107  	}
   108  }
   109  
   110  func Test_haveRevokedForTablet(t *testing.T) {
   111  	tests := []struct {
   112  		name             string
   113  		durabilityPolicy string
   114  		primaryEligible  *topodatapb.Tablet
   115  		allTablets       []*topodatapb.Tablet
   116  		tabletsReached   []*topodatapb.Tablet
   117  		revoked          bool
   118  	}{
   119  		{
   120  			name:             "'none' durability policy - not revoked",
   121  			durabilityPolicy: "none",
   122  			primaryEligible:  primaryTablet,
   123  			allTablets: []*topodatapb.Tablet{
   124  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   125  			},
   126  			tabletsReached: []*topodatapb.Tablet{
   127  				replicaTablet, replicaCrossCellTablet, rdonlyTablet, rdonlyCrossCellTablet,
   128  			},
   129  			revoked: false,
   130  		}, {
   131  			name:             "'none' durability policy - revoked",
   132  			durabilityPolicy: "none",
   133  			primaryEligible:  primaryTablet,
   134  			allTablets: []*topodatapb.Tablet{
   135  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   136  			},
   137  			tabletsReached: []*topodatapb.Tablet{
   138  				primaryTablet, rdonlyTablet, rdonlyCrossCellTablet,
   139  			},
   140  			revoked: true,
   141  		}, {
   142  			name:             "'semi_sync' durability policy - revoked",
   143  			durabilityPolicy: "semi_sync",
   144  			primaryEligible:  primaryTablet,
   145  			allTablets: []*topodatapb.Tablet{
   146  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   147  			},
   148  			tabletsReached: []*topodatapb.Tablet{
   149  				replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet,
   150  			},
   151  			revoked: true,
   152  		}, {
   153  			name:             "'semi_sync' durability policy - not revoked",
   154  			durabilityPolicy: "semi_sync",
   155  			primaryEligible:  primaryTablet,
   156  			allTablets: []*topodatapb.Tablet{
   157  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   158  			},
   159  			tabletsReached: []*topodatapb.Tablet{
   160  				replicaTablet, rdonlyCrossCellTablet, rdonlyTablet,
   161  			},
   162  			revoked: false,
   163  		}, {
   164  			name:             "'cross_cell' durability policy - revoked",
   165  			durabilityPolicy: "cross_cell",
   166  			primaryEligible:  primaryTablet,
   167  			allTablets: []*topodatapb.Tablet{
   168  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   169  			},
   170  			tabletsReached: []*topodatapb.Tablet{
   171  				replicaCrossCellTablet,
   172  			},
   173  			revoked: true,
   174  		}, {
   175  			name:             "'cross_cell' durability policy - not revoked",
   176  			durabilityPolicy: "cross_cell",
   177  			primaryEligible:  primaryTablet,
   178  			allTablets: []*topodatapb.Tablet{
   179  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   180  			},
   181  			tabletsReached: []*topodatapb.Tablet{
   182  				replicaTablet, rdonlyCrossCellTablet, rdonlyTablet,
   183  			},
   184  			revoked: false,
   185  		}, {
   186  			name:             "'cross_cell' durability policy - primary in list",
   187  			durabilityPolicy: "cross_cell",
   188  			primaryEligible:  primaryTablet,
   189  			allTablets: []*topodatapb.Tablet{
   190  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   191  			},
   192  			tabletsReached: []*topodatapb.Tablet{
   193  				primaryTablet,
   194  			},
   195  			revoked: true,
   196  		},
   197  	}
   198  	for _, tt := range tests {
   199  		t.Run(tt.name, func(t *testing.T) {
   200  			durability, err := GetDurabilityPolicy(tt.durabilityPolicy)
   201  			require.NoError(t, err)
   202  			out := haveRevokedForTablet(durability, tt.primaryEligible, tt.tabletsReached, tt.allTablets)
   203  			require.Equal(t, tt.revoked, out)
   204  		})
   205  	}
   206  }
   207  
   208  func Test_haveRevoked(t *testing.T) {
   209  	tests := []struct {
   210  		name             string
   211  		durabilityPolicy string
   212  		tabletsReached   []*topodatapb.Tablet
   213  		allTablets       []*topodatapb.Tablet
   214  		revoked          bool
   215  	}{
   216  		{
   217  			name:             "'none' durability policy - all tablets revoked",
   218  			durabilityPolicy: "none",
   219  			tabletsReached: []*topodatapb.Tablet{
   220  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   221  			},
   222  			allTablets: []*topodatapb.Tablet{
   223  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   224  			},
   225  			revoked: true,
   226  		}, {
   227  			name:             "'semi_sync' durability policy - all tablets revoked",
   228  			durabilityPolicy: "semi_sync",
   229  			tabletsReached: []*topodatapb.Tablet{
   230  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   231  			},
   232  			allTablets: []*topodatapb.Tablet{
   233  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   234  			},
   235  			revoked: true,
   236  		}, {
   237  			name:             "'cross_cell' durability policy - all tablets revoked",
   238  			durabilityPolicy: "cross_cell",
   239  			tabletsReached: []*topodatapb.Tablet{
   240  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   241  			},
   242  			allTablets: []*topodatapb.Tablet{
   243  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   244  			},
   245  			revoked: true,
   246  		}, {
   247  			name:             "'none' durability policy - revoked",
   248  			durabilityPolicy: "none",
   249  			tabletsReached: []*topodatapb.Tablet{
   250  				primaryTablet, replicaTablet, replicaCrossCellTablet,
   251  			},
   252  			allTablets: []*topodatapb.Tablet{
   253  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   254  			},
   255  			revoked: true,
   256  		}, {
   257  			name:             "'semi_sync' durability policy - revoked",
   258  			durabilityPolicy: "semi_sync",
   259  			tabletsReached: []*topodatapb.Tablet{
   260  				replicaTablet, replicaCrossCellTablet, rdonlyTablet,
   261  			},
   262  			allTablets: []*topodatapb.Tablet{
   263  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   264  			},
   265  			revoked: true,
   266  		}, {
   267  			name:             "'cross_cell' durability policy - revoked",
   268  			durabilityPolicy: "cross_cell",
   269  			tabletsReached: []*topodatapb.Tablet{
   270  				replicaCrossCellTablet,
   271  			},
   272  			allTablets: []*topodatapb.Tablet{
   273  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   274  			},
   275  			revoked: true,
   276  		}, {
   277  			name:             "'none' durability policy - not revoked",
   278  			durabilityPolicy: "none",
   279  			tabletsReached: []*topodatapb.Tablet{
   280  				primaryTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   281  			},
   282  			allTablets: []*topodatapb.Tablet{
   283  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   284  			},
   285  			revoked: false,
   286  		}, {
   287  			name:             "'semi_sync' durability policy - not revoked",
   288  			durabilityPolicy: "semi_sync",
   289  			tabletsReached: []*topodatapb.Tablet{
   290  				primaryTablet, rdonlyCrossCellTablet, rdonlyTablet,
   291  			},
   292  			allTablets: []*topodatapb.Tablet{
   293  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   294  			},
   295  			revoked: false,
   296  		}, {
   297  			name:             "'cross_cell' durability policy - not revoked",
   298  			durabilityPolicy: "cross_cell",
   299  			tabletsReached: []*topodatapb.Tablet{
   300  				primaryTablet, rdonlyCrossCellTablet, rdonlyTablet,
   301  			},
   302  			allTablets: []*topodatapb.Tablet{
   303  				primaryTablet, replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   304  			},
   305  			revoked: false,
   306  		},
   307  	}
   308  	for _, tt := range tests {
   309  		t.Run(tt.name, func(t *testing.T) {
   310  			durability, err := GetDurabilityPolicy(tt.durabilityPolicy)
   311  			require.NoError(t, err)
   312  			out := haveRevoked(durability, tt.tabletsReached, tt.allTablets)
   313  			require.Equal(t, tt.revoked, out)
   314  		})
   315  	}
   316  }
   317  
   318  func Test_canEstablishForTablet(t *testing.T) {
   319  	tests := []struct {
   320  		name             string
   321  		durabilityPolicy string
   322  		primaryEligible  *topodatapb.Tablet
   323  		tabletsReached   []*topodatapb.Tablet
   324  		canEstablish     bool
   325  	}{
   326  		{
   327  			name:             "primary not reached",
   328  			durabilityPolicy: "none",
   329  			primaryEligible:  primaryTablet,
   330  			tabletsReached: []*topodatapb.Tablet{
   331  				replicaTablet, replicaCrossCellTablet, rdonlyCrossCellTablet, rdonlyTablet,
   332  			},
   333  			canEstablish: false,
   334  		}, {
   335  			name:             "not established",
   336  			durabilityPolicy: "semi_sync",
   337  			primaryEligible:  primaryTablet,
   338  			tabletsReached: []*topodatapb.Tablet{
   339  				primaryTablet, rdonlyCrossCellTablet, rdonlyTablet,
   340  			},
   341  			canEstablish: false,
   342  		}, {
   343  			name:             "not established",
   344  			durabilityPolicy: "cross_cell",
   345  			primaryEligible:  primaryTablet,
   346  			tabletsReached: []*topodatapb.Tablet{
   347  				primaryTablet, replicaTablet, rdonlyCrossCellTablet, rdonlyTablet,
   348  			},
   349  			canEstablish: false,
   350  		}, {
   351  			name:             "established",
   352  			durabilityPolicy: "none",
   353  			primaryEligible:  primaryTablet,
   354  			tabletsReached: []*topodatapb.Tablet{
   355  				primaryTablet,
   356  			},
   357  			canEstablish: true,
   358  		}, {
   359  			name:             "established",
   360  			durabilityPolicy: "semi_sync",
   361  			primaryEligible:  primaryTablet,
   362  			tabletsReached: []*topodatapb.Tablet{
   363  				primaryTablet, replicaTablet,
   364  			},
   365  			canEstablish: true,
   366  		}, {
   367  			name:             "established",
   368  			durabilityPolicy: "cross_cell",
   369  			primaryEligible:  primaryTablet,
   370  			tabletsReached: []*topodatapb.Tablet{
   371  				primaryTablet, replicaCrossCellTablet,
   372  			},
   373  			canEstablish: true,
   374  		},
   375  	}
   376  	for _, tt := range tests {
   377  		t.Run(fmt.Sprintf("'%s' durability policy - %s", tt.durabilityPolicy, tt.name), func(t *testing.T) {
   378  			durability, err := GetDurabilityPolicy(tt.durabilityPolicy)
   379  			require.NoError(t, err)
   380  			require.Equalf(t, tt.canEstablish, canEstablishForTablet(durability, tt.primaryEligible, tt.tabletsReached), "canEstablishForTablet(%v, %v)", tt.primaryEligible, tt.tabletsReached)
   381  		})
   382  	}
   383  }