github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/upgrade/upgrade_test.go (about)

     1  // Copyright 2020 PingCAP, Inc.
     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  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package upgrade
    15  
    16  import (
    17  	"context"
    18  	"fmt"
    19  	"testing"
    20  
    21  	. "github.com/pingcap/check"
    22  	"github.com/pingcap/tiflow/dm/common"
    23  	clientv3 "go.etcd.io/etcd/client/v3"
    24  	"go.etcd.io/etcd/tests/v3/integration"
    25  )
    26  
    27  var (
    28  	mockCluster   *integration.ClusterV3
    29  	bigTxnCluster *integration.ClusterV3
    30  	etcdTestCli   *clientv3.Client
    31  	bigTxnTestCli *clientv3.Client
    32  )
    33  
    34  func TestUpgrade(t *testing.T) {
    35  	integration.BeforeTestExternal(t)
    36  
    37  	suite.(*testForEtcd).testT = t
    38  	suiteForBigTxn.(*testForBigTxn).testT = t
    39  
    40  	TestingT(t)
    41  }
    42  
    43  func clearTestData(c *C) {
    44  	clearVersion := clientv3.OpDelete(common.ClusterVersionKey)
    45  	_, err := etcdTestCli.Txn(context.Background()).Then(clearVersion).Commit()
    46  	c.Assert(err, IsNil)
    47  }
    48  
    49  type testForEtcd struct {
    50  	testT *testing.T
    51  }
    52  
    53  type testForBigTxn struct {
    54  	testT *testing.T
    55  }
    56  
    57  var (
    58  	suite          = SerialSuites(&testForEtcd{})
    59  	suiteForBigTxn = SerialSuites(&testForBigTxn{})
    60  )
    61  
    62  func (t *testForEtcd) SetUpSuite(c *C) {
    63  	mockCluster = integration.NewClusterV3(t.testT, &integration.ClusterConfig{Size: 1})
    64  	etcdTestCli = mockCluster.RandClient()
    65  }
    66  
    67  func (t *testForEtcd) TearDownSuite(c *C) {
    68  	mockCluster.Terminate(t.testT)
    69  }
    70  
    71  func (t *testForBigTxn) SetUpSuite(c *C) {
    72  	bigTxnCluster = integration.NewClusterV3(t.testT, &integration.ClusterConfig{Size: 1, MaxTxnOps: 2048})
    73  	bigTxnTestCli = bigTxnCluster.RandClient()
    74  }
    75  
    76  func (t *testForBigTxn) TearDownSuite(c *C) {
    77  	bigTxnCluster.Terminate(t.testT)
    78  }
    79  
    80  func (t *testForEtcd) TestTryUpgrade(c *C) {
    81  	defer clearTestData(c)
    82  
    83  	// mock upgrade functions.
    84  	oldUpgrades := upgrades
    85  	defer func() {
    86  		upgrades = oldUpgrades
    87  	}()
    88  	mockVerNo := uint64(0)
    89  	upgrades = []func(cli *clientv3.Client, uctx Context) error{
    90  		func(cli *clientv3.Client, uctx Context) error {
    91  			mockVerNo = currentInternalNo + 1
    92  			return nil
    93  		},
    94  	}
    95  
    96  	// no previous version exist, new cluster.
    97  	ver, rev1, err := GetVersion(etcdTestCli)
    98  	c.Assert(err, IsNil)
    99  	c.Assert(rev1, Greater, int64(0))
   100  	c.Assert(ver.NotSet(), IsTrue)
   101  
   102  	// try to upgrade, run actual upgrade functions
   103  	c.Assert(TryUpgrade(etcdTestCli, newUpgradeContext()), IsNil)
   104  	ver, rev2, err := GetVersion(etcdTestCli)
   105  	c.Assert(err, IsNil)
   106  	c.Assert(rev2, Greater, rev1)
   107  	c.Assert(ver, DeepEquals, CurrentVersion)
   108  	c.Assert(mockVerNo, Equals, uint64(5))
   109  
   110  	// try to upgrade again, do nothing because the version is the same.
   111  	mockVerNo = 0
   112  	c.Assert(TryUpgrade(etcdTestCli, newUpgradeContext()), IsNil)
   113  	ver, rev3, err := GetVersion(etcdTestCli)
   114  	c.Assert(err, IsNil)
   115  	c.Assert(rev3, Equals, rev2)
   116  	c.Assert(ver, DeepEquals, CurrentVersion)
   117  	c.Assert(mockVerNo, Equals, uint64(0))
   118  
   119  	// mock a newer current version.
   120  	oldCurrentVer := CurrentVersion
   121  	defer func() {
   122  		CurrentVersion = oldCurrentVer
   123  	}()
   124  	newerVer := NewVersion(currentInternalNo+1, "mock-current-ver")
   125  	CurrentVersion = newerVer
   126  
   127  	// try to upgrade, to a newer version, upgrade operations applied.
   128  	c.Assert(TryUpgrade(etcdTestCli, newUpgradeContext()), IsNil)
   129  	ver, rev4, err := GetVersion(etcdTestCli)
   130  	c.Assert(err, IsNil)
   131  	c.Assert(rev4, Greater, rev3)
   132  	c.Assert(ver, DeepEquals, newerVer)
   133  	c.Assert(mockVerNo, Equals, currentInternalNo+1)
   134  
   135  	// try to upgrade, to an older version, do nothing.
   136  	mockVerNo = 0
   137  	CurrentVersion = oldCurrentVer
   138  	c.Assert(TryUpgrade(etcdTestCli, newUpgradeContext()), IsNil)
   139  	ver, rev5, err := GetVersion(etcdTestCli)
   140  	c.Assert(err, IsNil)
   141  	c.Assert(rev5, Equals, rev4)
   142  	c.Assert(ver, DeepEquals, newerVer) // not changed.
   143  	c.Assert(mockVerNo, Equals, uint64(0))
   144  }
   145  
   146  func (t *testForEtcd) TestUpgradeToVer3(c *C) {
   147  	ctx := context.Background()
   148  	source := "source-1"
   149  	oldKey := common.UpstreamConfigKeyAdapterV1.Encode(source)
   150  	oldVal := "test"
   151  
   152  	_, err := etcdTestCli.Put(ctx, oldKey, oldVal)
   153  	c.Assert(err, IsNil)
   154  	c.Assert(upgradeToVer3(ctx, etcdTestCli), IsNil)
   155  
   156  	newKey := common.UpstreamConfigKeyAdapter.Encode(source)
   157  	resp, err := etcdTestCli.Get(ctx, newKey)
   158  	c.Assert(err, IsNil)
   159  	c.Assert(resp.Kvs, HasLen, 1)
   160  	c.Assert(string(resp.Kvs[0].Value), Equals, oldVal)
   161  
   162  	// test won't overwrite new value
   163  	newVal := "test2"
   164  	_, err = etcdTestCli.Put(ctx, newKey, newVal)
   165  	c.Assert(err, IsNil)
   166  	c.Assert(upgradeToVer3(ctx, etcdTestCli), IsNil)
   167  	resp, err = etcdTestCli.Get(ctx, newKey)
   168  	c.Assert(err, IsNil)
   169  	c.Assert(resp.Kvs, HasLen, 1)
   170  	c.Assert(string(resp.Kvs[0].Value), Equals, newVal)
   171  
   172  	for i := 0; i < 500; i++ {
   173  		key := common.UpstreamConfigKeyAdapterV1.Encode(fmt.Sprintf("%s-%d", source, i))
   174  		val := fmt.Sprintf("%s-%d", oldVal, i)
   175  		_, err := etcdTestCli.Put(ctx, key, val)
   176  		c.Assert(err, IsNil)
   177  	}
   178  	c.Assert(upgradeToVer3(ctx, etcdTestCli), ErrorMatches, ".*too many operations in txn request.*")
   179  }
   180  
   181  func (t *testForBigTxn) TestUpgradeToVer3(c *C) {
   182  	source := "source-1"
   183  	oldVal := "test"
   184  	ctx := context.Background()
   185  
   186  	for i := 0; i < 1000; i++ {
   187  		key := common.UpstreamConfigKeyAdapterV1.Encode(fmt.Sprintf("%s-%d", source, i))
   188  		val := fmt.Sprintf("%s-%d", oldVal, i)
   189  		_, err := bigTxnTestCli.Put(ctx, key, val)
   190  		c.Assert(err, IsNil)
   191  	}
   192  	c.Assert(upgradeToVer3(ctx, bigTxnTestCli), IsNil)
   193  }