diff --git a/contrib/log/zap/zap.go b/contrib/log/zap/zap.go index 411bd1c11..5929c4860 100644 --- a/contrib/log/zap/zap.go +++ b/contrib/log/zap/zap.go @@ -48,5 +48,5 @@ func (l *Logger) Sync() error { } func (l *Logger) Close() error { - return l.log.Sync() + return l.Sync() } diff --git a/contrib/log/zap/zap_test.go b/contrib/log/zap/zap_test.go index efaca2582..393af79e9 100644 --- a/contrib/log/zap/zap_test.go +++ b/contrib/log/zap/zap_test.go @@ -4,14 +4,39 @@ import ( "testing" "go.uber.org/zap" + "go.uber.org/zap/zapcore" "github.com/go-kratos/kratos/v2/log" ) +type testWriteSyncer struct { + output []string +} + +func (x *testWriteSyncer) Write(p []byte) (n int, err error) { + x.output = append(x.output, string(p)) + return len(p), nil +} + +func (x *testWriteSyncer) Sync() error { + return nil +} + func TestLogger(t *testing.T) { - logger := NewLogger(zap.NewExample()) + syncer := &testWriteSyncer{} + encoderCfg := zapcore.EncoderConfig{ + MessageKey: "msg", + LevelKey: "level", + NameKey: "logger", + EncodeLevel: zapcore.LowercaseLevelEncoder, + EncodeTime: zapcore.ISO8601TimeEncoder, + EncodeDuration: zapcore.StringDurationEncoder, + } + core := zapcore.NewCore(zapcore.NewJSONEncoder(encoderCfg), syncer, zap.DebugLevel) + zlogger := zap.New(core).WithOptions() + logger := NewLogger(zlogger) - defer func() { _ = logger.Sync() }() + defer func() { _ = logger.Close() }() zlog := log.NewHelper(logger) @@ -19,4 +44,19 @@ func TestLogger(t *testing.T) { zlog.Infow("log", "info") zlog.Warnw("log", "warn") zlog.Errorw("log", "error") + zlog.Errorw("log", "error", "except warn") + + except := []string{ + "{\"level\":\"debug\",\"msg\":\"\",\"log\":\"debug\"}\n", + "{\"level\":\"info\",\"msg\":\"\",\"log\":\"info\"}\n", + "{\"level\":\"warn\",\"msg\":\"\",\"log\":\"warn\"}\n", + "{\"level\":\"error\",\"msg\":\"\",\"log\":\"error\"}\n", + "{\"level\":\"warn\",\"msg\":\"Keyvalues must appear in pairs: [log error except warn]\"}\n", + } + for i, s := range except { + if s != syncer.output[i] { + t.Logf("except=%s, got=%s", s, syncer.output[i]) + t.Fail() + } + } } diff --git a/contrib/registry/zookeeper/register_test.go b/contrib/registry/zookeeper/register_test.go index 8054548da..131f3ee12 100644 --- a/contrib/registry/zookeeper/register_test.go +++ b/contrib/registry/zookeeper/register_test.go @@ -2,6 +2,7 @@ package zookeeper import ( "context" + "reflect" "testing" "time" @@ -9,79 +10,410 @@ import ( "github.com/go-zookeeper/zk" ) -func TestRegistry(t *testing.T) { - ctx := context.Background() - s := ®istry.ServiceInstance{ - ID: "0", - Name: "helloworld", - Endpoints: []string{"http://127.0.0.1:1111"}, - } - +func TestRegistry_GetService(t *testing.T) { conn, _, err := zk.Connect([]string{"127.0.0.1:2181"}, time.Second*15) if err != nil { t.Fatal(err) return } r := New(conn) - err = r.Register(ctx, s) - if err != nil { - t.Fatal(err) - return + + svrHello := ®istry.ServiceInstance{ + ID: "1", + Name: "hello", + Version: "v1.0.0", + Endpoints: []string{"127.0.0.1:8080"}, } - time.Sleep(time.Second) - w, err := r.Watch(ctx, s.Name) - if err != nil { - t.Fatal(err) - return + type fields struct { + registry *Registry + } + type args struct { + ctx context.Context + serviceName string } - defer func() { - _ = w.Stop() - }() - go func() { - for { - res, nextErr := w.Next() - if nextErr != nil { - t.Errorf("watch next error: %s", nextErr) + tests := []struct { + name string + fields fields + args args + want []*registry.ServiceInstance + wantErr bool + preFunc func(t *testing.T) + deferFunc func(t *testing.T) + }{ + { + name: "normal", + preFunc: func(t *testing.T) { + err = r.Register(context.Background(), svrHello) + if err != nil { + t.Error(err) + } + }, + deferFunc: func(t *testing.T) { + err = r.Deregister(context.Background(), svrHello) + if err != nil { + t.Error(err) + } + }, + fields: fields{ + registry: r, + }, + args: args{ + ctx: context.Background(), + serviceName: svrHello.Name, + }, + want: []*registry.ServiceInstance{svrHello}, + wantErr: false, + }, + { + name: "can't get any", + fields: fields{ + registry: r, + }, + args: args{ + ctx: context.Background(), + serviceName: "helloxxx", + }, + want: nil, + wantErr: true, + }, + { + name: "conn close", + preFunc: func(t *testing.T) { + conn.Close() + }, + fields: fields{ + registry: r, + }, + args: args{ + ctx: context.Background(), + serviceName: "hello", + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.preFunc != nil { + tt.preFunc(t) + } + if tt.deferFunc != nil { + defer tt.deferFunc(t) + } + r := tt.fields.registry + got, err := r.GetService(tt.args.ctx, tt.args.serviceName) + if (err != nil) != tt.wantErr { + t.Errorf("GetService() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("GetService() got = %v", got) return } - t.Logf("watch: %d", len(res)) - for _, r := range res { - t.Logf("next: %+v", r) + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetService() got = %v, want %v", got, tt.want) } - } - }() - time.Sleep(time.Second) + }) + } +} - if err = r.Register(ctx, s); err != nil { +func TestRegistry_Register(t *testing.T) { + conn, _, err := zk.Connect([]string{"127.0.0.1:2181"}, time.Second*15) + if err != nil { t.Fatal(err) + return + } + r := New(conn) + + svrHello := ®istry.ServiceInstance{ + ID: "1", + Name: "hello", + Version: "v1.0.0", + Endpoints: []string{"127.0.0.1:8080"}, + } + + type fields struct { + registry *Registry + } + type args struct { + ctx context.Context + service *registry.ServiceInstance } - time.Sleep(time.Second) + tests := []struct { + name string + fields fields + args args + wantErr bool + preFunc func(t *testing.T) + deferFunc func(t *testing.T) + }{ + { + name: "normal", + fields: fields{ + registry: r, + }, + args: args{ + ctx: context.Background(), + service: svrHello, + }, + wantErr: false, + }, + { + name: "invalid path", + fields: fields{ + registry: New(conn, WithRootPath("invalid")), + }, + args: args{ + ctx: context.Background(), + service: ®istry.ServiceInstance{ + ID: "1", + Name: "hello1", + Version: "v1.0.0", + Endpoints: []string{"127.0.0.1:8080"}, + }, + }, + wantErr: true, + }, + { + name: "auth", + preFunc: func(t *testing.T) { + err = conn.AddAuth("digest", []byte("test:test")) + if err != nil { + t.Error(err) + } + }, + fields: fields{ + registry: New(conn, WithRootPath("/tt1"), WithDigestACL("test", "test")), + }, + args: args{ + ctx: context.Background(), + service: ®istry.ServiceInstance{ + ID: "1", + Name: "hello2", + Version: "v1.0.0", + Endpoints: []string{"127.0.0.1:8080"}, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.preFunc != nil { + tt.preFunc(t) + } + if tt.deferFunc != nil { + defer tt.deferFunc(t) + } + r := tt.fields.registry + if err := r.Register(tt.args.ctx, tt.args.service); (err != nil) != tt.wantErr { + t.Errorf("Register() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} - res, err := r.GetService(ctx, s.Name) +func TestRegistry_Deregister(t *testing.T) { + conn, _, err := zk.Connect([]string{"127.0.0.1:2181"}, time.Second*15) if err != nil { t.Fatal(err) + return } - for i, re := range res { - t.Logf("first %d re:%v\n", i, re) + r := New(conn) + + svrHello := ®istry.ServiceInstance{ + ID: "1", + Name: "hello", + Version: "v1.0.0", + Endpoints: []string{"127.0.0.1:8080"}, + } + + cancelCtx, cancel := context.WithCancel(context.Background()) + cancel() + type fields struct { + registry *Registry } - if len(res) != 1 && res[0].Name != s.Name { - t.Errorf("not expected: %+v", res) + type args struct { + ctx context.Context + service *registry.ServiceInstance } + tests := []struct { + name string + fields fields + args args + wantErr bool + preFunc func(t *testing.T) + deferFunc func(t *testing.T) + }{ + { + name: "normal", + fields: fields{ + registry: r, + }, + args: args{ + ctx: context.Background(), + service: svrHello, + }, + wantErr: false, + preFunc: func(t *testing.T) { + err = r.Register(context.Background(), svrHello) + if err != nil { + t.Error(err) + } + }, + }, + { + name: "with ctx cancel", + fields: fields{ + registry: r, + }, + args: args{ + ctx: cancelCtx, + service: svrHello, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := tt.fields.registry + if err := r.Deregister(tt.args.ctx, tt.args.service); (err != nil) != tt.wantErr { + t.Errorf("Deregister() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} - if err = r.Deregister(ctx, s); err != nil { +func TestRegistry_Watch(t *testing.T) { + conn, _, err := zk.Connect([]string{"127.0.0.1:2181"}, time.Second*15) + if err != nil { t.Fatal(err) + return } - time.Sleep(time.Second) - - res, err = r.GetService(ctx, s.Name) + closeConn, _, err := zk.Connect([]string{"127.0.0.1:2181"}, time.Second*15) if err != nil { t.Fatal(err) + return + } + r := New(conn) + + svrHello := ®istry.ServiceInstance{ + ID: "1", + Name: "hello", + Version: "v1.0.0", + Endpoints: []string{"127.0.0.1:8080"}, } - for i, re := range res { - t.Logf("second %d re:%v\n", i, re) + + cancelCtx, cancel := context.WithCancel(context.Background()) + type fields struct { + registry *Registry + } + type args struct { + ctx context.Context + serviceName string + } + tests := []struct { + name string + fields fields + args args + wantErr bool + want []*registry.ServiceInstance + + preFunc func(t *testing.T) + deferFunc func(t *testing.T) + processFunc func(t *testing.T, w registry.Watcher) + }{ + { + name: "normal", + fields: fields{ + registry: r, + }, + args: args{ + ctx: context.Background(), + serviceName: svrHello.Name, + }, + wantErr: false, + want: []*registry.ServiceInstance{svrHello}, + deferFunc: func(t *testing.T) { + err = r.Deregister(context.Background(), svrHello) + if err != nil { + t.Error(err) + } + }, + processFunc: func(t *testing.T, w registry.Watcher) { + err = r.Register(context.Background(), svrHello) + if err != nil { + t.Error(err) + } + }, + }, + { + name: "ctx cancel", + fields: fields{ + registry: r, + }, + args: args{ + ctx: cancelCtx, + serviceName: svrHello.Name, + }, + wantErr: true, + want: nil, + processFunc: func(t *testing.T, w registry.Watcher) { + cancel() + }, + }, + { + name: "disconnect", + fields: fields{ + registry: New(closeConn), + }, + args: args{ + ctx: context.Background(), + serviceName: svrHello.Name, + }, + wantErr: true, + want: nil, + processFunc: func(t *testing.T, w registry.Watcher) { + closeConn.Close() + }, + }, } - if len(res) != 0 { - t.Errorf("not expected empty") + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.preFunc != nil { + tt.preFunc(t) + } + if tt.deferFunc != nil { + defer tt.deferFunc(t) + } + r := tt.fields.registry + watcher, err := r.Watch(tt.args.ctx, tt.args.serviceName) + if err != nil { + t.Error(err) + return + } + defer func() { + err = watcher.Stop() + if err != nil { + t.Error(err) + } + }() + _, err = watcher.Next() + if err != nil { + t.Error(err) + return + } + + if tt.processFunc != nil { + tt.processFunc(t, watcher) + } + + want, err := watcher.Next() + if (err != nil) != tt.wantErr { + t.Errorf("Watch() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(want, tt.want) { + t.Errorf("Watch() watcher = %v, want %v", watcher, tt.want) + } + }) } }