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 992c2972c test: add unit test for protocol/base (#3139)
992c2972c is described below

commit 992c2972cb573aae5bf7ed91fb397ca2fc13fe38
Author: Akashisang <[email protected]>
AuthorDate: Sat Dec 27 16:00:48 2025 +0800

    test: add unit test for protocol/base (#3139)
    
    * test: add unit test for protocol/base
---
 protocol/base/base_exporter_test.go | 113 ++++++++++++++++
 protocol/base/base_invoker_test.go  | 104 +++++++++++++++
 protocol/base/base_protocol_test.go | 250 ++++++++++++++++++++++++++++++++++++
 protocol/base/rpc_status_test.go    | 183 +++++++++++++++++++++++++-
 4 files changed, 649 insertions(+), 1 deletion(-)

diff --git a/protocol/base/base_exporter_test.go 
b/protocol/base/base_exporter_test.go
new file mode 100644
index 000000000..e7f14e64d
--- /dev/null
+++ b/protocol/base/base_exporter_test.go
@@ -0,0 +1,113 @@
+/*
+ * 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 base
+
+import (
+       "sync"
+       "testing"
+)
+
+import (
+       "github.com/stretchr/testify/assert"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3/common"
+)
+
+func TestNewBaseExporter(t *testing.T) {
+       url, _ := common.NewURL("dubbo://localhost:9090")
+       invoker := NewBaseInvoker(url)
+       exporterMap := &sync.Map{}
+       key := "test-key"
+
+       exporter := NewBaseExporter(key, invoker, exporterMap)
+
+       assert.NotNil(t, exporter)
+       assert.Equal(t, key, exporter.key)
+       assert.Equal(t, invoker, exporter.invoker)
+       assert.Equal(t, exporterMap, exporter.exporterMap)
+}
+
+func TestBaseExporter_GetInvoker(t *testing.T) {
+       url, _ := common.NewURL("dubbo://localhost:9090")
+       invoker := NewBaseInvoker(url)
+       exporterMap := &sync.Map{}
+       key := "test-key"
+
+       exporter := NewBaseExporter(key, invoker, exporterMap)
+       gotInvoker := exporter.GetInvoker()
+
+       assert.NotNil(t, gotInvoker)
+       assert.Equal(t, invoker, gotInvoker)
+       assert.Equal(t, url, gotInvoker.GetURL())
+}
+
+func TestBaseExporter_UnExport(t *testing.T) {
+       url, _ := common.NewURL("dubbo://localhost:9090")
+       invoker := NewBaseInvoker(url)
+       exporterMap := &sync.Map{}
+       key := "test-key"
+
+       // Store the exporter in the map
+       exporter := NewBaseExporter(key, invoker, exporterMap)
+       exporterMap.Store(key, exporter)
+
+       // Verify it's stored
+       _, ok := exporterMap.Load(key)
+       assert.True(t, ok)
+
+       // Test UnExport
+       exporter.UnExport()
+
+       // Verify invoker is destroyed
+       assert.True(t, invoker.IsDestroyed())
+       assert.False(t, invoker.IsAvailable())
+
+       // Verify exporter is removed from map
+       _, ok = exporterMap.Load(key)
+       assert.False(t, ok)
+}
+
+func TestBaseExporter_UnExport_MultipleEntries(t *testing.T) {
+       exporterMap := &sync.Map{}
+
+       // Create multiple exporters
+       url1, _ := common.NewURL("dubbo://localhost:9090")
+       invoker1 := NewBaseInvoker(url1)
+       exporter1 := NewBaseExporter("key1", invoker1, exporterMap)
+       exporterMap.Store("key1", exporter1)
+
+       url2, _ := common.NewURL("dubbo://localhost:9091")
+       invoker2 := NewBaseInvoker(url2)
+       exporter2 := NewBaseExporter("key2", invoker2, exporterMap)
+       exporterMap.Store("key2", exporter2)
+
+       // Unexport first exporter
+       exporter1.UnExport()
+
+       // Verify first is removed, second remains
+       _, ok1 := exporterMap.Load("key1")
+       assert.False(t, ok1)
+       _, ok2 := exporterMap.Load("key2")
+       assert.True(t, ok2)
+
+       // Verify only first invoker is destroyed
+       assert.True(t, invoker1.IsDestroyed())
+       assert.False(t, invoker2.IsDestroyed())
+}
diff --git a/protocol/base/base_invoker_test.go 
b/protocol/base/base_invoker_test.go
index badba1ca9..7182a49cf 100644
--- a/protocol/base/base_invoker_test.go
+++ b/protocol/base/base_invoker_test.go
@@ -18,6 +18,7 @@
 package base
 
 import (
+       "context"
        "testing"
 )
 
@@ -42,3 +43,106 @@ func TestBaseInvoker(t *testing.T) {
        assert.False(t, ivk.IsAvailable())
        assert.True(t, ivk.IsDestroyed())
 }
+
+func TestBaseInvokerWithFullURL(t *testing.T) {
+       url, err := 
common.NewURL("dubbo://localhost:20880/com.example.Service?version=1.0.0&group=test")
+       assert.Nil(t, err)
+
+       ivk := NewBaseInvoker(url)
+
+       // Test GetURL
+       returnedURL := ivk.GetURL()
+       assert.NotNil(t, returnedURL)
+       assert.Equal(t, "dubbo", returnedURL.Protocol)
+       assert.Equal(t, "localhost", returnedURL.Ip)
+       assert.Equal(t, "20880", returnedURL.Port)
+
+       // Test initial state
+       assert.True(t, ivk.IsAvailable())
+       assert.False(t, ivk.IsDestroyed())
+
+       // Test String method before destroy
+       str := ivk.String()
+       assert.Contains(t, str, "dubbo")
+       assert.Contains(t, str, "localhost")
+       assert.Contains(t, str, "20880")
+
+       // Test Destroy
+       ivk.Destroy()
+       assert.False(t, ivk.IsAvailable())
+       assert.True(t, ivk.IsDestroyed())
+       assert.Nil(t, ivk.GetURL())
+
+       // Test String method after destroy (url is nil)
+       str = ivk.String()
+       assert.Contains(t, str, "BaseInvoker")
+}
+
+func TestBaseInvokerInvoke(t *testing.T) {
+       url, err := common.NewURL("dubbo://localhost:9090/test.Service")
+       assert.Nil(t, err)
+
+       ivk := NewBaseInvoker(url)
+
+       // Create a mock invocation
+       ctx := context.Background()
+
+       // Invoke method should return an empty RPCResult
+       result := ivk.Invoke(ctx, nil)
+       assert.NotNil(t, result)
+}
+
+func TestBaseInvokerMultipleDestroy(t *testing.T) {
+       url, err := common.NewURL("dubbo://localhost:9090")
+       assert.Nil(t, err)
+
+       ivk := NewBaseInvoker(url)
+
+       // First destroy
+       ivk.Destroy()
+       assert.True(t, ivk.IsDestroyed())
+       assert.False(t, ivk.IsAvailable())
+
+       // Second destroy should not cause panic
+       ivk.Destroy()
+       assert.True(t, ivk.IsDestroyed())
+       assert.False(t, ivk.IsAvailable())
+}
+
+func TestBaseInvokerStringWithDifferentURLs(t *testing.T) {
+       tests := []struct {
+               name     string
+               urlStr   string
+               contains []string
+       }{
+               {
+                       name:     "Standard URL",
+                       urlStr:   "dubbo://localhost:8080/test.Service",
+                       contains: []string{"dubbo", "localhost", "8080", 
"test.Service"},
+               },
+               {
+                       name:     "URL with path",
+                       urlStr:   "tri://localhost:9090/org.apache.Service",
+                       contains: []string{"tri", "localhost", "9090", 
"org.apache.Service"},
+               },
+               {
+                       name:     "URL with port only",
+                       urlStr:   "dubbo://:8888/Service",
+                       contains: []string{"dubbo", "8888"},
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       url, err := common.NewURL(tt.urlStr)
+                       assert.Nil(t, err)
+
+                       ivk := NewBaseInvoker(url)
+                       str := ivk.String()
+
+                       for _, contain := range tt.contains {
+                               assert.Contains(t, str, contain)
+                       }
+               })
+       }
+}
diff --git a/protocol/base/base_protocol_test.go 
b/protocol/base/base_protocol_test.go
new file mode 100644
index 000000000..2c35820e3
--- /dev/null
+++ b/protocol/base/base_protocol_test.go
@@ -0,0 +1,250 @@
+/*
+ * 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 base
+
+import (
+       "testing"
+)
+
+import (
+       "github.com/stretchr/testify/assert"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3/common"
+)
+
+func TestNewBaseProtocol(t *testing.T) {
+       protocol := NewBaseProtocol()
+
+       assert.NotNil(t, protocol)
+       assert.NotNil(t, protocol.exporterMap)
+       assert.Empty(t, protocol.invokers)
+}
+
+func TestBaseProtocol_SetExporterMap(t *testing.T) {
+       protocol := NewBaseProtocol()
+       url, _ := common.NewURL("dubbo://localhost:9090")
+       invoker := NewBaseInvoker(url)
+       exporter := NewBaseExporter("test-key", invoker, protocol.exporterMap)
+
+       protocol.SetExporterMap("test-key", exporter)
+
+       // Verify exporter is stored
+       val, ok := protocol.exporterMap.Load("test-key")
+       assert.True(t, ok)
+       assert.Equal(t, exporter, val)
+}
+
+func TestBaseProtocol_ExporterMap(t *testing.T) {
+       protocol := NewBaseProtocol()
+       exporterMap := protocol.ExporterMap()
+
+       assert.NotNil(t, exporterMap)
+       assert.Equal(t, protocol.exporterMap, exporterMap)
+}
+
+func TestBaseProtocol_SetInvokers(t *testing.T) {
+       protocol := NewBaseProtocol()
+       url1, _ := common.NewURL("dubbo://localhost:9090")
+       invoker1 := NewBaseInvoker(url1)
+       url2, _ := common.NewURL("dubbo://localhost:9091")
+       invoker2 := NewBaseInvoker(url2)
+
+       protocol.SetInvokers(invoker1)
+       protocol.SetInvokers(invoker2)
+
+       invokers := protocol.Invokers()
+       assert.Len(t, invokers, 2)
+       assert.Contains(t, invokers, invoker1)
+       assert.Contains(t, invokers, invoker2)
+}
+
+func TestBaseProtocol_Invokers(t *testing.T) {
+       protocol := NewBaseProtocol()
+       url, _ := common.NewURL("dubbo://localhost:9090")
+       invoker := NewBaseInvoker(url)
+
+       protocol.SetInvokers(invoker)
+       invokers := protocol.Invokers()
+
+       assert.Len(t, invokers, 1)
+       assert.Equal(t, invoker, invokers[0])
+}
+
+func TestBaseProtocol_Export(t *testing.T) {
+       protocol := NewBaseProtocol()
+       url, _ := common.NewURL("dubbo://localhost:9090")
+       invoker := NewBaseInvoker(url)
+
+       exporter := protocol.Export(invoker)
+
+       assert.NotNil(t, exporter)
+       assert.Equal(t, invoker, exporter.GetInvoker())
+
+       // Note: Export creates a BaseExporter but doesn't automatically store 
it
+       // The exporter needs to be manually stored using SetExporterMap if 
needed
+       baseExporter, ok := exporter.(*BaseExporter)
+       assert.True(t, ok)
+       assert.Equal(t, "base", baseExporter.key)
+       assert.Equal(t, protocol.exporterMap, baseExporter.exporterMap)
+}
+
+func TestBaseProtocol_Refer(t *testing.T) {
+       protocol := NewBaseProtocol()
+       url, _ := common.NewURL("dubbo://localhost:9090")
+
+       invoker := protocol.Refer(url)
+
+       assert.NotNil(t, invoker)
+       assert.Equal(t, url, invoker.GetURL())
+
+       // Type assert to BaseInvoker to access IsAvailable and IsDestroyed
+       baseInvoker, ok := invoker.(*BaseInvoker)
+       assert.True(t, ok)
+       assert.True(t, baseInvoker.IsAvailable())
+       assert.False(t, baseInvoker.IsDestroyed())
+}
+
+func TestBaseProtocol_Destroy(t *testing.T) {
+       protocol := NewBaseProtocol()
+
+       // Add invokers
+       url1, _ := common.NewURL("dubbo://localhost:9090")
+       invoker1 := NewBaseInvoker(url1)
+       protocol.SetInvokers(invoker1)
+
+       url2, _ := common.NewURL("dubbo://localhost:9091")
+       invoker2 := NewBaseInvoker(url2)
+       protocol.SetInvokers(invoker2)
+
+       // Add exporters
+       exporter1 := NewBaseExporter("key1", invoker1, protocol.exporterMap)
+       protocol.SetExporterMap("key1", exporter1)
+
+       exporter2 := NewBaseExporter("key2", invoker2, protocol.exporterMap)
+       protocol.SetExporterMap("key2", exporter2)
+
+       // Verify setup
+       assert.Len(t, protocol.Invokers(), 2)
+       _, ok1 := protocol.exporterMap.Load("key1")
+       assert.True(t, ok1)
+       _, ok2 := protocol.exporterMap.Load("key2")
+       assert.True(t, ok2)
+
+       // Test Destroy
+       protocol.Destroy()
+
+       // Verify all invokers are destroyed
+       assert.Empty(t, protocol.Invokers())
+       assert.True(t, invoker1.IsDestroyed())
+       assert.True(t, invoker2.IsDestroyed())
+
+       // Verify all exporters are unexported and removed
+       _, ok1 = protocol.exporterMap.Load("key1")
+       assert.False(t, ok1)
+       _, ok2 = protocol.exporterMap.Load("key2")
+       assert.False(t, ok2)
+}
+
+func TestBaseProtocol_Destroy_WithNilInvoker(t *testing.T) {
+       protocol := NewBaseProtocol()
+
+       // Add a nil invoker
+       protocol.invokers = append(protocol.invokers, nil)
+
+       // Add a valid invoker
+       url, _ := common.NewURL("dubbo://localhost:9090")
+       invoker := NewBaseInvoker(url)
+       protocol.SetInvokers(invoker)
+
+       // Should not panic
+       assert.NotPanics(t, func() {
+               protocol.Destroy()
+       })
+
+       assert.Empty(t, protocol.Invokers())
+}
+
+func TestBaseProtocol_Destroy_WithNilExporter(t *testing.T) {
+       protocol := NewBaseProtocol()
+
+       // Add a nil exporter
+       protocol.exporterMap.Store("nil-key", nil)
+
+       // Add a valid exporter
+       url, _ := common.NewURL("dubbo://localhost:9090")
+       invoker := NewBaseInvoker(url)
+       exporter := NewBaseExporter("valid-key", invoker, protocol.exporterMap)
+       protocol.SetExporterMap("valid-key", exporter)
+
+       // Should not panic
+       assert.NotPanics(t, func() {
+               protocol.Destroy()
+       })
+
+       // Verify nil entry is deleted
+       _, ok := protocol.exporterMap.Load("nil-key")
+       assert.False(t, ok)
+
+       // Verify valid exporter is unexported
+       _, ok = protocol.exporterMap.Load("valid-key")
+       assert.False(t, ok)
+}
+
+func TestBaseProtocol_Destroy_EmptyProtocol(t *testing.T) {
+       protocol := NewBaseProtocol()
+
+       // Should not panic on empty protocol
+       assert.NotPanics(t, func() {
+               protocol.Destroy()
+       })
+
+       assert.Empty(t, protocol.Invokers())
+}
+
+func TestBaseProtocol_MultipleExportRefer(t *testing.T) {
+       protocol := NewBaseProtocol()
+
+       // Export multiple services
+       url1, _ := common.NewURL("dubbo://localhost:9090/service1")
+       invoker1 := NewBaseInvoker(url1)
+       exporter1 := protocol.Export(invoker1)
+
+       url2, _ := common.NewURL("dubbo://localhost:9091/service2")
+       invoker2 := NewBaseInvoker(url2)
+       exporter2 := protocol.Export(invoker2)
+
+       // Refer multiple services
+       url3, _ := common.NewURL("dubbo://localhost:9092/service3")
+       referInvoker1 := protocol.Refer(url3)
+
+       url4, _ := common.NewURL("dubbo://localhost:9093/service4")
+       referInvoker2 := protocol.Refer(url4)
+
+       // Verify all are created correctly
+       assert.NotNil(t, exporter1)
+       assert.NotNil(t, exporter2)
+       assert.NotNil(t, referInvoker1)
+       assert.NotNil(t, referInvoker2)
+
+       assert.Equal(t, url1, exporter1.GetInvoker().GetURL())
+       assert.Equal(t, url2, exporter2.GetInvoker().GetURL())
+       assert.Equal(t, url3, referInvoker1.GetURL())
+       assert.Equal(t, url4, referInvoker2.GetURL())
+}
diff --git a/protocol/base/rpc_status_test.go b/protocol/base/rpc_status_test.go
index 277634732..07b6e89e1 100644
--- a/protocol/base/rpc_status_test.go
+++ b/protocol/base/rpc_status_test.go
@@ -31,7 +31,7 @@ import (
 )
 
 const (
-       mockCommonDubboUrl = 
"dubbo://192.168.10.10:20000/com.ikurento.user.UserProvider" //NOSONAR just for 
test
+       mockCommonDubboUrl = 
"dubbo://localhost:20000/com.ikurento.user.UserProvider"
 )
 
 func TestBeginCount(t *testing.T) {
@@ -155,3 +155,184 @@ func TestCurrentTimeMillis(t *testing.T) {
        i, _ := strconv.ParseInt(str, 10, 64)
        assert.Equal(t, c, i)
 }
+
+func TestRPCStatusGetters(t *testing.T) {
+       defer CleanAllStatus()
+
+       url, _ := common.NewURL(mockCommonDubboUrl)
+
+       // Test all getter methods
+       request(url, "test", 100, false, true)
+
+       urlStatus := GetURLStatus(url)
+       methodStatus := GetMethodStatus(url, "test")
+
+       // Test GetActive
+       assert.Equal(t, int32(0), urlStatus.GetActive())
+       assert.Equal(t, int32(0), methodStatus.GetActive())
+
+       // Test GetTotal
+       assert.Equal(t, int32(1), urlStatus.GetTotal())
+       assert.Equal(t, int32(1), methodStatus.GetTotal())
+
+       // Test GetFailed
+       assert.Equal(t, int32(0), urlStatus.GetFailed())
+       assert.Equal(t, int32(0), methodStatus.GetFailed())
+
+       // Test GetTotalElapsed
+       assert.Equal(t, int64(100), urlStatus.GetTotalElapsed())
+       assert.Equal(t, int64(100), methodStatus.GetTotalElapsed())
+
+       // Test GetFailedElapsed
+       assert.Equal(t, int64(0), urlStatus.GetFailedElapsed())
+       assert.Equal(t, int64(0), methodStatus.GetFailedElapsed())
+
+       // Test GetMaxElapsed
+       assert.Equal(t, int64(100), urlStatus.GetMaxElapsed())
+       assert.Equal(t, int64(100), methodStatus.GetMaxElapsed())
+
+       // Test GetFailedMaxElapsed
+       assert.Equal(t, int64(0), urlStatus.GetFailedMaxElapsed())
+       assert.Equal(t, int64(0), methodStatus.GetFailedMaxElapsed())
+
+       // Test GetSucceededMaxElapsed
+       assert.Equal(t, int64(100), urlStatus.GetSucceededMaxElapsed())
+       assert.Equal(t, int64(100), methodStatus.GetSucceededMaxElapsed())
+
+       // Test GetSuccessiveRequestFailureCount
+       assert.Equal(t, int32(0), urlStatus.GetSuccessiveRequestFailureCount())
+       assert.Equal(t, int32(0), 
methodStatus.GetSuccessiveRequestFailureCount())
+
+       // Add a failed request to test failure-related getters
+       request(url, "test", 150, false, false)
+
+       assert.Equal(t, int32(1), urlStatus.GetFailed())
+       assert.Equal(t, int64(150), urlStatus.GetFailedElapsed())
+       assert.Equal(t, int64(150), urlStatus.GetFailedMaxElapsed())
+       assert.Equal(t, int32(1), urlStatus.GetSuccessiveRequestFailureCount())
+
+       // Test GetLastRequestFailedTimestamp
+       timestamp := urlStatus.GetLastRequestFailedTimestamp()
+       assert.True(t, timestamp > 0)
+}
+
+func TestInvokerBlackList(t *testing.T) {
+       defer CleanAllStatus()
+
+       url, _ := common.NewURL(mockCommonDubboUrl)
+       invoker := NewBaseInvoker(url)
+
+       // Test healthy status initially
+       assert.True(t, GetInvokerHealthyStatus(invoker))
+
+       // Set invoker to unhealthy
+       SetInvokerUnhealthyStatus(invoker)
+       assert.False(t, GetInvokerHealthyStatus(invoker))
+
+       // Test GetBlackListInvokers
+       blackListInvokers := GetBlackListInvokers(10)
+       assert.Equal(t, 1, len(blackListInvokers))
+       assert.Equal(t, invoker.GetURL().Key(), 
blackListInvokers[0].GetURL().Key())
+
+       // Test with blockSize smaller than actual size
+       blackListInvokers = GetBlackListInvokers(0)
+       assert.Equal(t, 0, len(blackListInvokers))
+
+       // Remove invoker from unhealthy status
+       RemoveInvokerUnhealthyStatus(invoker)
+       assert.True(t, GetInvokerHealthyStatus(invoker))
+
+       // Test RemoveUrlKeyUnhealthyStatus
+       SetInvokerUnhealthyStatus(invoker)
+       assert.False(t, GetInvokerHealthyStatus(invoker))
+       RemoveUrlKeyUnhealthyStatus(invoker.GetURL().Key())
+       assert.True(t, GetInvokerHealthyStatus(invoker))
+}
+
+func TestGetAndRefreshState(t *testing.T) {
+       defer CleanAllStatus()
+
+       url, _ := common.NewURL(mockCommonDubboUrl)
+       invoker := NewBaseInvoker(url)
+
+       // Clear initial state
+       GetAndRefreshState()
+
+       // After setting unhealthy status, it should be true
+       SetInvokerUnhealthyStatus(invoker)
+       state := GetAndRefreshState()
+       assert.True(t, state)
+
+       // After getting, it should be false again
+       state = GetAndRefreshState()
+       assert.False(t, state)
+
+       // Test state change again
+       RemoveInvokerUnhealthyStatus(invoker)
+       state = GetAndRefreshState()
+       assert.True(t, state)
+
+       state = GetAndRefreshState()
+       assert.False(t, state)
+}
+
+func TestTryRefreshBlackList(t *testing.T) {
+       defer CleanAllStatus()
+
+       url1, _ := common.NewURL(mockCommonDubboUrl)
+       url2, _ := 
common.NewURL("dubbo://localhost:20001/com.ikurento.user.UserProvider")
+
+       invoker1 := NewBaseInvoker(url1)
+       invoker2 := NewBaseInvoker(url2)
+
+       // Add invokers to black list
+       SetInvokerUnhealthyStatus(invoker1)
+       SetInvokerUnhealthyStatus(invoker2)
+
+       assert.False(t, GetInvokerHealthyStatus(invoker1))
+       assert.False(t, GetInvokerHealthyStatus(invoker2))
+
+       // Try refresh black list - since invokers are available, they should 
be removed
+       TryRefreshBlackList()
+
+       // Give goroutines time to complete
+       // Note: In real scenario, invokers would be checked for availability
+       // Since our mock invokers are always available, they should be removed
+
+       // Verify black list was processed
+       blackList := GetBlackListInvokers(10)
+       // The behavior depends on the actual IsAvailable() implementation
+       assert.NotNil(t, blackList)
+}
+
+func TestMultipleMethodsStatus(t *testing.T) {
+       defer CleanAllStatus()
+
+       url, _ := common.NewURL(mockCommonDubboUrl)
+
+       // Test multiple methods on same URL
+       request(url, "method1", 100, false, true)
+       request(url, "method2", 200, false, true)
+       request(url, "method3", 150, false, false)
+
+       method1Status := GetMethodStatus(url, "method1")
+       method2Status := GetMethodStatus(url, "method2")
+       method3Status := GetMethodStatus(url, "method3")
+       urlStatus := GetURLStatus(url)
+
+       // Verify individual method stats
+       assert.Equal(t, int32(1), method1Status.GetTotal())
+       assert.Equal(t, int64(100), method1Status.GetTotalElapsed())
+
+       assert.Equal(t, int32(1), method2Status.GetTotal())
+       assert.Equal(t, int64(200), method2Status.GetTotalElapsed())
+       assert.Equal(t, int64(200), method2Status.GetMaxElapsed())
+
+       assert.Equal(t, int32(1), method3Status.GetTotal())
+       assert.Equal(t, int32(1), method3Status.GetFailed())
+
+       // Verify URL aggregates all methods
+       assert.Equal(t, int32(3), urlStatus.GetTotal())
+       assert.Equal(t, int64(450), urlStatus.GetTotalElapsed())
+       assert.Equal(t, int32(1), urlStatus.GetFailed())
+}

Reply via email to