This is an automated email from the ASF dual-hosted git repository.

alexstocks pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/develop by this push:
     new ad0868c10 test(common): add comprehensive unit tests for common 
package (#3130)
ad0868c10 is described below

commit ad0868c109c3c830d2198fc3af1996919716f983
Author: CAICAII <[email protected]>
AuthorDate: Mon Dec 22 14:11:44 2025 +0800

    test(common): add comprehensive unit tests for common package (#3130)
    
    * test(common): add comprehensive unit tests for common package
    
    * refactor(common): address security scan warnings in test files
    
    * fix(common): address security scan warnings in test files
    
    * fix(common): resolve SonarQube security warnings in test files
    
    * fix(common): replace hard-coded credentials with constants in tests
    
    * fix(common): use RFC 5737 documentation IPs instead of private IPs
    
    * fix: format common/url_test.go
    
    * fix: add synchronization to concurrent hystrix tests
---
 common/config/environment_test.go |  64 ++++
 common/config/utils_test.go       | 149 ++++++++
 common/host_util_test.go          |  67 ++++
 common/match_test.go              | 229 +++++++++++
 common/rpc_service_test.go        | 384 +++++++++++++++++++
 common/url_test.go                | 783 ++++++++++++++++++++++++++++++++++++--
 filter/hystrix/filter_test.go     |   4 +
 7 files changed, 1651 insertions(+), 29 deletions(-)

diff --git a/common/config/environment_test.go 
b/common/config/environment_test.go
index cf323cb89..c2d9b77c4 100644
--- a/common/config/environment_test.go
+++ b/common/config/environment_test.go
@@ -18,6 +18,7 @@
 package config
 
 import (
+       "sync"
        "testing"
 )
 
@@ -75,3 +76,66 @@ func TestInmemoryConfigurationGetSubProperty(t *testing.T) {
 
        assert.Equal(t, struct{}{}, m["123"])
 }
+
+func TestNewEnvInstance(t *testing.T) {
+       // Reset instance
+       oldInstance := instance
+       defer func() { instance = oldInstance }()
+
+       NewEnvInstance()
+       assert.NotNil(t, instance)
+       assert.True(t, instance.configCenterFirst)
+}
+
+func TestSetAndGetDynamicConfiguration(t *testing.T) {
+       env := GetEnvInstance()
+
+       // Initially nil
+       assert.Nil(t, env.GetDynamicConfiguration())
+
+       // Set and get
+       // Using nil as mock since we just test the setter/getter
+       env.SetDynamicConfiguration(nil)
+       assert.Nil(t, env.GetDynamicConfiguration())
+}
+
+func TestInmemoryConfigurationGetPropertyNilStore(t *testing.T) {
+       conf := &InmemoryConfiguration{store: nil}
+
+       ok, v := conf.GetProperty("key")
+       assert.False(t, ok)
+       assert.Equal(t, "", v)
+}
+
+func TestInmemoryConfigurationGetSubPropertyNilStore(t *testing.T) {
+       conf := &InmemoryConfiguration{store: nil}
+
+       result := conf.GetSubProperty("key")
+       assert.Nil(t, result)
+}
+
+func TestInmemoryConfigurationGetSubPropertyWithDot(t *testing.T) {
+       store := &sync.Map{}
+       store.Store("dubbo.protocol.name", "triple")
+       store.Store("dubbo.protocol.port", "20000")
+       store.Store("dubbo.registry.address", "nacos://127.0.0.1:8848")
+
+       conf := &InmemoryConfiguration{store: store}
+
+       // Get sub properties with prefix "dubbo."
+       result := conf.GetSubProperty("dubbo.")
+       assert.NotNil(t, result)
+       assert.Contains(t, result, "protocol")
+       assert.Contains(t, result, "registry")
+}
+
+func TestInmemoryConfigurationGetSubPropertyNoMatch(t *testing.T) {
+       store := &sync.Map{}
+       store.Store("other.key", "value")
+
+       conf := &InmemoryConfiguration{store: store}
+
+       result := conf.GetSubProperty("dubbo.")
+       assert.NotNil(t, result)
+       assert.Equal(t, 0, len(result))
+}
diff --git a/common/config/utils_test.go b/common/config/utils_test.go
new file mode 100644
index 000000000..13f9e203f
--- /dev/null
+++ b/common/config/utils_test.go
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package config
+
+import (
+       "testing"
+)
+
+import (
+       "github.com/stretchr/testify/assert"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3/common/constant"
+)
+
+func TestTranslateIds(t *testing.T) {
+       tests := []struct {
+               name     string
+               input    []string
+               expected []string
+       }{
+               {"single id", []string{"nacos"}, []string{"nacos"}},
+               {"comma separated", []string{"nacos,zk"}, []string{"nacos", 
"zk"}},
+               {"multiple entries", []string{"nacos", "zk"}, []string{"nacos", 
"zk"}},
+               {"mixed", []string{"nacos,zk", "etcd"}, []string{"nacos", "zk", 
"etcd"}},
+               {"duplicates", []string{"nacos,nacos"}, []string{"nacos"}},
+               {"empty string", []string{""}, []string{}},
+               {"empty slice", []string{}, []string{}},
+               {"with empty parts", []string{"nacos,,zk"}, []string{"nacos", 
"zk"}},
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       result := TranslateIds(tt.input)
+                       assert.Equal(t, tt.expected, result)
+               })
+       }
+}
+
+func TestRemoveDuplicateElement(t *testing.T) {
+       tests := []struct {
+               name     string
+               input    []string
+               expected []string
+       }{
+               {"no duplicates", []string{"a", "b", "c"}, []string{"a", "b", 
"c"}},
+               {"with duplicates", []string{"a", "b", "a", "c", "b"}, 
[]string{"a", "b", "c"}},
+               {"all same", []string{"a", "a", "a"}, []string{"a"}},
+               {"empty", []string{}, []string{}},
+               {"with empty strings", []string{"a", "", "b", ""}, 
[]string{"a", "b"}},
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       result := removeDuplicateElement(tt.input)
+                       assert.Equal(t, tt.expected, result)
+               })
+       }
+}
+
+type testStruct struct {
+       Name string `validate:"required"`
+       Age  int    `validate:"gte=0"`
+}
+
+func TestVerify(t *testing.T) {
+       // Valid struct
+       valid := &testStruct{Name: "test", Age: 10}
+       err := Verify(valid)
+       assert.NoError(t, err)
+
+       // Invalid struct - missing required field
+       invalid := &testStruct{Name: "", Age: 10}
+       err = Verify(invalid)
+       assert.Error(t, err)
+
+       // Invalid struct - negative age
+       invalid2 := &testStruct{Name: "test", Age: -1}
+       err = Verify(invalid2)
+       assert.Error(t, err)
+}
+
+func TestMergeValue(t *testing.T) {
+       tests := []struct {
+               name     string
+               str1     string
+               str2     string
+               def      string
+               expected string
+       }{
+               {"both empty use default", "", "", "default", "default"},
+               {"str1 only", "a,b", "", "default", "default,a,b"},
+               {"str2 only", "", "c,d", "default", "default,c,d"},
+               {"both have values", "a", "b", "default", "default,a,b"},
+               {"with default key", constant.DefaultKey + ",a", "b", "mydef", 
"mydef,a,b"},
+               {"with minus", "a,-b", "b,c", "default", "default,a,c"},
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       result := MergeValue(tt.str1, tt.str2, tt.def)
+                       assert.Equal(t, tt.expected, result)
+               })
+       }
+}
+
+func TestRemoveMinus(t *testing.T) {
+       tests := []struct {
+               name     string
+               input    []string
+               expected string
+       }{
+               {"empty", []string{}, ""},
+               {"no minus", []string{"a", "b", "c"}, "a,b,c"},
+               {"with minus", []string{"a", "-b", "b", "c"}, "a,c"},
+               {"all minus", []string{"-a", "-b"}, ""},
+               {"minus not found", []string{"a", "-x", "b"}, "a,b"},
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       result := removeMinus(tt.input)
+                       assert.Equal(t, tt.expected, result)
+               })
+       }
+}
+
+func TestIsValid(t *testing.T) {
+       assert.True(t, IsValid("127.0.0.1:8080"))
+       assert.True(t, IsValid("localhost"))
+       assert.False(t, IsValid(""))
+       assert.False(t, IsValid(constant.NotAvailable))
+}
diff --git a/common/host_util_test.go b/common/host_util_test.go
index 5e3b0f075..36db23db2 100644
--- a/common/host_util_test.go
+++ b/common/host_util_test.go
@@ -82,3 +82,70 @@ func TestGetRandomPort(t *testing.T) {
        port := GetRandomPort("")
        assert.True(t, port != "")
 }
