github.com/shuguocloud/go-zero@v1.3.0/core/discov/internal/registry_test.go (about)

     1  package internal
     2  
     3  import (
     4  	"context"
     5  	"sync"
     6  	"testing"
     7  
     8  	"github.com/golang/mock/gomock"
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/shuguocloud/go-zero/core/contextx"
    11  	"github.com/shuguocloud/go-zero/core/lang"
    12  	"github.com/shuguocloud/go-zero/core/logx"
    13  	"github.com/shuguocloud/go-zero/core/stringx"
    14  	"go.etcd.io/etcd/api/v3/mvccpb"
    15  	clientv3 "go.etcd.io/etcd/client/v3"
    16  )
    17  
    18  var mockLock sync.Mutex
    19  
    20  func init() {
    21  	logx.Disable()
    22  }
    23  
    24  func setMockClient(cli EtcdClient) func() {
    25  	mockLock.Lock()
    26  	NewClient = func([]string) (EtcdClient, error) {
    27  		return cli, nil
    28  	}
    29  	return func() {
    30  		NewClient = DialClient
    31  		mockLock.Unlock()
    32  	}
    33  }
    34  
    35  func TestGetCluster(t *testing.T) {
    36  	AddAccount([]string{"first"}, "foo", "bar")
    37  	c1, _ := GetRegistry().getCluster([]string{"first"})
    38  	c2, _ := GetRegistry().getCluster([]string{"second"})
    39  	c3, _ := GetRegistry().getCluster([]string{"first"})
    40  	assert.Equal(t, c1, c3)
    41  	assert.NotEqual(t, c1, c2)
    42  }
    43  
    44  func TestGetClusterKey(t *testing.T) {
    45  	assert.Equal(t, getClusterKey([]string{"localhost:1234", "remotehost:5678"}),
    46  		getClusterKey([]string{"remotehost:5678", "localhost:1234"}))
    47  }
    48  
    49  func TestCluster_HandleChanges(t *testing.T) {
    50  	ctrl := gomock.NewController(t)
    51  	l := NewMockUpdateListener(ctrl)
    52  	l.EXPECT().OnAdd(KV{
    53  		Key: "first",
    54  		Val: "1",
    55  	})
    56  	l.EXPECT().OnAdd(KV{
    57  		Key: "second",
    58  		Val: "2",
    59  	})
    60  	l.EXPECT().OnDelete(KV{
    61  		Key: "first",
    62  		Val: "1",
    63  	})
    64  	l.EXPECT().OnDelete(KV{
    65  		Key: "second",
    66  		Val: "2",
    67  	})
    68  	l.EXPECT().OnAdd(KV{
    69  		Key: "third",
    70  		Val: "3",
    71  	})
    72  	l.EXPECT().OnAdd(KV{
    73  		Key: "fourth",
    74  		Val: "4",
    75  	})
    76  	c := newCluster([]string{"any"})
    77  	c.listeners["any"] = []UpdateListener{l}
    78  	c.handleChanges("any", []KV{
    79  		{
    80  			Key: "first",
    81  			Val: "1",
    82  		},
    83  		{
    84  			Key: "second",
    85  			Val: "2",
    86  		},
    87  	})
    88  	assert.EqualValues(t, map[string]string{
    89  		"first":  "1",
    90  		"second": "2",
    91  	}, c.values["any"])
    92  	c.handleChanges("any", []KV{
    93  		{
    94  			Key: "third",
    95  			Val: "3",
    96  		},
    97  		{
    98  			Key: "fourth",
    99  			Val: "4",
   100  		},
   101  	})
   102  	assert.EqualValues(t, map[string]string{
   103  		"third":  "3",
   104  		"fourth": "4",
   105  	}, c.values["any"])
   106  }
   107  
   108  func TestCluster_Load(t *testing.T) {
   109  	ctrl := gomock.NewController(t)
   110  	defer ctrl.Finish()
   111  	cli := NewMockEtcdClient(ctrl)
   112  	restore := setMockClient(cli)
   113  	defer restore()
   114  	cli.EXPECT().Get(gomock.Any(), "any/", gomock.Any()).Return(&clientv3.GetResponse{
   115  		Kvs: []*mvccpb.KeyValue{
   116  			{
   117  				Key:   []byte("hello"),
   118  				Value: []byte("world"),
   119  			},
   120  		},
   121  	}, nil)
   122  	cli.EXPECT().Ctx().Return(context.Background())
   123  	c := &cluster{
   124  		values: make(map[string]map[string]string),
   125  	}
   126  	c.load(cli, "any")
   127  }
   128  
   129  func TestCluster_Watch(t *testing.T) {
   130  	tests := []struct {
   131  		name      string
   132  		method    int
   133  		eventType mvccpb.Event_EventType
   134  	}{
   135  		{
   136  			name:      "add",
   137  			eventType: clientv3.EventTypePut,
   138  		},
   139  		{
   140  			name:      "delete",
   141  			eventType: clientv3.EventTypeDelete,
   142  		},
   143  	}
   144  
   145  	for _, test := range tests {
   146  		t.Run(test.name, func(t *testing.T) {
   147  			ctrl := gomock.NewController(t)
   148  			defer ctrl.Finish()
   149  			cli := NewMockEtcdClient(ctrl)
   150  			restore := setMockClient(cli)
   151  			defer restore()
   152  			ch := make(chan clientv3.WatchResponse)
   153  			cli.EXPECT().Watch(gomock.Any(), "any/", gomock.Any()).Return(ch)
   154  			cli.EXPECT().Ctx().Return(context.Background())
   155  			var wg sync.WaitGroup
   156  			wg.Add(1)
   157  			c := &cluster{
   158  				listeners: make(map[string][]UpdateListener),
   159  				values:    make(map[string]map[string]string),
   160  			}
   161  			listener := NewMockUpdateListener(ctrl)
   162  			c.listeners["any"] = []UpdateListener{listener}
   163  			listener.EXPECT().OnAdd(gomock.Any()).Do(func(kv KV) {
   164  				assert.Equal(t, "hello", kv.Key)
   165  				assert.Equal(t, "world", kv.Val)
   166  				wg.Done()
   167  			}).MaxTimes(1)
   168  			listener.EXPECT().OnDelete(gomock.Any()).Do(func(_ interface{}) {
   169  				wg.Done()
   170  			}).MaxTimes(1)
   171  			go c.watch(cli, "any")
   172  			ch <- clientv3.WatchResponse{
   173  				Events: []*clientv3.Event{
   174  					{
   175  						Type: test.eventType,
   176  						Kv: &mvccpb.KeyValue{
   177  							Key:   []byte("hello"),
   178  							Value: []byte("world"),
   179  						},
   180  					},
   181  				},
   182  			}
   183  			wg.Wait()
   184  		})
   185  	}
   186  }
   187  
   188  func TestClusterWatch_RespFailures(t *testing.T) {
   189  	resps := []clientv3.WatchResponse{
   190  		{
   191  			Canceled: true,
   192  		},
   193  		{
   194  			// cause resp.Err() != nil
   195  			CompactRevision: 1,
   196  		},
   197  	}
   198  
   199  	for _, resp := range resps {
   200  		t.Run(stringx.Rand(), func(t *testing.T) {
   201  			ctrl := gomock.NewController(t)
   202  			defer ctrl.Finish()
   203  			cli := NewMockEtcdClient(ctrl)
   204  			restore := setMockClient(cli)
   205  			defer restore()
   206  			ch := make(chan clientv3.WatchResponse)
   207  			cli.EXPECT().Watch(gomock.Any(), "any/", gomock.Any()).Return(ch).AnyTimes()
   208  			cli.EXPECT().Ctx().Return(context.Background()).AnyTimes()
   209  			c := new(cluster)
   210  			c.done = make(chan lang.PlaceholderType)
   211  			go func() {
   212  				ch <- resp
   213  				close(c.done)
   214  			}()
   215  			c.watch(cli, "any")
   216  		})
   217  	}
   218  }
   219  
   220  func TestClusterWatch_CloseChan(t *testing.T) {
   221  	ctrl := gomock.NewController(t)
   222  	defer ctrl.Finish()
   223  	cli := NewMockEtcdClient(ctrl)
   224  	restore := setMockClient(cli)
   225  	defer restore()
   226  	ch := make(chan clientv3.WatchResponse)
   227  	cli.EXPECT().Watch(gomock.Any(), "any/", gomock.Any()).Return(ch).AnyTimes()
   228  	cli.EXPECT().Ctx().Return(context.Background()).AnyTimes()
   229  	c := new(cluster)
   230  	c.done = make(chan lang.PlaceholderType)
   231  	go func() {
   232  		close(ch)
   233  		close(c.done)
   234  	}()
   235  	c.watch(cli, "any")
   236  }
   237  
   238  func TestValueOnlyContext(t *testing.T) {
   239  	ctx := contextx.ValueOnlyFrom(context.Background())
   240  	ctx.Done()
   241  	assert.Nil(t, ctx.Err())
   242  }