diff --git a/client/egrpc/component_test.go b/client/egrpc/component_test.go index 258c88a9..afc3d9ab 100644 --- a/client/egrpc/component_test.go +++ b/client/egrpc/component_test.go @@ -7,14 +7,15 @@ import ( "net" "testing" - "github.com/gotomicro/ego/core/elog" - "github.com/gotomicro/ego/internal/test/errcode" - "github.com/gotomicro/ego/internal/test/helloworld" - "github.com/gotomicro/ego/server/egrpc" "github.com/stretchr/testify/assert" "google.golang.org/grpc" "google.golang.org/grpc/test/bufconn" "google.golang.org/protobuf/proto" + + "github.com/gotomicro/ego/core/elog" + "github.com/gotomicro/ego/internal/test/errcode" + "github.com/gotomicro/ego/internal/test/helloworld" + "github.com/gotomicro/ego/server/egrpc" ) var svc *egrpc.Component diff --git a/client/egrpc/interceptor_test.go b/client/egrpc/interceptor_test.go index 03c7a3d5..762afad7 100644 --- a/client/egrpc/interceptor_test.go +++ b/client/egrpc/interceptor_test.go @@ -3,21 +3,22 @@ package egrpc import ( "bytes" "context" - "io/ioutil" + "io" "log" "net/http/httptest" "os" "testing" "time" - "github.com/gotomicro/ego/core/util/xtime" - "github.com/gotomicro/ego/internal/test/helloworld" - "github.com/gotomicro/ego/internal/tools" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/stretchr/testify/assert" "google.golang.org/grpc" "google.golang.org/grpc/metadata" "google.golang.org/grpc/test/bufconn" + + "github.com/gotomicro/ego/core/util/xtime" + "github.com/gotomicro/ego/internal/test/helloworld" + "github.com/gotomicro/ego/internal/tools" ) func Test_customHeader(t *testing.T) { @@ -138,7 +139,7 @@ func TestPrometheusUnary(t *testing.T) { if err != nil { t.Fatal(err) } - text, err := ioutil.ReadAll(res.Body) + text, err := io.ReadAll(res.Body) if err != nil { t.Fatal(err) } @@ -184,8 +185,8 @@ type GreeterHeader struct { // SayHello ... func (g GreeterHeader) SayHello(context context.Context, request *helloworld.HelloRequest) (*helloworld.HelloResponse, error) { appName := tools.GrpcHeaderValue(context, "app") - //cpu := tools.GrpcHeaderValue(context, "enable-cpu-usage") - //assert.Equal(g.t, "true", cpu) + // cpu := tools.GrpcHeaderValue(context, "enable-cpu-usage") + // assert.Equal(g.t, "true", cpu) assert.Equal(g.t, "egrpc.test", appName) return &helloworld.HelloResponse{ diff --git a/client/egrpc/resolver/resolver_registry_test.go b/client/egrpc/resolver/resolver_registry_test.go index c917a5bf..79621aa0 100644 --- a/client/egrpc/resolver/resolver_registry_test.go +++ b/client/egrpc/resolver/resolver_registry_test.go @@ -5,10 +5,11 @@ import ( "net/url" "testing" - "github.com/gotomicro/ego/core/eregistry" - "github.com/gotomicro/ego/server" "github.com/stretchr/testify/assert" "google.golang.org/grpc/resolver" + + "github.com/gotomicro/ego/core/eregistry" + "github.com/gotomicro/ego/server" ) func TestResolver(t *testing.T) { @@ -18,6 +19,7 @@ func TestResolver(t *testing.T) { t: t, }, } + assert.Equal(t, "test", builder.Scheme()) targetName := "test:///hello" target, err := parseTarget(targetName) assert.NoError(t, err) diff --git a/client/ehttp/component_test.go b/client/ehttp/component_test.go new file mode 100644 index 00000000..711ef77b --- /dev/null +++ b/client/ehttp/component_test.go @@ -0,0 +1,21 @@ +package ehttp + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/gotomicro/ego/core/elog" +) + +func TestNewComponent(t *testing.T) { + // Normal case + t.Run("Normal case", func(t *testing.T) { + config := &Config{Addr: "http://hello.com"} + logger := elog.DefaultLogger + component := newComponent("hello", config, logger) + assert.Equal(t, "hello", component.name) + }) + + // Other case... +} diff --git a/client/ehttp/config_test.go b/client/ehttp/config_test.go new file mode 100644 index 00000000..4bd328d9 --- /dev/null +++ b/client/ehttp/config_test.go @@ -0,0 +1,33 @@ +package ehttp + +import ( + "reflect" + "runtime" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/gotomicro/ego/core/util/xtime" +) + +func Test_DefaultConfig(t *testing.T) { + assert.True(t, reflect.DeepEqual(&Config{ + Addr: "", + Debug: false, + RawDebug: false, + ReadTimeout: xtime.Duration("2s"), + SlowLogThreshold: xtime.Duration("500ms"), + IdleConnTimeout: 90 * time.Second, + MaxIdleConns: 100, + MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1, + EnableTraceInterceptor: true, + EnableKeepAlives: true, + EnableAccessInterceptor: false, + EnableAccessInterceptorRes: false, + EnableMetricInterceptor: false, + PathRelabel: nil, + cookieJar: nil, + httpClient: nil, + }, DefaultConfig())) +} diff --git a/client/ehttp/config_test/conf.toml b/client/ehttp/config_test/conf.toml new file mode 100644 index 00000000..c8df0b80 --- /dev/null +++ b/client/ehttp/config_test/conf.toml @@ -0,0 +1,5 @@ +[test] +"name" = "hello" + +[test1] +"name" = "world" \ No newline at end of file diff --git a/client/ehttp/container_test.go b/client/ehttp/container_test.go new file mode 100644 index 00000000..33ab764e --- /dev/null +++ b/client/ehttp/container_test.go @@ -0,0 +1,20 @@ +package ehttp + +import ( + "os" + "testing" + + "github.com/BurntSushi/toml" + "github.com/stretchr/testify/assert" + + "github.com/gotomicro/ego/core/econf" +) + +func TestLoad(t *testing.T) { + file, err := os.Open("./config_test/conf.toml") + assert.NoError(t, err) + err = econf.LoadFromReader(file, toml.Unmarshal) + assert.NoError(t, err) + container := Load("test").Build().name + assert.Equal(t, "test", container) +} diff --git a/client/ehttp/interceptor_test.go b/client/ehttp/interceptor_test.go new file mode 100644 index 00000000..03271167 --- /dev/null +++ b/client/ehttp/interceptor_test.go @@ -0,0 +1,74 @@ +package ehttp + +import ( + "context" + "net/url" + "strings" + "testing" + "time" + + "github.com/go-resty/resty/v2" + "github.com/stretchr/testify/assert" + + "github.com/gotomicro/ego/core/elog" +) + +func TestLogAccess(t *testing.T) { + name := "test" + config := &Config{} + logger := &elog.Component{} + u, err := url.Parse("https://hello.com/xxx") + assert.NoError(t, err) + ctx := context.WithValue(context.Background(), urlKey{}, u) + req := resty.New().R().SetContext(ctx) + res := &resty.Response{} + logAccess(name, config, logger, req, res, err) + assert.NoError(t, err) +} + +func TestBeg(t *testing.T) { + ctx := context.Background() + now := time.Now() + ctx = context.WithValue(ctx, begKey{}, now) + + result := beg(ctx) + assert.Equal(t, now, result) +} + +type CustomResolver struct { + Address string +} + +func (r *CustomResolver) GetAddr() string { + return r.Address +} + +func TestFixedInterceptor(t *testing.T) { + name := "test" + config := &Config{} + logger := &elog.Component{} + builder := &CustomResolver{Address: "https://test.com"} + + client := resty.New() + request := client.R() + request.SetContext(context.Background()) + request.URL = "https://hello.com/world" + middleware, _, _ := fixedInterceptor(name, config, logger, builder) + + // case 1 + config.Addr = "" + err := middleware(client, request) + assert.NoError(t, err) + + // case 2 + config.Addr = "https://xxxxx.com/xxx" + err = middleware(client, request) + assert.NoError(t, err) + assert.Equal(t, "https://test.com", client.HostURL) +} + +func TestFileWithLineNum(t *testing.T) { + file := "/usr/local/go/src/testing/testing.go" + got := fileWithLineNum() + assert.True(t, true, strings.HasPrefix(got, file)) +} diff --git a/client/ehttp/options_test.go b/client/ehttp/options_test.go new file mode 100644 index 00000000..14d42dbd --- /dev/null +++ b/client/ehttp/options_test.go @@ -0,0 +1,53 @@ +package ehttp + +import ( + "reflect" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestOptions(t *testing.T) { + c := &Container{ + config: &Config{}, + } + expectedAddr := "127.0.0.1:8080" + expectedReadTimeOut := time.Duration(5) + expectedSlowLogThreshold := time.Duration(5) + expectedIdleConnTimeOut := time.Duration(5) + + WithAddr(expectedAddr)(c) + WithDebug(true)(c) + WithRawDebug(false)(c) + WithReadTimeout(expectedReadTimeOut)(c) + WithSlowLogThreshold(expectedSlowLogThreshold)(c) + WithIdleConnTimeout(expectedIdleConnTimeOut)(c) + WithMaxIdleConns(3)(c) + WithMaxIdleConnsPerHost(3)(c) + WithEnableTraceInterceptor(true)(c) + WithEnableKeepAlives(true)(c) + WithEnableMetricInterceptor(true)(c) + WithEnableAccessInterceptor(true)(c) + WithEnableAccessInterceptorRes(true)(c) + WithPathRelabel("hello", "test")(c) + WithJar(nil)(c) + WithHTTPClient(nil)(c) + + assert.Equal(t, expectedAddr, c.config.Addr) + assert.Equal(t, true, c.config.Debug) + assert.Equal(t, false, c.config.RawDebug) + assert.Equal(t, expectedReadTimeOut, c.config.ReadTimeout) + assert.Equal(t, expectedSlowLogThreshold, c.config.SlowLogThreshold) + assert.Equal(t, expectedIdleConnTimeOut, c.config.IdleConnTimeout) + assert.Equal(t, 3, c.config.MaxIdleConns) + assert.Equal(t, 3, c.config.MaxIdleConnsPerHost) + assert.Equal(t, true, c.config.EnableTraceInterceptor) + assert.Equal(t, true, c.config.EnableKeepAlives) + assert.Equal(t, true, c.config.EnableMetricInterceptor) + assert.Equal(t, true, c.config.EnableAccessInterceptor) + assert.Equal(t, true, c.config.EnableAccessInterceptorRes) + reflect.DeepEqual(Relabel{Match: "hello", Replacement: "test"}, c.config.PathRelabel) + assert.Equal(t, nil, c.config.cookieJar) + reflect.DeepEqual(nil, c.config.httpClient) +} diff --git a/client/ehttp/resolver/resolver_func_test.go b/client/ehttp/resolver/resolver_func_test.go new file mode 100644 index 00000000..91dd1bc1 --- /dev/null +++ b/client/ehttp/resolver/resolver_func_test.go @@ -0,0 +1,164 @@ +package resolver + +import ( + "reflect" + "testing" + + "github.com/stretchr/testify/assert" + "google.golang.org/grpc/attributes" + + "github.com/gotomicro/ego/core/constant" + "github.com/gotomicro/ego/server" +) + +func Test_Equal(t *testing.T) { + oldAttr := attributes.New(constant.KeyServiceInfo, server.ServiceInfo{ + Name: "ego", + Scheme: "http", + Address: "192.168.1.1", + }) + assert.True(t, oldAttr.Equal(attributes.New(constant.KeyServiceInfo, server.ServiceInfo{ + Name: "ego", + Scheme: "http", + Address: "192.168.1.1", + }))) + + oldAttr2 := attributes.New(constant.KeyServiceInfo, server.ServiceInfo{ + Name: "ego", + Scheme: "http", + Address: "192.168.1.1", + Metadata: map[string]string{"hello": "world"}, + }) + assert.True(t, oldAttr2.Equal(attributes.New(constant.KeyServiceInfo, server.ServiceInfo{ + Name: "ego", + Scheme: "http", + Address: "192.168.1.1", + Metadata: map[string]string{"hello": "world"}, + }))) + + oldAttr3 := attributes.New(constant.KeyServiceInfo, server.ServiceInfo{ + Name: "ego", + Scheme: "http", + Address: "192.168.1.1", + Metadata: map[string]string{"hello": "world"}, + Services: map[string]*server.Service{ + "hellosvc": { + Namespace: "default", + Name: "first service", + Labels: nil, + Methods: nil, + }, + }, + }) + + assert.True(t, oldAttr3.Equal(attributes.New(constant.KeyServiceInfo, server.ServiceInfo{ + Name: "ego", + Scheme: "http", + Address: "192.168.1.1", + Metadata: map[string]string{"hello": "world"}, + Services: map[string]*server.Service{ + "hellosvc": { + Namespace: "default", + Name: "first service", + Labels: nil, + Methods: nil, + }, + }, + }))) +} + +func Test_tryUpdateAttrs(t *testing.T) { + res := &baseResolver{ + nodeInfo: make(map[string]*attributes.Attributes), + } + res.tryUpdateAttrs(map[string]server.ServiceInfo{ + "192.168.1.1": { + Name: "svc-user", + Scheme: "http", + Address: "192.168.1.1", + }, + "192.168.1.2": { + Name: "svc-user", + Scheme: "http", + Address: "192.168.1.2", + }, + }) + assert.Equal(t, 2, len(res.nodeInfo)) + assert.True(t, reflect.DeepEqual(res.nodeInfo, map[string]*attributes.Attributes{ + "192.168.1.1": attributes.New(constant.KeyServiceInfo, server.ServiceInfo{ + Name: "svc-user", + Scheme: "http", + Address: "192.168.1.1", + }), + "192.168.1.2": attributes.New(constant.KeyServiceInfo, server.ServiceInfo{ + Name: "svc-user", + Scheme: "http", + Address: "192.168.1.2", + }), + })) + + res.tryUpdateAttrs(map[string]server.ServiceInfo{ + "192.168.1.1": { + Name: "svc-user", + Scheme: "http", + Address: "192.168.1.1", + }, + "192.168.1.2": { + Name: "svc-user", + Scheme: "http", + Address: "192.168.1.2", + }, + "192.168.1.3": { + Name: "svc-user", + Scheme: "http", + Address: "192.168.1.3", + }, + }) + + assert.Equal(t, 3, len(res.nodeInfo)) + assert.True(t, reflect.DeepEqual(res.nodeInfo, map[string]*attributes.Attributes{ + "192.168.1.1": attributes.New(constant.KeyServiceInfo, server.ServiceInfo{ + Name: "svc-user", + Scheme: "http", + Address: "192.168.1.1", + }), + "192.168.1.2": attributes.New(constant.KeyServiceInfo, server.ServiceInfo{ + Name: "svc-user", + Scheme: "http", + Address: "192.168.1.2", + }), + "192.168.1.3": attributes.New(constant.KeyServiceInfo, server.ServiceInfo{ + Name: "svc-user", + Scheme: "http", + Address: "192.168.1.3", + }), + })) + + res.tryUpdateAttrs(map[string]server.ServiceInfo{ + "192.168.1.1": { + Name: "svc-user", + Scheme: "http", + Address: "192.168.1.1", + }, + "192.168.1.3": { + Name: "svc-user", + Scheme: "http", + Address: "192.168.1.3", + }, + }) + + assert.Equal(t, 2, len(res.nodeInfo)) + assert.True(t, reflect.DeepEqual(res.nodeInfo, map[string]*attributes.Attributes{ + "192.168.1.1": attributes.New(constant.KeyServiceInfo, server.ServiceInfo{ + Name: "svc-user", + Scheme: "http", + Address: "192.168.1.1", + }), + "192.168.1.3": attributes.New(constant.KeyServiceInfo, server.ServiceInfo{ + Name: "svc-user", + Scheme: "http", + Address: "192.168.1.3", + }), + })) + +} diff --git a/client/ehttp/resolver/resolver_test.go b/client/ehttp/resolver/resolver_test.go new file mode 100644 index 00000000..26bef326 --- /dev/null +++ b/client/ehttp/resolver/resolver_test.go @@ -0,0 +1,83 @@ +package resolver + +import ( + "context" + "net/url" + "testing" + + "github.com/stretchr/testify/assert" + "google.golang.org/grpc/resolver" + + "github.com/gotomicro/ego/core/eregistry" + "github.com/gotomicro/ego/server" +) + +func TestResolver(t *testing.T) { + builder := &baseBuilder{ + name: "test", + reg: &testRegistry{ + t: t, + }, + } + assert.Equal(t, "test", builder.Scheme()) + addr := "test:///hello" + _, err := parseTarget(addr) + assert.NoError(t, err) + + resolve, err := builder.Build(addr) + assert.NoError(t, err) + resolve.GetAddr() +} + +func TestResolver_http(t *testing.T) { + var b = &baseHttpBuilder{} + addr := "test:///hello" + _, err := b.Build(addr) + assert.Equal(t, nil, err) + assert.Equal(t, "", b.Scheme()) + var b1 = &baseHttpResolver{} + assert.Equal(t, "", b1.GetAddr()) +} + +// parseTarget uses RFC 3986 semantics to parse the given target into a +// resolver.Target struct containing scheme, authority and endpoint. Query +// params are stripped from the endpoint. +func parseTarget(addr string) (resolver.Target, error) { + u, err := url.Parse(addr) + if err != nil { + return resolver.Target{}, err + } + return resolver.Target{ + URL: *u, + }, nil +} + +type testRegistry struct { + resolver.ClientConn + t *testing.T +} + +// ListServices ... +func (n testRegistry) ListServices(ctx context.Context, target eregistry.Target) ([]*server.ServiceInfo, error) { + return nil, nil +} + +// WatchServices ... +func (n testRegistry) WatchServices(ctx context.Context, target eregistry.Target) (chan eregistry.Endpoints, error) { + assert.Equal(n.t, "hello", target.Endpoint) + assert.Equal(n.t, "test", target.Scheme) + assert.Equal(n.t, "http", target.Protocol) + return nil, nil +} + +// RegisterService ... +func (n testRegistry) RegisterService(context.Context, *server.ServiceInfo) error { return nil } + +// UnregisterService ... +func (n testRegistry) UnregisterService(context.Context, *server.ServiceInfo) error { return nil } + +// SyncServices 同步所有服务 +func (n testRegistry) SyncServices(context.Context, eregistry.SyncServicesOptions) error { return nil } + +// Close ... +func (n testRegistry) Close() error { return nil } diff --git a/core/econf/api_test.go b/core/econf/api_test.go index 2a0bf296..4160f652 100644 --- a/core/econf/api_test.go +++ b/core/econf/api_test.go @@ -1,138 +1,19 @@ -package econf_test +package econf import ( - "io/ioutil" - "os" - "os/exec" - "path" - "runtime" - "sync" - "sync/atomic" "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/gotomicro/ego/core/econf" - _ "github.com/gotomicro/ego/core/econf/file" - "github.com/gotomicro/ego/core/econf/manager" ) -func TestWatchFile(t *testing.T) { - if runtime.GOOS == "linux" { - t.Skip("Skip test on Linux ...") - } - t.Run("file content changed", func(t *testing.T) { - // given a `config.yaml` file being watched - v, configFile, cleanup, wg := newWithConfigFile(t) - defer cleanup() - _, err := os.Stat(configFile) - require.NoError(t, err) - t.Logf("test config file: %s\n", configFile) - // when overwriting the file and waiting for the custom change notification handler to be triggered - err = ioutil.WriteFile(configFile, []byte("foo: baz\n"), 0640) - require.Nil(t, err) - wg.Wait() - // then the config value should have changed - assert.Equal(t, "baz", v.Get("foo")) - }) - - t.Run("link to real file changed (Kubernetes)", func(t *testing.T) { - // skip if not executed on Linux - if runtime.GOOS != "linux" { - t.Skipf("Skipping test as symlink replacements don't work on non-linux environment...") - } - - v, watchDir, _, _, wg := newWithSymlinkedConfigFile(t) - // defer cleanup() - // when link to another `config.yaml` file - dataDir2 := path.Join(watchDir, "data2") - err := os.Mkdir(dataDir2, 0777) - require.Nil(t, err) - configFile2 := path.Join(dataDir2, "config.yaml") - err = ioutil.WriteFile(configFile2, []byte("foo: baz\n"), 0640) - require.Nil(t, err) - // change the symlink using the `ln -sfn` command - err = exec.Command("ln", "-sfn", dataDir2, path.Join(watchDir, "data")).Run() - require.Nil(t, err) - wg.Wait() - // then - require.Nil(t, err) - assert.Equal(t, "baz", v.Get("foo")) - }) -} - -func newWithConfigFile(t *testing.T) (*econf.Configuration, string, func(), *sync.WaitGroup) { - watchDir, err := ioutil.TempDir("", "") - require.Nil(t, err) - configFile := path.Join(watchDir, "config.yaml") - err = ioutil.WriteFile(configFile, []byte("foo: bar\n"), 0640) - require.Nil(t, err) - cleanup := func() { - os.RemoveAll(watchDir) - } - v := econf.New() - provider, parser, tag, err := manager.NewDataSource(configFile, true) - assert.Nil(t, err) - - wg := &sync.WaitGroup{} - wg.Add(2) - var init int64 - v.OnChange(func(configuration *econf.Configuration) { - if atomic.CompareAndSwapInt64(&init, 0, 1) { - t.Logf("config init") - } else { - t.Logf("config file changed") - } - wg.Done() - }) - err = v.LoadFromDataSource(provider, parser, econf.WithTagName(tag)) - assert.Nil(t, err) - require.Equal(t, "bar", v.Get("foo")) - return v, configFile, cleanup, wg -} - -func newWithSymlinkedConfigFile(t *testing.T) (*econf.Configuration, string, string, func(), *sync.WaitGroup) { - watchDir, err := ioutil.TempDir("", "") - require.Nil(t, err) - dataDir1 := path.Join(watchDir, "data1") - err = os.Mkdir(dataDir1, 0777) - require.Nil(t, err) - realConfigFile := path.Join(dataDir1, "config.yaml") - t.Logf("Real config file location: %s\n", realConfigFile) - err = ioutil.WriteFile(realConfigFile, []byte("foo: bar\n"), 0640) - require.Nil(t, err) - cleanup := func() { - os.RemoveAll(watchDir) - } - // now, symlink the tm `data1` dir to `data` in the baseDir - err = os.Symlink(dataDir1, path.Join(watchDir, "data")) - require.Nil(t, err) - - // and link the `/datadir1/config.yaml` to `/config.yaml` - configFile := path.Join(watchDir, "config.yaml") - err = os.Symlink(path.Join(watchDir, "data", "config.yaml"), configFile) - require.Nil(t, err) - - t.Logf("Config file location: %s\n", path.Join(watchDir, "config.yaml")) - - v := econf.New() - provider, parser, tag, err := manager.NewDataSource(configFile, true) - require.Nil(t, err) - - wg := &sync.WaitGroup{} - wg.Add(2) - var init int64 - v.OnChange(func(configuration *econf.Configuration) { - if atomic.CompareAndSwapInt64(&init, 0, 1) { - t.Logf("config init") - } else { - t.Logf("config file changed") - } - wg.Done() - }) - err = v.LoadFromDataSource(provider, parser, econf.WithTagName(tag)) - require.Nil(t, err) - require.Equal(t, "bar", v.Get("foo")) - return v, watchDir, configFile, cleanup, wg +func TestApi(t *testing.T) { + fn := func(configuration *Configuration) {} + OnChange(fn) + Sub("") + Reset() + Traverse("") + RawConfig() + Debug("") + Get("") + assert.NoError(t, nil) } diff --git a/core/econf/conf.go b/core/econf/conf.go index c3a50b3e..b5055c48 100644 --- a/core/econf/conf.go +++ b/core/econf/conf.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "reflect" "strings" "sync" @@ -124,7 +123,7 @@ func (c *Configuration) Load(content []byte, unmarshal Unmarshaller) error { // LoadFromReader loads configuration from provided data source. func (c *Configuration) LoadFromReader(reader io.Reader, unmarshaller Unmarshaller) error { - content, err := ioutil.ReadAll(reader) + content, err := io.ReadAll(reader) if err != nil { return err } diff --git a/core/econf/conf_test.go b/core/econf/conf_test.go new file mode 100644 index 00000000..8269e0e1 --- /dev/null +++ b/core/econf/conf_test.go @@ -0,0 +1,163 @@ +package econf_test + +import ( + "io/ioutil" + "os" + "os/exec" + "path" + "runtime" + "sync" + "sync/atomic" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/gotomicro/ego/core/econf" + _ "github.com/gotomicro/ego/core/econf/file" + "github.com/gotomicro/ego/core/econf/manager" +) + +func TestWatchFile(t *testing.T) { + if runtime.GOOS == "linux" { + t.Skip("Skip test on Linux ...") + } + t.Run("file content changed", func(t *testing.T) { + // given a `config.yaml` file being watched + v, configFile, cleanup, wg := newWithConfigFile(t) + defer cleanup() + _, err := os.Stat(configFile) + require.NoError(t, err) + t.Logf("test config file: %s\n", configFile) + // when overwriting the file and waiting for the custom change notification handler to be triggered + err = ioutil.WriteFile(configFile, []byte("foo: baz\n"), 0640) + require.Nil(t, err) + wg.Wait() + // then the config value should have changed + assert.Equal(t, "baz", v.Get("foo")) + }) + + t.Run("link to real file changed (Kubernetes)", func(t *testing.T) { + // skip if not executed on Linux + if runtime.GOOS != "linux" { + t.Skipf("Skipping test as symlink replacements don't work on non-linux environment...") + } + + v, watchDir, _, _, wg := newWithSymlinkedConfigFile(t) + // defer cleanup() + // when link to another `config.yaml` file + dataDir2 := path.Join(watchDir, "data2") + err := os.Mkdir(dataDir2, 0777) + require.Nil(t, err) + configFile2 := path.Join(dataDir2, "config.yaml") + err = ioutil.WriteFile(configFile2, []byte("foo: baz\n"), 0640) + require.Nil(t, err) + // change the symlink using the `ln -sfn` command + err = exec.Command("ln", "-sfn", dataDir2, path.Join(watchDir, "data")).Run() + require.Nil(t, err) + wg.Wait() + // then + require.Nil(t, err) + assert.Equal(t, "baz", v.Get("foo")) + }) +} + +func newWithConfigFile(t *testing.T) (*econf.Configuration, string, func(), *sync.WaitGroup) { + watchDir, err := ioutil.TempDir("", "") + require.Nil(t, err) + configFile := path.Join(watchDir, "config.yaml") + err = ioutil.WriteFile(configFile, []byte("foo: bar\n"), 0640) + require.Nil(t, err) + cleanup := func() { + os.RemoveAll(watchDir) + } + v := econf.New() + provider, parser, tag, err := manager.NewDataSource(configFile, true) + assert.Nil(t, err) + + wg := &sync.WaitGroup{} + wg.Add(2) + var init int64 + v.OnChange(func(configuration *econf.Configuration) { + if atomic.CompareAndSwapInt64(&init, 0, 1) { + t.Logf("config init") + } else { + t.Logf("config file changed") + } + wg.Done() + }) + err = v.LoadFromDataSource(provider, parser, econf.WithTagName(tag)) + assert.Nil(t, err) + require.Equal(t, "bar", v.Get("foo")) + return v, configFile, cleanup, wg +} + +func newWithSymlinkedConfigFile(t *testing.T) (*econf.Configuration, string, string, func(), *sync.WaitGroup) { + watchDir, err := ioutil.TempDir("", "") + require.Nil(t, err) + dataDir1 := path.Join(watchDir, "data1") + err = os.Mkdir(dataDir1, 0777) + require.Nil(t, err) + realConfigFile := path.Join(dataDir1, "config.yaml") + t.Logf("Real config file location: %s\n", realConfigFile) + err = ioutil.WriteFile(realConfigFile, []byte("foo: bar\n"), 0640) + require.Nil(t, err) + cleanup := func() { + os.RemoveAll(watchDir) + } + // now, symlink the tm `data1` dir to `data` in the baseDir + err = os.Symlink(dataDir1, path.Join(watchDir, "data")) + require.Nil(t, err) + + // and link the `/datadir1/config.yaml` to `/config.yaml` + configFile := path.Join(watchDir, "config.yaml") + err = os.Symlink(path.Join(watchDir, "data", "config.yaml"), configFile) + require.Nil(t, err) + + t.Logf("Config file location: %s\n", path.Join(watchDir, "config.yaml")) + + v := econf.New() + provider, parser, tag, err := manager.NewDataSource(configFile, true) + require.Nil(t, err) + + wg := &sync.WaitGroup{} + wg.Add(2) + var init int64 + v.OnChange(func(configuration *econf.Configuration) { + if atomic.CompareAndSwapInt64(&init, 0, 1) { + t.Logf("config init") + } else { + t.Logf("config file changed") + } + wg.Done() + }) + err = v.LoadFromDataSource(provider, parser, econf.WithTagName(tag)) + require.Nil(t, err) + require.Equal(t, "bar", v.Get("foo")) + return v, watchDir, configFile, cleanup, wg +} + +func TestSetKeyDelim(t *testing.T) { + v := econf.New() + v.SetKeyDelim("") + assert.NoError(t, nil) + + err := v.WriteConfig() + assert.NoError(t, err) +} + +func TestGet(t *testing.T) { + econf.GetString("") + econf.GetInt("") + econf.GetInt64("") + econf.GetFloat64("") + econf.GetTime("") + econf.GetDuration("") + econf.GetStringSlice("") + econf.GetSlice("") + econf.GetStringMap("") + econf.GetStringMapString("") + econf.GetStringMapStringSlice("") + assert.NoError(t, nil) + assert.Equal(t, false, econf.GetBool("")) +} diff --git a/core/econf/container_test.go b/core/econf/container_test.go new file mode 100644 index 00000000..02c81c8f --- /dev/null +++ b/core/econf/container_test.go @@ -0,0 +1,18 @@ +package econf + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestContainer(t *testing.T) { + out1 := GetOptionTagName() + assert.Equal(t, "mapstructure", out1) + + out2 := GetOptionWeaklyTypedInput() + assert.Equal(t, false, out2) + + out3 := GetOptionSquash() + assert.Equal(t, false, out3) +} diff --git a/core/econf/file/conf_test/cfg.json b/core/econf/file/conf_test/cfg.json new file mode 100644 index 00000000..e69de29b diff --git a/core/econf/file/conf_test/conf.json b/core/econf/file/conf_test/conf.json new file mode 100644 index 00000000..04bcf6d8 --- /dev/null +++ b/core/econf/file/conf_test/conf.json @@ -0,0 +1,4 @@ +{ + "test1": "hello", + "test2": "world" +} \ No newline at end of file diff --git a/core/econf/file/conf_test/conf.toml b/core/econf/file/conf_test/conf.toml new file mode 100644 index 00000000..15780464 --- /dev/null +++ b/core/econf/file/conf_test/conf.toml @@ -0,0 +1,3 @@ +[test] +name1 = "hello" +name2 = "world" \ No newline at end of file diff --git a/core/econf/file/conf_test/conf.yaml b/core/econf/file/conf_test/conf.yaml new file mode 100644 index 00000000..7d497b75 --- /dev/null +++ b/core/econf/file/conf_test/conf.yaml @@ -0,0 +1,3 @@ +Test: + name1: "hello" + name2: "world" \ No newline at end of file diff --git a/core/econf/file/file.go b/core/econf/file/file.go index 234dec0a..7d85dc0e 100644 --- a/core/econf/file/file.go +++ b/core/econf/file/file.go @@ -1,12 +1,14 @@ package file import ( - "github.com/gotomicro/ego/core/constant" "log" "os" "path/filepath" + "github.com/gotomicro/ego/core/constant" + "github.com/fsnotify/fsnotify" + "github.com/gotomicro/ego/core/econf" "github.com/gotomicro/ego/core/econf/manager" "github.com/gotomicro/ego/core/elog" diff --git a/core/econf/file/file_test.go b/core/econf/file/file_test.go new file mode 100644 index 00000000..6f3f8d2b --- /dev/null +++ b/core/econf/file/file_test.go @@ -0,0 +1,67 @@ +package file + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/gotomicro/ego/core/econf" +) + +func TestParse(t *testing.T) { + cases := []struct { + in string + expected econf.ConfigType + }{ + {in: "./conf_test/conf.json", expected: "json"}, + {in: "./conf_test/conf.toml", expected: "toml"}, + {in: "./conf_test/conf.yaml", expected: "yaml"}, + {in: "./conf_test/cfg.json", expected: "json"}, + } + + for _, c := range cases { + fp := &fileDataSource{} + out := fp.Parse(c.in, true) + assert.Equal(t, c.expected, out) + } +} + +func TestReadConfig(t *testing.T) { + cases := []struct { + in string + expected []byte + }{ + {in: "./conf_test/conf.json", expected: []byte(`{ + "test1": "hello", + "test2": "world" +}`)}, + {in: "./conf_test/conf.toml", expected: []byte(`[test] +name1 = "hello" +name2 = "world"`)}, + {in: "./conf_test/conf.yaml", expected: []byte(`Test: + name1: "hello" + name2: "world"`)}, + {in: "./conf_test/cfg.json", expected: []byte(``)}, + } + + for _, c := range cases { + fp := &fileDataSource{path: c.in} + out, _ := fp.ReadConfig() + assert.Equal(t, c.expected, out) + } +} + +func TestClose(t *testing.T) { + c := make(chan struct{}) + fp := &fileDataSource{changed: c} + out := fp.Close() + assert.Equal(t, nil, out) +} + +func TestIsConfigChanged(t *testing.T) { + c := make(chan struct{}) + exp := (<-chan struct{})(c) + fp := &fileDataSource{changed: c} + out := fp.IsConfigChanged() + assert.Equal(t, exp, out) +} diff --git a/core/econf/manager/manager.go b/core/econf/manager/manager.go index d9eed663..607f31f4 100644 --- a/core/econf/manager/manager.go +++ b/core/econf/manager/manager.go @@ -7,8 +7,9 @@ import ( "os" "github.com/BurntSushi/toml" - "github.com/gotomicro/ego/core/econf" "gopkg.in/yaml.v3" + + "github.com/gotomicro/ego/core/econf" ) var defaultScheme = "file" diff --git a/core/econf/manager/manager_test.go b/core/econf/manager/manager_test.go new file mode 100644 index 00000000..14465df9 --- /dev/null +++ b/core/econf/manager/manager_test.go @@ -0,0 +1,80 @@ +package manager + +import ( + "reflect" + "testing" + + "github.com/gotomicro/ego/core/econf" +) + +var MyDataSource econf.DataSource + +func TestRegister(t *testing.T) { + type args struct { + scheme string + creator econf.DataSource + } + tests := []struct { + name string + args args + }{ + { + name: "test1", + args: args{defaultScheme, MyDataSource}, + }, + { + // TODO: more tests + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + Register(tt.args.scheme, tt.args.creator) + }) + } +} + +func TestNewDataSource(t *testing.T) { + type args struct { + configAddr string + watch bool + } + var u econf.Unmarshaller + tests := []struct { + name string + args args + want econf.DataSource + want1 econf.Unmarshaller + want2 econf.ConfigType + wantErr bool + }{ + { + name: "test", + args: args{"https://test.com/xxx", true}, + want: MyDataSource, + want1: u, + want2: "", + wantErr: false, + }, + { + // TODO: more tests + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, got1, got2, err := NewDataSource(tt.args.configAddr, tt.args.watch) + if (err != nil) == tt.wantErr { + t.Errorf("NewDataSource() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewDataSource() got = %v, want %v", got, tt.want) + } + if !reflect.DeepEqual(got1, tt.want1) { + t.Errorf("NewDataSource() got1 = %T, want %T", got1, tt.want1) + } + if got2 != tt.want2 { + t.Errorf("NewDataSource() got2 = %v, want %v", got2, tt.want2) + } + }) + } +} diff --git a/core/econf/options_test.go b/core/econf/options_test.go index 9fd07c2d..e472cceb 100644 --- a/core/econf/options_test.go +++ b/core/econf/options_test.go @@ -29,4 +29,9 @@ func TestWithTagName(t *testing.T) { require.Nil(t, err) assert.Equal(t, "yaml", econf.GetOptionTagName()) assert.Equal(t, true, econf.GetOptionWeaklyTypedInput()) + + err = v.LoadFromDataSource(provider, parser, econf.WithSquash(true)) + require.Nil(t, err) + econf.WithSquash(true) + assert.NoError(t, nil) } diff --git a/core/eerrors/errors.pb.go b/core/eerrors/errors.pb.go index 62f1678f..d1b9f840 100644 --- a/core/eerrors/errors.pb.go +++ b/core/eerrors/errors.pb.go @@ -7,10 +7,11 @@ package eerrors import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" + "reflect" + "sync" + + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/core/eerrors/errors_test.go b/core/eerrors/errors_test.go index 7ec21f2f..eb1cbedf 100644 --- a/core/eerrors/errors_test.go +++ b/core/eerrors/errors_test.go @@ -19,16 +19,37 @@ func TestRegister(t *testing.T) { errUnknown := New(int(codes.Unknown), "unknown", "unknown") Register(errUnknown) - // 一个新error,添加信息 - newErrUnknown := errUnknown.WithMessage("unknown something").WithMetadata(map[string]string{ + md := map[string]string{ "hello": "world", - }).(*EgoError) + } + + // 一个新error,添加信息 + newErrUnknown := errUnknown.WithMessage("unknown something").WithMetadata(md).(*EgoError) assert.Equal(t, "unknown something", newErrUnknown.GetMessage()) - assert.Equal(t, map[string]string{ - "hello": "world", - }, newErrUnknown.GetMetadata()) + assert.Equal(t, md, newErrUnknown.GetMetadata()) assert.ErrorIs(t, newErrUnknown, errUnknown) + + errUnknown.Error() + assert.NoError(t, nil) + errUnknown.GRPCStatus() + assert.NoError(t, nil) + errUnknown.WithMd(md) + assert.NoError(t, nil) + errUnknown.WithMsg("unknown") + assert.NoError(t, nil) + errUnknown.ToHTTPStatusCode() + assert.NoError(t, nil) + errUnknown.Reset() + assert.NoError(t, nil) + errUnknown.String() + assert.NoError(t, nil) + errUnknown.ProtoMessage() + assert.NoError(t, nil) + errUnknown.GetCode() + assert.NoError(t, nil) + errUnknown.GetReason() + assert.NoError(t, nil) } func TestIs(t *testing.T) { diff --git a/core/eflag/flag1_test.go b/core/eflag/flag1_test.go new file mode 100644 index 00000000..834dd517 --- /dev/null +++ b/core/eflag/flag1_test.go @@ -0,0 +1,99 @@ +package eflag + +import ( + "flag" + "os" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/gotomicro/ego/core/constant" +) + +func TestApply(t *testing.T) { + _ = os.Setenv(constant.EgoConfigPath, "config/env.toml") + defer os.Unsetenv(constant.EgoConfigPath) + resetFlagSet() + + Register(&Float64Flag{ + Name: "watch", + Usage: "--watch", + Default: 222, + EnvVar: constant.EgoConfigPath, + Action: func(name string, fs *FlagSet) {}, + }) + _ = Parse() + _ = flag.Set("config", ConfigFlagToml) + + err := ParseWithArgs([]string{"--watch-false"}) + assert.NoError(t, err) + + Float64("watch") + assert.NoError(t, nil) + _, err1 := Float64E("watch") + assert.NoError(t, err1) + +} + +func TestInt(t *testing.T) { + _ = os.Setenv(constant.EgoConfigPath, "config/env.toml") + defer os.Unsetenv(constant.EgoConfigPath) + resetFlagSet() + Register(&IntFlag{ + Name: "watch", + Usage: "--watch", + Default: 222, + EnvVar: constant.EgoConfigPath, + Action: func(name string, fs *FlagSet) {}, + }) + _ = Parse() + _ = flag.Set("config", ConfigFlagToml) + err := ParseWithArgs([]string{"--watch-false"}) + assert.NoError(t, err) + Int("watch") + assert.NoError(t, nil) + _, err1 := IntE("watch") + assert.NoError(t, err1) +} + +func TestUint(t *testing.T) { + _ = os.Setenv(constant.EgoConfigPath, "config/env.toml") + defer os.Unsetenv(constant.EgoConfigPath) + resetFlagSet() + Register(&UintFlag{ + Name: "watch", + Usage: "--watch", + Default: 222, + EnvVar: constant.EgoConfigPath, + Action: func(name string, fs *FlagSet) {}, + }) + _ = Parse() + _ = flag.Set("config", ConfigFlagToml) + err := ParseWithArgs([]string{"--watch-false"}) + assert.NoError(t, err) + Uint("watch") + assert.NoError(t, nil) + _, err1 := UintE("watch") + assert.NoError(t, err1) +} + +func TestString(t *testing.T) { + _ = os.Setenv(constant.EgoConfigPath, "config/env.toml") + defer os.Unsetenv(constant.EgoConfigPath) + resetFlagSet() + Register(&StringFlag{ + Name: "watch", + Usage: "--watch", + Default: "test", + EnvVar: constant.EgoConfigPath, + Action: func(name string, fs *FlagSet) {}, + }) + _ = Parse() + _ = flag.Set("config", ConfigFlagToml) + err := ParseWithArgs([]string{"--watch-false"}) + assert.NoError(t, err) + String("watch") + assert.NoError(t, nil) + _, err1 := StringE("watch") + assert.NoError(t, err1) +} diff --git a/core/elog/elog_api_test.go b/core/elog/elog_api_test.go new file mode 100644 index 00000000..e047da4c --- /dev/null +++ b/core/elog/elog_api_test.go @@ -0,0 +1,30 @@ +package elog + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "go.uber.org/zap" +) + +func TestElogAPI(t *testing.T) { + f := zap.Field{ + Key: "test", + Type: 9, + Integer: 11, + String: "test", + Interface: nil, + } + Info("", f) + assert.NoError(t, nil) + + Debug("", f) + assert.NoError(t, nil) + + Warn("", f) + assert.NoError(t, nil) + + Error("", f) + assert.NoError(t, nil) + +} diff --git a/core/elog/elog_field.go b/core/elog/elog_field.go index 09002afa..1f152f6a 100644 --- a/core/elog/elog_field.go +++ b/core/elog/elog_field.go @@ -5,8 +5,9 @@ import ( "strings" "time" - "github.com/gotomicro/ego/core/etrace" "go.uber.org/zap" + + "github.com/gotomicro/ego/core/etrace" ) // FieldComponent constructs an elog Field with component type name diff --git a/core/elog/elog_field_test.go b/core/elog/elog_field_test.go index a4919079..0526e411 100644 --- a/core/elog/elog_field_test.go +++ b/core/elog/elog_field_test.go @@ -1,6 +1,7 @@ package elog import ( + "context" "reflect" "testing" @@ -34,7 +35,70 @@ func TestFieldComponentName(t *testing.T) { assert.True(t, reflect.DeepEqual(value, FieldComponentName("ego"))) } -// func TestFieldCost(t *testing.T) { -// value := zap.Field{Key: "compName", Type: zapcore.Float64Type, Integer: int64(math.Float64bits(0.16))} -// assert.True(t, reflect.DeepEqual(value, FieldCost(0.16))) -// } +func TestFieldCost(t *testing.T) { + FieldCost(111) + assert.NoError(t, nil) +} + +func TestFieldKey(t *testing.T) { + FieldKey("hello") + assert.NoError(t, nil) + + FieldName("test") + assert.NoError(t, nil) + + FieldType("type") + assert.NoError(t, nil) + + FieldKind("kind") + assert.NoError(t, nil) + + FieldUniformCode(11) + assert.NoError(t, nil) + + FieldTid("tid") + assert.NoError(t, nil) + + ctx := context.Background() + FieldCtxTid(ctx) + assert.NoError(t, nil) + + FieldSize(11) + assert.NoError(t, nil) + + FieldValue("") + assert.NoError(t, nil) + + FieldValueAny("") + assert.NoError(t, nil) + + FieldErrKind("") + assert.NoError(t, nil) + + FieldErr(nil) + assert.NoError(t, nil) + + FieldErrAny(nil) + assert.NoError(t, nil) + + FieldMethod("") + assert.NoError(t, nil) + + FieldEvent("") + assert.NoError(t, nil) + + FieldIP("") + assert.NoError(t, nil) + + FieldPeerIP("") + assert.NoError(t, nil) + + FieldPeerName("") + assert.NoError(t, nil) + + FieldCustomKeyValue("hello", "world") + assert.NoError(t, nil) + + FieldLogName("") + assert.NoError(t, nil) +} diff --git a/core/emetric/counter_test.go b/core/emetric/counter_test.go new file mode 100644 index 00000000..1d9a9f35 --- /dev/null +++ b/core/emetric/counter_test.go @@ -0,0 +1,14 @@ +package emetric + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNewCounterVec(t *testing.T) { + name := "test" + labels := []string{"test"} + NewCounterVec(name, labels) + assert.NoError(t, nil) +} diff --git a/core/emetric/gauge_test.go b/core/emetric/gauge_test.go new file mode 100644 index 00000000..1b617c51 --- /dev/null +++ b/core/emetric/gauge_test.go @@ -0,0 +1,14 @@ +package emetric + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNewGaugeVec(t *testing.T) { + name := "test_" + labels := []string{"hello_", "world_"} + NewGaugeVec(name, labels) + assert.NoError(t, nil) +} diff --git a/core/eregistry/endpoint_test.go b/core/eregistry/endpoint_test.go index 8bd6fed9..b588890c 100644 --- a/core/eregistry/endpoint_test.go +++ b/core/eregistry/endpoint_test.go @@ -4,14 +4,19 @@ import ( "reflect" "testing" - "github.com/gotomicro/ego/server" "github.com/stretchr/testify/assert" + + "github.com/gotomicro/ego/server" ) func TestEndpoints_DeepCopy(t *testing.T) { in := newEndpoints() + if in == nil { + return + } in.DeepCopy() - assert.True(t, reflect.DeepEqual(in, in.DeepCopy())) + // assert.True(t, reflect.DeepEqual(in, in.DeepCopy())) + assert.Equal(t, in, in.DeepCopy()) var in2 *Endpoints assert.Nil(t, in2.DeepCopy()) @@ -20,8 +25,21 @@ func TestEndpoints_DeepCopy(t *testing.T) { func TestEndpoints_DeepCopyInfo(t *testing.T) { in := newEndpoints() out := newEndpoints() + for key, info := range in.Nodes { + out.Nodes[key] = info + } + for key, config := range in.RouteConfigs { + out.RouteConfigs[key] = config + } + for key, config := range in.ConsumerConfigs { + out.ConsumerConfigs[key] = config + } + for key, config := range in.ProviderConfigs { + out.ProviderConfigs[key] = config + } in.deepCopyInfo(out) - assert.True(t, reflect.DeepEqual(in, out)) + // assert.True(t, reflect.DeepEqual(in, out)) + assert.Equal(t, in, out) } func Test_newEndpoints(t *testing.T) { diff --git a/core/esentinel/component.go b/core/esentinel/component.go index a98ff56c..c1819f5e 100644 --- a/core/esentinel/component.go +++ b/core/esentinel/component.go @@ -10,6 +10,7 @@ import ( sentinelconfig "github.com/alibaba/sentinel-golang/core/config" "github.com/alibaba/sentinel-golang/core/flow" "github.com/fsnotify/fsnotify" + "github.com/gotomicro/ego/core/elog" ) diff --git a/core/esentinel/component_test.go b/core/esentinel/component_test.go new file mode 100644 index 00000000..88033f67 --- /dev/null +++ b/core/esentinel/component_test.go @@ -0,0 +1,28 @@ +package esentinel + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/gotomicro/ego/core/elog" +) + +var logger = &elog.Component{} + +func TestNewComponent(t *testing.T) { + conf := &Config{} + newComponent(conf, logger) + assert.NoError(t, nil) +} + +func TestSyncFlowRules(t *testing.T) { + filePath := "./config_test/sentinel.json" + err := syncFlowRules(filePath, logger) + assert.NoError(t, err) +} + +func TestIsResMap(t *testing.T) { + res := "test" + assert.Equal(t, false, IsResExist(res)) +} diff --git a/core/esentinel/config_test.go b/core/esentinel/config_test.go new file mode 100644 index 00000000..5f5aef4b --- /dev/null +++ b/core/esentinel/config_test.go @@ -0,0 +1,13 @@ +package esentinel + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDefaultConfig(t *testing.T) { + c := DefaultConfig() + assert.Equal(t, "./logs", c.LogPath) + assert.Equal(t, "", c.FlowRulesFile) +} diff --git a/core/esentinel/config_test/sentinel.json b/core/esentinel/config_test/sentinel.json new file mode 100644 index 00000000..8b94607f --- /dev/null +++ b/core/esentinel/config_test/sentinel.json @@ -0,0 +1,8 @@ +[ + { + "resource": "/helloworld.Greeter/SayHello", + "threshold": 2, + "tokenCalculateStrategy": 0, + "controlBehavior": 0 + } +] \ No newline at end of file diff --git a/core/esentinel/config_test/test.toml b/core/esentinel/config_test/test.toml new file mode 100644 index 00000000..db8f9b4e --- /dev/null +++ b/core/esentinel/config_test/test.toml @@ -0,0 +1,9 @@ +[server.grpc] +port = 9202 +enableAccessInterceptorReq = true +enableAccessInterceptorRes = true +enableSentinel = true +[server.governor] +port = 9003 +[sentinel] +flowRulesFile = "./config_test/sentinel.json" \ No newline at end of file diff --git a/core/esentinel/container_test.go b/core/esentinel/container_test.go new file mode 100644 index 00000000..d3c4e993 --- /dev/null +++ b/core/esentinel/container_test.go @@ -0,0 +1,32 @@ +package esentinel + +import ( + "strings" + "testing" + + "github.com/BurntSushi/toml" + "github.com/stretchr/testify/assert" + + "github.com/gotomicro/ego/core/econf" + "github.com/gotomicro/ego/core/elog" +) + +func TestDefaultContainer(t *testing.T) { + in := &Container{ + config: DefaultConfig(), + logger: elog.EgoLogger.With(elog.FieldComponent(PackageName)), + } + out := DefaultContainer() + assert.Equal(t, in, out) +} + +func TestLoad(t *testing.T) { + conf := ` +[test] +addr = ":9091" +` + err := econf.LoadFromReader(strings.NewReader(conf), toml.Unmarshal) + assert.NoError(t, err) + Load("test").Build() + assert.NoError(t, nil) +} diff --git a/core/etrace/compatible_test.go b/core/etrace/compatible_test.go new file mode 100644 index 00000000..36a5857d --- /dev/null +++ b/core/etrace/compatible_test.go @@ -0,0 +1,23 @@ +package etrace + +import ( + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "google.golang.org/grpc/metadata" +) + +func TestCompatibleExtractHTTPTraceID(t *testing.T) { + header := make(http.Header) + header.Set("X-Trace-Id", "111222") + CompatibleExtractHTTPTraceID(header) + var tp = header.Get("X-Trace-Id") + assert.Equal(t, "111222", tp) +} + +func TestCompatibleExtractGrpcTraceID(t *testing.T) { + header := make(metadata.MD) + CompatibleExtractGrpcTraceID(header) + assert.NoError(t, nil) +} diff --git a/core/etrace/otel/config.go b/core/etrace/otel/config.go index 18bfc69d..07c43a21 100644 --- a/core/etrace/otel/config.go +++ b/core/etrace/otel/config.go @@ -140,7 +140,7 @@ func (config *Config) buildJaegerTP() trace.TracerProvider { tracesdk.WithSampler(tracesdk.ParentBased(tracesdk.TraceIDRatioBased(config.Fraction))), // Always be sure to batch in production. tracesdk.WithBatcher(exp), - // Record information about this application in an Resource. + // Record information about this application in a Resource. tracesdk.WithResource(resource.NewSchemaless( semconv.ServiceNameKey.String(config.ServiceName), )), @@ -193,7 +193,7 @@ func (config *Config) buildOtlpTP() trace.TracerProvider { tracesdk.WithSampler(tracesdk.ParentBased(tracesdk.TraceIDRatioBased(config.Fraction))), // WithSpanProcessor registers the SpanProcessor with a TracerProvider. tracesdk.WithSpanProcessor(tracesdk.NewBatchSpanProcessor(traceExp)), - // Record information about this application in an Resource. + // Record information about this application in a Resource. tracesdk.WithResource(res), } tpOptions = append(tpOptions, config.options...) diff --git a/core/etrace/otel/config_test.go b/core/etrace/otel/config_test.go new file mode 100644 index 00000000..220a2fa4 --- /dev/null +++ b/core/etrace/otel/config_test.go @@ -0,0 +1,17 @@ +package otel + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBuildOtlpTP(t *testing.T) { + Load("").Build() + assert.NoError(t, nil) + c := DefaultConfig() + c.buildJaegerTP() + assert.NoError(t, nil) + err := c.Stop() + assert.NoError(t, err) +} diff --git a/core/etrace/trace.go b/core/etrace/trace.go index dd4414db..5b22828f 100644 --- a/core/etrace/trace.go +++ b/core/etrace/trace.go @@ -64,7 +64,7 @@ func NewTracer(kind trace.SpanKind, opts ...Option) *Tracer { return &Tracer{tracer: otel.Tracer("ego"), kind: kind, opt: &op} } -// Start start tracing span +// Start tracing span func (t *Tracer) Start(ctx context.Context, operation string, carrier propagation.TextMapCarrier, opts ...trace.SpanStartOption) (context.Context, trace.Span) { if (t.kind == trace.SpanKindServer || t.kind == trace.SpanKindConsumer) && carrier != nil { ctx = t.opt.propagator.Extract(ctx, carrier) diff --git a/core/etrace/trace_test.go b/core/etrace/trace_test.go new file mode 100644 index 00000000..0dee43c8 --- /dev/null +++ b/core/etrace/trace_test.go @@ -0,0 +1,16 @@ +package etrace + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestIsGlobalTracerRegistered(t *testing.T) { + assert.True(t, true, IsGlobalTracerRegistered()) +} + +func TestCustomTag2(t *testing.T) { + CustomTag("hello", "world") + assert.NoError(t, nil) +} diff --git a/core/transport/grpc_transport_test.go b/core/transport/grpc_transport_test.go new file mode 100644 index 00000000..a8db68e9 --- /dev/null +++ b/core/transport/grpc_transport_test.go @@ -0,0 +1,24 @@ +package transport + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +var mc = &GrpcHeaderCarrier{} + +func TestGet(t *testing.T) { + key := "test" + assert.Equal(t, "", mc.Get(key)) +} + +func TestSet(t *testing.T) { + mc.Set("hello", "world") + assert.Nil(t, nil) +} + +func TestKeys(t *testing.T) { + out := mc.Keys() + assert.Equal(t, []string{"hello"}, out) +} diff --git a/core/transport/transport_test.go b/core/transport/transport_test.go index 42fd0018..378d3da7 100644 --- a/core/transport/transport_test.go +++ b/core/transport/transport_test.go @@ -21,18 +21,6 @@ func TestValue(t *testing.T) { ctx = WithValue(ctx, "X-EGO-Test", "hello") val := ctx.Value("X-EGO-Test") assert.Equal(t, "hello", val) -} - -//func Test_newContextKey(t *testing.T) { -// key := newContextKey("hello") -// assert.Equal(t, "ego context value hello", key.String()) -//} - -func TestWithValue(t *testing.T) { - Set([]string{"X-EGO-Test"}) - ctx := context.Background() - ctx = WithValue(ctx, "X-EGO-Test", "hello1") - ctx = WithValue(ctx, "X-EGO-Test", "hello2") - val := ctx.Value("X-EGO-Test") - assert.Equal(t, "hello1", val) + Value(ctx, "test") + assert.NoError(t, nil) } diff --git a/core/util/xdebug/print_test.go b/core/util/xdebug/print_test.go index 6b505128..176ed24a 100644 --- a/core/util/xdebug/print_test.go +++ b/core/util/xdebug/print_test.go @@ -3,15 +3,57 @@ package xdebug import ( "testing" "time" + + "github.com/stretchr/testify/assert" ) -func TestMakeReqAndResError(t *testing.T) { +func TestMakeReqResInfo(t *testing.T) { + compName := "TestComponent" + addr := "test.address.com" + cost := 150 * time.Millisecond + req := "test request" + reply := "test reply" + MakeReqResInfo(compName, addr, cost, req, reply) + assert.NoError(t, nil) +} + +func TestMakeReqResError(t *testing.T) { + compName := "Test" + addr := "test" + cost := 150 * time.Millisecond + req := "test" + err := "test" + MakeReqResError(compName, addr, cost, req, err) + assert.NoError(t, nil) +} + +func TestMakeReqResErrorV2(t *testing.T) { + compName := "Test" + addr := "test" + cost := 150 * time.Millisecond + req := "test" + MakeReqResErrorV2(11, compName, addr, cost, req, "") + assert.NoError(t, nil) +} - err := MakeReqAndResError("test", "test", "test", time.Until(time.Now()), "test", "test") - t.Log(err) +func TestMakeReqAndResError(t *testing.T) { + line := "test" + compName := "Test" + addr := "test" + cost := 150 * time.Millisecond + req := "test" + err := "test" + MakeReqAndResError(line, compName, addr, cost, req, err) + assert.NoError(t, nil) } func TestMakeReqAndResInfo(t *testing.T) { - err := MakeReqAndResInfo("test", "test", "test", time.Until(time.Now()), "test", "test") - t.Log(err) + line := "test" + compName := "Test" + addr := "test" + cost := 150 * time.Millisecond + req := "test" + reply := "test" + MakeReqAndResInfo(line, compName, addr, cost, req, reply) + assert.NoError(t, nil) } diff --git a/core/util/xstring/function_test.go b/core/util/xstring/function_test.go index 66e30149..ac098894 100644 --- a/core/util/xstring/function_test.go +++ b/core/util/xstring/function_test.go @@ -12,6 +12,11 @@ func TestFunctionName(t *testing.T) { want string }{ // TODO: Add test cases. + { + name: "case1", + args: args{i: TestFunctionName}, + want: "github.com/gotomicro/ego/core/util/xstring.TestFunctionName", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -32,6 +37,11 @@ func TestObjectName(t *testing.T) { want string }{ // TODO: Add test cases. + { + name: "", + args: args{i: TestObjectName}, + want: ".", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -52,6 +62,11 @@ func TestCallerName(t *testing.T) { want string }{ // TODO: Add test cases. + { + name: "", + args: args{skip: 0}, + want: "github.com/gotomicro/ego/core/util/xstring.CallerName", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/internal/egrpcinteceptor/inteceptor_test.go b/internal/egrpcinteceptor/inteceptor_test.go new file mode 100644 index 00000000..490f90e7 --- /dev/null +++ b/internal/egrpcinteceptor/inteceptor_test.go @@ -0,0 +1,22 @@ +package egrpcinteceptor + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" +) + +var ctx context.Context +var m = messageType{} + +func TestEvent(t *testing.T) { + m.Event(ctx, 111, "") + assert.NoError(t, nil) +} + +func TestSplitMethodName(t *testing.T) { + f := "GET/https://test.com/xxx" + SplitMethodName(f) + assert.NoError(t, nil) +} diff --git a/internal/egrpclog/gopclog_test.go b/internal/egrpclog/gopclog_test.go new file mode 100644 index 00000000..13ef4ce8 --- /dev/null +++ b/internal/egrpclog/gopclog_test.go @@ -0,0 +1,12 @@ +package egrpclog + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBuild(t *testing.T) { + Build() + assert.NoError(t, nil) +} diff --git a/internal/util/map_test.go b/internal/util/map_test.go index 4b456a75..4b0156f3 100644 --- a/internal/util/map_test.go +++ b/internal/util/map_test.go @@ -146,3 +146,62 @@ func TestToMapStringInterface(t *testing.T) { }) } } + +func TestDeepSearchInMap1(t *testing.T) { + type args struct { + m map[string]interface{} + paths []string + } + tests := []struct { + name string + args args + want map[string]interface{} + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := DeepSearchInMap(tt.args.m, tt.args.paths...); !reflect.DeepEqual(got, tt.want) { + t.Errorf("DeepSearchInMap() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestMergeStringMap1(t *testing.T) { + type args struct { + dest map[string]interface{} + src map[string]interface{} + } + tests := []struct { + name string + args args + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + MergeStringMap(tt.args.dest, tt.args.src) + }) + } +} + +func TestToMapStringInterface1(t *testing.T) { + type args struct { + src map[interface{}]interface{} + } + tests := []struct { + name string + args args + want map[string]interface{} + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := ToMapStringInterface(tt.args.src); !reflect.DeepEqual(got, tt.want) { + t.Errorf("ToMapStringInterface() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/server/egin/component_test.go b/server/egin/component_test.go index 3054dd17..24a37927 100644 --- a/server/egin/component_test.go +++ b/server/egin/component_test.go @@ -181,7 +181,7 @@ func TestServerReadTimeout(t *testing.T) { }() time.Sleep(1 * time.Second) - // Slow client that should timeout. + // Slow client that should time out. t1 := time.Now() conn, err := net.Dial("tcp", cmp.Listener().Addr().String()) assert.Nil(t, err) @@ -235,7 +235,7 @@ func TestContextTimeout(t *testing.T) { }() time.Sleep(1 * time.Second) - // Slow client that should timeout. + // Slow client that should time out. t1 := time.Now() err := eginClient(context.Background(), cmp, "/test") assert.Nil(t, err) @@ -283,7 +283,7 @@ func testServerTimeouts(timeout time.Duration) error { string(got), err, expected) } - // Slow client that should timeout. + // Slow client that should time out. t1 := time.Now() conn, err := net.Dial("tcp", ts.Listener.Addr().String()) if err != nil { diff --git a/server/egin/component_websocket_test.go b/server/egin/component_websocket_test.go new file mode 100644 index 00000000..0532143e --- /dev/null +++ b/server/egin/component_websocket_test.go @@ -0,0 +1,91 @@ +package egin + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/fasthttp/websocket" + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" +) + +// simpleBufferPool is an implementation of BufferPool for TestWriteBufferPool. +type simpleBufferPool struct { + v interface{} +} + +func (p *simpleBufferPool) Get() interface{} { + v := p.v + p.v = nil + return v +} + +func (p *simpleBufferPool) Put(v interface{}) { + p.v = v +} + +func TestUpgrade(t *testing.T) { + c := DefaultContainer().Build() + ws := &WebSocket{} + handler := func(conn *WebSocketConn, err error) {} + c.Upgrade("test", ws, handler) + assert.NoError(t, nil) +} + +func TestBuildWebsocket(t *testing.T) { + opt := func(ws *WebSocket) { + ws.Upgrader = &websocket.Upgrader{ + HandshakeTimeout: 3, + ReadBufferSize: 1024, + WriteBufferSize: 1024, + WriteBufferPool: &simpleBufferPool{}, + CheckOrigin: func(r *http.Request) bool { + return true + }, + Subprotocols: make([]string, 0), + Error: nil, + EnableCompression: true} + } + c := DefaultContainer().Build() // 设置config + c.BuildWebsocket(opt) + assert.NoError(t, nil) + + err := c.Prepare() + assert.Equal(t, nil, err) + + h := c.Health() + assert.Equal(t, false, h) + + c.HTTPEmbedFs() + assert.NoError(t, nil) + + c.GetEmbedWrapper() + assert.NoError(t, nil) + + e := &EmbedWrapper{} + e.Open("test") + assert.NoError(t, nil) +} + +func TestWebSocket_Upgrade(t *testing.T) { + ws := &WebSocket{ + &websocket.Upgrader{ + HandshakeTimeout: 3, + ReadBufferSize: 1024, + WriteBufferSize: 1024, + WriteBufferPool: &simpleBufferPool{}, + CheckOrigin: func(r *http.Request) bool { + return true + }, + Subprotocols: make([]string, 0), + Error: nil, + EnableCompression: true}, + } + w := httptest.NewRecorder() + r := &http.Request{} + c := &gin.Context{} + handler := func(conn *WebSocketConn, err error) {} + ws.Upgrade(w, r, c, handler) + assert.NoError(t, nil) +} diff --git a/server/egin/config_test.go b/server/egin/config_test.go new file mode 100644 index 00000000..3b2a8a38 --- /dev/null +++ b/server/egin/config_test.go @@ -0,0 +1,82 @@ +package egin + +import ( + "crypto/tls" + "fmt" + "net/http" + "net/http/httptest" + "testing" + + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" + + "github.com/gotomicro/ego/core/util/xtime" +) + +func TestDefaultConfig(t *testing.T) { + in := &Config{ + // Host: eflag.String("host"), + Port: 9090, + Mode: gin.ReleaseMode, + Network: "tcp", + EnableAccessInterceptor: true, + EnableTraceInterceptor: true, + EnableMetricInterceptor: true, + EnableSentinel: true, + SlowLogThreshold: xtime.Duration("500ms"), + EnableWebsocketCheckOrigin: false, + TrustedPlatform: "", + recoveryFunc: defaultRecoveryFunc, + } + out := DefaultConfig() + assert.Equal(t, in.Port, out.Port) + assert.Equal(t, in.Mode, out.Mode) + assert.Equal(t, in.Network, out.Network) + assert.Equal(t, in.EnableAccessInterceptor, out.EnableAccessInterceptor) + assert.Equal(t, in.EnableTraceInterceptor, out.EnableTraceInterceptor) + assert.Equal(t, in.EnableMetricInterceptor, out.EnableMetricInterceptor) + assert.Equal(t, in.EnableSentinel, out.EnableSentinel) + assert.Equal(t, in.SlowLogThreshold, out.SlowLogThreshold) + assert.Equal(t, in.EnableWebsocketCheckOrigin, out.EnableWebsocketCheckOrigin) + assert.Equal(t, in.TrustedPlatform, out.TrustedPlatform) +} + +func TestAddress(t *testing.T) { + config := Config{ + Host: PackageName, + Port: 9090, + } + out := config.Address() + assert.Equal(t, "server.egin:9090", out) +} + +func TestClientAuthType(t *testing.T) { + config := &Config{TLSClientAuth: "RequireAnyClientCert"} + assert.Equal(t, tls.RequireAnyClientCert, config.ClientAuthType()) + + config.TLSClientAuth = "RequestClientCert" + assert.Equal(t, tls.RequestClientCert, config.ClientAuthType()) + + config.TLSClientAuth = "VerifyClientCertIfGiven" + assert.Equal(t, tls.VerifyClientCertIfGiven, config.ClientAuthType()) + + config.TLSClientAuth = "RequireAndVerifyClientCert" + assert.Equal(t, tls.RequireAndVerifyClientCert, config.ClientAuthType()) + + config.TLSClientAuth = "NoClientCert" + assert.Equal(t, tls.NoClientCert, config.ClientAuthType()) +} + +func TestDefaultRecoveryFunc(t *testing.T) { + gin.SetMode(gin.TestMode) + router := gin.New() + router.GET("/test", func(c *gin.Context) { + c.AbortWithStatus(http.StatusInternalServerError) + }) + req, err := http.NewRequest("GET", "/test", nil) + assert.NoError(t, err) + w := httptest.NewRecorder() + router.ServeHTTP(w, req) + fmt.Printf("w.Code: %v\n", w.Code) + assert.Equal(t, http.StatusInternalServerError, w.Code) +} diff --git a/server/egin/container_test.go b/server/egin/container_test.go new file mode 100644 index 00000000..d206095d --- /dev/null +++ b/server/egin/container_test.go @@ -0,0 +1,12 @@ +package egin + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestLoad2(t *testing.T) { + Load("").Build() + assert.NoError(t, nil) +} diff --git a/server/egin/grpc_proxy_test.go b/server/egin/grpc_proxy_test.go index b6708aa4..981d2fcf 100644 --- a/server/egin/grpc_proxy_test.go +++ b/server/egin/grpc_proxy_test.go @@ -5,8 +5,9 @@ import ( "testing" "github.com/gin-gonic/gin" - "github.com/gotomicro/ego/examples/helloworld" "github.com/stretchr/testify/assert" + + "github.com/gotomicro/ego/examples/helloworld" ) type GreeterMock struct{} diff --git a/server/egin/interceptor_gzip.go b/server/egin/interceptor_gzip.go index 07f2aeaa..4b94c2f2 100644 --- a/server/egin/interceptor_gzip.go +++ b/server/egin/interceptor_gzip.go @@ -39,7 +39,7 @@ func (g *gzipWriter) Write(data []byte) (int, error) { return g.writer.Write(data) } -// Fix: https://github.com/mholt/caddy/issues/38 +// WriteHeader Fix: https://github.com/mholt/caddy/issues/38 func (g *gzipWriter) WriteHeader(code int) { g.Header().Del("Content-Length") g.ResponseWriter.WriteHeader(code) diff --git a/server/egin/interceptor_gzip_test.go b/server/egin/interceptor_gzip_test.go new file mode 100644 index 00000000..71678121 --- /dev/null +++ b/server/egin/interceptor_gzip_test.go @@ -0,0 +1,47 @@ +package egin + +import ( + "testing" + + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" +) + +func TestGzip(t *testing.T) { + opts := func(options *GzipOptions) {} + Gzip(3, opts) + assert.NoError(t, nil) + + newGzipHandler(3, opts) + assert.NoError(t, nil) +} + +func TestWithGzipExcludedExtensions(t *testing.T) { + a := []string{"hello", "world"} + WithGzipExcludedExtensions(a) + WithGzipExcludedPaths(a) + WithGzipExcludedPathsRegexs(a) + NewExcludedPaths(a) + NewExcludedPathesRegexs(a) + assert.NoError(t, nil) +} + +func TestWithGzipDecompressFn(t *testing.T) { + d := func(c *gin.Context) {} + WithGzipDecompressFn(d) + assert.NoError(t, nil) +} + +func TestContains(t *testing.T) { + var e = ExcludedPathesRegexs{} + out := e.Contains("") + assert.Equal(t, false, out) + + var ee = ExcludedPaths{} + out1 := ee.Contains("") + assert.Equal(t, false, out1) + + var a = ExcludedExtensions{} + out2 := a.Contains("") + assert.Equal(t, false, out2) +} diff --git a/server/egovernor/component_test.go b/server/egovernor/component_test.go new file mode 100644 index 00000000..0912bd40 --- /dev/null +++ b/server/egovernor/component_test.go @@ -0,0 +1,43 @@ +package egovernor + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/gotomicro/ego/core/constant" + "github.com/gotomicro/ego/core/elog" +) + +func TestComponent(t *testing.T) { + cfg := Config{ + Host: "0.0.0.0", + Port: 9001, + Network: "tcp4", + } + c := newComponent("test", &cfg, elog.DefaultLogger) + assert.Equal(t, "test", c.Name()) + assert.Equal(t, PackageName, c.PackageName()) + assert.NoError(t, c.Init()) + + info := c.Info() + assert.NotEmpty(t, info.Name) + assert.Equal(t, "http", info.Scheme) + assert.Equal(t, "0.0.0.0:9001", info.Address) + assert.Equal(t, constant.ServiceGovernor, info.Kind) + + go func() { + assert.NoError(t, c.Start()) + }() + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + <-ctx.Done() + assert.NoError(t, c.Stop()) + assert.NoError(t, c.GracefulStop(context.Background())) + + t.Log("done") +} diff --git a/server/egovernor/config_test.go b/server/egovernor/config_test.go new file mode 100644 index 00000000..9006d4b7 --- /dev/null +++ b/server/egovernor/config_test.go @@ -0,0 +1,25 @@ +package egovernor + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/gotomicro/ego/core/eflag" +) + +func TestDefaultConfig(t *testing.T) { + in := &Config{ + Host: eflag.String("host"), + Network: "tcp4", + Port: 9003, + } + out := DefaultConfig() + assert.Equal(t, in, out) +} + +func TestAddress(t *testing.T) { + config := Config{Host: "hello", Port: 111, EnableLocalMainIP: true, Network: "tcp4"} + out := config.Address() + assert.Equal(t, "hello:111", out) +} diff --git a/server/egovernor/container_test.go b/server/egovernor/container_test.go new file mode 100644 index 00000000..80060202 --- /dev/null +++ b/server/egovernor/container_test.go @@ -0,0 +1,44 @@ +package egovernor + +import ( + "strings" + "testing" + + "github.com/BurntSushi/toml" + "github.com/stretchr/testify/assert" + + "github.com/gotomicro/ego/core/econf" + "github.com/gotomicro/ego/core/elog" +) + +func TestDefaultContainer(t *testing.T) { + in := &Container{ + config: DefaultConfig(), + logger: elog.EgoLogger.With(elog.FieldComponent(PackageName)), + } + out := DefaultContainer() + assert.Equal(t, in, out) +} + +func TestLoad(t *testing.T) { + conf := ` +[test] +addr = ":9091" +` + err := econf.LoadFromReader(strings.NewReader(conf), toml.Unmarshal) + assert.NoError(t, err) + Load("test").Build() + assert.NoError(t, nil) +} + +func TestBuild(t *testing.T) { + var c = &Container{ + name: "test", + config: &Config{Host: "test", Port: 8080}, + logger: nil, + } + opt1 := WithHost("test") + opt2 := WithPort(8080) + c.Build(opt1, opt2) + assert.NoError(t, nil) +} diff --git a/server/egovernor/options_test.go b/server/egovernor/options_test.go new file mode 100644 index 00000000..62c93692 --- /dev/null +++ b/server/egovernor/options_test.go @@ -0,0 +1,21 @@ +package egovernor + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestWithHost(t *testing.T) { + c := &Container{config: &Config{Host: "test"}} + opt := WithHost("test") + opt(c) + assert.Equal(t, "test", c.config.Host) +} + +func TestWithPost(t *testing.T) { + c := &Container{config: &Config{Port: 8080}} + opt := WithPort(8080) + opt(c) + assert.Equal(t, 8080, c.config.Port) +} diff --git a/server/egrpc/component_test.go b/server/egrpc/component_test.go index 09767616..5bac30cc 100644 --- a/server/egrpc/component_test.go +++ b/server/egrpc/component_test.go @@ -14,22 +14,26 @@ import ( func TestNewComponent(t *testing.T) { cfg := Config{ Host: "0.0.0.0", - Port: 9001, + Port: 9007, Network: "tcp4", } cmp := newComponent("test-cmp", &cfg, elog.DefaultLogger) assert.Equal(t, "test-cmp", cmp.Name()) assert.Equal(t, "server.egrpc", cmp.PackageName()) - assert.Equal(t, "0.0.0.0:9001", cmp.Address()) + assert.Equal(t, "0.0.0.0:9007", cmp.Address()) + assert.NoError(t, cmp.Prepare()) assert.NoError(t, cmp.Init()) info := cmp.Info() assert.NotEmpty(t, info.Name) assert.Equal(t, "grpc", info.Scheme) - assert.Equal(t, "0.0.0.0:9001", info.Address) + assert.Equal(t, "0.0.0.0:9007", info.Address) assert.Equal(t, constant.ServiceProvider, info.Kind) + assert.NoError(t, nil, cmp.listener.Addr()) + assert.Equal(t, false, cmp.Health()) + // err = cmp.Start() go func() { assert.NoError(t, cmp.Start()) @@ -40,6 +44,7 @@ func TestNewComponent(t *testing.T) { <-ctx.Done() assert.NoError(t, cmp.Stop()) + assert.NoError(t, cmp.GracefulStop(context.Background())) t.Log("done") } diff --git a/server/egrpc/interceptor_test.go b/server/egrpc/interceptor_test.go index cde5db5f..2de1f6ea 100644 --- a/server/egrpc/interceptor_test.go +++ b/server/egrpc/interceptor_test.go @@ -239,3 +239,9 @@ type PanicGreeter struct { func (g PanicGreeter) SayHello(context context.Context, request *helloworld.HelloRequest) (*helloworld.HelloResponse, error) { panic("we have a panic") } + +func TestCtxStoreSet(t *testing.T) { + ctx := context.Background() + CtxStoreSet(ctx, "", "") + assert.NoError(t, nil) +} diff --git a/server/egrpc/options_test.go b/server/egrpc/options_test.go index ecb7e724..356fe8de 100644 --- a/server/egrpc/options_test.go +++ b/server/egrpc/options_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/BurntSushi/toml" + "github.com/alibaba/sentinel-golang/core/base" "github.com/stretchr/testify/assert" "google.golang.org/grpc" @@ -67,3 +68,19 @@ func TestWithLogger(t *testing.T) { comp := DefaultContainer().Build(WithLogger(logger)) assert.Equal(t, logger, comp.logger) } + +func TestWithUnaryServerResourceExtractor(t *testing.T) { + fn := func(context.Context, interface{}, *grpc.UnaryServerInfo) string { + return "" + } + WithUnaryServerResourceExtractor(fn) + assert.NoError(t, nil) +} + +func TestWithUnaryServerBlockFallback(t *testing.T) { + fn := func(context.Context, interface{}, *grpc.UnaryServerInfo, *base.BlockError) (interface{}, error) { + return "", nil + } + WithUnaryServerBlockFallback(fn) + assert.NoError(t, nil) +}