diff --git a/config/options.go b/config/options.go index ec583e3fe..5bc9ebf0b 100644 --- a/config/options.go +++ b/config/options.go @@ -30,7 +30,7 @@ func WithDecoder(d Decoder) Option { } } -// WithLogger with config loogger. +// WithLogger with config logger. func WithLogger(l log.Logger) Option { return func(o *options) { o.logger = l diff --git a/config/reader_test.go b/config/reader_test.go new file mode 100644 index 000000000..d7c3d179b --- /dev/null +++ b/config/reader_test.go @@ -0,0 +1,128 @@ +package config + +import ( + "fmt" + "testing" + + "github.com/go-kratos/kratos/v2/encoding" + "github.com/stretchr/testify/assert" +) + +func TestReader_Merge(t *testing.T) { + var ( + err error + ok bool + ) + opts := options{ + decoder: func(kv *KeyValue, v map[string]interface{}) error { + if codec := encoding.GetCodec(kv.Format); codec != nil { + return codec.Unmarshal(kv.Value, &v) + } + return fmt.Errorf("unsupported key: %s format: %s", kv.Key, kv.Format) + }, + } + r := newReader(opts) + err = r.Merge(&KeyValue{ + Key: "a", + Value: []byte("bad"), + Format: "json", + }) + assert.Error(t, err) + + err = r.Merge(&KeyValue{ + Key: "b", + Value: []byte(`{"nice": "boat", "x": 1}`), + Format: "json", + }) + assert.NoError(t, err) + vv, ok := r.Value("nice") + assert.True(t, ok) + vvv, err := vv.String() + assert.NoError(t, err) + assert.Equal(t, "boat", vvv) + + err = r.Merge(&KeyValue{ + Key: "b", + Value: []byte(`{"x": 2}`), + Format: "json", + }) + assert.NoError(t, err) + vv, ok = r.Value("x") + assert.True(t, ok) + vvx, err := vv.Int() + assert.NoError(t, err) + assert.Equal(t, int64(2), vvx) +} + +func TestReader_Value(t *testing.T) { + var ( + err error + ok bool + ) + opts := options{ + decoder: func(kv *KeyValue, v map[string]interface{}) error { + if codec := encoding.GetCodec(kv.Format); codec != nil { + return codec.Unmarshal(kv.Value, &v) + } + return fmt.Errorf("unsupported key: %s format: %s", kv.Key, kv.Format) + }, + } + r := newReader(opts) + err = r.Merge(&KeyValue{ + Key: "b", + Value: []byte(`{"a": {"b": {"X": 1, "Y": "lol", "z": true}}}`), + Format: "json", + }) + assert.NoError(t, err) + vv, ok := r.Value("a.b.X") + assert.True(t, ok) + vvv, err := vv.Int() + assert.NoError(t, err) + assert.Equal(t, int64(1), vvv) + + assert.NoError(t, err) + vv, ok = r.Value("a.b.Y") + assert.True(t, ok) + vvy, err := vv.String() + assert.NoError(t, err) + assert.Equal(t, "lol", vvy) + + assert.NoError(t, err) + vv, ok = r.Value("a.b.z") + assert.True(t, ok) + vvz, err := vv.Bool() + assert.NoError(t, err) + assert.Equal(t, true, vvz) + + vv, ok = r.Value("aasasdg=234l.asdfk,") + assert.False(t, ok) + + vv, ok = r.Value("aas......asdg=234l.asdfk,") + assert.False(t, ok) + + vv, ok = r.Value("a.b.Y.") + assert.False(t, ok) +} + +func TestReader_Source(t *testing.T) { + var ( + err error + ) + opts := options{ + decoder: func(kv *KeyValue, v map[string]interface{}) error { + if codec := encoding.GetCodec(kv.Format); codec != nil { + return codec.Unmarshal(kv.Value, &v) + } + return fmt.Errorf("unsupported key: %s format: %s", kv.Key, kv.Format) + }, + } + r := newReader(opts) + err = r.Merge(&KeyValue{ + Key: "b", + Value: []byte(`{"a": {"b": {"X": 1}}}`), + Format: "json", + }) + b, err := r.Source() + assert.NoError(t, err) + assert.Equal(t, []byte(`{"a":{"b":{"X":1}}}`), b) +} diff --git a/config/value_test.go b/config/value_test.go new file mode 100644 index 000000000..4219bdf8a --- /dev/null +++ b/config/value_test.go @@ -0,0 +1,121 @@ +package config + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func Test_atomicValue_Bool(t *testing.T) { + var vlist []interface{} + vlist = []interface{}{"1", "t", "T", "true", "TRUE", "True", true} + for _, x := range vlist { + v := atomicValue{} + v.Store(x) + b, err := v.Bool() + assert.NoError(t, err, b) + assert.True(t, b, b) + } + + vlist = []interface{}{"0", "f", "F", "false", "FALSE", "False", false} + for _, x := range vlist { + v := atomicValue{} + v.Store(x) + b, err := v.Bool() + assert.NoError(t, err, b) + assert.False(t, b, b) + } + + vlist = []interface{}{int32(1), 1, uint16(1), "bbb", "-1"} + for _, x := range vlist { + v := atomicValue{} + v.Store(x) + b, err := v.Bool() + assert.Error(t, err, b) + } +} + +func Test_atomicValue_Int(t *testing.T) { + var vlist []interface{} + vlist = []interface{}{"123123", float64(123123), int64(123123)} + for _, x := range vlist { + v := atomicValue{} + v.Store(x) + b, err := v.Int() + assert.NoError(t, err, b) + assert.Equal(t, int64(123123), b, b) + } + + vlist = []interface{}{int32(1123123), 123131, uint16(1), "bbb", "-x1"} + for _, x := range vlist { + v := atomicValue{} + v.Store(x) + b, err := v.Int() + assert.Error(t, err, b) + } +} + +func Test_atomicValue_Float(t *testing.T) { + var vlist []interface{} + vlist = []interface{}{"123123.1", float64(123123.1)} + for _, x := range vlist { + v := atomicValue{} + v.Store(x) + b, err := v.Float() + assert.NoError(t, err, b) + assert.Equal(t, float64(123123.1), b, b) + } + + vlist = []interface{}{float32(1123123), 123131, uint16(1), "bbb", "-x1"} + for _, x := range vlist { + v := atomicValue{} + v.Store(x) + b, err := v.Float() + assert.Error(t, err, b) + } +} + +func Test_atomicValue_String(t *testing.T) { + var vlist []interface{} + vlist = []interface{}{"1", float64(1), int64(1)} + for _, x := range vlist { + v := atomicValue{} + v.Store(x) + b, err := v.String() + assert.NoError(t, err, b) + assert.Equal(t, "1", b, b) + } + + v := atomicValue{} + v.Store(true) + b, err := v.String() + assert.NoError(t, err, b) + assert.Equal(t, "true", b, b) +} + +func Test_atomicValue_Duration(t *testing.T) { + var vlist []interface{} + vlist = []interface{}{int64(5)} + for _, x := range vlist { + v := atomicValue{} + v.Store(x) + b, err := v.Duration() + assert.NoError(t, err) + assert.Equal(t, time.Duration(5), b) + } +} + +func Test_atomicValue_Scan(t *testing.T) { + var err error + v := atomicValue{} + err = v.Scan(&struct { + A string `json:"a"` + }{"a"}) + assert.NoError(t, err) + + err = v.Scan(&struct { + A string `json:"a"` + }{"a"}) + assert.NoError(t, err) +} diff --git a/encoding/json/json.go b/encoding/json/json.go index 826b688e6..f2f3097e4 100644 --- a/encoding/json/json.go +++ b/encoding/json/json.go @@ -13,7 +13,7 @@ import ( const Name = "json" var ( - // MarshalOptions is a configurable JSON format marshaler. + // MarshalOptions is a configurable JSON format marshaller. MarshalOptions = protojson.MarshalOptions{ EmitUnpopulated: true, }