diff --git a/model/metric.go b/model/metric.go index 48210ab..32f9d7f 100644 --- a/model/metric.go +++ b/model/metric.go @@ -101,7 +101,7 @@ type COWMetric struct { // Set sets a label name in the wrapped Metric to a given value and copies the // Metric initially, if it is not already a copy. -func (m COWMetric) Set(ln LabelName, lv LabelValue) { +func (m *COWMetric) Set(ln LabelName, lv LabelValue) { m.doCOW() m.Metric[ln] = lv } diff --git a/model/metric_test.go b/model/metric_test.go index f4cd6ee..d51b184 100644 --- a/model/metric_test.go +++ b/model/metric_test.go @@ -70,3 +70,52 @@ func BenchmarkMetric(b *testing.B) { testMetric(b) } } + +func TestCOWMetric(t *testing.T) { + testMetric := Metric{ + "to_delete": "test1", + "to_change": "test2", + } + + scenarios := []struct { + fn func(*COWMetric) + out Metric + }{ + { + fn: func(cm *COWMetric) { + cm.Delete("to_delete") + }, + out: Metric{ + "to_change": "test2", + }, + }, + { + fn: func(cm *COWMetric) { + cm.Set("to_change", "changed") + }, + out: Metric{ + "to_delete": "test1", + "to_change": "changed", + }, + }, + } + + for i, s := range scenarios { + orig := testMetric.Clone() + cm := &COWMetric{ + Metric: orig, + } + + s.fn(cm) + + // Test that the original metric was not modified. + if !orig.Equal(testMetric) { + t.Fatalf("%d. original metric changed; expected %v, got %v", i, testMetric, orig) + } + + // Test that the new metric has the right changes. + if !cm.Metric.Equal(s.out) { + t.Fatalf("%d. copied metric doesn't contain expected changes; expected %v, got %v", i, s.out, cm.Metric) + } + } +}