Copilot commented on code in PR #3122:
URL: https://github.com/apache/dubbo-go/pull/3122#discussion_r2637579091
##########
metrics/bus_test.go:
##########
@@ -44,11 +44,37 @@ func init() {
}
func TestBusPublish(t *testing.T) {
- t.Run("testBusPublish", func(t *testing.T) {
- event := <-mockChan
+ event := <-mockChan
- if event, ok := event.(MockEvent); ok {
- assert.Equal(t, event, NewEmptyMockEvent())
- }
- })
+ if event, ok := event.(MockEvent); ok {
+ assert.Equal(t, event, NewEmptyMockEvent())
+ }
+}
+
+func TestBusUnsubscribe(t *testing.T) {
+ testChan := make(chan MetricsEvent, 1)
+ eventType := "dubbo.metrics.test.unsubscribe"
+
+ Subscribe(eventType, testChan)
+
+ testEvent := &MockEvent{}
+ Publish(testEvent)
+
+ Unsubscribe(eventType)
+
+ Publish(testEvent)
+}
+
+func TestBusPublishChannelFull(t *testing.T) {
+ testChan := make(chan MetricsEvent, 1)
+ eventType := "dubbo.metrics.test.full"
+
+ Subscribe(eventType, testChan)
+
+ testEvent := &MockEvent{}
+ testChan <- testEvent
+
+ Publish(testEvent)
+
+ Unsubscribe(eventType)
}
Review Comment:
The test TestBusPublishChannelFull does not verify the expected behavior
when publishing to a full channel. The channel is filled with one event, then a
Publish is attempted, but there's no assertion to verify what happens (e.g.,
whether the event is dropped, logged, or blocks). Consider adding assertions to
verify the expected behavior when the channel is full.
##########
metrics/bus_test.go:
##########
@@ -44,11 +44,37 @@ func init() {
}
func TestBusPublish(t *testing.T) {
- t.Run("testBusPublish", func(t *testing.T) {
- event := <-mockChan
+ event := <-mockChan
- if event, ok := event.(MockEvent); ok {
- assert.Equal(t, event, NewEmptyMockEvent())
- }
- })
+ if event, ok := event.(MockEvent); ok {
+ assert.Equal(t, event, NewEmptyMockEvent())
+ }
+}
+
+func TestBusUnsubscribe(t *testing.T) {
+ testChan := make(chan MetricsEvent, 1)
+ eventType := "dubbo.metrics.test.unsubscribe"
+
+ Subscribe(eventType, testChan)
+
+ testEvent := &MockEvent{}
+ Publish(testEvent)
+
+ Unsubscribe(eventType)
+
+ Publish(testEvent)
+}
Review Comment:
The test TestBusUnsubscribe does not verify the behavior after
unsubscribing. After calling Unsubscribe, a second Publish is made, but there's
no assertion to verify that the event was not received on the unsubscribed
channel. Consider adding an assertion to verify the channel does not receive
the event after unsubscription, for example by using a select statement with a
timeout to confirm no event is received.
##########
metrics/api_test.go:
##########
@@ -0,0 +1,309 @@
+/*
+ * 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 metrics
+
+import (
+ "testing"
+)
+
+import (
+ "github.com/stretchr/testify/assert"
+)
+
+// mockMetricRegistry is a simple mock implementation of MetricRegistry for
testing
+type mockMetricRegistry struct {
+ counters map[string]*mockCounterMetric
+ gauges map[string]*mockGaugeMetric
+ histograms map[string]*mockObservableMetric
+ summaries map[string]*mockObservableMetric
+ rts map[string]*mockObservableMetric
+}
+
+func newMockMetricRegistry() *mockMetricRegistry {
+ return &mockMetricRegistry{
+ counters: make(map[string]*mockCounterMetric),
+ gauges: make(map[string]*mockGaugeMetric),
+ histograms: make(map[string]*mockObservableMetric),
+ summaries: make(map[string]*mockObservableMetric),
+ rts: make(map[string]*mockObservableMetric),
+ }
+}
+
+func (m *mockMetricRegistry) Counter(id *MetricId) CounterMetric {
+ if c, ok := m.counters[id.Name]; ok {
+ return c
+ }
+ c := &mockCounterMetric{}
+ m.counters[id.Name] = c
+ return c
+}
+
+func (m *mockMetricRegistry) Gauge(id *MetricId) GaugeMetric {
+ if g, ok := m.gauges[id.Name]; ok {
+ return g
+ }
+ g := &mockGaugeMetric{}
+ m.gauges[id.Name] = g
+ return g
+}
+
+func (m *mockMetricRegistry) Histogram(id *MetricId) ObservableMetric {
+ if h, ok := m.histograms[id.Name]; ok {
+ return h
+ }
+ h := &mockObservableMetric{}
+ m.histograms[id.Name] = h
+ return h
+}
+
+func (m *mockMetricRegistry) Summary(id *MetricId) ObservableMetric {
+ if s, ok := m.summaries[id.Name]; ok {
+ return s
+ }
+ s := &mockObservableMetric{}
+ m.summaries[id.Name] = s
+ return s
+}
+
+func (m *mockMetricRegistry) Rt(id *MetricId, opts *RtOpts) ObservableMetric {
+ if rt, ok := m.rts[id.Name]; ok {
+ return rt
+ }
+ rt := &mockObservableMetric{}
+ m.rts[id.Name] = rt
+ return rt
+}
+
+func (m *mockMetricRegistry) Export() {}
+
+type mockCounterMetric struct {
+ value float64
+}
+
+func (m *mockCounterMetric) Inc() { m.value++ }
+func (m *mockCounterMetric) Add(v float64) { m.value += v }
+
+type mockGaugeMetric struct {
+ value float64
+}
+
+func (m *mockGaugeMetric) Set(v float64) { m.value = v }
+func (m *mockGaugeMetric) Inc() { m.value++ }
+func (m *mockGaugeMetric) Dec() { m.value-- }
+func (m *mockGaugeMetric) Add(v float64) { m.value += v }
+func (m *mockGaugeMetric) Sub(v float64) { m.value -= v }
+
+type mockObservableMetric struct {
+ value float64
+}
+
+func (m *mockObservableMetric) Observe(v float64) { m.value = v }
+
+func TestMetricIdTagKeys(t *testing.T) {
+ tests := []struct {
+ name string
+ tags map[string]string
+ want int
+ }{
+ {
+ name: "empty tags",
+ tags: map[string]string{},
+ want: 0,
+ },
+ {
+ name: "single tag",
+ tags: map[string]string{"app": "dubbo"},
+ want: 1,
+ },
+ {
+ name: "multiple tags",
+ tags: map[string]string{
+ "app": "dubbo",
+ "version": "1.0.0",
+ "ip": "127.0.0.1",
+ },
+ want: 3,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ m := &MetricId{Name: "test_metric", Tags: tt.tags}
+ got := m.TagKeys()
+ assert.Equal(t, tt.want, len(got))
+ for k := range tt.tags {
+ assert.Contains(t, got, k)
+ }
+ })
+ }
+}
+
+func TestBaseCollectorStateCount(t *testing.T) {
+ registry := newMockMetricRegistry()
+ collector := &BaseCollector{R: registry}
+ level := GetApplicationLevel()
+
+ totalKey := NewMetricKey("total", "Total requests")
+ succKey := NewMetricKey("succ", "Success requests")
+ failKey := NewMetricKey("fail", "Failed requests")
+
+ t.Run("success", func(t *testing.T) {
+ collector.StateCount(totalKey, succKey, failKey, level, true)
+
+ total := registry.counters["total"]
+ succ := registry.counters["succ"]
+ fail := registry.counters["fail"]
+
+ assert.NotNil(t, total)
+ assert.NotNil(t, succ)
+ assert.Equal(t, float64(1), total.value)
+ assert.Equal(t, float64(1), succ.value)
+ if fail != nil {
+ assert.Equal(t, float64(0), fail.value)
+ }
+ })
+
+ t.Run("failure", func(t *testing.T) {
+ collector.StateCount(totalKey, succKey, failKey, level, false)
+
+ total := registry.counters["total"]
+ fail := registry.counters["fail"]
+
+ assert.NotNil(t, total)
+ assert.NotNil(t, fail)
+ assert.Equal(t, float64(2), total.value)
+ assert.Equal(t, float64(1), fail.value)
+ })
+}
+
+func TestDefaultCounterVec(t *testing.T) {
+ registry := newMockMetricRegistry()
+ key := NewMetricKey("test_counter", "Test counter")
+ counterVec := NewCounterVec(registry, key)
+ labels := map[string]string{"app": "dubbo", "version": "1.0.0"}
+
+ t.Run("Inc", func(t *testing.T) {
+ counterVec.Inc(labels)
+ metricId := NewMetricIdByLabels(key, labels)
+ counter := registry.Counter(metricId).(*mockCounterMetric)
+ assert.Equal(t, float64(1), counter.value)
+ })
+
+ t.Run("Add", func(t *testing.T) {
+ counterVec.Add(labels, 5.0)
+ metricId := NewMetricIdByLabels(key, labels)
+ counter := registry.Counter(metricId).(*mockCounterMetric)
+ assert.Equal(t, float64(6), counter.value)
+ })
+}
+
+func TestDefaultGaugeVec(t *testing.T) {
+ registry := newMockMetricRegistry()
+ key := NewMetricKey("test_gauge", "Test gauge")
+ gaugeVec := NewGaugeVec(registry, key)
+ labels := map[string]string{"app": "dubbo", "version": "1.0.0"}
+
+ t.Run("Set", func(t *testing.T) {
+ gaugeVec.Set(labels, 100.0)
+ gauge := registry.Gauge(NewMetricIdByLabels(key,
labels)).(*mockGaugeMetric)
+ assert.Equal(t, float64(100), gauge.value)
+ })
+
+ t.Run("Inc", func(t *testing.T) {
+ gaugeVec.Inc(labels)
+ gauge := registry.Gauge(NewMetricIdByLabels(key,
labels)).(*mockGaugeMetric)
+ assert.Equal(t, float64(101), gauge.value)
+ })
+
+ t.Run("Dec", func(t *testing.T) {
+ gaugeVec.Dec(labels)
+ gauge := registry.Gauge(NewMetricIdByLabels(key,
labels)).(*mockGaugeMetric)
+ assert.Equal(t, float64(100), gauge.value)
+ })
+
+ t.Run("Add", func(t *testing.T) {
+ gaugeVec.Add(labels, 50.0)
+ gauge := registry.Gauge(NewMetricIdByLabels(key,
labels)).(*mockGaugeMetric)
+ assert.Equal(t, float64(150), gauge.value)
+ })
+
+ t.Run("Sub", func(t *testing.T) {
+ gaugeVec.Sub(labels, 30.0)
+ gauge := registry.Gauge(NewMetricIdByLabels(key,
labels)).(*mockGaugeMetric)
+ assert.Equal(t, float64(120), gauge.value)
+ })
+}
Review Comment:
The subtests in TestDefaultGaugeVec share the same registry instance and
labels map, which creates test interdependence. The "Inc" subtest expects 101
(assuming "Set" ran first with 100), "Dec" expects 100, "Add" expects 150, and
"Sub" expects 120. Each subtest depends on the execution and final state of all
previous subtests. This makes tests fragile and order-dependent. Consider
creating a fresh registry for each subtest to ensure test isolation and
independence.
##########
metrics/metadata/collector_test.go:
##########
@@ -0,0 +1,66 @@
+/*
+ * 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 metadata
+
+import (
+ "testing"
+ "time"
+)
+
+import (
+ "github.com/stretchr/testify/assert"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
+)
+
+func TestMetadataMetricEventType(t *testing.T) {
+ event := &MetadataMetricEvent{
+ Name: MetadataPush,
+ Succ: true,
+ }
+
+ assert.Equal(t, constant.MetricsMetadata, event.Type())
+}
+
+func TestMetadataMetricEventCostMs(t *testing.T) {
+ start := time.Now()
+ time.Sleep(10 * time.Millisecond)
+ end := time.Now()
+
+ event := &MetadataMetricEvent{
+ Name: MetadataPush,
+ Start: start,
+ End: end,
+ }
+
+ cost := event.CostMs()
+ assert.Greater(t, cost, 0.0)
+ assert.Less(t, cost, 100.0) // Should be around 10ms
+}
Review Comment:
This test uses time.Sleep to create a delay for testing timing calculations,
which can lead to flaky tests in CI/CD environments with variable execution
speeds. The assertion on line 55 checks that cost is less than 100ms when only
10ms was slept, which provides a wide margin but could still be fragile.
Consider using mock time or more deterministic approaches for testing
time-based calculations, or at least document that this test may be affected by
system load.
##########
metrics/api_test.go:
##########
@@ -0,0 +1,309 @@
+/*
+ * 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 metrics
+
+import (
+ "testing"
+)
+
+import (
+ "github.com/stretchr/testify/assert"
+)
+
+// mockMetricRegistry is a simple mock implementation of MetricRegistry for
testing
+type mockMetricRegistry struct {
+ counters map[string]*mockCounterMetric
+ gauges map[string]*mockGaugeMetric
+ histograms map[string]*mockObservableMetric
+ summaries map[string]*mockObservableMetric
+ rts map[string]*mockObservableMetric
+}
+
+func newMockMetricRegistry() *mockMetricRegistry {
+ return &mockMetricRegistry{
+ counters: make(map[string]*mockCounterMetric),
+ gauges: make(map[string]*mockGaugeMetric),
+ histograms: make(map[string]*mockObservableMetric),
+ summaries: make(map[string]*mockObservableMetric),
+ rts: make(map[string]*mockObservableMetric),
+ }
+}
+
+func (m *mockMetricRegistry) Counter(id *MetricId) CounterMetric {
+ if c, ok := m.counters[id.Name]; ok {
+ return c
+ }
+ c := &mockCounterMetric{}
+ m.counters[id.Name] = c
+ return c
+}
+
+func (m *mockMetricRegistry) Gauge(id *MetricId) GaugeMetric {
+ if g, ok := m.gauges[id.Name]; ok {
+ return g
+ }
+ g := &mockGaugeMetric{}
+ m.gauges[id.Name] = g
+ return g
+}
+
+func (m *mockMetricRegistry) Histogram(id *MetricId) ObservableMetric {
+ if h, ok := m.histograms[id.Name]; ok {
+ return h
+ }
+ h := &mockObservableMetric{}
+ m.histograms[id.Name] = h
+ return h
+}
+
+func (m *mockMetricRegistry) Summary(id *MetricId) ObservableMetric {
+ if s, ok := m.summaries[id.Name]; ok {
+ return s
+ }
+ s := &mockObservableMetric{}
+ m.summaries[id.Name] = s
+ return s
+}
+
+func (m *mockMetricRegistry) Rt(id *MetricId, opts *RtOpts) ObservableMetric {
+ if rt, ok := m.rts[id.Name]; ok {
+ return rt
+ }
+ rt := &mockObservableMetric{}
+ m.rts[id.Name] = rt
+ return rt
+}
+
+func (m *mockMetricRegistry) Export() {}
+
+type mockCounterMetric struct {
+ value float64
+}
+
+func (m *mockCounterMetric) Inc() { m.value++ }
+func (m *mockCounterMetric) Add(v float64) { m.value += v }
+
+type mockGaugeMetric struct {
+ value float64
+}
+
+func (m *mockGaugeMetric) Set(v float64) { m.value = v }
+func (m *mockGaugeMetric) Inc() { m.value++ }
+func (m *mockGaugeMetric) Dec() { m.value-- }
+func (m *mockGaugeMetric) Add(v float64) { m.value += v }
+func (m *mockGaugeMetric) Sub(v float64) { m.value -= v }
+
+type mockObservableMetric struct {
+ value float64
+}
+
+func (m *mockObservableMetric) Observe(v float64) { m.value = v }
+
+func TestMetricIdTagKeys(t *testing.T) {
+ tests := []struct {
+ name string
+ tags map[string]string
+ want int
+ }{
+ {
+ name: "empty tags",
+ tags: map[string]string{},
+ want: 0,
+ },
+ {
+ name: "single tag",
+ tags: map[string]string{"app": "dubbo"},
+ want: 1,
+ },
+ {
+ name: "multiple tags",
+ tags: map[string]string{
+ "app": "dubbo",
+ "version": "1.0.0",
+ "ip": "127.0.0.1",
+ },
+ want: 3,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ m := &MetricId{Name: "test_metric", Tags: tt.tags}
+ got := m.TagKeys()
+ assert.Equal(t, tt.want, len(got))
+ for k := range tt.tags {
+ assert.Contains(t, got, k)
+ }
+ })
+ }
+}
+
+func TestBaseCollectorStateCount(t *testing.T) {
+ registry := newMockMetricRegistry()
+ collector := &BaseCollector{R: registry}
+ level := GetApplicationLevel()
+
+ totalKey := NewMetricKey("total", "Total requests")
+ succKey := NewMetricKey("succ", "Success requests")
+ failKey := NewMetricKey("fail", "Failed requests")
+
+ t.Run("success", func(t *testing.T) {
+ collector.StateCount(totalKey, succKey, failKey, level, true)
+
+ total := registry.counters["total"]
+ succ := registry.counters["succ"]
+ fail := registry.counters["fail"]
+
+ assert.NotNil(t, total)
+ assert.NotNil(t, succ)
+ assert.Equal(t, float64(1), total.value)
+ assert.Equal(t, float64(1), succ.value)
+ if fail != nil {
+ assert.Equal(t, float64(0), fail.value)
+ }
+ })
+
+ t.Run("failure", func(t *testing.T) {
+ collector.StateCount(totalKey, succKey, failKey, level, false)
+
+ total := registry.counters["total"]
+ fail := registry.counters["fail"]
+
+ assert.NotNil(t, total)
+ assert.NotNil(t, fail)
+ assert.Equal(t, float64(2), total.value)
+ assert.Equal(t, float64(1), fail.value)
+ })
+}
+
+func TestDefaultCounterVec(t *testing.T) {
+ registry := newMockMetricRegistry()
+ key := NewMetricKey("test_counter", "Test counter")
+ counterVec := NewCounterVec(registry, key)
+ labels := map[string]string{"app": "dubbo", "version": "1.0.0"}
+
+ t.Run("Inc", func(t *testing.T) {
+ counterVec.Inc(labels)
+ metricId := NewMetricIdByLabels(key, labels)
+ counter := registry.Counter(metricId).(*mockCounterMetric)
+ assert.Equal(t, float64(1), counter.value)
+ })
+
+ t.Run("Add", func(t *testing.T) {
+ counterVec.Add(labels, 5.0)
+ metricId := NewMetricIdByLabels(key, labels)
+ counter := registry.Counter(metricId).(*mockCounterMetric)
+ assert.Equal(t, float64(6), counter.value)
+ })
+}
Review Comment:
The subtests in TestDefaultCounterVec share the same registry instance and
labels map, which means state carries over between subtests. The "Add" subtest
on line 207 expects a value of 6, which assumes the "Inc" subtest ran first and
set the value to 1. This creates test interdependence where the order of
subtest execution matters. Consider creating a fresh registry for each subtest
to ensure test isolation and independence.
##########
metrics/registry/event_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 registry
+
+import (
+ "testing"
+ "time"
+)
+
+import (
+ "github.com/stretchr/testify/assert"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
+)
+
+func TestRegistryMetricsEventType(t *testing.T) {
+ event := &RegistryMetricsEvent{
+ Name: Reg,
+ Succ: true,
+ }
+
+ assert.Equal(t, constant.MetricsRegistry, event.Type())
+}
+
+func TestRegistryMetricsEventCostMs(t *testing.T) {
+ start := time.Now()
+ time.Sleep(10 * time.Millisecond)
+ end := time.Now()
+
+ event := &RegistryMetricsEvent{
+ Name: Reg,
+ Start: start,
+ End: end,
+ }
+
+ cost := event.CostMs()
+ assert.Greater(t, cost, 0.0)
+ assert.Less(t, cost, 100.0)
+}
Review Comment:
This test uses time.Sleep to create a delay for testing timing calculations,
which can lead to flaky tests in CI/CD environments with variable execution
speeds. The assertion on line 55 checks that cost is less than 100ms when only
10ms was slept, which provides a wide margin but could still be fragile.
Consider using mock time or more deterministic approaches for testing
time-based calculations, or at least document that this test may be affected by
system load.
##########
metrics/bus_test.go:
##########
@@ -44,11 +44,37 @@ func init() {
}
func TestBusPublish(t *testing.T) {
- t.Run("testBusPublish", func(t *testing.T) {
- event := <-mockChan
+ event := <-mockChan
- if event, ok := event.(MockEvent); ok {
- assert.Equal(t, event, NewEmptyMockEvent())
- }
- })
+ if event, ok := event.(MockEvent); ok {
+ assert.Equal(t, event, NewEmptyMockEvent())
Review Comment:
The type assertion on line 49 shadows the event variable from line 47, which
could lead to confusion. The inner event variable (from the type assertion) is
then compared to a pointer (*MockEvent from NewEmptyMockEvent()), but the
assertion extracts a non-pointer MockEvent. This comparison will always fail
since you're comparing a MockEvent value to a *MockEvent pointer. Consider
either asserting to *MockEvent or adjusting the comparison logic.
```suggestion
if mockEvent, ok := event.(*MockEvent); ok {
assert.Equal(t, NewEmptyMockEvent(), mockEvent)
```
##########
metrics/common_test.go:
##########
@@ -0,0 +1,103 @@
+/*
+ * 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 metrics
+
+import (
+ "testing"
+)
+
+import (
+ "github.com/stretchr/testify/assert"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/common/constant"
+)
+
+func TestGetApplicationLevel(t *testing.T) {
+ InitAppInfo("test-app", "1.0.0")
+ level := GetApplicationLevel()
+
+ assert.NotNil(t, level)
+ assert.Equal(t, "test-app", level.ApplicationName)
+ assert.Equal(t, "1.0.0", level.Version)
+ assert.NotEmpty(t, level.Ip)
+ assert.NotEmpty(t, level.HostName)
+}
+
+func TestApplicationMetricLevelTags(t *testing.T) {
+ InitAppInfo("test-app", "1.0.0")
+ level := GetApplicationLevel()
+ tags := level.Tags()
+
+ assert.NotNil(t, tags)
+ assert.Equal(t, "test-app", tags[constant.TagApplicationName])
+ assert.Equal(t, "1.0.0", tags[constant.TagApplicationVersion])
+ assert.NotEmpty(t, tags[constant.TagIp])
+ assert.NotEmpty(t, tags[constant.TagHostname])
+ assert.Equal(t, "", tags[constant.TagGitCommitId])
+}
+
+func TestServiceMetricLevelTags(t *testing.T) {
+ InitAppInfo("test-app", "1.0.0")
+ serviceMetric := NewServiceMetric("com.example.Service")
+ tags := serviceMetric.Tags()
+
+ assert.NotNil(t, tags)
+ assert.Equal(t, "test-app", tags[constant.TagApplicationName])
+ assert.Equal(t, "1.0.0", tags[constant.TagApplicationVersion])
+ assert.Equal(t, "com.example.Service", tags[constant.TagInterface])
+ assert.NotEmpty(t, tags[constant.TagIp])
+ assert.NotEmpty(t, tags[constant.TagHostname])
+}
+
+func TestMethodMetricLevelTags(t *testing.T) {
+ InitAppInfo("test-app", "1.0.0")
+ serviceMetric := NewServiceMetric("com.example.Service")
+ methodLevel := MethodMetricLevel{
+ ServiceMetricLevel: serviceMetric,
+ Method: "TestMethod",
+ Group: "test-group",
+ Version: "1.0.0",
+ }
+
+ tags := methodLevel.Tags()
+
+ assert.NotNil(t, tags)
+ assert.Equal(t, "test-app", tags[constant.TagApplicationName])
+ assert.Equal(t, "1.0.0", tags[constant.TagApplicationVersion])
+ assert.Equal(t, "com.example.Service", tags[constant.TagInterface])
+ assert.Equal(t, "TestMethod", tags[constant.TagMethod])
+ assert.Equal(t, "test-group", tags[constant.TagGroup])
+ assert.Equal(t, "1.0.0", tags[constant.TagVersion])
+}
+
+func TestConfigCenterLevelTags(t *testing.T) {
+ InitAppInfo("test-app", "1.0.0")
+ level := NewConfigCenterLevel("test-key", "test-group", "nacos",
"added")
+ tags := level.Tags()
+
+ assert.NotNil(t, tags)
+ assert.Equal(t, "test-app", tags[constant.TagApplicationName])
+ assert.Equal(t, "test-key", tags[constant.TagKey])
+ assert.Equal(t, "test-group", tags[constant.TagGroup])
+ assert.Equal(t, "nacos", tags[constant.TagConfigCenter])
+ assert.Equal(t, "added", tags[constant.TagChangeType])
+ assert.NotEmpty(t, tags[constant.TagIp])
+ assert.NotEmpty(t, tags[constant.TagHostname])
+}
Review Comment:
Each test function calls InitAppInfo with the same values ("test-app",
"1.0.0"). If InitAppInfo modifies global state or has side effects, this could
lead to test interference when tests run in parallel. Consider calling
InitAppInfo once in a TestMain function or in an init function, or ensure that
each test properly isolates its state if tests are meant to run independently.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]