Repository: go-kratos/kratos
Pull request #2189 (2022-07-11 18:39:51)

build(deps): bump actions/setup-go from 3.2.0 to 3.2.1
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3.2.0 to 3.2.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/actions/setup-go/releases">actions/setup-go's releases</a>.</em></p>
<blockquote>
<h2>Update actions/cache version to 3.0.0</h2>
<p>In scope of this release we updated <code>actions/cache</code> package as the new version contains fixes for <a href="https://github-redirect.dependabot.com/actions/setup-go/pull/238">caching error handling</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/actions/setup-go/commit/84cbf8094393cdc5fe1fe1671ff2647332956b1a"><code>84cbf80</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/actions/setup-go/issues/238">#238</a> from vsafonkin/v-vsafonkin/cache-error-handling</li>
<li><a href="https://github.com/actions/setup-go/commit/dd64cc9b01c2a6ef710d1e35042215ad9bf1ea72"><code>dd64cc9</code></a> Build dist</li>
<li><a href="https://github.com/actions/setup-go/commit/9eecd2d0d7ac148636f537a0b829f408c9afa171"><code>9eecd2d</code></a> Minor fix</li>
<li><a href="https://github.com/actions/setup-go/commit/75be6485711141eae71e9b720c3c6997a65bb2d7"><code>75be648</code></a> Fix license</li>
<li><a href="https://github.com/actions/setup-go/commit/bb9cf4268879d1e23037541e947c2d73238f6705"><code>bb9cf42</code></a> Fix license</li>
<li><a href="https://github.com/actions/setup-go/commit/97919d33f5faa2be792f864aeed063ccccdf7dac"><code>97919d3</code></a> Fix license</li>
<li><a href="https://github.com/actions/setup-go/commit/df0583a96c7157c696ea38b0e42ee4fa1e9851a5"><code>df0583a</code></a> Fix license</li>
<li><a href="https://github.com/actions/setup-go/commit/5ea2b37572926b27fa9d943a747eec3c509a8628"><code>5ea2b37</code></a> Fix license</li>
<li><a href="https://github.com/actions/setup-go/commit/e52a7c55ca89d8ef76f05325857c1097316c6239"><code>e52a7c5</code></a> Update license</li>
<li><a href="https://github.com/actions/setup-go/commit/ed8da5df3995b614d2f8d6a1caab1f180c720e9c"><code>ed8da5d</code></a> Build js</li>
<li>Additional commits viewable in <a href="https://github.com/actions/setup-go/compare/v3.2.0...v3.2.1">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-go&package-manager=github_actions&previous-version=3.2.0&new-version=3.2.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