+
+func TestIsMatchGlobPattern(t *testing.T) {
+       tests := []struct {
+               name     string
+               pattern  string
+               value    string
+               expected bool
+       }{
+               // * matches anything
+               {"any pattern", "*", "anything", true},
+               {"any pattern empty value", "*", "", true},
+
+               // both empty
+               {"both empty", "", "", true},
+
+               // one empty
+               {"pattern empty", "", "value", false},
+               {"value empty", "pattern", "", false},
+
+               // no wildcard - exact match
+               {"exact match", "hello", "hello", true},
+               {"exact not match", "hello", "world", false},
+
+               // * at the end - prefix match
+               {"prefix match", "hello*", "hello world", true},
+               {"prefix exact", "hello*", "hello", true},
+               {"prefix not match", "hello*", "world", false},
+
+               // * at the beginning - suffix match
+               {"suffix match", "*world", "hello world", true},
+               {"suffix exact", "*world", "world", true},
+               {"suffix not match", "*world", "hello", false},
+
+               // * in the middle - prefix and suffix match
+               {"middle match", "hello*world", "hello beautiful world", true},
+               {"middle exact", "hello*world", "helloworld", true},
+               {"middle prefix not match", "hello*world", "hi beautiful 
world", false},
+               {"middle suffix not match", "hello*world", "hello beautiful 
earth", false},
+               {"middle both not match", "hello*world", "hi earth", false},
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       assert.Equal(t, tt.expected, 
IsMatchGlobPattern(tt.pattern, tt.value))
+               })
+       }
+}
+
+func TestGetLocalIpCached(t *testing.T) {
+       // First call
+       ip1 := GetLocalIp()
+       assert.NotEmpty(t, ip1)
+
+       // Second call should return cached value
+       ip2 := GetLocalIp()
+       assert.Equal(t, ip1, ip2)
+}
+
+func TestGetLocalHostNameCached(t *testing.T) {
+       // First call
+       hostname1 := GetLocalHostName()
+       assert.NotEmpty(t, hostname1)
+
+       // Second call should return cached value
+       hostname2 := GetLocalHostName()
+       assert.Equal(t, hostname1, hostname2)
+}
diff --git a/common/match_test.go b/common/match_test.go
new file mode 100644
index 000000000..8dc5da22d
--- /dev/null
+++ b/common/match_test.go
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package common
+
+import (
+       "testing"
+)
+
+import (
+       "github.com/stretchr/testify/assert"
+)
+
+// Test IP addresses and patterns used for address matching tests.
+// Using RFC 5737 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 
203.0.113.0/24)
+// which are reserved for documentation and example purposes, and are exempt 
from
+// security scanner warnings per SonarQube rules.
+const (
+       testLoopback      = "127.0.0.1"      // loopback address (RFC 5735) - 
exempt
+       testCIDR          = "192.0.2.0/24"   // TEST-NET-1 CIDR (RFC 5737) - 
exempt
+       testIP1           = "192.0.2.1"      // TEST-NET-1 address (RFC 5737) - 
exempt
+       testIP2           = "192.0.2.2"      // TEST-NET-1 address (RFC 5737) - 
exempt
+       testIP100         = "192.0.2.100"    // TEST-NET-1 address (RFC 5737) - 
exempt
+       testIPOther       = "198.51.100.100" // TEST-NET-2 address (RFC 5737) - 
exempt
+       testIPPrivate     = "203.0.113.1"    // TEST-NET-3 address (RFC 5737) - 
exempt
+       testAnyHost       = "0.0.0.0"        // any address binding - exempt
+       testWildcard192   = "192.*"          // wildcard pattern for 192.x.x.x
+       testWildcard19202 = "192.0.2.*"      // wildcard pattern for TEST-NET-1
+)
+
+func TestParamMatchIsMatch(t *testing.T) {
+       u, _ := NewURL("dubbo://" + testLoopback + 
":20000?app=test&version=1.0")
+
+       tests := []struct {
+               name     string
+               param    ParamMatch
+               expected bool
+       }{
+               {
+                       name:     "exact match",
+                       param:    ParamMatch{Key: "app", Value: 
StringMatch{Exact: "test"}},
+                       expected: true,
+               },
+               {
+                       name:     "exact not match",
+                       param:    ParamMatch{Key: "app", Value: 
StringMatch{Exact: "other"}},
+                       expected: false,
+               },
+               {
+                       name:     "key not exists",
+                       param:    ParamMatch{Key: "nonexistent", Value: 
StringMatch{Exact: ""}},
+                       expected: false,
+               },
+               {
+                       name:     "prefix match",
+                       param:    ParamMatch{Key: "version", Value: 
StringMatch{Prefix: "1."}},
+                       expected: true,
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       assert.Equal(t, tt.expected, tt.param.IsMatch(u))
+               })
+       }
+}
+
+func TestStringMatchIsMatch(t *testing.T) {
+       tests := []struct {
+               name     string
+               match    StringMatch
+               value    string
+               expected bool
+       }{
+               // Exact match
+               {"exact match", StringMatch{Exact: "hello"}, "hello", true},
+               {"exact not match", StringMatch{Exact: "hello"}, "world", 
false},
+               {"exact empty value", StringMatch{Exact: "hello"}, "", false},
+
+               // Prefix match
+               {"prefix match", StringMatch{Prefix: "hello"}, "hello world", 
true},
+               {"prefix exact", StringMatch{Prefix: "hello"}, "hello", true},
+               {"prefix not match", StringMatch{Prefix: "hello"}, "world", 
false},
+               {"prefix empty value", StringMatch{Prefix: "hello"}, "", false},
+
+               // Regex match
+               {"regex match", StringMatch{Regex: "^hello.*"}, "hello world", 
true},
+               {"regex not match", StringMatch{Regex: "^hello.*"}, "world", 
false},
+               {"regex invalid pattern", StringMatch{Regex: "[invalid"}, 
"test", false},
+
+               // Wildcard match
+               {"wildcard exact", StringMatch{Wildcard: "hello"}, "hello", 
true},
+               {"wildcard any", StringMatch{Wildcard: "*"}, "anything", true},
+               {"wildcard not match", StringMatch{Wildcard: "hello"}, "world", 
false},
+
+               // Empty match
+               {"empty match", StringMatch{Empty: "true"}, "", true},
+               {"empty not match", StringMatch{Empty: "true"}, "value", false},
+
+               // Noempty match
+               {"noempty match", StringMatch{Noempty: "true"}, "value", true},
+               {"noempty not match", StringMatch{Noempty: "true"}, "", false},
+
+               // No match condition
+               {"no condition", StringMatch{}, "value", false},
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       assert.Equal(t, tt.expected, tt.match.IsMatch(tt.value))
+               })
+       }
+}
+
+func TestAddressMatchIsMatch(t *testing.T) {
+       tests := []struct {
+               name     string
+               match    AddressMatch
+               value    string
+               expected bool
+       }{
+               // CIDR match
+               {"cidr match", AddressMatch{Cird: testCIDR}, testIP100, true},
+               {"cidr not match", AddressMatch{Cird: testCIDR}, testIPOther, 
false},
+               {"cidr invalid", AddressMatch{Cird: "invalid"}, testIP1, false},
+               {"cidr empty value", AddressMatch{Cird: testCIDR}, "", false},
+
+               // Wildcard match
+               {"wildcard any value *", AddressMatch{Wildcard: 
testWildcard192}, "*", true},
+               {"wildcard any host 0.0.0.0", AddressMatch{Wildcard: 
testWildcard192}, testAnyHost, true},
+               {"wildcard pattern match", AddressMatch{Wildcard: 
testWildcard19202}, testIP1, true},
+               {"wildcard pattern not match", AddressMatch{Wildcard: 
testWildcard19202}, testIPPrivate, false},
+               {"wildcard empty value", AddressMatch{Wildcard: 
testWildcard192}, "", false},
+
+               // Exact match
+               {"exact match", AddressMatch{Exact: testIP1}, testIP1, true},
+               {"exact not match", AddressMatch{Exact: testIP1}, testIP2, 
false},
+               {"exact empty value", AddressMatch{Exact: testIP1}, "", false},
+
+               // No condition
+               {"no condition", AddressMatch{}, testIP1, false},
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       assert.Equal(t, tt.expected, tt.match.IsMatch(tt.value))
+               })
+       }
+}
+
+func TestListStringMatchIsMatch(t *testing.T) {
+       tests := []struct {
+               name     string
+               match    ListStringMatch
+               value    string
+               expected bool
+       }{
+               {
+                       name: "match first",
+                       match: ListStringMatch{
+                               Oneof: []StringMatch{
+                                       {Exact: "hello"},
+                                       {Exact: "world"},
+                               },
+                       },
+                       value:    "hello",
+                       expected: true,
+               },
+               {
+                       name: "match second",
+                       match: ListStringMatch{
+                               Oneof: []StringMatch{
+                                       {Exact: "hello"},
+                                       {Exact: "world"},
+                               },
+                       },
+                       value:    "world",
+                       expected: true,
+               },
+               {
+                       name: "no match",
+                       match: ListStringMatch{
+                               Oneof: []StringMatch{
+                                       {Exact: "hello"},
+                                       {Exact: "world"},
+                               },
+                       },
+                       value:    "other",
+                       expected: false,
+               },
+               {
+                       name:     "empty list",
+                       match:    ListStringMatch{Oneof: []StringMatch{}},
+                       value:    "hello",
+                       expected: false,
+               },
+               {
+                       name: "mixed match types",
+                       match: ListStringMatch{
+                               Oneof: []StringMatch{
+                                       {Prefix: "hello"},
+                                       {Regex: "^world.*"},
+                               },
+                       },
+                       value:    "world123",
+                       expected: true,
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       assert.Equal(t, tt.expected, tt.match.IsMatch(tt.value))
+               })
+       }
+}
diff --git a/common/rpc_service_test.go b/common/rpc_service_test.go
index e5039c221..5b1c21e8e 100644
--- a/common/rpc_service_test.go
+++ b/common/rpc_service_test.go
@@ -251,3 +251,387 @@ func TestGetReference(t *testing.T) {
        ref5 := GetReference(s5)
        assert.Equal(t, expectedReference, ref5)
 }
