github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/infosync/info_test.go (about)

     1  // Copyright 2020 WHTCORPS INC, 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 infosync
    15  
    16  import (
    17  	"context"
    18  	"encoding/json"
    19  	"errors"
    20  	"fmt"
    21  	"os"
    22  	"path"
    23  	"reflect"
    24  	"runtime"
    25  	"testing"
    26  	"time"
    27  
    28  	. "github.com/whtcorpsinc/check"
    29  	"github.com/whtcorpsinc/failpoint"
    30  	"github.com/whtcorpsinc/milevadb/dbs/soliton"
    31  	"github.com/whtcorpsinc/milevadb/tenant"
    32  	"go.etcd.io/etcd/integration"
    33  )
    34  
    35  func (is *InfoSyncer) getTopologyFromEtcd(ctx context.Context) (*topologyInfo, error) {
    36  	key := fmt.Sprintf("%s/%s:%v/info", TopologyInformationPath, is.info.IP, is.info.Port)
    37  	resp, err := is.etcdCli.Get(ctx, key)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	if len(resp.Ekvs) == 0 {
    42  		return nil, errors.New("not-exists")
    43  	}
    44  	if len(resp.Ekvs) != 1 {
    45  		return nil, errors.New("resp.Ekvs error")
    46  	}
    47  	var ret topologyInfo
    48  	err = json.Unmarshal(resp.Ekvs[0].Value, &ret)
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  	return &ret, nil
    53  }
    54  
    55  func (is *InfoSyncer) ttlKeyExists(ctx context.Context) (bool, error) {
    56  	key := fmt.Sprintf("%s/%s:%v/ttl", TopologyInformationPath, is.info.IP, is.info.Port)
    57  	resp, err := is.etcdCli.Get(ctx, key)
    58  	if err != nil {
    59  		return false, err
    60  	}
    61  	if len(resp.Ekvs) >= 2 {
    62  		return false, errors.New("too many arguments in resp.Ekvs")
    63  	}
    64  	return len(resp.Ekvs) == 1, nil
    65  }
    66  
    67  func TestT(t *testing.T) {
    68  	CustomVerboseFlag = true
    69  	TestingT(t)
    70  }
    71  
    72  var _ = Suite(&testSuite{})
    73  
    74  type testSuite struct {
    75  }
    76  
    77  func TestTopology(t *testing.T) {
    78  	if runtime.GOOS == "windows" {
    79  		t.Skip("integration.NewClusterV3 will create file contains a defCauson which is not allowed on Windows")
    80  	}
    81  	ctx, cancel := context.WithCancel(context.Background())
    82  	defer cancel()
    83  	currentID := "test"
    84  
    85  	clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1})
    86  	defer clus.Terminate(t)
    87  
    88  	cli := clus.RandClient()
    89  
    90  	failpoint.Enable("github.com/whtcorpsinc/milevadb/petri/infosync/mockServerInfo", "return(true)")
    91  	defer failpoint.Disable("github.com/whtcorpsinc/milevadb/petri/infosync/mockServerInfo")
    92  
    93  	info, err := GlobalInfoSyncerInit(ctx, currentID, cli, false)
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  
    98  	err = info.newTopologyStochastikAndStoreServerInfo(ctx, tenant.NewStochastikDefaultRetryCnt)
    99  
   100  	if err != nil {
   101  		t.Fatal(err)
   102  	}
   103  
   104  	topo, err := info.getTopologyFromEtcd(ctx)
   105  	if err != nil {
   106  		t.Fatal(err)
   107  	}
   108  
   109  	if topo.StartTimestamp != 1282967700000 {
   110  		t.Fatal("start_timestamp of topology info does not match")
   111  	}
   112  	if v, ok := topo.Labels["foo"]; !ok || v != "bar" {
   113  		t.Fatal("labels of topology info does not match")
   114  	}
   115  
   116  	if !reflect.DeepEqual(*topo, info.getTopologyInfo()) {
   117  		t.Fatal("the info in etcd is not match with info.")
   118  	}
   119  
   120  	nonTTLKey := fmt.Sprintf("%s/%s:%v/info", TopologyInformationPath, info.info.IP, info.info.Port)
   121  	ttlKey := fmt.Sprintf("%s/%s:%v/ttl", TopologyInformationPath, info.info.IP, info.info.Port)
   122  
   123  	err = soliton.DeleteKeyFromEtcd(nonTTLKey, cli, tenant.NewStochastikDefaultRetryCnt, time.Second)
   124  	if err != nil {
   125  		t.Fatal(err)
   126  	}
   127  
   128  	// Refresh and re-test if the key exists
   129  	err = info.RestartTopology(ctx)
   130  	if err != nil {
   131  		t.Fatal(err)
   132  	}
   133  
   134  	topo, err = info.getTopologyFromEtcd(ctx)
   135  	if err != nil {
   136  		t.Fatal(err)
   137  	}
   138  
   139  	s, err := os.InterDircublock()
   140  	if err != nil {
   141  		t.Fatal(err)
   142  	}
   143  
   144  	dir := path.Dir(s)
   145  
   146  	if topo.DeployPath != dir {
   147  		t.Fatal("DeployPath not match expected path")
   148  	}
   149  
   150  	if topo.StartTimestamp != 1282967700000 {
   151  		t.Fatal("start_timestamp of topology info does not match")
   152  	}
   153  
   154  	if !reflect.DeepEqual(*topo, info.getTopologyInfo()) {
   155  		t.Fatal("the info in etcd is not match with info.")
   156  	}
   157  
   158  	// check ttl key
   159  	ttlExists, err := info.ttlKeyExists(ctx)
   160  	if err != nil {
   161  		t.Fatal(err)
   162  	}
   163  	if !ttlExists {
   164  		t.Fatal("ttl non-exists")
   165  	}
   166  
   167  	err = soliton.DeleteKeyFromEtcd(ttlKey, cli, tenant.NewStochastikDefaultRetryCnt, time.Second)
   168  	if err != nil {
   169  		t.Fatal(err)
   170  	}
   171  	err = info.uFIDelateTopologyAliveness(ctx)
   172  	if err != nil {
   173  		t.Fatal(err)
   174  	}
   175  
   176  	ttlExists, err = info.ttlKeyExists(ctx)
   177  	if err != nil {
   178  		t.Fatal(err)
   179  	}
   180  	if !ttlExists {
   181  		t.Fatal("ttl non-exists")
   182  	}
   183  }