package storage import ( "fmt" "reflect" "testing" ) func TestMetricNameString(t *testing.T) { f := func(mn *MetricName, resultExpected string) { t.Helper() result := mn.String() if result != resultExpected { t.Fatalf("unexpected result\ngot\n%s\nwant\n%s", result, resultExpected) } } f(&MetricName{ AccountID: 123, ProjectID: 456, MetricGroup: []byte("foobar"), }, "AccountID=123, ProjectID=456, foobar{}") f(&MetricName{ MetricGroup: []byte("abc"), Tags: []Tag{ { Key: []byte("foo"), Value: []byte("bar"), }, { Key: []byte("baz"), Value: []byte("123"), }, }, }, `AccountID=0, ProjectID=0, abc{baz="123",foo="bar"}`) } func TestMetricNameSortTags(t *testing.T) { testMetricNameSortTags(t, []string{}, []string{}) testMetricNameSortTags(t, []string{"foo"}, []string{"foo"}) testMetricNameSortTags(t, []string{"job"}, []string{"job"}) testMetricNameSortTags(t, []string{"server"}, []string{"server"}) testMetricNameSortTags(t, []string{"host", "foo", "bar", "service"}, []string{"service", "host", "bar", "foo"}) testMetricNameSortTags(t, []string{"model", "foo", "job", "host", "server", "instance"}, []string{"job", "model", "instance", "host", "server", "foo"}) } func testMetricNameSortTags(t *testing.T, tags, expectedTags []string) { t.Helper() var mn MetricName for _, t := range tags { mn.AddTag(t, "") } mn.sortTags() resultTags := []string{} for i := range mn.Tags { resultTags = append(resultTags, string(mn.Tags[i].Key)) } if !reflect.DeepEqual(resultTags, expectedTags) { t.Fatalf("unexpected resultTags\ngot\n%q\nwant\n%q", resultTags, expectedTags) } } func TestMetricNameMarshalDuplicateKeys(t *testing.T) { var mn MetricName mn.AccountID = 123 mn.ProjectID = 324 mn.MetricGroup = []byte("xxx") mn.AddTag("foo", "bar") mn.AddTag("duplicate", "tag1") mn.AddTag("duplicate", "tag2") mn.AddTag("tt", "xx") mn.AddTag("foo", "abc") mn.AddTag("duplicate", "tag3") var mnExpected MetricName mnExpected.AccountID = 123 mnExpected.ProjectID = 324 mnExpected.MetricGroup = []byte("xxx") mnExpected.AddTag("duplicate", "tag3") mnExpected.AddTag("foo", "abc") mnExpected.AddTag("tt", "xx") mn.sortTags() data := mn.Marshal(nil) var mn1 MetricName if err := mn1.Unmarshal(data); err != nil { t.Fatalf("cannot unmarshal mn %s: %s", &mn, err) } if !reflect.DeepEqual(&mnExpected, &mn1) { t.Fatalf("unexpected mn unmarshaled;\ngot\n%+v\nwant\n%+v", &mn1, &mnExpected) } } func TestMetricNameMarshalUnmarshal(t *testing.T) { for i := 0; i < 10; i++ { for tagsCount := 0; tagsCount < 10; tagsCount++ { var mn MetricName mn.AccountID = uint32(i) mn.ProjectID = uint32(i + 1) for j := 0; j < tagsCount; j++ { key := fmt.Sprintf("key_%d_%d_\x00\x01\x02", i, j) value := fmt.Sprintf("\x02\x00\x01value_%d_%d", i, j) mn.AddTag(key, value) } mn.sortTags() data := mn.Marshal(nil) var mn1 MetricName if err := mn1.Unmarshal(data); err != nil { t.Fatalf("cannot unmarshal mn %s: %s", &mn, err) } if !reflect.DeepEqual(&mn, &mn1) { t.Fatalf("unexpected mn unmarshaled;\ngot\n%+v\nwant\n%+v", &mn1, &mn) } // Try unmarshaling MetricName without tag value. brokenData := marshalTagValue(data, []byte("foobar")) if err := mn1.Unmarshal(brokenData); err == nil { t.Fatalf("expecting non-zero error when unmarshaling MetricName without tag value") } // Try unmarshaling MetricName with invalid tag key. brokenData[len(brokenData)-1] = 123 if err := mn1.Unmarshal(brokenData); err == nil { t.Fatalf("expecting non-zero error when unmarshaling MetricName with invalid tag key") } // Try unmarshaling MetricName with invalid tag value. brokenData = marshalTagValue(data, []byte("foobar")) brokenData = marshalTagValue(brokenData, []byte("aaa")) brokenData[len(brokenData)-1] = 123 if err := mn1.Unmarshal(brokenData); err == nil { t.Fatalf("expecting non-zero error when unmarshaling MetricName with invalid tag value") } } } } func TestMetricNameMarshalUnmarshalRaw(t *testing.T) { for i := 0; i < 10; i++ { for tagsCount := 0; tagsCount < 10; tagsCount++ { var mn MetricName mn.AccountID = uint32(i) mn.ProjectID = uint32(tagsCount) for j := 0; j < tagsCount; j++ { key := fmt.Sprintf("key_%d_%d_\x00\x01\x02", i, j) value := fmt.Sprintf("\x02\x00\x01value_%d_%d", i, j) mn.AddTag(key, value) } data := mn.marshalRaw(nil) var mn1 MetricName if err := mn1.UnmarshalRaw(data); err != nil { t.Fatalf("cannot unmarshal mn %s: %s", &mn, err) } if !reflect.DeepEqual(&mn, &mn1) { t.Fatalf("unexpected mn unmarshaled;\ngot\n%+v\nwant\n%+v", &mn1, &mn) } // Try unmarshaling MetricName without tag value. brokenData := marshalTagValue(data, []byte("foobar")) if err := mn1.UnmarshalRaw(brokenData); err == nil { t.Fatalf("expecting non-zero error when unmarshaling MetricName without tag value") } // Try unmarshaling MetricName with invalid tag key. brokenData[len(brokenData)-1] = 123 if err := mn1.UnmarshalRaw(brokenData); err == nil { t.Fatalf("expecting non-zero error when unmarshaling MetricName with invalid tag key") } // Try unmarshaling MetricName with invalid tag value. brokenData = marshalTagValue(data, []byte("foobar")) brokenData = marshalTagValue(brokenData, []byte("aaa")) brokenData[len(brokenData)-1] = 123 if err := mn1.UnmarshalRaw(brokenData); err == nil { t.Fatalf("expecting non-zero error when unmarshaling MetricName with invalid tag value") } } } } func TestMetricNameCopyFrom(t *testing.T) { var from MetricName from.MetricGroup = []byte("group") from.AddTag("key", "value") var to MetricName to.CopyFrom(&from) var expected MetricName expected.MetricGroup = []byte("group") expected.AddTag("key", "value") if !reflect.DeepEqual(expected, to) { t.Fatalf("expecting equal metics exp: %s, got %s", &expected, &to) } } func TestMetricNameRemoveTagsOn(t *testing.T) { var emptyMN MetricName emptyMN.MetricGroup = []byte("name") emptyMN.AddTag("key", "value") emptyMN.RemoveTagsOn(nil) if len(emptyMN.MetricGroup) != 0 || len(emptyMN.Tags) != 0 { t.Fatalf("expecitng empty metric name got %s", &emptyMN) } var asIsMN MetricName asIsMN.MetricGroup = []byte("name") asIsMN.AddTag("key", "value") asIsMN.RemoveTagsOn([]string{"__name__", "key"}) var expAsIsMN MetricName expAsIsMN.MetricGroup = []byte("name") expAsIsMN.AddTag("key", "value") if !reflect.DeepEqual(expAsIsMN, asIsMN) { t.Fatalf("expecitng %s got %s", &expAsIsMN, &asIsMN) } var mn MetricName mn.MetricGroup = []byte("name") mn.AddTag("foo", "bar") mn.AddTag("baz", "qux") mn.RemoveTagsOn([]string{"baz"}) var expMN MetricName expMN.AddTag("baz", "qux") if !reflect.DeepEqual(expMN.Tags, mn.Tags) || len(mn.MetricGroup) != len(expMN.MetricGroup) { t.Fatalf("expecitng %s got %s", &expMN, &mn) } } func TestMetricNameRemoveTag(t *testing.T) { var mn MetricName mn.MetricGroup = []byte("name") mn.AddTag("foo", "bar") mn.AddTag("baz", "qux") mn.RemoveTag("__name__") if len(mn.MetricGroup) != 0 { t.Fatalf("expecting empty metric group got %s", &mn) } mn.RemoveTag("foo") var expMN MetricName expMN.AddTag("baz", "qux") if !reflect.DeepEqual(expMN.Tags, mn.Tags) || len(mn.MetricGroup) != len(expMN.MetricGroup) { t.Fatalf("expecitng %s got %s", &expMN, &mn) } } func TestMetricNameRemoveTagsIgnoring(t *testing.T) { var mn MetricName mn.MetricGroup = []byte("name") mn.AddTag("foo", "bar") mn.AddTag("baz", "qux") mn.RemoveTagsIgnoring([]string{"__name__", "foo"}) var expMN MetricName expMN.AddTag("baz", "qux") if !reflect.DeepEqual(expMN.Tags, mn.Tags) || len(mn.MetricGroup) != len(expMN.MetricGroup) { t.Fatalf("expecitng %s got %s", &expMN, &mn) } }