From 64d1e1efd5d853c6d3613607fcf767f33f10216e Mon Sep 17 00:00:00 2001 From: size12 Date: Thu, 7 Mar 2024 09:35:09 +0300 Subject: [PATCH 1/6] dict impl --- internal/params/dict.go | 229 ++++++++++++++++++++++++++++++++++ internal/params/dict_test.go | 31 +++++ internal/params/parameters.go | 7 ++ 3 files changed, 267 insertions(+) create mode 100644 internal/params/dict.go create mode 100644 internal/params/dict_test.go diff --git a/internal/params/dict.go b/internal/params/dict.go new file mode 100644 index 000000000..3cb0778f7 --- /dev/null +++ b/internal/params/dict.go @@ -0,0 +1,229 @@ +package params + +import ( + "time" + + "github.com/ydb-platform/ydb-go-sdk/v3/internal/value" +) + +type ( + dict struct { + parent Builder + name string + values []value.DictValueField + } + dictPair struct { + parent *dict + keyValue value.Value + } + dictValue struct { + pair *dictPair + } +) + +func (d *dict) Pair() *dictPair { + return &dictPair{ + parent: d, + } +} + +func (d *dict) AddPairs(pairs ...value.DictValueField) *dict { + d.values = append(d.values, pairs...) + + return d +} + +func (d *dictPair) Text(v string) *dictValue { + d.keyValue = value.TextValue(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Bytes(v []byte) *dictValue { + d.keyValue = value.BytesValue(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Bool(v bool) *dictValue { + d.keyValue = value.BoolValue(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Uint64(v uint64) *dictValue { + d.keyValue = value.Uint64Value(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Int64(v int64) *dictValue { + d.keyValue = value.Int64Value(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Uint32(v uint32) *dictValue { + d.keyValue = value.Uint32Value(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Int32(v int32) *dictValue { + d.keyValue = value.Int32Value(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Uint16(v uint16) *dictValue { + d.keyValue = value.Uint16Value(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Int16(v int16) *dictValue { + d.keyValue = value.Int16Value(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Uint8(v uint8) *dictValue { + d.keyValue = value.Uint8Value(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Int8(v int8) *dictValue { + d.keyValue = value.Int8Value(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Float(v float32) *dictValue { + d.keyValue = value.FloatValue(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Double(v float64) *dictValue { + d.keyValue = value.DoubleValue(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Decimal(v [16]byte, precision, scale uint32) *dictValue { + d.keyValue = value.DecimalValue(v, precision, scale) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Timestamp(v time.Time) *dictValue { + d.keyValue = value.TimestampValueFromTime(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Date(v time.Time) *dictValue { + d.keyValue = value.DateValueFromTime(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Datetime(v time.Time) *dictValue { + d.keyValue = value.DatetimeValueFromTime(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) Interval(v time.Duration) *dictValue { + d.keyValue = value.IntervalValueFromDuration(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) JSON(v string) *dictValue { + d.keyValue = value.JSONValue(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) JSONDocument(v string) *dictValue { + d.keyValue = value.JSONDocumentValue(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) YSON(v []byte) *dictValue { + d.keyValue = value.YSONValue(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictPair) UUID(v [16]byte) *dictValue { + d.keyValue = value.UUIDValue(v) + + return &dictValue{ + pair: d, + } +} + +func (d *dictValue) Uint64(v uint64) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.Uint64Value(v), + }) + + return d.pair.parent +} + +func (d *dict) Build() Builder { + d.parent.params = append(d.parent.params, &Parameter{ + parent: d.parent, + name: d.name, + value: value.DictValue(d.values...), + }) + + return d.parent +} diff --git a/internal/params/dict_test.go b/internal/params/dict_test.go new file mode 100644 index 000000000..9b5e31678 --- /dev/null +++ b/internal/params/dict_test.go @@ -0,0 +1,31 @@ +package params + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/ydb-platform/ydb-go-genproto/protos/Ydb" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/allocator" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" +) + +func TestDict(t *testing.T) { + for _, tt := range []struct { + name string + builder Builder + params map[string]*Ydb.TypedValue + }{ + { + name: xtest.CurrentFileLine(), + builder: Builder{}.Param("$x").Dict().Pair().Int32(2).Uint64(21).Build(), + params: map[string]*Ydb.TypedValue{}, + }, + } { + t.Run(tt.name, func(t *testing.T) { + a := allocator.New() + defer a.Free() + params := tt.builder.Build().ToYDB(a) + require.Equal(t, paramsToJSON(tt.params), paramsToJSON(params)) + }) + } +} diff --git a/internal/params/parameters.go b/internal/params/parameters.go index 96ef92591..21d1a3b8d 100644 --- a/internal/params/parameters.go +++ b/internal/params/parameters.go @@ -116,6 +116,13 @@ func (p *Parameter) Set() *set { } } +func (p *Parameter) Dict() *dict { + return &dict{ + parent: p.parent, + name: p.name, + } +} + func (p *Parameter) Text(v string) Builder { p.value = value.TextValue(v) p.parent.params = append(p.parent.params, p) From e811fc4bf9ad10af7aaf31ef6f1542cebd4eac91 Mon Sep 17 00:00:00 2001 From: size12 Date: Thu, 7 Mar 2024 14:53:43 +0300 Subject: [PATCH 2/6] finished dict impl --- internal/params/dict.go | 189 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) diff --git a/internal/params/dict.go b/internal/params/dict.go index 3cb0778f7..3632f5c1f 100644 --- a/internal/params/dict.go +++ b/internal/params/dict.go @@ -209,6 +209,33 @@ func (d *dictPair) UUID(v [16]byte) *dictValue { } } +func (d *dictValue) Text(v string) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.TextValue(v), + }) + + return d.pair.parent +} + +func (d *dictValue) Bytes(v []byte) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.BytesValue(v), + }) + + return d.pair.parent +} + +func (d *dictValue) Bool(v bool) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.BoolValue(v), + }) + + return d.pair.parent +} + func (d *dictValue) Uint64(v uint64) *dict { d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ K: d.pair.keyValue, @@ -218,6 +245,168 @@ func (d *dictValue) Uint64(v uint64) *dict { return d.pair.parent } +func (d *dictValue) Int64(v int64) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.Int64Value(v), + }) + + return d.pair.parent +} + +func (d *dictValue) Uint32(v uint32) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.Uint32Value(v), + }) + + return d.pair.parent +} + +func (d *dictValue) Int32(v int32) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.Int32Value(v), + }) + + return d.pair.parent +} + +func (d *dictValue) Uint16(v uint16) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.Uint16Value(v), + }) + + return d.pair.parent +} + +func (d *dictValue) Int16(v int16) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.Int16Value(v), + }) + + return d.pair.parent +} + +func (d *dictValue) Uint8(v uint8) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.Uint8Value(v), + }) + + return d.pair.parent +} + +func (d *dictValue) Int8(v int8) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.Int8Value(v), + }) + + return d.pair.parent +} + +func (d *dictValue) Float(v float32) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.FloatValue(v), + }) + + return d.pair.parent +} + +func (d *dictValue) Double(v float64) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.DoubleValue(v), + }) + + return d.pair.parent +} + +func (d *dictValue) Decimal(v [16]byte, precision, scale uint32) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.DecimalValue(v, precision, scale), + }) + + return d.pair.parent +} + +func (d *dictValue) Timestamp(v time.Time) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.TimestampValueFromTime(v), + }) + + return d.pair.parent +} + +func (d *dictValue) Date(v time.Time) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.DateValueFromTime(v), + }) + + return d.pair.parent +} + +func (d *dictValue) Datetime(v time.Time) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.DatetimeValueFromTime(v), + }) + + return d.pair.parent +} + +func (d *dictValue) Interval(v time.Duration) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.IntervalValueFromDuration(v), + }) + + return d.pair.parent +} + +func (d *dictValue) JSON(v string) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.JSONValue(v), + }) + + return d.pair.parent +} + +func (d *dictValue) JSONDocument(v string) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.JSONDocumentValue(v), + }) + + return d.pair.parent +} + +func (d *dictValue) YSON(v []byte) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.YSONValue(v), + }) + + return d.pair.parent +} + +func (d *dictValue) UUID(v [16]byte) *dict { + d.pair.parent.values = append(d.pair.parent.values, value.DictValueField{ + K: d.pair.keyValue, + V: value.UUIDValue(v), + }) + + return d.pair.parent +} + func (d *dict) Build() Builder { d.parent.params = append(d.parent.params, &Parameter{ parent: d.parent, From 2656b0511dbea5db460441f2606d526dde6b6ee6 Mon Sep 17 00:00:00 2001 From: size12 Date: Thu, 7 Mar 2024 21:42:28 +0300 Subject: [PATCH 3/6] tests for dict params builder --- internal/params/dict_test.go | 404 +++++++++++++++++++++++++++-- internal/xtest/call_method.go | 25 ++ internal/xtest/call_method_test.go | 38 +++ 3 files changed, 452 insertions(+), 15 deletions(-) create mode 100644 internal/xtest/call_method.go create mode 100644 internal/xtest/call_method_test.go diff --git a/internal/params/dict_test.go b/internal/params/dict_test.go index 9b5e31678..1412131d7 100644 --- a/internal/params/dict_test.go +++ b/internal/params/dict_test.go @@ -1,31 +1,405 @@ package params import ( + "fmt" "testing" + "time" "github.com/stretchr/testify/require" "github.com/ydb-platform/ydb-go-genproto/protos/Ydb" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/allocator" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" ) func TestDict(t *testing.T) { - for _, tt := range []struct { - name string - builder Builder - params map[string]*Ydb.TypedValue + type expected struct { + kind *Ydb.Type + value *Ydb.Value + } + + tests := []struct { + method string + args []any + + expected expected }{ { - name: xtest.CurrentFileLine(), - builder: Builder{}.Param("$x").Dict().Pair().Int32(2).Uint64(21).Build(), - params: map[string]*Ydb.TypedValue{}, - }, - } { - t.Run(tt.name, func(t *testing.T) { - a := allocator.New() - defer a.Free() - params := tt.builder.Build().ToYDB(a) - require.Equal(t, paramsToJSON(tt.params), paramsToJSON(params)) - }) + method: "Uint64", + args: []any{uint64(123)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT64}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_Uint64Value{ + Uint64Value: 123, + }, + }, + }, + }, + { + method: "Int64", + args: []any{int64(123)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT64}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_Int64Value{ + Int64Value: 123, + }, + }, + }, + }, + { + method: "Uint32", + args: []any{uint32(123)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT32}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 123, + }, + }, + }, + }, + { + method: "Int32", + args: []any{int32(123)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT32}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_Int32Value{ + Int32Value: 123, + }, + }, + }, + }, + { + method: "Uint16", + args: []any{uint16(123)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT16}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 123, + }, + }, + }, + }, + { + method: "Int16", + args: []any{int16(123)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT16}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_Int32Value{ + Int32Value: 123, + }, + }, + }, + }, + { + method: "Uint8", + args: []any{uint8(123)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UINT8}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 123, + }, + }, + }, + }, + { + method: "Int8", + args: []any{int8(123)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INT8}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_Int32Value{ + Int32Value: 123, + }, + }, + }, + }, + { + method: "Bool", + args: []any{true}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_BOOL}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_BoolValue{ + BoolValue: true, + }, + }, + }, + }, + { + method: "Text", + args: []any{"test"}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UTF8}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: "test", + }, + }, + }, + }, + { + method: "Bytes", + args: []any{[]byte("test")}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_STRING}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_BytesValue{ + BytesValue: []byte("test"), + }, + }, + }, + }, + { + method: "Float", + args: []any{float32(123)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_FLOAT}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_FloatValue{ + FloatValue: float32(123), + }, + }, + }, + }, + { + method: "Double", + args: []any{float64(123)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DOUBLE}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_DoubleValue{ + DoubleValue: float64(123), + }, + }, + }, + }, + { + method: "Interval", + args: []any{time.Second}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_INTERVAL}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_Int64Value{ + Int64Value: 1000000, + }, + }, + }, + }, + { + method: "Datetime", + args: []any{time.Unix(123456789, 456)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DATETIME}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 123456789, + }, + }, + }, + }, + { + method: "Date", + args: []any{time.Unix(123456789, 456)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_DATE}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_Uint32Value{ + Uint32Value: 1428, + }, + }, + }, + }, + { + method: "Timestamp", + args: []any{time.Unix(123456789, 456)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_TIMESTAMP}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_Uint64Value{ + Uint64Value: 123456789000000, + }, + }, + }, + }, + { + method: "Decimal", + args: []any{[...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6}, uint32(22), uint32(9)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_DecimalType{ + DecimalType: &Ydb.DecimalType{ + Precision: 22, + Scale: 9, + }, + }, + }, + value: &Ydb.Value{ + High_128: 72623859790382856, + Value: &Ydb.Value_Low_128{ + Low_128: 648519454493508870, + }, + }, + }, + }, + { + method: "JSON", + args: []any{`{"a": 1,"b": "B"}`}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_JSON}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: `{"a": 1,"b": "B"}`, + }, + }, + }, + }, + { + method: "JSONDocument", + args: []any{`{"a": 1,"b": "B"}`}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_JSON_DOCUMENT}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_TextValue{ + TextValue: `{"a": 1,"b": "B"}`, + }, + }, + }, + }, + { + method: "YSON", + args: []any{[]byte(`{"a": 1,"b": "B"}`)}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_YSON}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_BytesValue{ + BytesValue: []byte(`{"a": 1,"b": "B"}`), + }, + }, + }, + }, + { + method: "UUID", + args: []any{[...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}, + + expected: expected{ + kind: &Ydb.Type{ + Type: &Ydb.Type_TypeId{TypeId: Ydb.Type_UUID}, + }, + value: &Ydb.Value{ + Value: &Ydb.Value_Low_128{ + Low_128: 651345242494996240, + }, + High_128: 72623859790382856, + }, + }, + }, + } + + for _, key := range tests { + for _, val := range tests { + t.Run(fmt.Sprintf("%s:%s", key.method, val.method), func(t *testing.T) { + a := allocator.New() + defer a.Free() + + item := Builder{}.Param("$x").Dict().Pair() + + addedKey, ok := xtest.CallMethod(item, key.method, key.args...)[0].(*dictValue) + require.True(t, ok) + + d, ok := xtest.CallMethod(addedKey, val.method, val.args...)[0].(*dict) + require.True(t, ok) + + params := d.Build().Build().ToYDB(a) + require.Equal(t, paramsToJSON( + map[string]*Ydb.TypedValue{ + "$x": { + Type: &Ydb.Type{ + Type: &Ydb.Type_DictType{ + DictType: &Ydb.DictType{ + Key: key.expected.kind, + Payload: val.expected.kind, + }, + }, + }, + Value: &Ydb.Value{ + Pairs: []*Ydb.ValuePair{ + { + Key: key.expected.value, + Payload: val.expected.value, + }, + }, + }, + }, + }), paramsToJSON(params)) + }) + } } } diff --git a/internal/xtest/call_method.go b/internal/xtest/call_method.go new file mode 100644 index 000000000..a7e060a8a --- /dev/null +++ b/internal/xtest/call_method.go @@ -0,0 +1,25 @@ +package xtest + +import ( + "reflect" +) + +func CallMethod(object any, name string, args ...any) []any { + method := reflect.ValueOf(object).MethodByName(name) + + inputs := make([]reflect.Value, len(args)) + + for i := range args { + inputs[i] = reflect.ValueOf(args[i]) + } + + output := method.Call(inputs) + + result := make([]any, len(output)) + + for i := range output { + result[i] = output[i].Interface() + } + + return result +} diff --git a/internal/xtest/call_method_test.go b/internal/xtest/call_method_test.go new file mode 100644 index 000000000..155f7d2c9 --- /dev/null +++ b/internal/xtest/call_method_test.go @@ -0,0 +1,38 @@ +package xtest + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestCallMethod(t *testing.T) { + object := bytes.NewBuffer(nil) + + result := CallMethod(object, "WriteString", "Hello world!") + n := result[0].(int) + err := result[1] + + require.Equal(t, 12, n) + require.Nil(t, err) + + result = CallMethod(object, "String") + + str, ok := result[0].(string) + require.True(t, ok) + + require.Equal(t, object.String(), str) + + require.Panics(t, func() { + CallMethod(object, "NonameMethod") + }) + + require.Panics(t, func() { + CallMethod(object, "String", "wrong", "arguments", "count") + }) + + require.Panics(t, func() { + CallMethod(object, "String", 123) + }) +} From c447e41499d2a19b38a79284cbf94e7cbde8baed Mon Sep 17 00:00:00 2001 From: size12 Date: Fri, 8 Mar 2024 10:00:06 +0300 Subject: [PATCH 4/6] test for (*dict).AddPairs() --- internal/params/dict_test.go | 69 ++++++++++++++++++++++++++++++ internal/xtest/call_method_test.go | 3 +- 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/internal/params/dict_test.go b/internal/params/dict_test.go index 1412131d7..683e53c8b 100644 --- a/internal/params/dict_test.go +++ b/internal/params/dict_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/require" "github.com/ydb-platform/ydb-go-genproto/protos/Ydb" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/value" "github.com/ydb-platform/ydb-go-sdk/v3/internal/allocator" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" @@ -403,3 +404,71 @@ func TestDict(t *testing.T) { } } } + +func TestDict_AddPairs(t *testing.T) { + a := allocator.New() + defer a.Free() + + pairs := []value.DictValueField{ + { + K: value.Int64Value(123), + V: value.BoolValue(true), + }, + { + K: value.Int64Value(321), + V: value.BoolValue(false), + }, + } + + params := Builder{}.Param("$x").Dict().AddPairs(pairs...).Build().Build().ToYDB(a) + + require.Equal(t, paramsToJSON( + map[string]*Ydb.TypedValue{ + "$x": { + Type: &Ydb.Type{ + Type: &Ydb.Type_DictType{ + DictType: &Ydb.DictType{ + Key: &Ydb.Type{ + Type: &Ydb.Type_TypeId{ + TypeId: Ydb.Type_INT64, + }, + }, + Payload: &Ydb.Type{ + Type: &Ydb.Type_TypeId{ + TypeId: Ydb.Type_BOOL, + }, + }, + }, + }, + }, + Value: &Ydb.Value{ + Pairs: []*Ydb.ValuePair{ + { + Key: &Ydb.Value{ + Value: &Ydb.Value_Int64Value{ + Int64Value: 123, + }, + }, + Payload: &Ydb.Value{ + Value: &Ydb.Value_BoolValue{ + BoolValue: true, + }, + }, + }, + { + Key: &Ydb.Value{ + Value: &Ydb.Value_Int64Value{ + Int64Value: 321, + }, + }, + Payload: &Ydb.Value{ + Value: &Ydb.Value_BoolValue{ + BoolValue: false, + }, + }, + }, + }, + }, + }, + }), paramsToJSON(params)) +} diff --git a/internal/xtest/call_method_test.go b/internal/xtest/call_method_test.go index 155f7d2c9..fe721761d 100644 --- a/internal/xtest/call_method_test.go +++ b/internal/xtest/call_method_test.go @@ -33,6 +33,7 @@ func TestCallMethod(t *testing.T) { }) require.Panics(t, func() { - CallMethod(object, "String", 123) + // Wrong argument type. + CallMethod(object, "WriteString", 123) }) } From b495c1fbf8d98f1eb8c676470376332a593879d2 Mon Sep 17 00:00:00 2001 From: size12 Date: Fri, 8 Mar 2024 10:01:16 +0300 Subject: [PATCH 5/6] fixed linter warnings --- internal/params/dict_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/params/dict_test.go b/internal/params/dict_test.go index 683e53c8b..835816698 100644 --- a/internal/params/dict_test.go +++ b/internal/params/dict_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/require" "github.com/ydb-platform/ydb-go-genproto/protos/Ydb" - "github.com/ydb-platform/ydb-go-sdk/v3/internal/value" "github.com/ydb-platform/ydb-go-sdk/v3/internal/allocator" + "github.com/ydb-platform/ydb-go-sdk/v3/internal/value" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" ) From 0c367eaedec11067866104d88c46a5ec805492a7 Mon Sep 17 00:00:00 2001 From: size12 Date: Tue, 12 Mar 2024 16:55:40 +0300 Subject: [PATCH 6/6] CHANGELOG.md update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22dcb0e6d..1098b5b03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ +* Added `Dict` support for `ydb.ParamsBuilder()` * Added experimental implementation of query service client * Fixed sometime panic on topic writer closing * Added experimental query parameters builder `ydb.ParamsBuilder()`