github.com/matrixorigin/matrixone@v1.2.0/pkg/pb/logservice/logservice_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  	"testing"
    19  
    20  	"github.com/matrixorigin/matrixone/pkg/pb/metadata"
    21  	"github.com/stretchr/testify/assert"
    22  )
    23  
    24  func TestLogRecord(t *testing.T) {
    25  	r := LogRecord{
    26  		Data: make([]byte, 32),
    27  	}
    28  	assert.Equal(t, 32-HeaderSize-8, len(r.Payload()))
    29  	r.ResizePayload(2)
    30  	assert.Equal(t, HeaderSize+8+2, len(r.Data))
    31  	assert.Equal(t, 2, len(r.Payload()))
    32  }
    33  
    34  func TestCNStateUpdate(t *testing.T) {
    35  	state := CNState{Stores: map[string]CNStoreInfo{}}
    36  
    37  	hb1 := CNStoreHeartbeat{UUID: "cn-a", ServiceAddress: "addr-a", Role: metadata.CNRole_AP}
    38  	tick1 := uint64(100)
    39  
    40  	state.Update(hb1, tick1)
    41  	assert.Equal(t, state.Stores[hb1.UUID], CNStoreInfo{
    42  		Tick:           tick1,
    43  		ServiceAddress: hb1.ServiceAddress,
    44  		Role:           metadata.CNRole_AP,
    45  		WorkState:      metadata.WorkState_Working,
    46  		Labels:         map[string]metadata.LabelList{},
    47  		UpTime:         state.Stores[hb1.UUID].UpTime,
    48  	})
    49  
    50  	hb2 := CNStoreHeartbeat{UUID: "cn-b", ServiceAddress: "addr-b", Role: metadata.CNRole_TP}
    51  	tick2 := uint64(200)
    52  
    53  	state.Update(hb2, tick2)
    54  	assert.Equal(t, state.Stores[hb2.UUID], CNStoreInfo{
    55  		Tick:           tick2,
    56  		ServiceAddress: hb2.ServiceAddress,
    57  		Role:           metadata.CNRole_TP,
    58  		WorkState:      metadata.WorkState_Working,
    59  		Labels:         map[string]metadata.LabelList{},
    60  		UpTime:         state.Stores[hb2.UUID].UpTime,
    61  	})
    62  
    63  	hb3 := CNStoreHeartbeat{UUID: "cn-a", ServiceAddress: "addr-a", Role: metadata.CNRole_TP}
    64  	tick3 := uint64(300)
    65  
    66  	state.Update(hb3, tick3)
    67  	assert.Equal(t, state.Stores[hb3.UUID], CNStoreInfo{
    68  		Tick:           tick3,
    69  		ServiceAddress: hb3.ServiceAddress,
    70  		Role:           metadata.CNRole_TP,
    71  		WorkState:      metadata.WorkState_Working,
    72  		Labels:         map[string]metadata.LabelList{},
    73  		UpTime:         state.Stores[hb3.UUID].UpTime,
    74  	})
    75  }
    76  
    77  func TestTNStateUpdate(t *testing.T) {
    78  	state := TNState{Stores: map[string]TNStoreInfo{}}
    79  
    80  	hb1 := TNStoreHeartbeat{
    81  		UUID:           "dn-a",
    82  		ServiceAddress: "addr-a",
    83  		Shards: []TNShardInfo{{
    84  			ShardID:   1,
    85  			ReplicaID: 1,
    86  		}},
    87  		LogtailServerAddress: "addr-0",
    88  	}
    89  	tick1 := uint64(100)
    90  
    91  	state.Update(hb1, tick1)
    92  	assert.Equal(t, state.Stores["dn-a"], TNStoreInfo{
    93  		Tick:                 tick1,
    94  		ServiceAddress:       hb1.ServiceAddress,
    95  		Shards:               hb1.Shards,
    96  		LogtailServerAddress: hb1.LogtailServerAddress,
    97  	})
    98  
    99  	hb2 := TNStoreHeartbeat{
   100  		UUID:           "dn-a",
   101  		ServiceAddress: "addr-a",
   102  		Shards: []TNShardInfo{
   103  			{ShardID: 1, ReplicaID: 1},
   104  			{ShardID: 2, ReplicaID: 1}},
   105  		LogtailServerAddress: "addr-0",
   106  	}
   107  	tick2 := uint64(200)
   108  
   109  	state.Update(hb2, tick2)
   110  	assert.Equal(t, state.Stores[hb2.UUID], TNStoreInfo{
   111  		Tick:                 tick2,
   112  		ServiceAddress:       hb2.ServiceAddress,
   113  		Shards:               hb2.Shards,
   114  		LogtailServerAddress: "addr-0",
   115  	})
   116  }
   117  
   118  func TestLogStateUpdateStores(t *testing.T) {
   119  	defer func() {
   120  		if r := recover(); r == nil {
   121  			t.Errorf("The code did not panic")
   122  		}
   123  	}()
   124  
   125  	state := LogState{
   126  		Shards: map[uint64]LogShardInfo{},
   127  		Stores: map[string]LogStoreInfo{},
   128  	}
   129  
   130  	hb1 := LogStoreHeartbeat{
   131  		UUID:           "log-a",
   132  		RaftAddress:    "raft-a",
   133  		ServiceAddress: "addr-a",
   134  		GossipAddress:  "gossip-a",
   135  		Replicas: []LogReplicaInfo{{
   136  			LogShardInfo: LogShardInfo{
   137  				ShardID:  1,
   138  				Replicas: map[uint64]string{1: "log-a"},
   139  				Epoch:    1,
   140  				LeaderID: 1,
   141  				Term:     1,
   142  			},
   143  			ReplicaID: 1,
   144  		}},
   145  	}
   146  	tick1 := uint64(100)
   147  	state.Update(hb1, tick1)
   148  	assert.Equal(t, state.Stores[hb1.UUID], LogStoreInfo{
   149  		Tick:           tick1,
   150  		RaftAddress:    hb1.RaftAddress,
   151  		ServiceAddress: hb1.ServiceAddress,
   152  		GossipAddress:  hb1.GossipAddress,
   153  		Replicas:       hb1.Replicas,
   154  	})
   155  
   156  	hb2 := LogStoreHeartbeat{
   157  		UUID:           "log-a",
   158  		RaftAddress:    "raft-a",
   159  		ServiceAddress: "addr-a",
   160  		GossipAddress:  "gossip-a",
   161  		Replicas: []LogReplicaInfo{{
   162  			LogShardInfo: LogShardInfo{
   163  				ShardID:  1,
   164  				Replicas: map[uint64]string{1: "log-a", 2: "log-b"},
   165  				Epoch:    2,
   166  				LeaderID: 1,
   167  				Term:     2,
   168  			},
   169  			ReplicaID: 1,
   170  		}},
   171  	}
   172  	tick2 := uint64(200)
   173  	state.Update(hb2, tick2)
   174  	assert.Equal(t, state.Stores[hb2.UUID], LogStoreInfo{
   175  		Tick:           tick2,
   176  		RaftAddress:    hb2.RaftAddress,
   177  		ServiceAddress: hb2.ServiceAddress,
   178  		GossipAddress:  hb2.GossipAddress,
   179  		Replicas:       hb2.Replicas,
   180  	})
   181  
   182  	hb3 := LogStoreHeartbeat{
   183  		UUID:           "log-a",
   184  		RaftAddress:    "raft-a",
   185  		ServiceAddress: "addr-a",
   186  		GossipAddress:  "gossip-a",
   187  		Replicas: []LogReplicaInfo{{
   188  			LogShardInfo: LogShardInfo{
   189  				ShardID:  1,
   190  				Replicas: map[uint64]string{1: "log-a"},
   191  				Epoch:    2,
   192  				LeaderID: 1,
   193  				Term:     2,
   194  			},
   195  			ReplicaID: 1,
   196  		}},
   197  	}
   198  	tick3 := uint64(200)
   199  
   200  	// should panic()
   201  	state.Update(hb3, tick3)
   202  }
   203  
   204  func TestLogString(t *testing.T) {
   205  	cases := []struct {
   206  		desc string
   207  
   208  		command  ScheduleCommand
   209  		expected string
   210  	}{
   211  		{
   212  			desc: "add log replica",
   213  			command: ScheduleCommand{
   214  				UUID:          "storeA",
   215  				Bootstrapping: false,
   216  				ConfigChange: &ConfigChange{
   217  					Replica: Replica{
   218  						UUID:       "storeB",
   219  						ShardID:    1,
   220  						ReplicaID:  4,
   221  						Epoch:      1,
   222  						LogShardID: 0,
   223  					},
   224  					ChangeType:     AddReplica,
   225  					InitialMembers: nil,
   226  				},
   227  				ServiceType:   LogService,
   228  				ShutdownStore: nil,
   229  			},
   230  			expected: "L/Add storeA storeB:1:4:1",
   231  		},
   232  		{
   233  			desc: "remove log replica",
   234  			command: ScheduleCommand{
   235  				UUID:          "storeA",
   236  				Bootstrapping: false,
   237  				ConfigChange: &ConfigChange{
   238  					Replica: Replica{
   239  						UUID:       "storeB",
   240  						ShardID:    1,
   241  						ReplicaID:  4,
   242  						Epoch:      1,
   243  						LogShardID: 0,
   244  					},
   245  					ChangeType:     RemoveReplica,
   246  					InitialMembers: nil,
   247  				},
   248  				ServiceType:   LogService,
   249  				ShutdownStore: nil,
   250  			},
   251  			expected: "L/Remove storeA storeB:1:4:1",
   252  		},
   253  		{
   254  			desc: "remove log replica",
   255  			command: ScheduleCommand{
   256  				UUID:          "storeA",
   257  				Bootstrapping: false,
   258  				ConfigChange: &ConfigChange{
   259  					Replica: Replica{
   260  						UUID:       "storeA",
   261  						ShardID:    1,
   262  						ReplicaID:  4,
   263  						Epoch:      1,
   264  						LogShardID: 0,
   265  					},
   266  					ChangeType:     StartReplica,
   267  					InitialMembers: nil,
   268  				},
   269  				ServiceType:   LogService,
   270  				ShutdownStore: nil,
   271  			},
   272  			expected: "L/Start storeA storeA:1:4:1",
   273  		},
   274  		{
   275  			desc: "remove log replica",
   276  			command: ScheduleCommand{
   277  				UUID:          "storeA",
   278  				Bootstrapping: false,
   279  				ConfigChange: &ConfigChange{
   280  					Replica: Replica{
   281  						UUID:       "storeA",
   282  						ShardID:    1,
   283  						ReplicaID:  4,
   284  						Epoch:      1,
   285  						LogShardID: 0,
   286  					},
   287  					ChangeType:     StartReplica,
   288  					InitialMembers: nil,
   289  				},
   290  				ServiceType:   TNService,
   291  				ShutdownStore: nil,
   292  			},
   293  			expected: "D/Start storeA storeA:1:4:1",
   294  		},
   295  		{
   296  			desc: "remove log replica",
   297  			command: ScheduleCommand{
   298  				UUID:          "storeA",
   299  				Bootstrapping: false,
   300  				ServiceType:   LogService,
   301  				ShutdownStore: &ShutdownStore{
   302  					StoreID: "storeA",
   303  				},
   304  			},
   305  			expected: "L/shutdown storeA",
   306  		},
   307  		{
   308  			desc: "kill zombie",
   309  			command: ScheduleCommand{
   310  				UUID:          "storeA",
   311  				Bootstrapping: false,
   312  				ConfigChange: &ConfigChange{
   313  					Replica: Replica{
   314  						UUID:    "storeA",
   315  						ShardID: 1,
   316  					},
   317  					ChangeType: KillZombie,
   318  				},
   319  				ServiceType: LogService,
   320  			},
   321  			expected: "L/Kill storeA storeA:1:0:0",
   322  		},
   323  		{
   324  			desc: "bootstrapping",
   325  			command: ScheduleCommand{
   326  				UUID:          "storeA",
   327  				Bootstrapping: true,
   328  				ConfigChange: &ConfigChange{
   329  					Replica: Replica{
   330  						UUID:      "storeA",
   331  						ShardID:   1,
   332  						ReplicaID: 1,
   333  					},
   334  					ChangeType:     StartReplica,
   335  					InitialMembers: map[uint64]string{1: "storeA123", 2: "storeB", 3: "storeC"},
   336  				},
   337  				ServiceType: LogService,
   338  			},
   339  			expected: "L/Start storeA storeA:1:1:0 [1:storeA123 2:storeB 3:storeC]",
   340  		},
   341  	}
   342  
   343  	for _, c := range cases {
   344  		output := c.command.LogString()
   345  		assert.Equal(t, c.expected, output)
   346  	}
   347  }
   348  
   349  func TestCNLabelUpdate(t *testing.T) {
   350  	state := CNState{Stores: map[string]CNStoreInfo{}}
   351  
   352  	label := CNStoreLabel{
   353  		UUID: "cn-1",
   354  		Labels: map[string]metadata.LabelList{
   355  			"account": {
   356  				Labels: []string{"a1", "a2"},
   357  			},
   358  			"role": {
   359  				Labels: []string{"r1"},
   360  			},
   361  		},
   362  	}
   363  
   364  	state.UpdateLabel(label)
   365  	// No heartbeat yet, nothing happens.
   366  	assert.Equal(t, state.Stores[label.UUID], CNStoreInfo{})
   367  
   368  	// Add CN store to HAKeeper.
   369  	hb1 := CNStoreHeartbeat{UUID: "cn-1", ServiceAddress: "addr-a", Role: metadata.CNRole_AP}
   370  	tick1 := uint64(100)
   371  
   372  	state.Update(hb1, tick1)
   373  	assert.Equal(t, state.Stores[hb1.UUID], CNStoreInfo{
   374  		Tick:           tick1,
   375  		ServiceAddress: hb1.ServiceAddress,
   376  		Role:           metadata.CNRole_AP,
   377  		WorkState:      metadata.WorkState_Working,
   378  		Labels:         map[string]metadata.LabelList{},
   379  		UpTime:         state.Stores[hb1.UUID].UpTime,
   380  	})
   381  
   382  	label = CNStoreLabel{
   383  		UUID: "cn-1",
   384  		Labels: map[string]metadata.LabelList{
   385  			"account": {
   386  				Labels: []string{"a1", "a2"},
   387  			},
   388  			"role": {
   389  				Labels: []string{"r1"},
   390  			},
   391  		},
   392  	}
   393  
   394  	state.UpdateLabel(label)
   395  	assert.Equal(t, state.Stores[label.UUID], CNStoreInfo{
   396  		Tick:           tick1,
   397  		ServiceAddress: hb1.ServiceAddress,
   398  		Role:           metadata.CNRole_AP,
   399  		WorkState:      metadata.WorkState_Working,
   400  		Labels: map[string]metadata.LabelList{
   401  			"account": {
   402  				Labels: []string{"a1", "a2"},
   403  			},
   404  			"role": {
   405  				Labels: []string{"r1"},
   406  			},
   407  		},
   408  		UpTime: state.Stores[label.UUID].UpTime,
   409  	})
   410  
   411  	label = CNStoreLabel{
   412  		UUID: "cn-1",
   413  		Labels: map[string]metadata.LabelList{
   414  			"role": {
   415  				Labels: []string{"r1"},
   416  			},
   417  		},
   418  	}
   419  
   420  	state.UpdateLabel(label)
   421  	assert.Equal(t, state.Stores[label.UUID], CNStoreInfo{
   422  		Tick:           tick1,
   423  		ServiceAddress: hb1.ServiceAddress,
   424  		Role:           metadata.CNRole_AP,
   425  		WorkState:      metadata.WorkState_Working,
   426  		Labels: map[string]metadata.LabelList{
   427  			"role": {
   428  				Labels: []string{"r1"},
   429  			},
   430  		},
   431  		UpTime: state.Stores[label.UUID].UpTime,
   432  	})
   433  }
   434  
   435  func TestCNWorkStateUpdate(t *testing.T) {
   436  	state := CNState{Stores: map[string]CNStoreInfo{}}
   437  
   438  	workState := CNWorkState{
   439  		UUID:  "cn-1",
   440  		State: metadata.WorkState_Working,
   441  	}
   442  	state.UpdateWorkState(workState)
   443  	// No heartbeat yet, nothing happens.
   444  	assert.Equal(t, state.Stores[workState.UUID], CNStoreInfo{})
   445  
   446  	// Add CN store to HAKeeper.
   447  	hb1 := CNStoreHeartbeat{UUID: "cn-1", ServiceAddress: "addr-a", Role: metadata.CNRole_AP}
   448  	tick1 := uint64(100)
   449  
   450  	state.Update(hb1, tick1)
   451  	assert.Equal(t, state.Stores[hb1.UUID], CNStoreInfo{
   452  		Tick:           tick1,
   453  		ServiceAddress: hb1.ServiceAddress,
   454  		Role:           metadata.CNRole_AP,
   455  		WorkState:      metadata.WorkState_Working,
   456  		Labels:         map[string]metadata.LabelList{},
   457  		UpTime:         state.Stores[hb1.UUID].UpTime,
   458  	})
   459  
   460  	workState = CNWorkState{
   461  		UUID:  "cn-1",
   462  		State: metadata.WorkState_Draining,
   463  	}
   464  
   465  	state.UpdateWorkState(workState)
   466  	assert.Equal(t, state.Stores[workState.UUID], CNStoreInfo{
   467  		Tick:           tick1,
   468  		ServiceAddress: hb1.ServiceAddress,
   469  		Role:           metadata.CNRole_AP,
   470  		WorkState:      metadata.WorkState_Draining,
   471  		Labels:         map[string]metadata.LabelList{},
   472  		UpTime:         state.Stores[workState.UUID].UpTime,
   473  	})
   474  
   475  	workState = CNWorkState{
   476  		UUID:  "cn-1",
   477  		State: metadata.WorkState_Working,
   478  	}
   479  
   480  	state.UpdateWorkState(workState)
   481  	assert.Equal(t, state.Stores[workState.UUID], CNStoreInfo{
   482  		Tick:           tick1,
   483  		ServiceAddress: hb1.ServiceAddress,
   484  		Role:           metadata.CNRole_AP,
   485  		WorkState:      metadata.WorkState_Working,
   486  		Labels:         map[string]metadata.LabelList{},
   487  		UpTime:         state.Stores[workState.UUID].UpTime,
   488  	})
   489  }
   490  
   491  func TestCNStateLabelPatch(t *testing.T) {
   492  	state := CNState{Stores: map[string]CNStoreInfo{}}
   493  
   494  	stateLabel := CNStateLabel{
   495  		UUID:  "cn-1",
   496  		State: metadata.WorkState_Working,
   497  		Labels: map[string]metadata.LabelList{
   498  			"account": {
   499  				Labels: []string{"a1", "a2"},
   500  			},
   501  			"role": {
   502  				Labels: []string{"r1"},
   503  			},
   504  		},
   505  	}
   506  	state.PatchCNStore(stateLabel)
   507  	// No heartbeat yet, nothing happens.
   508  	assert.Equal(t, state.Stores[stateLabel.UUID], CNStoreInfo{})
   509  
   510  	// Add CN store to HAKeeper.
   511  	hb1 := CNStoreHeartbeat{UUID: "cn-1", ServiceAddress: "addr-a", Role: metadata.CNRole_AP}
   512  	tick1 := uint64(100)
   513  
   514  	state.Update(hb1, tick1)
   515  	assert.Equal(t, state.Stores[hb1.UUID], CNStoreInfo{
   516  		Tick:           tick1,
   517  		ServiceAddress: hb1.ServiceAddress,
   518  		Role:           metadata.CNRole_AP,
   519  		WorkState:      metadata.WorkState_Working,
   520  		Labels:         map[string]metadata.LabelList{},
   521  		UpTime:         state.Stores[hb1.UUID].UpTime,
   522  	})
   523  
   524  	stateLabel = CNStateLabel{
   525  		UUID:  "cn-1",
   526  		State: metadata.WorkState_Draining,
   527  		Labels: map[string]metadata.LabelList{
   528  			"account": {
   529  				Labels: []string{"a1", "a2"},
   530  			},
   531  			"role": {
   532  				Labels: []string{"r1"},
   533  			},
   534  		},
   535  	}
   536  	state.PatchCNStore(stateLabel)
   537  	assert.Equal(t, state.Stores[stateLabel.UUID], CNStoreInfo{
   538  		Tick:           tick1,
   539  		ServiceAddress: hb1.ServiceAddress,
   540  		Role:           metadata.CNRole_AP,
   541  		WorkState:      metadata.WorkState_Draining,
   542  		Labels: map[string]metadata.LabelList{
   543  			"account": {
   544  				Labels: []string{"a1", "a2"},
   545  			},
   546  			"role": {
   547  				Labels: []string{"r1"},
   548  			},
   549  		},
   550  		UpTime: state.Stores[stateLabel.UUID].UpTime,
   551  	})
   552  
   553  	stateLabel = CNStateLabel{
   554  		UUID:  "cn-1",
   555  		State: metadata.WorkState_Drained,
   556  	}
   557  	state.PatchCNStore(stateLabel)
   558  	assert.Equal(t, state.Stores[stateLabel.UUID], CNStoreInfo{
   559  		Tick:           tick1,
   560  		ServiceAddress: hb1.ServiceAddress,
   561  		Role:           metadata.CNRole_AP,
   562  		WorkState:      metadata.WorkState_Drained,
   563  		Labels: map[string]metadata.LabelList{
   564  			"account": {
   565  				Labels: []string{"a1", "a2"},
   566  			},
   567  			"role": {
   568  				Labels: []string{"r1"},
   569  			},
   570  		},
   571  		UpTime: state.Stores[stateLabel.UUID].UpTime,
   572  	})
   573  
   574  	stateLabel = CNStateLabel{
   575  		UUID: "cn-1",
   576  		Labels: map[string]metadata.LabelList{
   577  			"role": {
   578  				Labels: []string{"r1"},
   579  			},
   580  		},
   581  	}
   582  	state.PatchCNStore(stateLabel)
   583  	assert.Equal(t, state.Stores[stateLabel.UUID], CNStoreInfo{
   584  		Tick:           tick1,
   585  		ServiceAddress: hb1.ServiceAddress,
   586  		Role:           metadata.CNRole_AP,
   587  		WorkState:      metadata.WorkState_Working,
   588  		Labels: map[string]metadata.LabelList{
   589  			"role": {
   590  				Labels: []string{"r1"},
   591  			},
   592  		},
   593  		UpTime: state.Stores[stateLabel.UUID].UpTime,
   594  	})
   595  }
   596  
   597  func TestProxyStateUpdate(t *testing.T) {
   598  	state := ProxyState{Stores: map[string]ProxyStore{}}
   599  
   600  	hb1 := ProxyHeartbeat{
   601  		UUID:          "proxy-1",
   602  		ListenAddress: "addr-a",
   603  	}
   604  	tick1 := uint64(100)
   605  
   606  	state.Update(hb1, tick1)
   607  	assert.Equal(t, state.Stores[hb1.UUID], ProxyStore{
   608  		UUID:          hb1.UUID,
   609  		Tick:          tick1,
   610  		ListenAddress: hb1.ListenAddress,
   611  	})
   612  
   613  	hb2 := ProxyHeartbeat{
   614  		UUID:          "proxy-1",
   615  		ListenAddress: "addr-a",
   616  	}
   617  	tick2 := uint64(200)
   618  
   619  	state.Update(hb2, tick2)
   620  	assert.Equal(t, state.Stores[hb2.UUID], ProxyStore{
   621  		UUID:          hb1.UUID,
   622  		Tick:          tick2,
   623  		ListenAddress: hb1.ListenAddress,
   624  	})
   625  }