blob: 6314294666c53261ba61181fe1c9f4df867cdede [file]
// Copyright 2022 CeresDB Project Authors. Licensed under Apache-2.0.
package member
import (
"context"
"testing"
"time"
"github.com/CeresDB/ceresmeta/server/etcdutil"
"github.com/stretchr/testify/assert"
clientv3 "go.etcd.io/etcd/client/v3"
"go.etcd.io/etcd/server/v3/etcdserver"
)
type mockWatchCtx struct {
stopped bool
client *clientv3.Client
srv *etcdserver.EtcdServer
}
func (ctx *mockWatchCtx) ShouldStop() bool {
return ctx.stopped
}
func (ctx *mockWatchCtx) EtcdLeaderID() (uint64, error) {
return ctx.srv.Lead(), nil
}
func TestWatchLeaderSingle(t *testing.T) {
etcd, client, closeSrv := etcdutil.PrepareEtcdServerAndClient(t)
defer closeSrv()
watchCtx := &mockWatchCtx{
stopped: false,
client: client,
srv: etcd.Server,
}
leaderGetter := &etcdutil.LeaderGetterWrapper{Server: etcd.Server}
rpcTimeout := time.Duration(10) * time.Second
leaseTTLSec := int64(1)
mem := NewMember("", uint64(etcd.Server.ID()), "mem0", "", client, leaderGetter, rpcTimeout)
leaderWatcher := NewLeaderWatcher(watchCtx, mem, leaseTTLSec, true)
ctx, cancelWatch := context.WithCancel(context.Background())
watchedDone := make(chan struct{}, 1)
go func() {
leaderWatcher.Watch(ctx, nil)
watchedDone <- struct{}{}
}()
// Wait for watcher starting
// TODO: This unit test may fail. Currently, it is solved by increasing the sleep time, and the code needs to be optimized in the future.
time.Sleep(time.Duration(2000) * time.Millisecond)
// check the member has been the leader
ctx, cancel := context.WithTimeout(context.Background(), rpcTimeout)
defer cancel()
resp, err := mem.getLeader(ctx)
assert.NoError(t, err)
assert.NotNil(t, resp)
assert.Equal(t, resp.Leader.Id, mem.ID)
// cancel the watch
cancelWatch()
<-watchedDone
// check again whether the leader should be reset
ctx, cancel = context.WithTimeout(context.Background(), rpcTimeout)
defer cancel()
resp, err = mem.getLeader(ctx)
assert.NoError(t, err)
assert.NotNil(t, resp)
assert.Nil(t, resp.Leader)
}