github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/lightning/tikv/tikv_test.go (about)

     1  package tikv_test
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"net/url"
    10  	"sort"
    11  	"sync"
    12  
    13  	"github.com/coreos/go-semver/semver"
    14  	. "github.com/pingcap/check"
    15  	"github.com/pingcap/kvproto/pkg/import_sstpb"
    16  
    17  	"github.com/pingcap/br/pkg/lightning/common"
    18  	kv "github.com/pingcap/br/pkg/lightning/tikv"
    19  )
    20  
    21  type tikvSuite struct{}
    22  
    23  var _ = Suite(&tikvSuite{})
    24  
    25  var (
    26  	// Samples from importer backend for testing the Check***Version functions.
    27  	// No need keep these versions in sync.
    28  	requiredMinPDVersion   = *semver.New("2.1.0")
    29  	requiredMinTiKVVersion = *semver.New("2.1.0")
    30  	requiredMaxPDVersion   = *semver.New("6.0.0")
    31  	requiredMaxTiKVVersion = *semver.New("6.0.0")
    32  )
    33  
    34  func (s *tikvSuite) TestForAllStores(c *C) {
    35  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
    36  		_, err := w.Write([]byte(`
    37  			{
    38  				"count": 5,
    39  				"stores": [
    40  					{
    41  						"store": {
    42  							"id": 1,
    43  							"address": "127.0.0.1:20160",
    44  							"version": "3.0.0-beta.1",
    45  							"state_name": "Up"
    46  						},
    47  						"status": {}
    48  					},
    49  					{
    50  						"store": {
    51  							"id": 2,
    52  							"address": "127.0.0.1:20161",
    53  							"version": "3.0.0-rc.1",
    54  							"state_name": "Down"
    55  						},
    56  						"status": {}
    57  					},
    58  					{
    59  						"store": {
    60  							"id": 3,
    61  							"address": "127.0.0.1:20162",
    62  							"version": "3.0.0-rc.2",
    63  							"state_name": "Disconnected"
    64  						},
    65  						"status": {}
    66  					},
    67  					{
    68  						"store": {
    69  							"id": 4,
    70  							"address": "127.0.0.1:20163",
    71  							"version": "3.0.0",
    72  							"state_name": "Tombstone"
    73  						},
    74  						"status": {}
    75  					},
    76  					{
    77  						"store": {
    78  							"id": 5,
    79  							"address": "127.0.0.1:20164",
    80  							"version": "3.0.1",
    81  							"state_name": "Offline"
    82  						},
    83  						"status": {}
    84  					}
    85  				]
    86  			}
    87  		`))
    88  		c.Assert(err, IsNil)
    89  	}))
    90  	defer server.Close()
    91  
    92  	ctx := context.Background()
    93  	var (
    94  		allStoresLock sync.Mutex
    95  		allStores     []*kv.Store
    96  	)
    97  	tls := common.NewTLSFromMockServer(server)
    98  	err := kv.ForAllStores(ctx, tls, kv.StoreStateDown, func(c2 context.Context, store *kv.Store) error {
    99  		allStoresLock.Lock()
   100  		allStores = append(allStores, store)
   101  		allStoresLock.Unlock()
   102  		return nil
   103  	})
   104  	c.Assert(err, IsNil)
   105  
   106  	sort.Slice(allStores, func(i, j int) bool { return allStores[i].Address < allStores[j].Address })
   107  
   108  	c.Assert(allStores, DeepEquals, []*kv.Store{
   109  		{
   110  			Address: "127.0.0.1:20160",
   111  			Version: "3.0.0-beta.1",
   112  			State:   kv.StoreStateUp,
   113  		},
   114  		{
   115  			Address: "127.0.0.1:20161",
   116  			Version: "3.0.0-rc.1",
   117  			State:   kv.StoreStateDown,
   118  		},
   119  		{
   120  			Address: "127.0.0.1:20162",
   121  			Version: "3.0.0-rc.2",
   122  			State:   kv.StoreStateDisconnected,
   123  		},
   124  		{
   125  			Address: "127.0.0.1:20164",
   126  			Version: "3.0.1",
   127  			State:   kv.StoreStateOffline,
   128  		},
   129  	})
   130  }
   131  
   132  func (s *tikvSuite) TestFetchModeFromMetrics(c *C) {
   133  	testCases := []struct {
   134  		metrics string
   135  		mode    import_sstpb.SwitchMode
   136  		isErr   bool
   137  	}{
   138  		{
   139  			metrics: `tikv_config_rocksdb{cf="default",name="hard_pending_compaction_bytes_limit"} 274877906944`,
   140  			mode:    import_sstpb.SwitchMode_Normal,
   141  		},
   142  		{
   143  			metrics: `tikv_config_rocksdb{cf="default",name="hard_pending_compaction_bytes_limit"} 0`,
   144  			mode:    import_sstpb.SwitchMode_Import,
   145  		},
   146  		{
   147  			metrics: ``,
   148  			isErr:   true,
   149  		},
   150  	}
   151  
   152  	for _, tc := range testCases {
   153  		comment := Commentf("test case '%s'", tc.metrics)
   154  		mode, err := kv.FetchModeFromMetrics(tc.metrics)
   155  		if tc.isErr {
   156  			c.Assert(err, NotNil, comment)
   157  		} else {
   158  			c.Assert(err, IsNil, comment)
   159  			c.Assert(mode, Equals, tc.mode, comment)
   160  		}
   161  	}
   162  }
   163  
   164  func (s *tikvSuite) TestCheckPDVersion(c *C) {
   165  	var version string
   166  	ctx := context.Background()
   167  
   168  	mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
   169  		c.Assert(req.URL.Path, Equals, "/pd/api/v1/version")
   170  		w.WriteHeader(http.StatusOK)
   171  		_, err := w.Write([]byte(version))
   172  		c.Assert(err, IsNil)
   173  	}))
   174  	mockURL, err := url.Parse(mockServer.URL)
   175  	c.Assert(err, IsNil)
   176  
   177  	tls := common.NewTLSFromMockServer(mockServer)
   178  
   179  	version = `{
   180      "version": "v4.0.0-rc.2-451-g760fb650"
   181  }`
   182  	c.Assert(kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion), IsNil)
   183  
   184  	version = `{
   185      "version": "v4.0.0"
   186  }`
   187  	c.Assert(kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion), IsNil)
   188  
   189  	version = `{
   190      "version": "v9999.0.0"
   191  }`
   192  	c.Assert(kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion), ErrorMatches, "PD version too new.*")
   193  
   194  	version = `{
   195      "version": "v6.0.0"
   196  }`
   197  	c.Assert(kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion), ErrorMatches, "PD version too new.*")
   198  
   199  	version = `{
   200      "version": "v6.0.0-beta"
   201  }`
   202  	c.Assert(kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion), ErrorMatches, "PD version too new.*")
   203  
   204  	version = `{
   205      "version": "v1.0.0"
   206  }`
   207  	c.Assert(kv.CheckPDVersion(ctx, tls, mockURL.Host, requiredMinPDVersion, requiredMaxPDVersion), ErrorMatches, "PD version too old.*")
   208  }
   209  
   210  func (s *tikvSuite) TestCheckTiKVVersion(c *C) {
   211  	var versions []string
   212  	ctx := context.Background()
   213  
   214  	mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
   215  		c.Assert(req.URL.Path, Equals, "/pd/api/v1/stores")
   216  		w.WriteHeader(http.StatusOK)
   217  
   218  		stores := make([]map[string]interface{}, 0, len(versions))
   219  		for i, v := range versions {
   220  			stores = append(stores, map[string]interface{}{
   221  				"store": map[string]interface{}{
   222  					"address": fmt.Sprintf("tikv%d.test:20160", i),
   223  					"version": v,
   224  				},
   225  			})
   226  		}
   227  		err := json.NewEncoder(w).Encode(map[string]interface{}{
   228  			"count":  len(versions),
   229  			"stores": stores,
   230  		})
   231  		c.Assert(err, IsNil)
   232  	}))
   233  	mockURL, err := url.Parse(mockServer.URL)
   234  	c.Assert(err, IsNil)
   235  
   236  	tls := common.NewTLSFromMockServer(mockServer)
   237  
   238  	versions = []string{"4.1.0", "v4.1.0-alpha-9-ga27a7dd"}
   239  	c.Assert(kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinTiKVVersion, requiredMaxTiKVVersion), IsNil)
   240  
   241  	versions = []string{"9999.0.0", "4.0.0"}
   242  	c.Assert(kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinTiKVVersion, requiredMaxTiKVVersion), ErrorMatches, `TiKV \(at tikv0\.test:20160\) version too new.*`)
   243  
   244  	versions = []string{"4.0.0", "1.0.0"}
   245  	c.Assert(kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinTiKVVersion, requiredMaxTiKVVersion), ErrorMatches, `TiKV \(at tikv1\.test:20160\) version too old.*`)
   246  
   247  	versions = []string{"6.0.0"}
   248  	c.Assert(kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinTiKVVersion, requiredMaxTiKVVersion), ErrorMatches, `TiKV \(at tikv0\.test:20160\) version too new.*`)
   249  
   250  	versions = []string{"6.0.0-beta"}
   251  	c.Assert(kv.CheckTiKVVersion(ctx, tls, mockURL.Host, requiredMinTiKVVersion, requiredMaxTiKVVersion), ErrorMatches, `TiKV \(at tikv0\.test:20160\) version too new.*`)
   252  }