Skip to content

Commit

Permalink
update test cases (#391)
Browse files Browse the repository at this point in the history
Co-authored-by: Ting <[email protected]>
Co-authored-by: sevennt <[email protected]>
  • Loading branch information
3 people authored Jun 6, 2024
1 parent 0e79bac commit 846b876
Show file tree
Hide file tree
Showing 44 changed files with 706 additions and 591 deletions.
2 changes: 1 addition & 1 deletion client/egrpc/interceptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ func customHeader(egoLogExtraKeys []string) grpc.UnaryClientInterceptor {
if ctx.Value(key) != nil {
ctx = context.WithValue(ctx, key, value)

Check failure on line 393 in client/egrpc/interceptor.go

View workflow job for this annotation

GitHub Actions / lint

SA1029: should not use built-in type string as key for value; define your own type to avoid collisions (staticcheck)
}
//ctx = transport.WithValue(ctx, key, value)
// ctx = transport.WithValue(ctx, key, value)
}
}
return invoker(ctx, method, req, res, cc, opts...)
Expand Down
2 changes: 1 addition & 1 deletion client/egrpc/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (b *baseBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts
// implementations which expect the endpoint without the leading "/". So, we
// end up stripping the leading "/" here. But this will result in an
// incorrect parsing for something like "unix:///path/to/socket". Since we
// own the "unix" resolver, we can workaround in the unix resolver by using
// own the "unix" resolver, we can work around in the unix resolver by using
// the `URL` field instead of the `Endpoint` field.

endpoint := target.URL.Path
Expand Down
45 changes: 37 additions & 8 deletions client/ehttp/component_test.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,50 @@
package ehttp

import (
"net/http"
"testing"

"github.com/go-resty/resty/v2"
"github.com/stretchr/testify/assert"

"github.com/gotomicro/ego/client/ehttp/resolver"
"github.com/gotomicro/ego/core/eapp"
"github.com/gotomicro/ego/core/elog"
"github.com/gotomicro/ego/core/util/xtime"
)

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)
})
var logger = elog.DefaultLogger
config := &Config{
Addr: "https://hello.com/",
Debug: false,
RawDebug: false,
httpClient: nil,
ReadTimeout: xtime.Duration("2s"),
SlowLogThreshold: xtime.Duration("500ms"),
}
out := newComponent("test", config, logger)

// Other case...
target, err := parseTarget(config.Addr)
assert.NoError(t, err)
assert.Equal(t, "https", target.Scheme)
assert.Equal(t, "http", target.Protocol)
assert.Equal(t, "", target.Endpoint)
assert.Equal(t, "hello.com", target.Authority)

config.httpClient = &http.Client{Transport: createTransport(config), Jar: config.cookieJar}
cli := resty.NewWithClient(config.httpClient).
SetDebug(config.RawDebug).
SetTimeout(config.ReadTimeout).
SetHeader("app", eapp.Name()).
SetBaseURL(config.Addr)
in := &Component{
name: "test",
config: config,
logger: logger,
Client: cli,
builder: resolver.Get("https"),
}
assert.Equal(t, in.builder, out.builder)
// assert.Equal(t, in.Client, out.Client)
}
7 changes: 3 additions & 4 deletions client/ehttp/config_test/conf.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
[test]
"name" = "hello"

[test1]
"name" = "world"
Addr = "https://test.com"
Debug = true
RawDebug = false
10 changes: 6 additions & 4 deletions client/ehttp/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import (
"github.com/stretchr/testify/assert"

"github.com/gotomicro/ego/core/econf"
"github.com/gotomicro/ego/core/elog"
)

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)
err1 := econf.LoadFromReader(file, toml.Unmarshal)
assert.NoError(t, err1)
Load("test").Build()
logger := DefaultContainer().logger.With(elog.FieldComponentName("test"))
assert.Equal(t, logger, Load("test").logger)
}
2 changes: 1 addition & 1 deletion core/econf/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func Sub(key string) *Configuration {
}

