Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 43 additions & 8 deletions model/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package model

import (
"encoding/json"
"errors"
"fmt"
"regexp"
Expand Down Expand Up @@ -77,10 +78,13 @@ const (
UTF8Validation
)

var (
_ yaml.Marshaler = UnsetValidation
_ fmt.Stringer = UnsetValidation
Comment thread
juliusmh marked this conversation as resolved.
)
var _ interface {
yaml.Marshaler
yaml.Unmarshaler
json.Marshaler
json.Unmarshaler
fmt.Stringer
} = new(ValidationScheme)

// String returns the string representation of s.
func (s ValidationScheme) String() string {
Expand Down Expand Up @@ -114,15 +118,41 @@ func (s *ValidationScheme) UnmarshalYAML(unmarshal func(any) error) error {
if err := unmarshal(&scheme); err != nil {
return err
}
switch scheme {
return s.Set(scheme)
}

// MarshalJSON implements the json.Marshaler interface.
func (s ValidationScheme) MarshalJSON() ([]byte, error) {
switch s {
case UnsetValidation:
return json.Marshal("")
case UTF8Validation, LegacyValidation:
return json.Marshal(s.String())
default:
return nil, fmt.Errorf("unhandled ValidationScheme: %d", s)
}
}

// UnmarshalJSON implements the json.Unmarshaler interface.
func (s *ValidationScheme) UnmarshalJSON(bytes []byte) error {
var repr string
if err := json.Unmarshal(bytes, &repr); err != nil {
return err
}
return s.Set(repr)
}

// Set implements the pflag.Value interface.
func (s *ValidationScheme) Set(text string) error {
switch text {
case "":
// Don't change the value.

Copilot AI Jul 31, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment 'Don't change the value' is misleading for an empty string input. When Set() is called with an empty string, it should set the value to UnsetValidation, not leave it unchanged. Either update the logic to set *s = UnsetValidation or clarify the comment to explain why empty strings preserve the current value.

Suggested change
// Don't change the value.
// Set to UnsetValidation for empty string input.
*s = UnsetValidation

Copilot uses AI. Check for mistakes.
Comment thread
aknuds1 marked this conversation as resolved.
case "legacy":
case LegacyValidation.String():
*s = LegacyValidation
case "utf8":
case UTF8Validation.String():
*s = UTF8Validation
default:
return fmt.Errorf("unrecognized ValidationScheme: %q", scheme)
return fmt.Errorf("unrecognized ValidationScheme: %q", text)
}
return nil
}
Comment thread
aknuds1 marked this conversation as resolved.
Expand Down Expand Up @@ -174,6 +204,11 @@ func (s ValidationScheme) IsValidLabelName(labelName string) bool {
}
}

// Type implements the pflag.Value interface.
func (s ValidationScheme) Type() string {
return "validationScheme"
}

type EscapingScheme int

const (
Expand Down
89 changes: 89 additions & 0 deletions model/metric_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package model

import (
"encoding/json"
"errors"
"fmt"
"strings"
Expand Down Expand Up @@ -203,6 +204,94 @@ func TestValidationScheme_UnmarshalYAML(t *testing.T) {
}
}

func TestValidationScheme_UnmarshalJSON(t *testing.T) {
testCases := []struct {
name string
input string
want ValidationScheme
wantErr bool
}{
{
name: "invalid",
input: `invalid`,
wantErr: true,
},
{
name: "empty",
input: `""`,
want: UnsetValidation,
},
{
name: "legacy validation",
input: `"legacy"`,
want: LegacyValidation,
},
{
name: "utf8 validation",
input: `"utf8"`,
want: UTF8Validation,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var got ValidationScheme
err := json.Unmarshal([]byte(tc.input), &got)
if tc.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
require.Equal(t, tc.want, ValidationScheme(got))
Comment thread
aknuds1 marked this conversation as resolved.
Outdated

output, err := json.Marshal(got)
require.NoError(t, err)
require.Equal(t, tc.input, string(output))
})
}
}

func TestValidationScheme_Set(t *testing.T) {
testCases := []struct {
name string
input string
want ValidationScheme
wantErr bool
}{
{
name: "invalid",
input: `invalid`,
wantErr: true,
},
{
name: "empty",
input: ``,
want: UnsetValidation,
},
{
name: "legacy validation",
input: `legacy`,
want: LegacyValidation,
},
{
name: "utf8 validation",
input: `utf8`,
want: UTF8Validation,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var got ValidationScheme
err := got.Set(tc.input)
if tc.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
require.Equal(t, tc.want, ValidationScheme(got))
Comment thread
aknuds1 marked this conversation as resolved.
Outdated
})
}
}

func TestValidationScheme_IsMetricNameValid(t *testing.T) {
scenarios := []struct {
mn string
Expand Down
Loading