codecov-commenter: # [Codecov](https://codecov.io/gh/go-kratos/kratos/pull/2189?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) Report
> Merging [#2189](https://codecov.io/gh/go-kratos/kratos/pull/2189?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) (654a1a0) into [main](https://codecov.io/gh/go-kratos/kratos/commit/1451b9e0c0e3e1ee88a4595d9f9cfaf24eb8150f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) (1451b9e) will **decrease** coverage by `0.05%`.
> The diff coverage is `n/a`.

> :exclamation: Current head 654a1a0 differs from pull request most recent head 1e0d683. Consider uploading reports for the commit 1e0d683 to get more accurate results

```diff
@@            Coverage Diff             @@
##             main    #2189      +/-   ##
==========================================
- Coverage   84.72%   84.67%   -0.06%     
==========================================
  Files          86       86              
  Lines        3758     3758              
==========================================
- Hits         3184     3182       -2     
- Misses        406      408       +2     
  Partials      168      168              
```


| [Impacted Files](https://codecov.io/gh/go-kratos/kratos/pull/2189?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos) | Coverage Δ | |
|---|---|---|
| [internal/context/context.go](https://codecov.io/gh/go-kratos/kratos/pull/2189/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos#diff-aW50ZXJuYWwvY29udGV4dC9jb250ZXh0Lmdv) | `97.01% <0.00%> (-2.99%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/go-kratos/kratos/pull/2189?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/go-kratos/kratos/pull/2189?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos). Last update [1451b9e...1e0d683](https://codecov.io/gh/go-kratos/kratos/pull/2189?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-kratos).


Patch:
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 3794a7c0..16bb0a9f 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -44,7 +44,7 @@ jobs:
     steps:
       - uses: actions/checkout@v3
       - name: Set up Go
-        uses: actions/setup-go@v3.2.0
+        uses: actions/setup-go@v3.2.1
         with:
           go-version: ${{ matrix.go }}
 


Test patch:
diff --git a/app_test.go b/app_test.go
index 80831b54..aa0a5ef7 100644
--- a/app_test.go
+++ b/app_test.go
@@ -3,6 +3,7 @@ package kratos
 import (
 	"context"
 	"fmt"
+	"net/url"
 	"reflect"
 	"sync"
 	"testing"
@@ -92,6 +93,80 @@ func TestApp_Metadata(t *testing.T) {
 }
 
 func TestApp_Endpoint(t *testing.T) {
+	v := []string{"https://go-kratos.dev", "localhost"}
+	var endpoints []*url.URL
+	for _, urlStr := range v {
+		if endpoint, err := url.Parse(urlStr); err != nil {
+			t.Errorf("invalid endpoint:%v", urlStr)
+		} else {
+			endpoints = append(endpoints, endpoint)
+		}
+	}
+	o := New(Endpoint(endpoints...))
+	if instance, err := o.buildInstance(); err != nil {
+		t.Error("build instance failed")
+	} else {
+		o.instance = instance
+	}
+	if !reflect.DeepEqual(o.Endpoint(), v) {
+		t.Errorf("Endpoint() = %v, want %v", o.Endpoint(), v)
+	}
+}
+
+func TestApp_buildInstance(t *testing.T) {
+	want := struct {
+		id        string
+		name      string
+		version   string
+		metadata  map[string]string
+		endpoints []string
+	}{
+		id:      "1",
+		name:    "kratos",
+		version: "v1.0.0",
+		metadata: map[string]string{
+			"a": "1",
+			"b": "2",
+		},
+		endpoints: []string{"https://go-kratos.dev", "localhost"},
+	}
+	var endpoints []*url.URL
+	for _, urlStr := range want.endpoints {
+		if endpoint, err := url.Parse(urlStr); err != nil {
+			t.Errorf("invalid endpoint:%v", urlStr)
+		} else {
+			endpoints = append(endpoints, endpoint)
+		}
+	}
+	app := New(
+		ID(want.id),
+		Name(want.name),
+		Version(want.version),
+		Metadata(want.metadata),
+		Endpoint(endpoints...),
+	)
+	if got, err := app.buildInstance(); err != nil {
+		t.Error("build got failed")
+	} else {
+		if got.ID != want.id {
+			t.Errorf("ID() = %v, want %v", got.ID, want.id)
+		}
+		if got.Name != want.name {
+			t.Errorf("Name() = %v, want %v", got.Name, want.name)
+		}
+		if got.Version != want.version {
+			t.Errorf("Version() = %v, want %v", got.Version, want.version)
+		}
+		if !reflect.DeepEqual(got.Endpoints, want.endpoints) {
+			t.Errorf("Endpoint() = %v, want %v", got.Endpoints, want.endpoints)
+		}
+		if !reflect.DeepEqual(got.Metadata, want.metadata) {
+			t.Errorf("Metadata() = %v, want %v", got.Metadata, want.metadata)
+		}
+	}
+}
+
+func TestApp_Context(t *testing.T) {
 	type fields struct {
 		id       string
 		version  string
diff --git a/config/env/env_test.go b/config/env/env_test.go
index b024dbee..6574c1d8 100644
--- a/config/env/env_test.go
+++ b/config/env/env_test.go
@@ -417,3 +417,13 @@ func Test_matchPrefix(t *testing.T) {
 		})
 	}
 }
+
+func Test_env_watch(t *testing.T) {
+	prefixs := []string{"BAR", "FOO"}
+	source := NewSource(prefixs...)
+	w, err := source.Watch()
+	if err != nil {
+		t.Errorf("expect no err, got %v", err)
+	}
+	_ = w.Stop()
+}
diff --git a/config/options_test.go b/config/options_test.go
index 3c46bc30..51e8b48e 100644
--- a/config/options_test.go
+++ b/config/options_test.go
@@ -2,6 +2,7 @@ package config
 
 import (
 	"reflect"
+	"strings"
 	"testing"
 )
 
@@ -197,3 +198,31 @@ func TestDefaultResolver(t *testing.T) {
 		})
 	}
 }
