github.com/matrixorigin/matrixone@v1.2.0/pkg/hakeeper/checkers/logservice/check_test.go (about)

     1  // Copyright 2021 - 2022 Matrix Origin
     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  
    15  package logservice
    16  
    17  import (
    18  	"fmt"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/common/runtime"
    23  	"github.com/matrixorigin/matrixone/pkg/hakeeper"
    24  	"github.com/matrixorigin/matrixone/pkg/hakeeper/checkers/util"
    25  	"github.com/matrixorigin/matrixone/pkg/hakeeper/operator"
    26  	"github.com/matrixorigin/matrixone/pkg/logutil"
    27  	pb "github.com/matrixorigin/matrixone/pkg/pb/logservice"
    28  	"github.com/matrixorigin/matrixone/pkg/pb/metadata"
    29  	"github.com/stretchr/testify/assert"
    30  )
    31  
    32  func TestMain(m *testing.M) {
    33  	logutil.SetupMOLogger(&logutil.LogConfig{
    34  		Level:  "debug",
    35  		Format: "console",
    36  	})
    37  
    38  	runtime.SetupProcessLevelRuntime(runtime.NewRuntime(metadata.ServiceType_LOG, "test", logutil.GetGlobalLogger()))
    39  	m.Run()
    40  }
    41  
    42  var expiredTick = uint64(hakeeper.DefaultLogStoreTimeout / time.Second * hakeeper.DefaultTickPerSecond)
    43  
    44  func TestCheck(t *testing.T) {
    45  	cases := []struct {
    46  		desc        string
    47  		cluster     pb.ClusterInfo
    48  		infos       pb.LogState
    49  		users       pb.TaskTableUser
    50  		removing    map[uint64][]uint64
    51  		adding      map[uint64][]uint64
    52  		currentTick uint64
    53  		expected    []*operator.Operator
    54  	}{
    55  		{
    56  			desc: "normal case",
    57  			cluster: pb.ClusterInfo{
    58  				LogShards: []metadata.LogShardRecord{{
    59  					ShardID:          1,
    60  					NumberOfReplicas: 3,
    61  				}},
    62  			},
    63  			infos: pb.LogState{
    64  				Shards: map[uint64]pb.LogShardInfo{1: {
    65  					ShardID:  1,
    66  					Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
    67  					Epoch:    1,
    68  					LeaderID: 1,
    69  					Term:     1,
    70  				}},
    71  				Stores: map[string]pb.LogStoreInfo{"a": {
    72  					Tick: 0,
    73  					Replicas: []pb.LogReplicaInfo{{
    74  						LogShardInfo: pb.LogShardInfo{
    75  							ShardID:  1,
    76  							Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
    77  							Epoch:    1,
    78  							LeaderID: 1,
    79  							Term:     1,
    80  						}, ReplicaID: 1}}},
    81  					"b": {
    82  						Tick: 0,
    83  						Replicas: []pb.LogReplicaInfo{{
    84  							LogShardInfo: pb.LogShardInfo{
    85  								ShardID:  1,
    86  								Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
    87  								Epoch:    1,
    88  								LeaderID: 1,
    89  								Term:     1,
    90  							}, ReplicaID: 2}}},
    91  					"c": {
    92  						Tick: 0,
    93  						Replicas: []pb.LogReplicaInfo{{
    94  							LogShardInfo: pb.LogShardInfo{
    95  								ShardID:  1,
    96  								Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
    97  								Epoch:    1,
    98  								LeaderID: 1,
    99  								Term:     1,
   100  							}, ReplicaID: 3}}},
   101  				},
   102  			},
   103  			removing:    nil,
   104  			adding:      nil,
   105  			currentTick: 0,
   106  			expected:    nil,
   107  		},
   108  		{
   109  			desc: "store \"a\" expired",
   110  			cluster: pb.ClusterInfo{
   111  				LogShards: []metadata.LogShardRecord{{
   112  					ShardID:          1,
   113  					NumberOfReplicas: 3,
   114  				}},
   115  			},
   116  			infos: pb.LogState{
   117  				Shards: map[uint64]pb.LogShardInfo{1: {
   118  					ShardID:  1,
   119  					Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   120  					Epoch:    1,
   121  					LeaderID: 1,
   122  					Term:     1,
   123  				}},
   124  				Stores: map[string]pb.LogStoreInfo{
   125  					"a": {
   126  						Tick: 0,
   127  						Replicas: []pb.LogReplicaInfo{{
   128  							LogShardInfo: pb.LogShardInfo{
   129  								ShardID:  1,
   130  								Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   131  								Epoch:    1,
   132  								LeaderID: 1,
   133  								Term:     1,
   134  							}, ReplicaID: 1}}},
   135  					"b": {
   136  						Tick: expiredTick + 1,
   137  						Replicas: []pb.LogReplicaInfo{{
   138  							LogShardInfo: pb.LogShardInfo{
   139  								ShardID:  1,
   140  								Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   141  								Epoch:    1,
   142  								LeaderID: 1,
   143  								Term:     1,
   144  							}, ReplicaID: 2}}},
   145  					"c": {
   146  						Tick: expiredTick + 1,
   147  						Replicas: []pb.LogReplicaInfo{{
   148  							LogShardInfo: pb.LogShardInfo{
   149  								ShardID:  1,
   150  								Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   151  								Epoch:    1,
   152  								LeaderID: 1,
   153  								Term:     1,
   154  							}, ReplicaID: 3}}},
   155  					"d": {
   156  						Tick: expiredTick + 1,
   157  					},
   158  				},
   159  			},
   160  			removing:    nil,
   161  			adding:      nil,
   162  			currentTick: expiredTick + 1,
   163  			expected: []*operator.Operator{
   164  				operator.NewOperator("", 1, 1,
   165  					operator.RemoveLogService{
   166  						Target: "b",
   167  						Replica: operator.Replica{
   168  							UUID:      "a",
   169  							ShardID:   1,
   170  							ReplicaID: 1,
   171  							Epoch:     1},
   172  					}),
   173  			},
   174  		},
   175  		{
   176  			desc: "shard 1 has only 2 replicas, which expected as 3",
   177  			cluster: pb.ClusterInfo{
   178  				LogShards: []metadata.LogShardRecord{{
   179  					ShardID:          1,
   180  					NumberOfReplicas: 3,
   181  				}},
   182  			},
   183  			infos: pb.LogState{
   184  				Shards: map[uint64]pb.LogShardInfo{1: {
   185  					ShardID:  1,
   186  					Replicas: map[uint64]string{1: "a", 2: "b"},
   187  					Epoch:    1,
   188  					LeaderID: 1,
   189  					Term:     1,
   190  				}},
   191  				Stores: map[string]pb.LogStoreInfo{"a": {
   192  					Tick: 0,
   193  					Replicas: []pb.LogReplicaInfo{{
   194  						LogShardInfo: pb.LogShardInfo{
   195  							ShardID:  1,
   196  							Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   197  							Epoch:    1,
   198  							LeaderID: 1,
   199  							Term:     1,
   200  						}, ReplicaID: 1}}},
   201  					"b": {
   202  						Tick: 0,
   203  						Replicas: []pb.LogReplicaInfo{{
   204  							LogShardInfo: pb.LogShardInfo{
   205  								ShardID:  1,
   206  								Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   207  								Epoch:    1,
   208  								LeaderID: 1,
   209  								Term:     1,
   210  							}, ReplicaID: 2}}},
   211  					"c": {Tick: 0, Replicas: []pb.LogReplicaInfo{}},
   212  				},
   213  			},
   214  			removing:    nil,
   215  			adding:      nil,
   216  			currentTick: 0,
   217  			expected: []*operator.Operator{operator.NewOperator("adding 1:4(at epoch 1) to c", 1,
   218  				1, operator.AddLogService{
   219  					Target: "a",
   220  					Replica: operator.Replica{
   221  						UUID:      "c",
   222  						ShardID:   1,
   223  						ReplicaID: 4,
   224  						Epoch:     1,
   225  					},
   226  				})},
   227  		},
   228  		{
   229  			desc: "replica 3 on store c is not started",
   230  			cluster: pb.ClusterInfo{
   231  				LogShards: []metadata.LogShardRecord{{
   232  					ShardID:          1,
   233  					NumberOfReplicas: 3,
   234  				}},
   235  			},
   236  			infos: pb.LogState{
   237  				Shards: map[uint64]pb.LogShardInfo{1: {
   238  					ShardID:  1,
   239  					Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   240  					Epoch:    1,
   241  					LeaderID: 1,
   242  					Term:     1,
   243  				}},
   244  				Stores: map[string]pb.LogStoreInfo{"a": {
   245  					Tick: 0,
   246  					Replicas: []pb.LogReplicaInfo{{
   247  						LogShardInfo: pb.LogShardInfo{
   248  							ShardID:  1,
   249  							Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   250  							Epoch:    1,
   251  							LeaderID: 1,
   252  							Term:     1,
   253  						}, ReplicaID: 1}}},
   254  					"b": {
   255  						Tick: 0,
   256  						Replicas: []pb.LogReplicaInfo{{
   257  							LogShardInfo: pb.LogShardInfo{
   258  								ShardID:  1,
   259  								Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   260  								Epoch:    1,
   261  								LeaderID: 1,
   262  								Term:     1,
   263  							}, ReplicaID: 2}}},
   264  					"c": {
   265  						Tick:     0,
   266  						Replicas: []pb.LogReplicaInfo{}},
   267  				},
   268  			},
   269  			removing:    nil,
   270  			adding:      nil,
   271  			currentTick: 0,
   272  			expected: []*operator.Operator{operator.NewOperator("", 1,
   273  				1, operator.StartLogService{
   274  					Replica: operator.Replica{
   275  						UUID:      "c",
   276  						ShardID:   1,
   277  						ReplicaID: 3},
   278  				})},
   279  		},
   280  		{
   281  			desc: "store \"a\" expired and is processing",
   282  			cluster: pb.ClusterInfo{
   283  				LogShards: []metadata.LogShardRecord{{
   284  					ShardID:          1,
   285  					NumberOfReplicas: 3,
   286  				}},
   287  			},
   288  			infos: pb.LogState{
   289  				Shards: map[uint64]pb.LogShardInfo{1: {
   290  					ShardID:  1,
   291  					Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   292  					Epoch:    1,
   293  					LeaderID: 1,
   294  					Term:     1,
   295  				}},
   296  				Stores: map[string]pb.LogStoreInfo{"a": {
   297  					Tick: 0,
   298  					Replicas: []pb.LogReplicaInfo{{
   299  						LogShardInfo: pb.LogShardInfo{
   300  							ShardID:  1,
   301  							Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   302  							Epoch:    1,
   303  							LeaderID: 1,
   304  							Term:     1,
   305  						}, ReplicaID: 1}}},
   306  					"b": {
   307  						Tick: expiredTick + 1,
   308  						Replicas: []pb.LogReplicaInfo{{
   309  							LogShardInfo: pb.LogShardInfo{
   310  								ShardID:  1,
   311  								Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   312  								Epoch:    1,
   313  								LeaderID: 1,
   314  								Term:     1,
   315  							}, ReplicaID: 2}}},
   316  					"c": {
   317  						Tick: expiredTick + 1,
   318  						Replicas: []pb.LogReplicaInfo{{
   319  							LogShardInfo: pb.LogShardInfo{
   320  								ShardID:  1,
   321  								Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   322  								Epoch:    1,
   323  								LeaderID: 1,
   324  								Term:     1,
   325  							}, ReplicaID: 3}}},
   326  				},
   327  			},
   328  			removing:    map[uint64][]uint64{1: {1}},
   329  			adding:      nil,
   330  			currentTick: expiredTick + 1,
   331  			expected:    []*operator.Operator{},
   332  		},
   333  		{
   334  			desc: "no more stores but need to create task service",
   335  			cluster: pb.ClusterInfo{
   336  				TNShards: []metadata.TNShardRecord{{
   337  					ShardID:    1,
   338  					LogShardID: 1,
   339  				}},
   340  				LogShards: []metadata.LogShardRecord{{
   341  					ShardID:          1,
   342  					NumberOfReplicas: 3,
   343  				}},
   344  			},
   345  			infos: pb.LogState{
   346  				Shards: map[uint64]pb.LogShardInfo{1: {
   347  					ShardID: 1,
   348  					Replicas: map[uint64]string{
   349  						1: "a",
   350  						2: "b",
   351  						3: "c",
   352  					},
   353  					Epoch:    1,
   354  					LeaderID: 1,
   355  					Term:     1,
   356  				}},
   357  				Stores: map[string]pb.LogStoreInfo{
   358  					"a": {
   359  						Tick: 0,
   360  						Replicas: []pb.LogReplicaInfo{{
   361  							LogShardInfo: pb.LogShardInfo{
   362  								ShardID:  1,
   363  								Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   364  								Epoch:    1,
   365  								LeaderID: 1,
   366  								Term:     1,
   367  							},
   368  							ReplicaID: 1,
   369  						}},
   370  						TaskServiceCreated: true,
   371  					},
   372  					"b": {
   373  						Tick: expiredTick + 1,
   374  						Replicas: []pb.LogReplicaInfo{{
   375  							LogShardInfo: pb.LogShardInfo{
   376  								ShardID:  1,
   377  								Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   378  								Epoch:    1,
   379  								LeaderID: 1,
   380  								Term:     1,
   381  							},
   382  						}},
   383  						TaskServiceCreated: true,
   384  					},
   385  					"c": {
   386  						Tick: expiredTick + 1,
   387  						Replicas: []pb.LogReplicaInfo{{
   388  							LogShardInfo: pb.LogShardInfo{
   389  								ShardID:  1,
   390  								Replicas: map[uint64]string{1: "a", 2: "b", 3: "c"},
   391  								Epoch:    1,
   392  								LeaderID: 1,
   393  								Term:     1,
   394  							},
   395  						}},
   396  						TaskServiceCreated: false,
   397  					},
   398  				},
   399  			},
   400  			users:       pb.TaskTableUser{Username: "abc"},
   401  			removing:    nil,
   402  			adding:      nil,
   403  			currentTick: 0,
   404  			expected: []*operator.Operator{operator.NewOperator("", 1,
   405  				1, operator.CreateTaskService{
   406  					StoreID:  "c",
   407  					TaskUser: pb.TaskTableUser{Username: "abc"},
   408  				})},
   409  		},
   410  	}
   411  
   412  	for i, c := range cases {
   413  		fmt.Printf("case %v: %s\n", i, c.desc)
   414  		alloc := util.NewTestIDAllocator(3)
   415  		cfg := hakeeper.Config{}
   416  		cfg.Fill()
   417  		executing := operator.ExecutingReplicas{
   418  			Adding:   c.adding,
   419  			Removing: c.removing,
   420  		}
   421  		operators := Check(alloc, cfg, c.cluster, c.infos, executing, c.users, c.currentTick)
   422  
   423  		assert.Equal(t, len(c.expected), len(operators))
   424  		for j, op := range operators {
   425  			assert.Equal(t, len(c.expected[j].OpSteps()), len(op.OpSteps()))
   426  			for k, step := range op.OpSteps() {
   427  				assert.Equal(t, c.expected[j].OpSteps()[k], step)
   428  			}
   429  		}
   430  	}
   431  }