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