Skip to content

Commit 70453fd

Browse files
committed
feat(model): ValidationScheme implements pflag.Value and json.Marshaler/Unmarshaler interfaces
1 parent 0e1982f commit 70453fd

File tree

2 files changed

+131
-8
lines changed

2 files changed

+131
-8
lines changed

model/metric.go

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package model
1515

1616
import (
17+
"encoding/json"
1718
"errors"
1819
"fmt"
1920
"regexp"
@@ -77,10 +78,12 @@ const (
7778
UTF8Validation
7879
)
7980

80-
var (
81-
_ yaml.Marshaler = UnsetValidation
82-
_ fmt.Stringer = UnsetValidation
83-
)
81+
var _ interface {
82+
yaml.Marshaler
83+
yaml.Unmarshaler
84+
json.Marshaler
85+
json.Unmarshaler
86+
} = new(ValidationScheme)
8487

8588
// String returns the string representation of s.
8689
func (s ValidationScheme) String() string {
@@ -114,19 +117,50 @@ func (s *ValidationScheme) UnmarshalYAML(unmarshal func(any) error) error {
114117
if err := unmarshal(&scheme); err != nil {
115118
return err
116119
}
117-
switch scheme {
120+
return s.Set(scheme)
121+
}
122+
123+
// MarshalJSON implements the json.Marshaler interface.
124+
func (s ValidationScheme) MarshalJSON() ([]byte, error) {
125+
switch s {
126+
case UnsetValidation:
127+
return json.Marshal("")
128+
case UTF8Validation, LegacyValidation:
129+
return json.Marshal(s.String())
130+
default:
131+
return nil, fmt.Errorf("unhandled ValidationScheme: %d", s)
132+
}
133+
}
134+
135+
// UnmarshalJSON implements the json.Unmarshaler interface.
136+
func (s *ValidationScheme) UnmarshalJSON(bytes []byte) error {
137+
var repr string
138+
if err := json.Unmarshal(bytes, &repr); err != nil {
139+
return err
140+
}
141+
return s.Set(repr)
142+
}
143+
144+
// Set implements the pflag.Value interface.
145+
func (s *ValidationScheme) Set(text string) error {
146+
switch text {
118147
case "":
119148
// Don't change the value.
120-
case "legacy":
149+
case LegacyValidation.String():
121150
*s = LegacyValidation
122-
case "utf8":
151+
case UTF8Validation.String():
123152
*s = UTF8Validation
124153
default:
125-
return fmt.Errorf("unrecognized ValidationScheme: %q", scheme)
154+
return fmt.Errorf("unrecognized ValidationScheme: %q", text)
126155
}
127156
return nil
128157
}
129158

159+
// Type implements the pflag.Value interface.
160+
func (s ValidationScheme) Type() string {
161+
return "validationScheme"
162+
}
163+
130164
type EscapingScheme int
131165

132166
const (

model/metric_test.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package model
1515

1616
import (
17+
"encoding/json"
1718
"errors"
1819
"strings"
1920
"testing"
@@ -202,6 +203,94 @@ func TestValidationScheme_UnmarshalYAML(t *testing.T) {
202203
}
203204
}
204205

206+
func TestValidationScheme_UnmarshalJSON(t *testing.T) {
207+
testCases := []struct {
208+
name string
209+
input string
210+
want ValidationScheme
211+
wantErr bool
212+
}{
213+
{
214+
name: "invalid",
215+
input: `invalid`,
216+
wantErr: true,
217+
},
218+
{
219+
name: "empty",
220+
input: `""`,
221+
want: UnsetValidation,
222+
},
223+
{
224+
name: "legacy validation",
225+
input: `"legacy"`,
226+
want: LegacyValidation,
227+
},
228+
{
229+
name: "utf8 validation",
230+
input: `"utf8"`,
231+
want: UTF8Validation,
232+
},
233+
}
234+
for _, tc := range testCases {
235+
t.Run(tc.name, func(t *testing.T) {
236+
var got ValidationScheme
237+
err := json.Unmarshal([]byte(tc.input), &got)
238+
if tc.wantErr {
239+
require.Error(t, err)
240+
return
241+
}
242+
require.NoError(t, err)
243+
require.Equal(t, tc.want, ValidationScheme(got))
244+
245+
output, err := json.Marshal(got)
246+
require.NoError(t, err)
247+
require.Equal(t, tc.input, string(output))
248+
})
249+
}
250+
}
251+
252+
func TestValidationScheme_Set(t *testing.T) {
253+
testCases := []struct {
254+
name string
255+
input string
256+
want ValidationScheme
257+
wantErr bool
258+
}{
259+
{
260+
name: "invalid",
261+
input: `invalid`,
262+
wantErr: true,
263+
},
264+
{
265+
name: "empty",
266+
input: ``,
267+
want: UnsetValidation,
268+
},
269+
{
270+
name: "legacy validation",
271+
input: `legacy`,
272+
want: LegacyValidation,
273+
},
274+
{
275+
name: "utf8 validation",
276+
input: `utf8`,
277+
want: UTF8Validation,
278+
},
279+
}
280+
for _, tc := range testCases {
281+
t.Run(tc.name, func(t *testing.T) {
282+
var got ValidationScheme
283+
err := got.Set(tc.input)
284+
if tc.wantErr {
285+
require.Error(t, err)
286+
return
287+
}
288+
require.NoError(t, err)
289+
require.Equal(t, tc.want, ValidationScheme(got))
290+
})
291+
}
292+
}
293+
205294
func TestMetricNameIsLegacyValid(t *testing.T) {
206295
scenarios := []struct {
207296
mn LabelValue

0 commit comments

Comments
 (0)