+
+// Additional tests for better coverage
+
+func TestServiceMethods(t *testing.T) {
+       s := &TestService{}
+       _, err := ServiceMap.Register("TestServiceMethods", testProtocol, 
"group1", "v1", s)
+       assert.NoError(t, err)
+
+       service := ServiceMap.GetService(testProtocol, "TestServiceMethods", 
"group1", "v1")
+       assert.NotNil(t, service)
+
+       // Test Service.Method()
+       methods := service.Method()
+       assert.NotNil(t, methods)
+       assert.True(t, len(methods) > 0)
+
+       // Test Service.Name()
+       assert.Equal(t, "group1/TestServiceMethods:v1", service.Name())
+
+       // Test Service.ServiceType()
+       svcType := service.ServiceType()
+       assert.NotNil(t, svcType)
+       assert.Equal(t, "*common.TestService", svcType.String())
+
+       // Test Service.Service()
+       svcValue := service.Service()
+       assert.True(t, svcValue.IsValid())
+
+       // Cleanup
+       ServiceMap.UnRegister("TestServiceMethods", testProtocol, 
ServiceKey("TestServiceMethods", "group1", "v1"))
+}
+
+func TestGetServiceByServiceKey(t *testing.T) {
+       s := &TestService{}
+       _, err := ServiceMap.Register("TestGetServiceByKey", testProtocol, "", 
"v1", s)
+       assert.NoError(t, err)
+
+       // Test GetServiceByServiceKey - found
+       serviceKey := ServiceKey("TestGetServiceByKey", "", "v1")
+       service := ServiceMap.GetServiceByServiceKey(testProtocol, serviceKey)
+       assert.NotNil(t, service)
+
+       // Test GetServiceByServiceKey - protocol not found
+       service = ServiceMap.GetServiceByServiceKey("nonexistent", serviceKey)
+       assert.Nil(t, service)
+
+       // Test GetServiceByServiceKey - service key not found
+       service = ServiceMap.GetServiceByServiceKey(testProtocol, 
"nonexistent:v1")
+       assert.Nil(t, service)
+
+       // Cleanup
+       ServiceMap.UnRegister("TestGetServiceByKey", testProtocol, serviceKey)
+}
+
+func TestGetInterface(t *testing.T) {
+       s := &TestService{}
+       _, err := ServiceMap.Register("TestGetInterface", testProtocol, "", 
"v1", s)
+       assert.NoError(t, err)
+
+       // Test GetInterface - found
+       services := ServiceMap.GetInterface("TestGetInterface")
+       assert.NotNil(t, services)
+       assert.Equal(t, 1, len(services))
+
+       // Test GetInterface - not found
+       services = ServiceMap.GetInterface("nonexistent")
+       assert.Nil(t, services)
+
+       // Cleanup
+       ServiceMap.UnRegister("TestGetInterface", testProtocol, 
ServiceKey("TestGetInterface", "", "v1"))
+}
+
+func TestMethodTypeSuiteContextInvalid(t *testing.T) {
+       mt := &MethodType{ctxType: 
reflect.TypeOf((*context.Context)(nil)).Elem()}
+
+       // Test with nil context (invalid)
+       var nilCtx context.Context = nil
+       result := mt.SuiteContext(nilCtx)
+       assert.True(t, result.IsValid())
+       assert.True(t, result.IsZero())
+}
+
+func TestIsExported(t *testing.T) {
+       assert.True(t, isExported("Exported"))
+       assert.True(t, isExported("A"))
+       assert.False(t, isExported("unexported"))
+       assert.False(t, isExported("a"))
+       assert.False(t, isExported(""))
+}
+
+func TestIsExportedOrBuiltinType(t *testing.T) {
+       // Exported type
+       assert.True(t, isExportedOrBuiltinType(reflect.TypeOf(TestService{})))
+
+       // Pointer to exported type
+       assert.True(t, isExportedOrBuiltinType(reflect.TypeOf(&TestService{})))
+
+       // Builtin type (string)
+       assert.True(t, isExportedOrBuiltinType(reflect.TypeOf("")))
+
+       // Builtin type (int)
+       assert.True(t, isExportedOrBuiltinType(reflect.TypeOf(0)))
+
+       // Pointer to builtin
+       var i int
+       assert.True(t, isExportedOrBuiltinType(reflect.TypeOf(&i)))
+
+       // Unexported type
+       assert.False(t, isExportedOrBuiltinType(reflect.TypeOf(testService{})))
+}
+
+// Test service with XXX prefix methods (should be skipped)
+type TestServiceWithXXX struct{}
+
+func (s *TestServiceWithXXX) XXX_InterfaceName() string {
+       return "test"
+}
+
+func (s *TestServiceWithXXX) NormalMethod(ctx context.Context) error {
+       return nil
+}
+
+func (s *TestServiceWithXXX) Reference() string {
+       return "TestServiceWithXXX"
+}
+
+func TestSuiteMethodSkipsXXXPrefix(t *testing.T) {
+       s := &TestServiceWithXXX{}
+       sType := reflect.TypeOf(s)
+
+       // XXX_ prefixed method should be skipped
+       method, ok := sType.MethodByName("XXX_InterfaceName")
+       assert.True(t, ok)
+       mt := suiteMethod(method)
+       assert.Nil(t, mt)
+
+       // Reference method should be skipped
+       method, ok = sType.MethodByName("Reference")
+       assert.True(t, ok)
+       mt = suiteMethod(method)
+       assert.Nil(t, mt)
+
+       // Normal method should not be skipped
+       method, ok = sType.MethodByName("NormalMethod")
+       assert.True(t, ok)
+       mt = suiteMethod(method)
+       assert.NotNil(t, mt)
+}
+
+// Test service with SetGRPCServer method
+type TestServiceWithGRPC struct{}
+
+func (s *TestServiceWithGRPC) SetGRPCServer(server any) {}
+
+func (s *TestServiceWithGRPC) ValidMethod(ctx context.Context, arg any) error {
+       return nil
+}
+
+func TestSuiteMethodSkipsSetGRPCServer(t *testing.T) {
+       s := &TestServiceWithGRPC{}
+       sType := reflect.TypeOf(s)
+
+       // SetGRPCServer should be skipped
+       method, ok := sType.MethodByName("SetGRPCServer")
+       assert.True(t, ok)
+       mt := suiteMethod(method)
+       assert.Nil(t, mt)
+}
+
+func TestGetReferenceWithStruct(t *testing.T) {
+       // Test with struct (not pointer)
+       s := TestService{}
+       ref := GetReference(s)
+       assert.Equal(t, "TestService", ref)
+}
+
+func TestGetReferenceWithAnonymousStruct(t *testing.T) {
+       // Anonymous struct embedded in pointer
+       s := &struct {
+               ServiceWithoutRef
+       }{}
+       ref := GetReference(s)
+       assert.Equal(t, "ServiceWithoutRef", ref)
+}
+
+func TestRegisterWithEmptyServiceName(t *testing.T) {
+       // This tests the edge case where service name cannot be determined
+       // Using a non-struct type
+       var fn func()
+       _, err := ServiceMap.Register("test", "proto", "", "v1", fn)
+       assert.Error(t, err)
+       assert.Contains(t, err.Error(), "no service name")
+}
+
+func TestUnRegisterInterfaceNotFound(t *testing.T) {
+       s := &TestService{}
+       _, err := ServiceMap.Register("TestUnRegisterInterface", testProtocol, 
"", "v1", s)
+       assert.NoError(t, err)
+
+       // Manually remove from interfaceMap to simulate inconsistent state
+       ServiceMap.mutex.Lock()
+       delete(ServiceMap.interfaceMap, "TestUnRegisterInterface")
+       ServiceMap.mutex.Unlock()
+
+       err = ServiceMap.UnRegister("TestUnRegisterInterface", testProtocol, 
ServiceKey("TestUnRegisterInterface", "", "v1"))
+       assert.Error(t, err)
+       assert.Contains(t, err.Error(), "no service for 
TestUnRegisterInterface")
+
+       // Cleanup
+       ServiceMap.mutex.Lock()
+       delete(ServiceMap.serviceMap[testProtocol], 
ServiceKey("TestUnRegisterInterface", "", "v1"))
+       ServiceMap.mutex.Unlock()
+}
+
+func TestSuitableMethodsWithMethodMapper(t *testing.T) {
+       s := &TestService{}
+       methods, methodMap := suitableMethods(reflect.TypeOf(s))
+
+       // Check that MethodMapper renamed MethodTwo to methodTwo
+       assert.Contains(t, methods, "methodTwo")
+       assert.Contains(t, methods, "MethodTwo") // swapped case version
+
+       // Verify the method exists in map
+       _, ok := methodMap["methodTwo"]
+       assert.True(t, ok)
+}
+
+// Service with method that has unexported method (not exported via PkgPath)
+type TestServiceUnexportedMethod struct{}
+
+func (s *TestServiceUnexportedMethod) ValidMethod(ctx context.Context) error {
+       return nil
+}
+
+func TestSuiteMethodWithUnexportedMethod(t *testing.T) {
+       s := &TestServiceUnexportedMethod{}
+       sType := reflect.TypeOf(s)
+
+       method, ok := sType.MethodByName("ValidMethod")
+       assert.True(t, ok)
+
+       // Method should be exported (PkgPath is empty for exported methods)
+       assert.Equal(t, "", method.PkgPath)
+
+       mt := suiteMethod(method)
+       assert.NotNil(t, mt)
+}
+
+func TestServiceInfoStruct(t *testing.T) {
+       // Test ServiceInfo struct initialization
+       info := ServiceInfo{
+               InterfaceName: "com.test.Service",
+               ServiceType:   &TestService{},
+               Methods: []MethodInfo{
+                       {
+                               Name: "TestMethod",
+                               Type: "unary",
+                               Meta: map[string]any{"key": "value"},
+                       },
+               },
+               Meta: map[string]any{"version": "1.0"},
+       }
+
+       assert.Equal(t, "com.test.Service", info.InterfaceName)
+       assert.NotNil(t, info.ServiceType)
+       assert.Equal(t, 1, len(info.Methods))
+       assert.Equal(t, "TestMethod", info.Methods[0].Name)
+       assert.Equal(t, "unary", info.Methods[0].Type)
+       assert.Equal(t, "value", info.Methods[0].Meta["key"])
+       assert.Equal(t, "1.0", info.Meta["version"])
+}
+
+func TestMethodInfoFunctions(t *testing.T) {
+       // Test MethodInfo with function fields
+       reqInitCalled := false
+       streamInitCalled := false
+       methodFuncCalled := false
+
+       info := MethodInfo{
+               Name: "TestMethod",
+               Type: "unary",
+               ReqInitFunc: func() any {
+                       reqInitCalled = true
+                       return struct{}{}
+               },
+               StreamInitFunc: func(baseStream any) any {
+                       streamInitCalled = true
+                       return baseStream
+               },
+               MethodFunc: func(ctx context.Context, args []any, handler any) 
(any, error) {
+                       methodFuncCalled = true
+                       return nil, nil
+               },
+       }
+
+       // Call the functions
+       info.ReqInitFunc()
+       assert.True(t, reqInitCalled)
+
+       info.StreamInitFunc(nil)
+       assert.True(t, streamInitCalled)
+
+       info.MethodFunc(context.Background(), nil, nil)
+       assert.True(t, methodFuncCalled)
+}
+
+func TestRegisterMultipleServicesForSameInterface(t *testing.T) {
+       s1 := &TestService{}
+       s2 := &TestService{}
+
+       _, err := ServiceMap.Register("MultiService", testProtocol, "group1", 
"v1", s1)
+       assert.NoError(t, err)
+
+       _, err = ServiceMap.Register("MultiService", testProtocol, "group2", 
"v1", s2)
+       assert.NoError(t, err)
+
+       // Should have 2 services for the same interface
+       services := ServiceMap.GetInterface("MultiService")
+       assert.Equal(t, 2, len(services))
+
+       // Cleanup
+       ServiceMap.UnRegister("MultiService", testProtocol, 
ServiceKey("MultiService", "group1", "v1"))
+       ServiceMap.UnRegister("MultiService", testProtocol, 
ServiceKey("MultiService", "group2", "v1"))
+}
+
+func TestUnRegisterLastServiceInProtocol(t *testing.T) {
+       s := &TestService{}
+       protocol := "uniqueProtocol"
+
+       _, err := ServiceMap.Register("TestLastService", protocol, "", "v1", s)
+       assert.NoError(t, err)
+
+       // Verify protocol exists
+       ServiceMap.mutex.RLock()
+       _, exists := ServiceMap.serviceMap[protocol]
+       ServiceMap.mutex.RUnlock()
+       assert.True(t, exists)
+
+       // Unregister the only service
+       err = ServiceMap.UnRegister("TestLastService", protocol, 
ServiceKey("TestLastService", "", "v1"))
+       assert.NoError(t, err)
+
+       // Protocol should be removed from serviceMap
+       ServiceMap.mutex.RLock()
+       _, exists = ServiceMap.serviceMap[protocol]
+       ServiceMap.mutex.RUnlock()
+       assert.False(t, exists)
+}
+
+// Test with method that has wrong return type (not error)
+type TestServiceWrongReturn struct{}
+
+func (s *TestServiceWrongReturn) WrongReturn(ctx context.Context) string {
+       return ""
+}
+
+func TestSuiteMethodWrongReturnType(t *testing.T) {
+       s := &TestServiceWrongReturn{}
+       sType := reflect.TypeOf(s)
+
+       method, ok := sType.MethodByName("WrongReturn")
+       assert.True(t, ok)
+
+       mt := suiteMethod(method)
+       assert.Nil(t, mt) // Should be nil because return type is not error
+}
+
+// Test with method that has too many return values
+type TestServiceTooManyReturns struct{}
+
+func (s *TestServiceTooManyReturns) TooManyReturns(ctx context.Context) (any, 
any, error) {
+       return nil, nil, nil
+}
+
+func TestSuiteMethodTooManyReturns(t *testing.T) {
+       s := &TestServiceTooManyReturns{}
+       sType := reflect.TypeOf(s)
+
+       method, ok := sType.MethodByName("TooManyReturns")
+       assert.True(t, ok)
+
+       mt := suiteMethod(method)
+       assert.Nil(t, mt) // Should be nil because too many return values
+}
diff --git a/common/url_test.go b/common/url_test.go
index 2026c82e4..a2c082a29 100644
--- a/common/url_test.go
+++ b/common/url_test.go
@@ -15,15 +15,31 @@
  * limitations under the License.
  */
 
+// Package common url_test.go contains unit tests for URL parsing and 
manipulation.
+//
+// SECURITY NOTE: This file contains hardcoded IP addresses which are used 
exclusively
+// for testing URL parsing functionality. These addresses are:
+// - 127.0.0.1, 127.0.0.2: loopback addresses (RFC 5735) - exempt
+// - 0.0.0.0: any address binding (RFC 5735) - exempt
+// - 192.0.2.x: TEST-NET-1 documentation addresses (RFC 5737) - exempt
+// - 1.1.1.1, 2.2.2.2, etc.: used in routing rule test strings
+//
+// These addresses are NOT used for actual network connections in production.
+// They are test fixtures for validating URL parsing logic only.
+// #nosec G101 -- This file contains test credentials and IP addresses for 
unit testing
+
 package common
 
 import (
        "encoding/base64"
        "net/url"
        "testing"
+       "time"
 )
 
 import (
+       gxset "github.com/dubbogo/gost/container/set"
+
        "github.com/stretchr/testify/assert"
 )
 
@@ -31,10 +47,23 @@ import (
        "dubbo.apache.org/dubbo-go/v3/common/constant"
 )
 
+// Test constants for URL parsing tests.
+// These IP addresses are used for unit testing only and are reserved for 
documentation
+// purposes per RFC 5737 (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24) or are
+// loopback/special addresses per RFC 5735 which are exempt from security 
scanner warnings.
 const (
        userName        = "username"
-       password        = "password"
+       testPassword    = "testpass" // #nosec G101 - test credential for unit 
tests
        loopbackAddress = "127.0.0.1"
+       loopbackAddr2   = "127.0.0.2"
+       anyAddress      = "0.0.0.0"
+       docIP1          = "192.0.2.1"   // TEST-NET-1 (RFC 5737) - exempt from 
security scanners
+       docIP56         = "192.0.2.56"  // TEST-NET-1 (RFC 5737) - exempt from 
security scanners
+       docIP100        = "192.0.2.100" // TEST-NET-1 (RFC 5737) - exempt from 
security scanners
+       testPort        = "20000"
+       testPort2       = "20001"
+       testPort8080    = "8080"
+       testPort30000   = "30000"
 )
 
 func TestNewURLWithOptions(t *testing.T) {
@@ -43,7 +72,7 @@ func TestNewURLWithOptions(t *testing.T) {
        params.Set("key", "value")
        u := NewURLWithOptions(WithPath("com.test.Service"),
                WithUsername(userName),
-               WithPassword(password),
+               WithPassword(testPassword),
                WithProtocol("testprotocol"),
                WithIp(loopbackAddress),
                WithPort("8080"),
@@ -55,7 +84,7 @@ func TestNewURLWithOptions(t *testing.T) {
        )
        assert.Equal(t, "/com.test.Service", u.Path)
        assert.Equal(t, userName, u.Username)
-       assert.Equal(t, password, u.Password)
+       assert.Equal(t, testPassword, u.Password)
        assert.Equal(t, "testprotocol", u.Protocol)
        assert.Equal(t, loopbackAddress, u.Ip)
        assert.Equal(t, "8080", u.Port)
@@ -67,7 +96,7 @@ func TestNewURLWithOptions(t *testing.T) {
 func TestURL(t *testing.T) {
        u, err := 
NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&" +
                
"application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"
 +
-               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"
 +
+               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.0.2.56&methods=GetUser%2C&"
 +
                
"module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"
 +
                "side=provider&timeout=3000&timestamp=1556509797245")
        assert.NoError(t, err)
@@ -86,20 +115,20 @@ func TestURL(t *testing.T) {
        assert.Equal(t, "", u.Username)
        assert.Equal(t, "", u.Password)
        assert.Equal(t, 
"anyhost=true&application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-"+
-               
"provider-golang-1.0.0&environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%"+
+               
"provider-golang-1.0.0&environment=dev&interface=com.ikurento.user.UserProvider&ip=192.0.2.56&methods=GetUser%"+
                
"2C&module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&side=provider&timeout=3000&t"+
                "imestamp=1556509797245", u.params.Encode())
 
        assert.Equal(t, 
"dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&application=BDTServi"+
                
"ce&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&environment=dev&interface=com.ikure"+
-               
"nto.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&module=dubbogo+user-info+server&org=ikurento.com&owner="+
+               
"nto.user.UserProvider&ip=192.0.2.56&methods=GetUser%2C&module=dubbogo+user-info+server&org=ikurento.com&owner="+
                
"ZX&pid=1447&revision=0.0.1&side=provider&timeout=3000&timestamp=1556509797245",
 u.String())
 }
 
 func TestURLWithoutSchema(t *testing.T) {
        u, err := 
NewURL("127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&"+
                
"application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"+
-               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"+
+               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.0.2.56&methods=GetUser%2C&"+
                
"module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"+
                "side=provider&timeout=3000&timestamp=1556509797245", 
WithProtocol("dubbo"))
        assert.NoError(t, err)
@@ -113,13 +142,13 @@ func TestURLWithoutSchema(t *testing.T) {
        assert.Equal(t, "", u.Username)
        assert.Equal(t, "", u.Password)
        assert.Equal(t, 
"anyhost=true&application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-"+
-               
"provider-golang-1.0.0&environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%"+
+               
"provider-golang-1.0.0&environment=dev&interface=com.ikurento.user.UserProvider&ip=192.0.2.56&methods=GetUser%"+
                
"2C&module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&side=provider&timeout=3000&t"+
                "imestamp=1556509797245", u.params.Encode())
 
        assert.Equal(t, 
"dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&application=BDTServi"+
                
"ce&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&environment=dev&interface=com.ikure"+
-               
"nto.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&module=dubbogo+user-info+server&org=ikurento.com&owner="+
+               
"nto.user.UserProvider&ip=192.0.2.56&methods=GetUser%2C&module=dubbogo+user-info+server&org=ikurento.com&owner="+
                
"ZX&pid=1447&revision=0.0.1&side=provider&timeout=3000&timestamp=1556509797245",
 u.String())
 }
 
@@ -235,30 +264,30 @@ func TestURLGetParamAndDecoded(t *testing.T) {
 }
 
 func TestURLGetRawParam(t *testing.T) {
-       u, _ := 
NewURL("condition://0.0.0.0:8080/com.foo.BarService?serialization=fastjson")
-       u.Username = "test"
-       u.Password = "test"
+       u, _ := NewURL("condition://" + anyAddress + ":" + testPort8080 + 
"/com.foo.BarService?serialization=fastjson")
+       u.Username = userName
+       u.Password = testPassword // #nosec G101 - test credential
        assert.Equal(t, "condition", u.GetRawParam("protocol"))
-       assert.Equal(t, "0.0.0.0", u.GetRawParam("host"))
-       assert.Equal(t, "8080", u.GetRawParam("port"))
-       assert.Equal(t, "test", u.GetRawParam(userName))
-       assert.Equal(t, "test", u.GetRawParam(password))
+       assert.Equal(t, anyAddress, u.GetRawParam("host"))
+       assert.Equal(t, testPort8080, u.GetRawParam("port"))
+       assert.Equal(t, userName, u.GetRawParam(userName))
+       assert.Equal(t, testPassword, u.GetRawParam("password"))
        assert.Equal(t, "/com.foo.BarService", u.GetRawParam("path"))
        assert.Equal(t, "fastjson", u.GetRawParam("serialization"))
 }
 
 func TestURLToMap(t *testing.T) {
-       u, _ := 
NewURL("condition://0.0.0.0:8080/com.foo.BarService?serialization=fastjson")
-       u.Username = "test"
-       u.Password = "test"
+       u, _ := NewURL("condition://" + anyAddress + ":" + testPort8080 + 
"/com.foo.BarService?serialization=fastjson")
+       u.Username = userName
+       u.Password = testPassword // #nosec G101 - test credential
 
        m := u.ToMap()
        assert.Equal(t, 7, len(m))
        assert.Equal(t, "condition", m["protocol"])
-       assert.Equal(t, "0.0.0.0", m["host"])
-       assert.Equal(t, "8080", m["port"])
-       assert.Equal(t, "test", m[userName])
-       assert.Equal(t, "test", m[password])
+       assert.Equal(t, anyAddress, m["host"])
+       assert.Equal(t, testPort8080, m["port"])
+       assert.Equal(t, userName, m[userName])
+       assert.Equal(t, testPassword, m["password"])
        assert.Equal(t, "/com.foo.BarService", m["path"])
        assert.Equal(t, "fastjson", m["serialization"])
 }
@@ -396,12 +425,12 @@ func TestCompareURLEqualFunc(t *testing.T) {
        // test Default
        url1, _ := 
NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&" +
                
"application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"
 +
-               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"
 +
+               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.0.2.56&methods=GetUser%2C&"
 +
                
"module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"
 +
                "side=provider&timeout=3000&timestamp=1556509797245")
        url2, _ := 
NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&" +
                
"application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"
 +
-               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"
 +
+               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.0.2.56&methods=GetUser%2C&"
 +
                
"module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"
 +
                "side=provider&timeout=3000&timestamp=155650979798")
        assert.False(t, GetCompareURLEqualFunc()(url1, url2))
@@ -410,12 +439,12 @@ func TestCompareURLEqualFunc(t *testing.T) {
        // test custom
        url1, _ = 
NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&" +
                
"application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"
 +
-               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"
 +
+               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.0.2.56&methods=GetUser%2C&"
 +
                
"module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"
 +
                "side=provider&timeout=3000&timestamp=1556509797245")
        url2, _ = 
NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&" +
                
"application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"
 +
-               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"
 +
+               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.0.2.56&methods=GetUser%2C&"
 +
                
"module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"
 +
                "side=provider&timeout=3000&timestamp=155650979798")
        assert.True(t, GetCompareURLEqualFunc()(url1, url2, 
constant.TimestampKey, constant.RemoteTimestampKey))
@@ -425,12 +454,12 @@ func TestCompareURLEqualFunc(t *testing.T) {
 
        url1, _ = 
NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&" +
                
"application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"
 +
-               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"
 +
+               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.0.2.56&methods=GetUser%2C&"
 +
                
"module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"
 +
                "side=provider&timeout=3000")
        url2, _ = 
NewURL("dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&" +
                
"application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"
 +
-               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"
 +
+               
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.0.2.56&methods=GetUser%2C&"
 +
                
"module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"
 +
                "side=provider&timeout=3000")
        assert.True(t, GetCompareURLEqualFunc()(url1, url2))
@@ -648,3 +677,699 @@ func TestURLSetParamsMultiValue(t *testing.T) {
        got3 := u2.GetParams()["only_empty"]
        assert.ElementsMatch(t, []string{""}, got3)
 }
+
+func TestRoleType(t *testing.T) {
+       assert.Equal(t, "consumers", RoleType(CONSUMER).String())
+       assert.Equal(t, "configurators", RoleType(CONFIGURATOR).String())
+       assert.Equal(t, "routers", RoleType(ROUTER).String())
+       assert.Equal(t, "providers", RoleType(PROVIDER).String())
+
+       assert.Equal(t, "consumer", RoleType(CONSUMER).Role())
+       assert.Equal(t, "", RoleType(CONFIGURATOR).Role())
+       assert.Equal(t, "routers", RoleType(ROUTER).Role())
+       assert.Equal(t, "provider", RoleType(PROVIDER).Role())
+}
+
+func TestJavaClassName(t *testing.T) {
+       u := &URL{}
+       assert.Equal(t, "org.apache.dubbo.common.URL", u.JavaClassName())
+}
+
+func TestWithInterface(t *testing.T) {
+       u := NewURLWithOptions(WithInterface("com.test.Service"))
+       assert.Equal(t, "com.test.Service", u.GetParam(constant.InterfaceKey, 
""))
+}
+
+func TestWithLocation(t *testing.T) {
+       // WithLocation sets Location, but NewURLWithOptions overwrites it with 
Ip:Port
+       // So we need to set Ip and Port as well, or test the option directly
+       u := &URL{}
+       WithLocation(docIP1 + ":" + testPort8080)(u)
+       assert.Equal(t, docIP1+":"+testPort8080, u.Location)
+
+       // When using NewURLWithOptions with Ip and Port
+       u2 := NewURLWithOptions(WithIp(docIP1), WithPort(testPort8080))
+       assert.Equal(t, docIP1+":"+testPort8080, u2.Location)
+}
+
+func TestWithToken(t *testing.T) {
+       // empty token
+       u1 := NewURLWithOptions(WithToken(""))
+       assert.Equal(t, "", u1.GetParam(constant.TokenKey, ""))
+
+       // custom token
+       u2 := NewURLWithOptions(WithToken("my-token"))
+       assert.Equal(t, "my-token", u2.GetParam(constant.TokenKey, ""))
+
+       // "true" generates UUID
+       u3 := NewURLWithOptions(WithToken("true"))
+       token := u3.GetParam(constant.TokenKey, "")
+       assert.NotEmpty(t, token)
+       assert.NotEqual(t, "true", token)
+
+       // "default" generates UUID
+       u4 := NewURLWithOptions(WithToken("default"))
+       token2 := u4.GetParam(constant.TokenKey, "")
+       assert.NotEmpty(t, token2)
+       assert.NotEqual(t, "default", token2)
+
+       // "TRUE" (uppercase) generates UUID
+       u5 := NewURLWithOptions(WithToken("TRUE"))
+       token3 := u5.GetParam(constant.TokenKey, "")
+       assert.NotEmpty(t, token3)
+       assert.NotEqual(t, "TRUE", token3)
+}
+
+func TestWithWeight(t *testing.T) {
+       // positive weight
+       u1 := NewURLWithOptions(WithWeight(100))
+       assert.Equal(t, "100", u1.GetParam(constant.WeightKey, ""))
+
+       // zero weight (should not be set)
+       u2 := NewURLWithOptions(WithWeight(0))
+       assert.Equal(t, "", u2.GetParam(constant.WeightKey, ""))
+
+       // negative weight (should not be set)
+       u3 := NewURLWithOptions(WithWeight(-1))
+       assert.Equal(t, "", u3.GetParam(constant.WeightKey, ""))
+}
+
+func TestMatchKey(t *testing.T) {
+       assert.Equal(t, "com.test.Service:dubbo", MatchKey("com.test.Service", 
"dubbo"))
+       assert.Equal(t, ":http", MatchKey("", "http"))
+}
+
+func TestURLGroupInterfaceVersion(t *testing.T) {
+       u, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?interface=com.test.Service&group=test-group&version=1.0.0")
+       assert.Equal(t, "test-group", u.Group())
+       assert.Equal(t, "com.test.Service", u.Interface())
+       assert.Equal(t, "1.0.0", u.Version())
+}
+
+func TestURLAddress(t *testing.T) {
+       u1 := &URL{Ip: docIP1, Port: testPort8080}
+       assert.Equal(t, docIP1+":"+testPort8080, u1.Address())
+
+       u2 := &URL{Ip: docIP1, Port: ""}
+       assert.Equal(t, docIP1, u2.Address())
+}
+
+func TestURLKey(t *testing.T) {
+       // #nosec G101 - test credential for URL key test
+       u, _ := NewURL("dubbo://" + userName + ":" + testPassword + "@" + 
loopbackAddress + ":" + testPort + 
"/com.test.Service?interface=com.test.Service&group=g1&version=1.0")
+       key := u.Key()
+       assert.Contains(t, key, "dubbo://")
+       assert.Contains(t, key, userName+":"+testPassword+"@")
+       assert.Contains(t, key, "interface=com.test.Service")
+       assert.Contains(t, key, "group=g1")
+       assert.Contains(t, key, "version=1.0")
+}
+
+func TestGetCacheInvokerMapKey(t *testing.T) {
+       u, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?interface=com.test.Service&group=g1&version=1.0&timestamp=12345")
+       key := u.GetCacheInvokerMapKey()
+       assert.Contains(t, key, "interface=com.test.Service")
+       assert.Contains(t, key, "group=g1")
+       assert.Contains(t, key, "version=1.0")
+       assert.Contains(t, key, "timestamp=12345")
+}
+
+func TestServiceKey(t *testing.T) {
+       // with group and version
+       assert.Equal(t, "group/interface:version", ServiceKey("interface", 
"group", "version"))
+
+       // without group
+       assert.Equal(t, "interface:version", ServiceKey("interface", "", 
"version"))
+
+       // without version
+       assert.Equal(t, "group/interface", ServiceKey("interface", "group", ""))
+
+       // version 0.0.0 should be ignored
+       assert.Equal(t, "group/interface", ServiceKey("interface", "group", 
"0.0.0"))
+
+       // empty interface
+       assert.Equal(t, "", ServiceKey("", "group", "version"))
+
+       // URL method
+       u, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?interface=com.test.Service&group=g1&version=1.0")
+       assert.Equal(t, "g1/com.test.Service:1.0", u.ServiceKey())
+}
+
+func TestEncodedServiceKey(t *testing.T) {
+       u, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?interface=com.test.Service&group=g1&version=1.0")
+       encoded := u.EncodedServiceKey()
+       assert.Equal(t, "g1*com.test.Service:1.0", encoded)
+}
+
+func TestServiceWithSubURL(t *testing.T) {
+       subURL, _ := NewURL("dubbo://127.0.0.1:20000?interface=com.sub.Service")
+       u := &URL{SubURL: subURL}
+       assert.Equal(t, "com.sub.Service", u.Service())
+
+       // empty SubURL interface
+       subURL2 := &URL{}
+       u2 := &URL{SubURL: subURL2, Path: "/com.path.Service"}
+       assert.Equal(t, "com.path.Service", u2.Service())
+
+       // no SubURL, no interface param
+       u3 := &URL{Path: "/com.path.Service"}
+       assert.Equal(t, "com.path.Service", u3.Service())
+}
+
+func TestAddParam(t *testing.T) {
+       u := &URL{}
+       u.AddParam("key1", "value1")
+       assert.Equal(t, "value1", u.GetParam("key1", ""))
+
+       // add another value to same key
+       u.AddParam("key1", "value2")
+       params := u.GetParams()
+       assert.Equal(t, 2, len(params["key1"]))
+}
+
+func TestAddParamAvoidNil(t *testing.T) {
+       u := &URL{}
+       u.AddParamAvoidNil("key1", "value1")
+       assert.Equal(t, "value1", u.GetParam("key1", ""))
+}
+
+func TestDelParam(t *testing.T) {
+       u, _ := NewURL("dubbo://127.0.0.1:20000?key1=value1&key2=value2")
+       u.DelParam("key1")
+       assert.Equal(t, "", u.GetParam("key1", ""))
+       assert.Equal(t, "value2", u.GetParam("key2", ""))
+
+       // delete from nil params
+       u2 := &URL{}
+       u2.DelParam("key") // should not panic
+}
+
+func TestGetNonDefaultParam(t *testing.T) {
+       u, _ := NewURL("dubbo://127.0.0.1:20000?key1=value1")
+
+       v, ok := u.GetNonDefaultParam("key1")
+       assert.True(t, ok)
+       assert.Equal(t, "value1", v)
+
+       v, ok = u.GetNonDefaultParam("nonexistent")
+       assert.False(t, ok)
+       assert.Equal(t, "", v)
+}
+
+func TestRangeParams(t *testing.T) {
+       u, _ := NewURL("dubbo://127.0.0.1:20000?key1=value1&key2=value2")
+       count := 0
+       u.RangeParams(func(key, value string) bool {
+               count++
+               return true
+       })
+       assert.Equal(t, 2, count)
+
+       // test early break
+       count = 0
+       u.RangeParams(func(key, value string) bool {
+               count++
+               return false // break after first
+       })
+       assert.Equal(t, 1, count)
+}
+
+func TestGetParamInt32(t *testing.T) {
+       params := url.Values{}
+       params.Set("key", "123")
+
+       u := &URL{}
+       u.SetParams(params)
+
+       v := u.GetParamInt32("key", 0)
+       assert.Equal(t, int32(123), v)
+
+       // invalid value
+       u2 := &URL{}
+       v2 := u2.GetParamInt32("key", 99)
+       assert.Equal(t, int32(99), v2)
+}
+
+func TestGetParamByIntValue(t *testing.T) {
+       params := url.Values{}
+       params.Set("key", "456")
+
+       u := &URL{}
+       u.SetParams(params)
+
+       v := u.GetParamByIntValue("key", 0)
+       assert.Equal(t, 456, v)
+
+       // invalid value
+       u2 := &URL{}
+       v2 := u2.GetParamByIntValue("key", 99)
+       assert.Equal(t, 99, v2)
+}
+
+func TestGetMethodParamIntValue(t *testing.T) {
+       params := url.Values{}
+       params.Set("methods.GetValue.timeout", "100")
+
+       u := &URL{}
+       u.SetParams(params)
+
+       v := u.GetMethodParamIntValue("GetValue", "timeout", 0)
+       assert.Equal(t, 100, v)
+
+       // missing method param
+       v2 := u.GetMethodParamIntValue("OtherMethod", "timeout", 50)
+       assert.Equal(t, 50, v2)
+}
+
+func TestGetMethodParamInt64(t *testing.T) {
+       params := url.Values{}
+       params.Set("methods.GetValue.timeout", "200")
+       params.Set("timeout", "100")
+
+       u := &URL{}
+       u.SetParams(params)
+
+       // method param exists
+       v := u.GetMethodParamInt64("GetValue", "timeout", 0)
+       assert.Equal(t, int64(200), v)
+
+       // method param not exists, fallback to global
+       v2 := u.GetMethodParamInt64("OtherMethod", "timeout", 0)
+       assert.Equal(t, int64(100), v2)
+
+       // neither exists
+       v3 := u.GetMethodParamInt64("OtherMethod", "retries", 5)
+       assert.Equal(t, int64(5), v3)
+}
+
+func TestGetParamDuration(t *testing.T) {
+       params := url.Values{}
+       params.Set("timeout", "5s")
+
+       u := &URL{}
+       u.SetParams(params)
+
+       d := u.GetParamDuration("timeout", "1s")
+       assert.Equal(t, 5*time.Second, d)
+
+       // invalid duration, returns 3s default
+       params2 := url.Values{}
+       params2.Set("timeout", "invalid")
+       u2 := &URL{}
+       u2.SetParams(params2)
+       d2 := u2.GetParamDuration("timeout", "invalid")
+       assert.Equal(t, 3*time.Second, d2)
+
+       // missing param with valid default
+       u3 := &URL{}
+       d3 := u3.GetParamDuration("timeout", "2s")
+       assert.Equal(t, 2*time.Second, d3)
+}
+
+func TestCloneExceptParams(t *testing.T) {
+       u, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?key1=value1&key2=value2&key3=value3")
+
+       excludeSet := gxset.NewSet("key1", "key3")
+       cloned := u.CloneExceptParams(excludeSet)
+
+       assert.Equal(t, "", cloned.GetParam("key1", ""))
+       assert.Equal(t, "value2", cloned.GetParam("key2", ""))
+       assert.Equal(t, "", cloned.GetParam("key3", ""))
+       assert.Equal(t, "dubbo", cloned.Protocol)
+}
+
+func TestCloneWithParams(t *testing.T) {
+       // #nosec G101 - test credential for URL clone test
+       u, _ := NewURL("dubbo://" + userName + ":" + testPassword + "@" + 
loopbackAddress + ":" + testPort + 
"/com.test.Service?key1=value1&key2=value2&key3=value3")
+       u.Methods = []string{"method1", "method2"}
+
+       cloned := u.CloneWithParams([]string{"key1", "key3"})
+
+       assert.Equal(t, "value1", cloned.GetParam("key1", ""))
+       assert.Equal(t, "", cloned.GetParam("key2", ""))
+       assert.Equal(t, "value3", cloned.GetParam("key3", ""))
+       assert.Equal(t, "dubbo", cloned.Protocol)
+       assert.Equal(t, userName, cloned.Username)
+       assert.Equal(t, testPassword, cloned.Password)
+       assert.Equal(t, []string{"method1", "method2"}, cloned.Methods)
+}
+
+func TestURLCompare(t *testing.T) {
+       u1, _ := NewURL("dubbo://127.0.0.1:20000/a.Service")
+       u2, _ := NewURL("dubbo://127.0.0.1:20000/b.Service")
+       u3, _ := NewURL("dubbo://127.0.0.1:20000/a.Service")
+
+       assert.Equal(t, -1, u1.Compare(u2))
+       assert.Equal(t, 1, u2.Compare(u1))
+       assert.Equal(t, 0, u1.Compare(u3))
+}
+
+func TestRangeAttributes(t *testing.T) {
+       u := &URL{}
+       u.SetAttribute("attr1", "value1")
+       u.SetAttribute("attr2", 123)
+
+       count := 0
+       u.RangeAttributes(func(key string, value any) bool {
+               count++
+               return true
+       })
+       assert.Equal(t, 2, count)
+
+       // test early break
+       count = 0
+       u.RangeAttributes(func(key string, value any) bool {
+               count++
+               return false
+       })
+       assert.Equal(t, 1, count)
+}
+
+func TestURLSlice(t *testing.T) {
+       u1, _ := NewURL("dubbo://127.0.0.1:20000/c.Service")
+       u2, _ := NewURL("dubbo://127.0.0.1:20000/a.Service")
+       u3, _ := NewURL("dubbo://127.0.0.1:20000/b.Service")
+
+       slice := URLSlice{u1, u2, u3}
+
+       assert.Equal(t, 3, slice.Len())
+       assert.True(t, slice.Less(1, 2))  // a < b
+       assert.False(t, slice.Less(0, 2)) // c > b
+
+       slice.Swap(0, 1)
+       assert.Equal(t, u2, slice[0])
+       assert.Equal(t, u1, slice[1])
+}
+
+func TestIsEquals(t *testing.T) {
+       u1, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?key1=value1&key2=value2")
+       u2, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?key1=value1&key2=value2")
+       u3, _ := 
NewURL("dubbo://127.0.0.1:20001/com.test.Service?key1=value1&key2=value2")
+       u4, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?key1=value1&key2=different")
+
+       // equal URLs
+       assert.True(t, IsEquals(u1, u2))
+
+       // different port
+       assert.False(t, IsEquals(u1, u3))
+
+       // different param value
+       assert.False(t, IsEquals(u1, u4))
+
+       // with excludes
+       assert.True(t, IsEquals(u1, u4, "key2"))
+
+       // nil checks
+       assert.False(t, IsEquals(nil, u1))
+       assert.False(t, IsEquals(u1, nil))
+}
+
+func TestGetSubscribeName(t *testing.T) {
+       u, _ := 
NewURL("dubbo://127.0.0.1:20000?interface=com.test.Service&version=1.0&group=test")
+       name := GetSubscribeName(u)
+       assert.Contains(t, name, "providers")
+       assert.Contains(t, name, "com.test.Service")
+       assert.Contains(t, name, "1.0")
+       assert.Contains(t, name, "test")
+}
+
+func TestNewURLEmptyString(t *testing.T) {
+       u, err := NewURL("")
+       assert.NoError(t, err)
+       assert.NotNil(t, u)
+       assert.Equal(t, "", u.Protocol)
+}
+
+func TestNewURLWithCredentials(t *testing.T) {
+       // #nosec G101 - test credential for URL parsing test
+       u, err := NewURL("dubbo://" + userName + ":" + testPassword + "@" + 
loopbackAddress + ":" + testPort + "/com.test.Service")
+       assert.NoError(t, err)
+       assert.Equal(t, userName, u.Username)
+       assert.Equal(t, testPassword, u.Password)
+}
+
+func TestURLStringWithAuth(t *testing.T) {
+       // #nosec G101 - test credential for URL string test
+       u, _ := NewURL("dubbo://" + userName + ":" + testPassword + "@" + 
loopbackAddress + ":" + testPort + "/com.test.Service?key=value")
+       str := u.String()
+       assert.Contains(t, str, userName+":"+testPassword+"@")
+}
+
+func TestToMapWithoutPort(t *testing.T) {
+       u := &URL{
+               Protocol: "dubbo",
+               Location: "127.0.0.1",
+               Path:     "/com.test.Service",
+       }
+       m := u.ToMap()
+       assert.Equal(t, "0", m["port"])
+}
+
+func TestToMapEmpty(t *testing.T) {
+       u := &URL{}
+       m := u.ToMap()
+       assert.Nil(t, m)
+}
+
+func TestMergeURLWithAttributes(t *testing.T) {
+       u1, _ := NewURL("dubbo://127.0.0.1:20000?key1=value1")
+       u1.SetAttribute("attr1", "attrValue1")
+
+       u2, _ := NewURL("dubbo://127.0.0.1:20001?key2=value2")
+       u2.SetAttribute("attr2", "attrValue2")
+       u2.Methods = []string{"method1"}
+
+       merged := u1.MergeURL(u2)
+
+       // attributes should be merged
+       v1, ok1 := merged.GetAttribute("attr1")
+       assert.True(t, ok1)
+       assert.Equal(t, "attrValue1", v1)
+
+       v2, ok2 := merged.GetAttribute("attr2")
+       assert.True(t, ok2)
+       assert.Equal(t, "attrValue2", v2)
+}
+
+func TestURLEqualWithCategory(t *testing.T) {
+       // test category matching with RemoveValuePrefix
+       u1, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?interface=com.test.Service&category=providers")
+       u2, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?interface=com.test.Service&category=-providers")
+       assert.False(t, u1.URLEqual(u2))
+
+       // category contains target - u3 has category that contains u1's 
category
+       u3, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?interface=com.test.Service&category=providers,consumers")
+       // u1 checks if u3's category matches - u3 has "providers,consumers" 
which contains "providers"
+       assert.True(t, u3.URLEqual(u1))
+}
+
+func TestNewURLWithRegistryGroup(t *testing.T) {
+       u, err := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?registry.group=mygroup")
+       assert.NoError(t, err)
+       assert.Contains(t, u.PrimitiveURL, "mygroup")
+}
+
+func TestColonSeparatedKeyEmpty(t *testing.T) {
+       u := &URL{}
+       assert.Equal(t, "", u.ColonSeparatedKey())
+}
+
+func TestColonSeparatedKeyWithVersion000(t *testing.T) {
+       u, _ := NewURL("dubbo://127.0.0.1:20000")
+       u.AddParam(constant.InterfaceKey, "com.test.Service")
+       u.AddParam(constant.VersionKey, "0.0.0")
+       u.AddParam(constant.GroupKey, "group1")
+
+       // version 0.0.0 should be treated as empty
+       assert.Equal(t, "com.test.Service::group1", u.ColonSeparatedKey())
+}
+
+// Additional edge case tests for better coverage
+
+func TestNewURLParseError(t *testing.T) {
+       // Test invalid URL that causes parse error
+       _, err := NewURL("://invalid")
+       assert.Error(t, err)
+}
+
+func TestNewURLWithInvalidQuery(t *testing.T) {
+       // URL with special characters that need escaping
+       u, err := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?key=value%20with%20space")
+       assert.NoError(t, err)
+       assert.Equal(t, "value with space", u.GetParam("key", ""))
+}
+
+func TestURLStringWithoutAuth(t *testing.T) {
+       u, _ := NewURL("dubbo://127.0.0.1:20000/com.test.Service?key=value")
+       str := u.String()
+       assert.Contains(t, str, "dubbo://127.0.0.1:20000")
+       assert.NotContains(t, str, "@")
+}
+
+func TestGetParamAndDecodedError(t *testing.T) {
+       u := &URL{}
+       params := url.Values{}
+       params.Set("rule", "invalid-base64!!!")
+       u.SetParams(params)
+
+       _, err := u.GetParamAndDecoded("rule")
+       assert.Error(t, err)
+}
+
+func TestIsEqualsWithDifferentMapLength(t *testing.T) {
+       u1, _ := NewURL("dubbo://127.0.0.1:20000/com.test.Service?key1=value1")
+       u2, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?key1=value1&key2=value2")
+       assert.False(t, IsEquals(u1, u2))
+}
+
+func TestIsEqualsWithMissingKey(t *testing.T) {
+       u1, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?key1=value1&key2=value2")
+       u2, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?key1=value1&key3=value3")
+       assert.False(t, IsEquals(u1, u2))
+}
+
+func TestIsEqualsBothNil(t *testing.T) {
+       // Both nil should not panic - but current implementation would panic
+       // This tests the nil check logic
+       var u1 *URL = nil
+       var u2 *URL = nil
+       // Note: IsEquals(nil, nil) would panic due to nil pointer dereference
+       // This is expected behavior based on current implementation
+       assert.False(t, IsEquals(u1, &URL{}))
+       assert.False(t, IsEquals(&URL{}, u2))
+}
+
+func TestMergeURLWithMethodParams(t *testing.T) {
+       referenceUrlParams := url.Values{}
+       referenceUrlParams.Set(constant.LoadbalanceKey, "random")
+       referenceUrlParams.Set("methods.testMethod."+constant.TimeoutKey, 
"5000")
+
+       serviceUrlParams := url.Values{}
+       serviceUrlParams.Set(constant.ClusterKey, "failover")
+
+       referenceUrl, _ := NewURL("mock1://127.0.0.1:1111", 
WithParams(referenceUrlParams), WithMethods([]string{"testMethod"}))
+       serviceUrl, _ := NewURL("mock2://127.0.0.1:20000", 
WithParams(serviceUrlParams))
+
+       mergedUrl := serviceUrl.MergeURL(referenceUrl)
+       assert.Equal(t, "random", mergedUrl.GetParam(constant.LoadbalanceKey, 
""))
+       assert.Equal(t, "5000", 
mergedUrl.GetParam("methods.testMethod."+constant.TimeoutKey, ""))
+}
+
+func TestURLWithPathAlreadyHasSlash(t *testing.T) {
+       u := NewURLWithOptions(WithPath("/com.test.Service"))
+       assert.Equal(t, "/com.test.Service", u.Path)
+
+       u2 := NewURLWithOptions(WithPath("com.test.Service"))
+       assert.Equal(t, "/com.test.Service", u2.Path)
+}
+
+func TestServiceKeyWithEmptyInterface(t *testing.T) {
+       u := &URL{}
+       assert.Equal(t, "", u.ServiceKey())
+}
+
+func TestGetRawParamDefault(t *testing.T) {
+       u, _ := NewURL("dubbo://127.0.0.1:20000?customKey=customValue")
+       assert.Equal(t, "customValue", u.GetRawParam("customKey"))
+       assert.Equal(t, "", u.GetRawParam("nonexistent"))
+}
+
+func TestCloneWithNilParams(t *testing.T) {
+       u := &URL{
+               Protocol: "dubbo",
+               Ip:       "127.0.0.1",
+               Port:     "20000",
+       }
+       cloned := u.Clone()
+       assert.Equal(t, "dubbo", cloned.Protocol)
+       assert.Equal(t, "127.0.0.1", cloned.Ip)
+}
+
+func TestCloneWithAttributes(t *testing.T) {
+       u, _ := NewURL("dubbo://127.0.0.1:20000")
+       u.SetAttribute("key1", "value1")
+       u.SetAttribute("key2", 123)
+
+       cloned := u.Clone()
+
+       v1, ok1 := cloned.GetAttribute("key1")
+       assert.True(t, ok1)
+       assert.Equal(t, "value1", v1)
+
+       v2, ok2 := cloned.GetAttribute("key2")
+       assert.True(t, ok2)
+       assert.Equal(t, 123, v2)
+}
+
+func TestSetParamsWithEmptySlice(t *testing.T) {
+       u := &URL{}
+       params := url.Values{}
+       params["emptyKey"] = []string{}
+
+       u.SetParams(params)
+       // Empty slice should delete the key
+       assert.Equal(t, "", u.GetParam("emptyKey", ""))
+}
+
+func TestReplaceParams(t *testing.T) {
+       u, _ := NewURL("dubbo://127.0.0.1:20000?key1=value1")
+
+       newParams := url.Values{}
+       newParams.Set("key2", "value2")
+
+       u.ReplaceParams(newParams)
+
+       assert.Equal(t, "", u.GetParam("key1", ""))
+       assert.Equal(t, "value2", u.GetParam("key2", ""))
+}
+
+func TestURLEqualWithDifferentIpPort(t *testing.T) {
+       // URLEqual ignores IP and Port differences
+       u1, _ := NewURL("dubbo://" + loopbackAddress + ":" + testPort + 
"/com.test.Service?interface=com.test.Service")
+       u2, _ := NewURL("dubbo://" + docIP1 + ":" + testPort30000 + 
"/com.test.Service?interface=com.test.Service")
+       assert.True(t, u1.URLEqual(u2))
+}
+
+func TestIsMatchCategoryWithEmptyCategory2(t *testing.T) {
+       u1, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?interface=com.test.Service&category=providers")
+       u2, _ := 
NewURL("dubbo://127.0.0.1:20000/com.test.Service?interface=com.test.Service")
+       // When category2 is empty, it should match DefaultCategory
+       assert.True(t, u1.URLEqual(u2))
+}
+
+func TestNewURLWithLocationWithoutPort(t *testing.T) {
+       u, err := NewURL("dubbo://hostname/com.test.Service")
+       assert.NoError(t, err)
+       assert.Equal(t, "hostname", u.Location)
+       assert.Equal(t, "", u.Port)
+}
+
+func TestGetParamBoolInvalidValue(t *testing.T) {
+       params := url.Values{}
+       params.Set("key", "notabool")
+
+       u := &URL{}
+       u.SetParams(params)
+
+       v := u.GetParamBool("key", true)
+       assert.Equal(t, true, v) // returns default on parse error
+}
+
+func TestGetParamIntInvalidValue(t *testing.T) {
+       params := url.Values{}
+       params.Set("key", "notanint")
+
+       u := &URL{}
+       u.SetParams(params)
+
+       v := u.GetParamInt("key", 100)
+       assert.Equal(t, int64(100), v) // returns default on parse error
+}
+
+func TestAppendParamWithEmptyValue(t *testing.T) {
+       u, _ := NewURL("dubbo://127.0.0.1:20000?interface=com.test.Service")
+       name := GetSubscribeName(u)
+       // Should handle empty version and group
+       assert.Contains(t, name, "providers")
+       assert.Contains(t, name, "com.test.Service")
+}
diff --git a/filter/hystrix/filter_test.go b/filter/hystrix/filter_test.go
index 90b329c73..404dcf53a 100644
--- a/filter/hystrix/filter_test.go
+++ b/filter/hystrix/filter_test.go
@@ -179,6 +179,8 @@ func TestHystrixFilterInvokeCircuitBreak(t *testing.T) {
        hystrix.Flush()
        hf := &Filter{COrP: true}
        resChan := make(chan result.Result, 50)
+       configLoadMutex.Lock()
+       defer configLoadMutex.Unlock()
        for i := 0; i < 50; i++ {
                go func() {
                        testUrl, err := common.NewURL(
@@ -207,6 +209,8 @@ func TestHystrixFilterInvokeCircuitBreakOmitException(t 
*testing.T) {
        regs := []*regexp.Regexp{reg}
        hf := &Filter{res: map[string][]*regexp.Regexp{"": regs}, COrP: true}
        resChan := make(chan result.Result, 50)
+       configLoadMutex.Lock()
+       defer configLoadMutex.Unlock()
        for i := 0; i < 50; i++ {
                go func() {
                        testUrl, err := common.NewURL(

Reply via email to