// LoadFromDataSource load configuration from data source
// if data source supports dynamic config, a monitor goroutinue
// if data source supports dynamic config, a monitor goroutine
// would be
func LoadFromDataSource(ds DataSource, unmarshaller Unmarshaller, opts ...Option) error {
return defaultConfiguration.LoadFromDataSource(ds, unmarshaller, opts...)
Expand Down
19 changes: 0 additions & 19 deletions core/econf/api_test.go

This file was deleted.

189 changes: 189 additions & 0 deletions core/econf/conf_api_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package econf

import (
"io/ioutil"
"log"
"net/url"
"os"
"os/exec"
"path"
"runtime"
"sync"
"sync/atomic"
"testing"

"github.com/BurntSushi/toml"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

type mockDataSource struct {
path string
enableWatch bool
changed chan struct{}
}

func (m *mockDataSource) Parse(path string, watch bool) ConfigType {
_, err := url.Parse(path)
if err != nil {
log.Panicf("Error: %v\n", err)
}
return ConfigTypeToml
}

func (m *mockDataSource) ReadConfig() ([]byte, error) {
return os.ReadFile(m.path)
}

func (m *mockDataSource) IsConfigChanged() <-chan struct{} {
changed := make(chan struct{})
if content, err := m.ReadConfig(); err == nil {
// 创建临时的配置对象
tempC := &Configuration{}
if err := toml.Unmarshal(content, tempC); err == nil {
tempC.mu.RLock()
defer tempC.mu.RUnlock()
for _, change := range tempC.onChanges {
change(tempC)
}
close(changed)
}
}
return changed
}

func (m *mockDataSource) Close() error {
close(m.changed)
return nil
}

var _ DataSource = (*mockDataSource)(nil)

func newMockDataSource(Addr string, watch bool) DataSource {
return &mockDataSource{path: Addr, enableWatch: watch}
}

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.toml` 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 = os.WriteFile(configFile, []byte(`foo= "baz"`), 0640)
require.Nil(t, err)
// wg.Wait()
wg.Done()
// 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
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.toml` file
dataDir2 := path.Join(watchDir, "data2")
err := os.Mkdir(dataDir2, 0777)
require.Nil(t, err)
configFile2 := path.Join(dataDir2, "config.toml")
err = os.WriteFile(configFile2, []byte(`foo= "baz"`), 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) (*Configuration, string, func(), *sync.WaitGroup) {
watchDir, err := ioutil.TempDir("", "")
require.Nil(t, err)
configFile := path.Join(watchDir, "config.toml")
err = os.WriteFile(configFile, []byte(`foo= "baz"`), 0640)
require.Nil(t, err)
content, err := os.ReadFile(configFile)
if err != nil {
log.Panicf("Error: %v\n", err)
}
t.Logf("Content of configFile: %v\n", string(content))

cleanup := func() {
err1 := os.RemoveAll(watchDir)
assert.NoError(t, err1)
}

v := New()
provider := newMockDataSource(configFile, true)

wg := &sync.WaitGroup{}
wg.Add(2)
var init int64
v.OnChange(func(configuration *Configuration) {
if atomic.CompareAndSwapInt64(&init, 0, 1) {
t.Logf("config init")
} else {
t.Logf("config file changed")
}
wg.Done()
})

err = v.LoadFromDataSource(provider, toml.Unmarshal)
assert.Nil(t, err)
assert.Equal(t, "baz", v.Get("foo"))
return v, configFile, cleanup, wg
}

func newWithSymlinkedConfigFile(t *testing.T) (*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.toml")
t.Logf("Real config file location: %s\n", realConfigFile)
err = os.WriteFile(realConfigFile, []byte(`foo= "baz"`), 0640)
require.Nil(t, err)
cleanup := func() {
err1 := os.RemoveAll(watchDir)
assert.NoError(t, err1)
}
// 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 `<watchdir>/datadir1/config.toml` to `<watchdir>/config.toml`
configFile := path.Join(watchDir, "config.toml")
err = os.Symlink(path.Join(watchDir, "data", "config.toml"), configFile)
require.Nil(t, err)
t.Logf("Config file location: %s\n", path.Join(watchDir, "config.toml"))

v := New()
provider := newMockDataSource(configFile, true)

wg := &sync.WaitGroup{}
wg.Add(2)
var init int64
v.OnChange(func(configuration *Configuration) {
if atomic.CompareAndSwapInt64(&init, 0, 1) {
t.Logf("config init")
} else {
t.Logf("config file changed")
}
wg.Done()
})
err = v.LoadFromDataSource(provider, toml.Unmarshal)
require.Nil(t, err)
require.Equal(t, "bar", v.Get("foo"))
return v, watchDir, configFile, cleanup, wg
}
Loading

0 comments on commit 846b876

Please sign in to comment.