+
+func TestExpand(t *testing.T) {
+	tests := []struct {
+		input   string
+		mapping func(string) string
+		want    string
+	}{
+		{
+			input: "${a}",
+			mapping: func(s string) string {
+				return strings.ToUpper(s)
+			},
+			want: "A",
+		},
+		{
+			input: "a",
+			mapping: func(s string) string {
+				return strings.ToUpper(s)
+			},
+			want: "a",
+		},
+	}
+	for _, tt := range tests {
+		if got := expand(tt.input, tt.mapping); got != tt.want {
+			t.Errorf("expand() want: %s, got: %s", tt.want, got)
+		}
+	}
+}
diff --git a/config/reader_test.go b/config/reader_test.go
index b8a5d23a..f2ac1444 100644
--- a/config/reader_test.go
+++ b/config/reader_test.go
@@ -208,3 +208,118 @@ func TestReader_Source(t *testing.T) {
 		t.Fatal("[]byte(`{\"a\":{\"b\":{\"X\":1}}}`) is not equal to b")
 	}
 }
+
+func TestCloneMap(t *testing.T) {
+	tests := []struct {
+		input map[string]interface{}
+		want  map[string]interface{}
+	}{
+		{
+			input: map[string]interface{}{
+				"a": 1,
+				"b": "2",
+				"c": true,
+			},
+			want: map[string]interface{}{
+				"a": 1,
+				"b": "2",
+				"c": true,
+			},
+		},
+		{
+			input: map[string]interface{}{},
+			want:  map[string]interface{}{},
+		},
+		{
+			input: nil,
+			want:  map[string]interface{}{},
+		},
+	}
+	for _, tt := range tests {
+		if got, err := cloneMap(tt.input); err != nil {
+			t.Errorf("expect no err, got %v", err)
+		} else if !reflect.DeepEqual(got, tt.want) {
+			t.Errorf("cloneMap(%v) = %v, want %v", tt.input, got, tt.want)
+		}
+	}
+}
+
+func TestConvertMap(t *testing.T) {
+	tests := []struct {
+		input interface{}
+		want  interface{}
+	}{
+		{
+			input: map[string]interface{}{
+				"a": 1,
+				"b": "2",
+				"c": true,
+				"d": []byte{65, 66, 67},
+			},
+			want: map[string]interface{}{
+				"a": 1,
+				"b": "2",
+				"c": true,
+				"d": "ABC",
+			},
+		},
+		{
+			input: []interface{}{1, 2.0, "3", true, nil, []interface{}{1, 2.0, "3", true, nil}},
+			want:  []interface{}{1, 2.0, "3", true, nil, []interface{}{1, 2.0, "3", true, nil}},
+		},
+		{
+			input: []byte{65, 66, 67},
+			want:  "ABC",
+		},
+	}
+	for _, tt := range tests {
+		if got := convertMap(tt.input); !reflect.DeepEqual(got, tt.want) {
+			t.Errorf("convertMap(%v) = %v, want %v", tt.input, got, tt.want)
+		}
+	}
+}
+
+func TestReadValue(t *testing.T) {
+	m := map[string]interface{}{
+		"a": 1,
+		"b": map[string]interface{}{
+			"c": "3",
+			"d": map[string]interface{}{
+				"e": true,
+			},
+		},
+	}
+	va := atomicValue{}
+	va.Store(1)
+
+	vbc := atomicValue{}
+	vbc.Store("3")
+
+	vbde := atomicValue{}
+	vbde.Store(true)
+
+	tests := []struct {
+		path string
+		want atomicValue
+	}{
+		{
+			path: "a",
+			want: va,
+		},
+		{
+			path: "b.c",
+			want: vbc,
+		},
+		{
+			path: "b.d.e",
+			want: vbde,
+		},
+	}
+	for _, tt := range tests {
+		if got, found := readValue(m, tt.path); !found {
+			t.Errorf("expect found %v in %v, but not.", tt.path, m)
+		} else if got.Load() != tt.want.Load() {
+			t.Errorf("readValue(%v, %v) = %v, want %v", m, tt.path, got, tt.want)
+		}
+	}
+}
diff --git a/contrib/registry/polaris/registry_test.go b/contrib/registry/polaris/registry_test.go
index d0564051..7d696064 100644
--- a/contrib/registry/polaris/registry_test.go
+++ b/contrib/registry/polaris/registry_test.go
@@ -5,20 +5,26 @@ import (
 	"testing"
 	"time"
 
-	"github.com/polarismesh/polaris-go/pkg/config"
-
-	"github.com/go-kratos/kratos/v2/log"
 	"github.com/go-kratos/kratos/v2/registry"
+
+	"github.com/polarismesh/polaris-go/pkg/config"
 )
 
