github.com/polarismesh/polaris@v1.17.8/store/mysql/admin_test.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package sqldb
    19  
    20  import (
    21  	"context"
    22  	"errors"
    23  	"os"
    24  	"testing"
    25  
    26  	"github.com/golang/mock/gomock"
    27  
    28  	"github.com/polarismesh/polaris/common/eventhub"
    29  	"github.com/polarismesh/polaris/common/utils"
    30  	"github.com/polarismesh/polaris/store/mock"
    31  )
    32  
    33  const (
    34  	TestElectKey = "test-key"
    35  )
    36  
    37  func setup() {
    38  	eventhub.InitEventHub()
    39  }
    40  
    41  func teardown() {
    42  }
    43  
    44  func TestAdminStore_LeaderElection_Follower1(t *testing.T) {
    45  	ctrl := gomock.NewController(t)
    46  	defer ctrl.Finish()
    47  
    48  	mockStore := mock.NewMockLeaderElectionStore(ctrl)
    49  	mockStore.EXPECT().CheckMtimeExpired(TestElectKey, int32(LeaseTime)).Return("127.0.0.2", false, nil)
    50  
    51  	ctx, cancel := context.WithCancel(context.TODO())
    52  	le := leaderElectionStateMachine{
    53  		electKey:   TestElectKey,
    54  		leStore:    mockStore,
    55  		leaderFlag: 0,
    56  		version:    0,
    57  		ctx:        ctx,
    58  		cancel:     cancel,
    59  	}
    60  
    61  	le.tick()
    62  	if le.isLeaderAtomic() {
    63  		t.Error("expect stay follower state")
    64  	}
    65  }
    66  
    67  func TestAdminStore_LeaderElection_Follower2(t *testing.T) {
    68  	ctrl := gomock.NewController(t)
    69  	defer ctrl.Finish()
    70  
    71  	mockStore := mock.NewMockLeaderElectionStore(ctrl)
    72  	mockStore.EXPECT().CheckMtimeExpired(TestElectKey, int32(LeaseTime)).Return(utils.LocalHost, true, nil)
    73  	mockStore.EXPECT().GetVersion(TestElectKey).Return(int64(0), nil)
    74  	mockStore.EXPECT().CompareAndSwapVersion(TestElectKey, int64(0), int64(1), "127.0.0.1").Return(false, nil)
    75  
    76  	ctx, cancel := context.WithCancel(context.TODO())
    77  	le := leaderElectionStateMachine{
    78  		electKey:   TestElectKey,
    79  		leStore:    mockStore,
    80  		leaderFlag: 0,
    81  		version:    0,
    82  		ctx:        ctx,
    83  		cancel:     cancel,
    84  	}
    85  
    86  	le.tick()
    87  	if le.isLeaderAtomic() {
    88  		t.Error("expect stay follower state")
    89  	}
    90  }
    91  
    92  func TestAdminStore_LeaderElection_Follower3(t *testing.T) {
    93  	ctrl := gomock.NewController(t)
    94  	defer ctrl.Finish()
    95  
    96  	mockStore := mock.NewMockLeaderElectionStore(ctrl)
    97  	mockStore.EXPECT().CheckMtimeExpired(TestElectKey, int32(LeaseTime)).Return(utils.LocalHost, false, errors.New("err"))
    98  	ctx, cancel := context.WithCancel(context.TODO())
    99  	le := leaderElectionStateMachine{
   100  		electKey:   TestElectKey,
   101  		leStore:    mockStore,
   102  		leaderFlag: 0,
   103  		version:    0,
   104  		ctx:        ctx,
   105  		cancel:     cancel,
   106  	}
   107  
   108  	le.tick()
   109  	if le.isLeaderAtomic() {
   110  		t.Error("expect stay follower state")
   111  	}
   112  }
   113  
   114  func TestAdminStore_LeaderElection_Follower4(t *testing.T) {
   115  	ctrl := gomock.NewController(t)
   116  	defer ctrl.Finish()
   117  
   118  	mockStore := mock.NewMockLeaderElectionStore(ctrl)
   119  	mockStore.EXPECT().CheckMtimeExpired(TestElectKey, int32(LeaseTime)).Return(utils.LocalHost, true, nil)
   120  	mockStore.EXPECT().GetVersion(TestElectKey).Return(int64(0), errors.New("err"))
   121  
   122  	ctx, cancel := context.WithCancel(context.TODO())
   123  	le := leaderElectionStateMachine{
   124  		electKey:   TestElectKey,
   125  		leStore:    mockStore,
   126  		leaderFlag: 0,
   127  		version:    0,
   128  		ctx:        ctx,
   129  		cancel:     cancel,
   130  	}
   131  
   132  	le.tick()
   133  	if le.isLeaderAtomic() {
   134  		t.Error("expect stay follower state")
   135  	}
   136  }
   137  
   138  func TestAdminStore_LeaderElection_Follower5(t *testing.T) {
   139  	ctrl := gomock.NewController(t)
   140  	defer ctrl.Finish()
   141  
   142  	mockStore := mock.NewMockLeaderElectionStore(ctrl)
   143  	mockStore.EXPECT().CheckMtimeExpired(TestElectKey, int32(LeaseTime)).Return(utils.LocalHost, true, nil)
   144  	mockStore.EXPECT().GetVersion(TestElectKey).Return(int64(0), nil)
   145  	mockStore.EXPECT().CompareAndSwapVersion(TestElectKey, int64(0), int64(1), "127.0.0.1").Return(false, errors.New("err"))
   146  
   147  	ctx, cancel := context.WithCancel(context.TODO())
   148  	le := leaderElectionStateMachine{
   149  		electKey:   TestElectKey,
   150  		leStore:    mockStore,
   151  		leaderFlag: 0,
   152  		version:    0,
   153  		ctx:        ctx,
   154  		cancel:     cancel,
   155  	}
   156  
   157  	le.tick()
   158  	if le.isLeaderAtomic() {
   159  		t.Error("expect stay follower state")
   160  	}
   161  }
   162  
   163  func TestAdminStore_LeaderElection_FollowerToLeader(t *testing.T) {
   164  	ctrl := gomock.NewController(t)
   165  	defer ctrl.Finish()
   166  
   167  	mockStore := mock.NewMockLeaderElectionStore(ctrl)
   168  	mockStore.EXPECT().CheckMtimeExpired(TestElectKey, int32(LeaseTime)).Return(utils.LocalHost, true, nil)
   169  	mockStore.EXPECT().GetVersion(TestElectKey).Return(int64(42), nil)
   170  	mockStore.EXPECT().CompareAndSwapVersion(TestElectKey, int64(42), int64(43), "127.0.0.1").Return(true, nil)
   171  
   172  	ctx, cancel := context.WithCancel(context.TODO())
   173  	le := leaderElectionStateMachine{
   174  		electKey:   TestElectKey,
   175  		leStore:    mockStore,
   176  		leaderFlag: 0,
   177  		version:    0,
   178  		ctx:        ctx,
   179  		cancel:     cancel,
   180  	}
   181  
   182  	le.tick()
   183  	if !le.isLeaderAtomic() {
   184  		t.Error("expect to leader state")
   185  	}
   186  	if le.version != 43 {
   187  		t.Errorf("epect version is %d, actual is %d", 43, le.version)
   188  	}
   189  }
   190  
   191  func TestAdminStore_LeaderElection_Leader1(t *testing.T) {
   192  	ctrl := gomock.NewController(t)
   193  	defer ctrl.Finish()
   194  
   195  	mockStore := mock.NewMockLeaderElectionStore(ctrl)
   196  	mockStore.EXPECT().CompareAndSwapVersion(TestElectKey, int64(42), int64(43), "127.0.0.1").Return(true, nil)
   197  
   198  	ctx, cancel := context.WithCancel(context.TODO())
   199  	le := leaderElectionStateMachine{
   200  		electKey:   TestElectKey,
   201  		leStore:    mockStore,
   202  		leaderFlag: 1,
   203  		version:    42,
   204  		ctx:        ctx,
   205  		cancel:     cancel,
   206  	}
   207  
   208  	le.tick()
   209  	if !le.isLeaderAtomic() {
   210  		t.Error("expect stay leader state")
   211  	}
   212  	if le.version != 43 {
   213  		t.Errorf("epect version is %d, actual is %d", 43, le.version)
   214  	}
   215  }
   216  
   217  func TestAdminStore_LeaderElection_LeaderToFollower1(t *testing.T) {
   218  	ctrl := gomock.NewController(t)
   219  	defer ctrl.Finish()
   220  
   221  	mockStore := mock.NewMockLeaderElectionStore(ctrl)
   222  	mockStore.EXPECT().CheckMtimeExpired(gomock.Any(), gomock.Any()).Return("127.0.0.2", false, nil)
   223  	mockStore.EXPECT().CompareAndSwapVersion(TestElectKey, int64(42), int64(43), "127.0.0.1").Return(false, errors.New("err"))
   224  
   225  	ctx, cancel := context.WithCancel(context.TODO())
   226  	le := leaderElectionStateMachine{
   227  		electKey:   TestElectKey,
   228  		leStore:    mockStore,
   229  		leaderFlag: 1,
   230  		version:    42,
   231  		ctx:        ctx,
   232  		cancel:     cancel,
   233  	}
   234  
   235  	le.tick()
   236  	if le.isLeaderAtomic() {
   237  		t.Error("expect to follower state")
   238  	}
   239  }
   240  
   241  func TestAdminStore_LeaderElection_LeaderToFollower2(t *testing.T) {
   242  	ctrl := gomock.NewController(t)
   243  	defer ctrl.Finish()
   244  
   245  	mockStore := mock.NewMockLeaderElectionStore(ctrl)
   246  	mockStore.EXPECT().CheckMtimeExpired(gomock.Any(), gomock.Any()).Return("127.0.0.2", false, nil)
   247  	mockStore.EXPECT().CompareAndSwapVersion(TestElectKey, int64(42), int64(43), "127.0.0.1").Return(false, nil)
   248  
   249  	ctx, cancel := context.WithCancel(context.TODO())
   250  	le := leaderElectionStateMachine{
   251  		electKey:   TestElectKey,
   252  		leStore:    mockStore,
   253  		leaderFlag: 1,
   254  		version:    42,
   255  		ctx:        ctx,
   256  		cancel:     cancel,
   257  	}
   258  
   259  	le.tick()
   260  	if le.isLeaderAtomic() {
   261  		t.Error("expect to follower state")
   262  	}
   263  }
   264  
   265  func TestAdminStore_StartLeaderElection1(t *testing.T) {
   266  	ctrl := gomock.NewController(t)
   267  	defer ctrl.Finish()
   268  
   269  	mockStore := mock.NewMockLeaderElectionStore(ctrl)
   270  	mockStore.EXPECT().CreateLeaderElection(TestElectKey).Return(errors.New("err"))
   271  
   272  	m := &adminStore{
   273  		leStore: mockStore,
   274  		leMap:   make(map[string]*leaderElectionStateMachine),
   275  	}
   276  
   277  	err := m.StartLeaderElection(TestElectKey)
   278  	if err == nil {
   279  		t.Errorf("should start failed")
   280  	}
   281  	_, ok := m.leMap[TestElectKey]
   282  	if ok {
   283  		t.Errorf("should not in map")
   284  	}
   285  }
   286  
   287  func TestAdminStore_StartLeaderElection2(t *testing.T) {
   288  	ctrl := gomock.NewController(t)
   289  	defer ctrl.Finish()
   290  
   291  	mockStore := mock.NewMockLeaderElectionStore(ctrl)
   292  	mockStore.EXPECT().CreateLeaderElection(TestElectKey).Return(nil)
   293  
   294  	m := &adminStore{
   295  		leStore: mockStore,
   296  		leMap:   make(map[string]*leaderElectionStateMachine),
   297  	}
   298  
   299  	err := m.StartLeaderElection(TestElectKey)
   300  	if err != nil {
   301  		t.Errorf("should start success")
   302  	}
   303  	_, ok := m.leMap[TestElectKey]
   304  	if !ok {
   305  		t.Errorf("should in map")
   306  	}
   307  
   308  	m.StopLeaderElections()
   309  }
   310  
   311  func TestAdminStore_StartLeaderElection3(t *testing.T) {
   312  	ctrl := gomock.NewController(t)
   313  	defer ctrl.Finish()
   314  
   315  	mockStore := mock.NewMockLeaderElectionStore(ctrl)
   316  	mockStore.EXPECT().CreateLeaderElection(TestElectKey).Return(nil)
   317  
   318  	m := &adminStore{
   319  		leStore: mockStore,
   320  		leMap:   make(map[string]*leaderElectionStateMachine),
   321  	}
   322  
   323  	err := m.StartLeaderElection(TestElectKey)
   324  	if err != nil {
   325  		t.Errorf("should start success")
   326  	}
   327  	_, ok := m.leMap[TestElectKey]
   328  	if !ok {
   329  		t.Errorf("should in map")
   330  	}
   331  
   332  	err = m.StartLeaderElection(TestElectKey)
   333  	if err != nil {
   334  		t.Errorf("expect no err if already started")
   335  	}
   336  
   337  	m.StopLeaderElections()
   338  }
   339  
   340  func TestAdminStore_ReleaseLeaderElection1(t *testing.T) {
   341  	ctrl := gomock.NewController(t)
   342  	defer ctrl.Finish()
   343  
   344  	mockStore := mock.NewMockLeaderElectionStore(ctrl)
   345  	mockStore.EXPECT().CompareAndSwapVersion(TestElectKey, int64(42), int64(43), "127.0.0.1").Return(true, nil)
   346  
   347  	ctx, cancel := context.WithCancel(context.TODO())
   348  	le := leaderElectionStateMachine{
   349  		electKey:         TestElectKey,
   350  		leStore:          mockStore,
   351  		leaderFlag:       1,
   352  		version:          42,
   353  		ctx:              ctx,
   354  		cancel:           cancel,
   355  		releaseSignal:    0,
   356  		releaseTickLimit: 0,
   357  	}
   358  
   359  	le.tick()
   360  	if !le.isLeaderAtomic() {
   361  		t.Error("expect stay leader state")
   362  	}
   363  
   364  	le.setReleaseSignal()
   365  	le.tick()
   366  	if le.isLeaderAtomic() {
   367  		t.Error("expect to follower state")
   368  	}
   369  
   370  	limit := le.releaseTickLimit
   371  	for i := 0; i < int(limit); i++ {
   372  		le.tick()
   373  		if le.isLeaderAtomic() {
   374  			t.Error("expect stay follower state")
   375  		}
   376  	}
   377  
   378  	mockStore.EXPECT().CheckMtimeExpired(TestElectKey, int32(LeaseTime)).Return(utils.LocalHost, true, nil)
   379  	mockStore.EXPECT().GetVersion(TestElectKey).Return(int64(101), nil)
   380  	mockStore.EXPECT().CompareAndSwapVersion(TestElectKey, int64(101), int64(102), "127.0.0.1").Return(true, nil)
   381  
   382  	le.tick()
   383  	if !le.isLeaderAtomic() {
   384  		t.Error("expect to leader state")
   385  	}
   386  }
   387  
   388  func TestAdminStore_ReleaseLeaderElection2(t *testing.T) {
   389  	ctrl := gomock.NewController(t)
   390  	defer ctrl.Finish()
   391  
   392  	mockStore := mock.NewMockLeaderElectionStore(ctrl)
   393  	mockStore.EXPECT().CreateLeaderElection(TestElectKey).Return(nil)
   394  
   395  	m := &adminStore{
   396  		leStore: mockStore,
   397  		leMap:   make(map[string]*leaderElectionStateMachine),
   398  	}
   399  
   400  	err := m.ReleaseLeaderElection(TestElectKey)
   401  	if err == nil {
   402  		t.Error("expect err when release not existed key")
   403  	}
   404  
   405  	_ = m.StartLeaderElection(TestElectKey)
   406  	err = m.ReleaseLeaderElection(TestElectKey)
   407  	if err != nil {
   408  		t.Errorf("unexpect err: %v", err)
   409  	}
   410  
   411  	m.StopLeaderElections()
   412  }
   413  
   414  func TestMain(m *testing.M) {
   415  	setup()
   416  	code := m.Run()
   417  	teardown()
   418  	os.Exit(code)
   419  }