-// TestRegistry . TestRegistryManyService
+// TestRegistry
 func TestRegistry(t *testing.T) {
 	conf := config.NewDefaultConfiguration([]string{"127.0.0.1:8091"})
 
 	r := NewRegistryWithConfig(
 		conf,
-		WithTimeout(time.Second*10),
-		WithTTL(100),
+		WithTimeout(time.Second),
+		WithHeartbeat(true),
+		WithHealthy(true),
+		WithIsolate(true),
+		WithNamespace("default"),
+		WithProtocol("tcp"),
+		WithRetryCount(0),
+		WithWeight(100),
+		WithTTL(10),
 	)
 
 	ctx := context.Background()
@@ -35,171 +41,197 @@ func TestRegistry(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	err = r.Deregister(ctx, svc)
+	time.Sleep(time.Second)
+
+	result, err := r.GetService(context.Background(), "kratos-provider-0-tcp")
 	if err != nil {
 		t.Fatal(err)
 	}
-}
 
-// TestRegistryMany . TestRegistryManyService
-func TestRegistryMany(t *testing.T) {
-	conf := config.NewDefaultConfiguration([]string{"127.0.0.1:8091"})
+	if len(result) != 1 {
+		t.Fatal("register error")
+	}
 
-	r := NewRegistryWithConfig(
-		conf,
-		WithTimeout(time.Second*10),
-		WithTTL(100),
-	)
+	for _, item := range result {
+		if item.Name != "kratos-provider-0-tcp" || item.Endpoints[0] != "tcp://127.0.0.1:9000" {
+			t.Fatal("register error")
+		}
+	}
 
-	svc := &registry.ServiceInstance{
-		Name:      "kratos-provider-1-",
-		Version:   "test",
-		Metadata:  map[string]string{"app": "kratos"},
-		Endpoints: []string{"tcp://127.0.0.1:9000?isSecure=false"},
+	watch, err := r.Watch(ctx, "kratos-provider-0-tcp")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Test update
+	svc.Version = "release1.0.0"
+
+	if err = r.Register(ctx, svc); err != nil {
+		t.Fatal(err)
 	}
+
+	result, err = watch.Next()
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if len(result) != 1 || result[0].Version != "release1.0.0" {
+		t.Fatal("register error")
+	}
+	// Test add instance
 	svc1 := &registry.ServiceInstance{
-		Name:      "kratos-provider-2-",
+		Name:      "kratos-provider-0-",
 		Version:   "test",
 		Metadata:  map[string]string{"app": "kratos"},
 		Endpoints: []string{"tcp://127.0.0.1:9001?isSecure=false"},
 	}
-	svc2 := &registry.ServiceInstance{
-		Name:      "kratos-provider-3-",
-		Version:   "test",
-		Metadata:  map[string]string{"app": "kratos"},
-		Endpoints: []string{"tcp://127.0.0.1:9002?isSecure=false"},
-	}
 
-	err := r.Register(context.Background(), svc)
-	if err != nil {
+	if err = r.Register(ctx, svc1); err != nil {
 		t.Fatal(err)
 	}
 
-	err = r.Register(context.Background(), svc1)
-	if err != nil {
+	if _, err = watch.Next(); err != nil {
 		t.Fatal(err)
 	}
 
-	err = r.Register(context.Background(), svc2)
+	result, err = r.GetService(ctx, "kratos-provider-0-tcp")
+
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	err = r.Deregister(context.Background(), svc)
-	if err != nil {
-		t.Fatal(err)
+	if len(result) != 2 {
+		t.Fatal("register error")
 	}
 
-	err = r.Deregister(context.Background(), svc1)
-	if err != nil {
+	if err = r.Deregister(ctx, svc); err != nil {
+		t.Fatal(err)
+	}
+	if err = r.Deregister(ctx, svc1); err != nil {
 		t.Fatal(err)
 	}
 
-	err = r.Deregister(context.Background(), svc2)
+	result, err = watch.Next()
 	if err != nil {
 		t.Fatal(err)
 	}
+
+	if len(result) != 0 {
+		t.Fatal("register error")
+	}
 }
 
-// TestGetService . TestGetService
-func TestGetService(t *testing.T) {
+// TestRegistryMany
+func TestRegistryMany(t *testing.T) {
 	conf := config.NewDefaultConfiguration([]string{"127.0.0.1:8091"})
 
 	r := NewRegistryWithConfig(
 		conf,
-		WithTimeout(time.Second*10),
-		WithTTL(100),
+		WithTimeout(time.Second),
+		WithHeartbeat(true),
+		WithHealthy(true),
+		WithIsolate(true),
+		WithNamespace("default"),
+		WithProtocol("tcp"),
+		WithRetryCount(0),
+		WithWeight(100),
+		WithTTL(10),
 	)
 
 	ctx := context.Background()
 
+	// Multi endpoint
 	svc := &registry.ServiceInstance{
-		Name:      "kratos-provider-4-",
+		Name:      "kratos-provider-1-",
 		Version:   "test",
 		Metadata:  map[string]string{"app": "kratos"},
-		Endpoints: []string{"tcp://127.0.0.1:9000?isSecure=false"},
+		Endpoints: []string{"tcp://127.0.0.1:9000?isSecure=false", "tcp://127.0.0.1:9001?isSecure=false"},
+	}
+	// Normal
+	svc1 := &registry.ServiceInstance{
+		Name:      "kratos-provider-2-",
+		Version:   "test",
+		Metadata:  map[string]string{"app": "kratos"},
+		Endpoints: []string{"tcp://127.0.0.1:9002?isSecure=false"},
+	}
+	// Without metadata
+	svc2 := &registry.ServiceInstance{
+		Name:      "kratos-provider-3-",
+		Version:   "test",
+		Endpoints: []string{"tcp://127.0.0.1:9003?isSecure=false"},
 	}
 
-	err := r.Register(ctx, svc)
-	if err != nil {
+	if err := r.Register(ctx, svc); err != nil {
 		t.Fatal(err)
 	}
-	time.Sleep(time.Second * 1)
-	serviceInstances, err := r.GetService(ctx, "kratos-provider-4-tcp")
-	if err != nil {
+
+	if err := r.Register(ctx, svc1); err != nil {
 		t.Fatal(err)
 	}
-	for _, instance := range serviceInstances {
-		log.Info(instance)
-	}
 
-	err = r.Deregister(ctx, svc)
-	if err != nil {
+	if err := r.Register(ctx, svc2); err != nil {
 		t.Fatal(err)
 	}
-}
 
-// TestWatch . TestWatch
-func TestWatch(t *testing.T) {
-	conf := config.NewDefaultConfiguration([]string{"127.0.0.1:8091"})
+	time.Sleep(3 * time.Second)
 
-	r := NewRegistryWithConfig(
-		conf,
-		WithTimeout(time.Second*10),
-		WithTTL(100),
-	)
+	result1, err := r.GetService(ctx, "kratos-provider-1-tcp")
 
-	svc := &registry.ServiceInstance{
-		Name:      "kratos-provider-4-",
-		Version:   "test",
-		Metadata:  map[string]string{"app": "kratos"},
-		Endpoints: []string{"tcp://127.0.0.1:9000?isSecure=false"},
+	if err != nil || len(result1) != 2 || result1[0].Name != "kratos-provider-1-tcp" {
+		t.Fatal(err)
 	}
 
-	watch, err := r.Watch(context.Background(), "kratos-provider-4-tcp")
-	if err != nil {
+	result2, err := r.GetService(ctx, "kratos-provider-2-tcp")
+
+	if err != nil || len(result2) != 1 || result2[0].Name != "kratos-provider-2-tcp" || result2[0].Endpoints[0] != "tcp://127.0.0.1:9002" {
 		t.Fatal(err)
 	}
 
-	err = r.Register(context.Background(), svc)
-	if err != nil {
+	result3, err := r.GetService(ctx, "kratos-provider-3-tcp")
+
+	if err != nil || len(result3) != 1 || result3[0].Name != "kratos-provider-3-tcp" || result3[0].Endpoints[0] != "tcp://127.0.0.1:9003" {
 		t.Fatal(err)
 	}
-	// watch svc
-	time.Sleep(time.Second * 1)
 
-	// svc register, AddEvent
-	next, err := watch.Next()
+	watch1, err := r.Watch(ctx, "kratos-provider-1-tcp")
 	if err != nil {
 		t.Fatal(err)
 	}
-	for _, instance := range next {
-		// it will output one instance
-		log.Info(instance)
+	watch2, err := r.Watch(ctx, "kratos-provider-2-tcp")
+	if err != nil {
+		t.Fatal(err)
 	}
-
-	err = r.Deregister(context.Background(), svc)
+	watch3, err := r.Watch(ctx, "kratos-provider-3-tcp")
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	// svc deregister, DeleteEvent
-	next, err = watch.Next()
-	if err != nil {
+	if err = r.Deregister(ctx, svc); err != nil {
 		t.Fatal(err)
 	}
-	for _, instance := range next {
-		// it will output nothing
-		log.Info(instance)
+
+	result1, err = watch1.Next()
+	if err != nil || len(result1) != 0 {
+		t.Fatal("deregister error")
 	}
 
-	err = watch.Stop()
+	err = r.Deregister(ctx, svc1)
 	if err != nil {
 		t.Fatal(err)
 	}
-	_, err = watch.Next()
-	if err == nil {
-		// if nil, stop failed
-		t.Fatal()
+
+	result2, err = watch2.Next()
+	if err != nil || len(result2) != 0 {
+		t.Fatal("deregister error")
+	}
+	err = r.Deregister(ctx, svc2)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	result3, err = watch3.Next()
+	if err != nil || len(result3) != 0 {
+		t.Fatal("deregister error")
 	}
 }
diff --git a/internal/endpoint/endpoint_test.go b/internal/endpoint/endpoint_test.go
index 356d8fbc..e8870c80 100644
--- a/internal/endpoint/endpoint_test.go
+++ b/internal/endpoint/endpoint_test.go
@@ -139,3 +139,87 @@ func TestParseEndpoint(t *testing.T) {
 		})
 	}
 }
+
+func TestIsSecure(t *testing.T) {
+	tests := []struct {
+		url  *url.URL
+		want bool
+	}{
+		{
+			url:  &url.URL{Scheme: "http", Host: "127.0.0.1"},
+			want: false,
+		},
+		{
+			url:  &url.URL{Scheme: "http", Host: "127.0.0.1", RawQuery: "isSecure=false"},
+			want: false,
+		},
+		{
+			url:  &url.URL{Scheme: "grpc", Host: "127.0.0.1", RawQuery: "isSecure=true"},
+			want: true,
+		},
+	}
+	for _, tt := range tests {
+		if got := IsSecure(tt.url); got != tt.want {
+			t.Errorf("IsSecure() = %v, want %v", got, tt.want)
+		}
+	}
+}
+
+func TestLegacyURLToNew(t *testing.T) {
+	tests := []struct {
+		url  *url.URL
+		want *url.URL
+	}{
+		{
+			url:  &url.URL{Scheme: "http", Host: "www.google.com", RawQuery: "isSecure=true"},
+			want: &url.URL{Scheme: "https", Host: "www.google.com"},
+		},
+		{
+			url:  &url.URL{Scheme: "https", Host: "www.google.com", RawQuery: "isSecure=true"},
+			want: &url.URL{Scheme: "https", Host: "www.google.com", RawQuery: "isSecure=true"},
+		},
+		{
+			url:  &url.URL{Scheme: "http", Host: "go-kratos.dev", RawQuery: "isSecure=false"},
+			want: &url.URL{Scheme: "http", Host: "go-kratos.dev", RawQuery: "isSecure=false"},
+		},
+	}
+	for _, tt := range tests {
+		if got := legacyURLToNew(tt.url); !reflect.DeepEqual(got, tt.want) {
+			t.Errorf("legacyURLToNew() = %v, want %v", got, tt.want)
+		}
+	}
+}
+
+func TestSchema(t *testing.T) {
+	tests := []struct {
+		schema string
+		secure bool
+		want   string
+	}{
+		{
+			schema: "http",
+			secure: true,
+			want:   "https",
+		},
+		{
+			schema: "http",
+			secure: false,
+			want:   "http",
+		},
+		{
+			schema: "grpc",
+			secure: true,
+			want:   "grpcs",
+		},
+		{
+			schema: "grpc",
+			secure: false,
+			want:   "grpc",
+		},
+	}
+	for _, tt := range tests {
+		if got := Scheme(tt.schema, tt.secure); got != tt.want {
+			t.Errorf("Schema() = %v, want %v", got, tt.want)
+		}
+	}
+}
diff --git a/log/global_test.go b/log/global_test.go
index 91482331..04bb19c5 100644
--- a/log/global_test.go
+++ b/log/global_test.go
@@ -11,7 +11,12 @@ import (
 
 func TestGlobalLog(t *testing.T) {
 	buffer := &bytes.Buffer{}
-	SetLogger(NewStdLogger(buffer))
+	logger := NewStdLogger(buffer)
+	SetLogger(logger)
+
+	if GetLogger() != logger {
+		t.Error("GetLogger() is not equal to logger")
+	}
 
 	testCases := []struct {
 		level   Level
@@ -48,19 +53,38 @@ func TestGlobalLog(t *testing.T) {
 		msg := fmt.Sprintf(tc.content[0].(string), tc.content[1:]...)
 		switch tc.level {
 		case LevelDebug:
+			Debug(msg)
+			expected = append(expected, fmt.Sprintf("%s msg=%s", "DEBUG", msg))
 			Debugf(tc.content[0].(string), tc.content[1:]...)
 			expected = append(expected, fmt.Sprintf("%s msg=%s", "DEBUG", msg))
+			Debugw("log", msg)
+			expected = append(expected, fmt.Sprintf("%s log=%s", "DEBUG", msg))
 		case LevelInfo:
+			Info(msg)
+			expected = append(expected, fmt.Sprintf("%s msg=%s", "INFO", msg))
 			Infof(tc.content[0].(string), tc.content[1:]...)
 			expected = append(expected, fmt.Sprintf("%s msg=%s", "INFO", msg))
+			Infow("log", msg)
+			expected = append(expected, fmt.Sprintf("%s log=%s", "INFO", msg))
 		case LevelWarn:
+			Warn(msg)
+			expected = append(expected, fmt.Sprintf("%s msg=%s", "WARN", msg))
 			Warnf(tc.content[0].(string), tc.content[1:]...)
 			expected = append(expected, fmt.Sprintf("%s msg=%s", "WARN", msg))
+			Warnw("log", msg)
+			expected = append(expected, fmt.Sprintf("%s log=%s", "WARN", msg))
 		case LevelError:
+			Error(msg)
+			expected = append(expected, fmt.Sprintf("%s msg=%s", "ERROR", msg))
 			Errorf(tc.content[0].(string), tc.content[1:]...)
 			expected = append(expected, fmt.Sprintf("%s msg=%s", "ERROR", msg))
+			Errorw("log", msg)
+			expected = append(expected, fmt.Sprintf("%s log=%s", "ERROR", msg))
 		}
 	}
+	Log(LevelInfo, DefaultMessageKey, "test log")
+	expected = append(expected, fmt.Sprintf("%s msg=%s", "INFO", "test log"))
+
 	expected = append(expected, "")
 
 	t.Logf("Content: %s", buffer.String())
@@ -85,7 +109,7 @@ func TestGlobalLogUpdate(t *testing.T) {
 	}
 }
 
-func TestGolbalContext(t *testing.T) {
+func TestGlobalContext(t *testing.T) {
 	buffer := &bytes.Buffer{}
 	SetLogger(NewStdLogger(buffer))
 	Context(context.Background()).Infof("111")
diff --git a/log/log_test.go b/log/log_test.go
index 542bb79d..38417f76 100644
--- a/log/log_test.go
+++ b/log/log_test.go
@@ -7,7 +7,8 @@ import (
 
 func TestInfo(t *testing.T) {
 	logger := DefaultLogger
-	logger = With(logger, "ts", DefaultTimestamp, "caller", DefaultCaller)
+	logger = With(logger, "ts", DefaultTimestamp)
+	logger = With(logger, "caller", DefaultCaller)
 	_ = logger.Log(LevelInfo, "key1", "value1")
 }