From 9a91d0c78aa57005fb44c2374421bb4192e247d2 Mon Sep 17 00:00:00 2001 From: Alexej Kubarev Date: Thu, 16 May 2024 12:05:28 +0200 Subject: [PATCH 1/6] decoder: Renaming badly named test --- decode_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/decode_test.go b/decode_test.go index 8717ac6..4898162 100644 --- a/decode_test.go +++ b/decode_test.go @@ -622,7 +622,8 @@ func Test_structMemberToFieldName(t *testing.T) { } } -func Test_github(t *testing.T) { +// Issue: https://github.com/alexejk/go-xmlrpc/issues/84 +func Test_github_84(t *testing.T) { dec := &StdDecoder{} decodeTarget := struct { Array []any From 5479a22ba67e7b6a98435e9e99595cb6716108ae Mon Sep 17 00:00:00 2001 From: Alexej Kubarev Date: Thu, 16 May 2024 12:20:48 +0200 Subject: [PATCH 2/6] build(lint): golangci-lint upgrade to 1.58.1 --- .golangci.yml | 9 ++++++--- hack/linter.sh | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 8fd343a..0c25dde 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -10,7 +10,10 @@ linters-settings: - $gostd - github.com/stretchr/testify gci: - local-prefixes: github.com/golangci/golangci-lint + sections: + - standard # Standard section: captures all standard packages. + - default + - prefix(alexejk.io/go-xmlrpc) goconst: min-len: 2 min-occurrences: 2 @@ -29,7 +32,7 @@ linters-settings: - wrapperFunc goimports: local-prefixes: alexejk.io/go-xmlrpc - gomnd: + mnd: settings: mnd: # don't include the "operation" and "assign" @@ -63,7 +66,7 @@ linters: - gocritic - gofmt - goimports - - gomnd + - mnd - goprintffuncname - gosec - gosimple diff --git a/hack/linter.sh b/hack/linter.sh index e47348a..39fb56e 100644 --- a/hack/linter.sh +++ b/hack/linter.sh @@ -6,7 +6,7 @@ GREEN="\033[32m" YELLOW="\033[33m" NORMAL="\033[39m" -LINTER_VERSION=1.56.1 +LINTER_VERSION=1.58.1 LINTER_BINDIR=$(go env GOPATH)/bin LINTER_NAME=golangci-lint From 722b0d890152fd7cb2ae90e8fc57863460a25bd8 Mon Sep 17 00:00:00 2001 From: Alexej Kubarev Date: Thu, 16 May 2024 12:23:32 +0200 Subject: [PATCH 3/6] decoder: Add support for nested mixed type slice decoding where `[]any` may contain another slice of mixed types --- client_test.go | 82 ++++++++++++++++++++ decode.go | 13 +++- decode_test.go | 7 ++ testdata/response_array_mixed_with_array.xml | 27 +++++++ 4 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 testdata/response_array_mixed_with_array.xml diff --git a/client_test.go b/client_test.go index 68102e0..eb7d743 100644 --- a/client_test.go +++ b/client_test.go @@ -68,6 +68,88 @@ func TestClient_Call(t *testing.T) { require.Equal(t, 12345, resp.Index) } +func TestClient_Github_86(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + m := &struct { + Name string `xml:"methodName"` + Params []*ResponseParam `xml:"params>param"` + }{} + body, err := io.ReadAll(r.Body) + require.NoError(t, err, "test server: read body") + + err = xml.Unmarshal(body, m) + require.NoError(t, err, "test server: unmarshal body") + + require.Equal(t, "di", m.Name) + require.Equal(t, 3, len(m.Params)) + + expected := []string{"abc", "def", "hij"} + for i, p := range m.Params { + require.Equal(t, expected[i], *p.Value.String) + } + + respBody := ` + + + + OK + + + 200 + + + + + + 200 + Some String + Server: Sip Express Media Server (5.1.0 (x86_64/Linux)) calls: 0 active/0 total/0 connect/0 min + + + + + +` + _, _ = fmt.Fprintln(w, respBody) + })) + defer ts.Close() + + c, err := NewClient(ts.URL) + require.NoError(t, err) + require.NotNil(t, c) + + type DiRequest struct { + First string + Second string + Third string + } + + type DiResponse struct { + Status string + Code int + Data []any + } + + req := &DiRequest{ + First: "abc", + Second: "def", + Third: "hij", + } + resp := &DiResponse{} + + err = c.Call("di", req, resp) + require.NoError(t, err) + require.Equal(t, "OK", resp.Status) + require.Equal(t, 200, resp.Code) + + // Data array decoding validation + require.NotEmpty(t, resp.Data) + require.Len(t, resp.Data, 3) + require.Equal(t, 200, resp.Data[0].(int)) + require.Equal(t, []any{"Some String"}, resp.Data[1].([]any)) + require.Equal(t, "Server: Sip Express Media Server (5.1.0 (x86_64/Linux)) calls: 0 active/0 total/0 connect/0 min", resp.Data[2].(string)) +} + func TestClient_Fault(t *testing.T) { ts := mockupServer(t, "response_fault.xml") defer ts.Close() diff --git a/decode.go b/decode.go index 0d93769..3e26949 100644 --- a/decode.go +++ b/decode.go @@ -119,7 +119,18 @@ func (d *StdDecoder) decodeValue(value *ResponseValue, field reflect.Value) erro // Array decoding case value.Array != nil: - if field.Kind() != reflect.Slice { + fieldKind := field.Kind() + + // When dealing with nested arrays of []any type, initial kind for the nested array will be reflect.Interface + if fieldKind == reflect.Interface { + // Create a new []interface{} and assign it to field + fieldType := reflect.SliceOf(reflect.TypeOf((*interface{})(nil)).Elem()) + fieldKind = reflect.Slice + + field.Set(reflect.MakeSlice(fieldType, 0, 0)) + } + + if fieldKind != reflect.Slice { return fmt.Errorf(errFormatInvalidFieldType, reflect.Slice.String(), field.Kind().String()) } diff --git a/decode_test.go b/decode_test.go index 4898162..33b5449 100644 --- a/decode_test.go +++ b/decode_test.go @@ -407,6 +407,13 @@ func TestStdDecoder_DecodeRaw_Arrays(t *testing.T) { Array: []any{0, "4099", "O3D217AC", "123"}, }, }, + // Related to issue #86: https://github.com/alexejk/go-xmlrpc/issues/86 + "Basic mixed array - with nested mixed array (Github #86)": { + testFile: "response_array_mixed_with_array.xml", + expect: &TestStruct{ + Array: []any{10, "s11", true, []any{"Some String"}}, + }, + }, } for name, tt := range tests { diff --git a/testdata/response_array_mixed_with_array.xml b/testdata/response_array_mixed_with_array.xml new file mode 100644 index 0000000..095b761 --- /dev/null +++ b/testdata/response_array_mixed_with_array.xml @@ -0,0 +1,27 @@ + + + + + + + + + 10 + s11 + 1 + + + + Some String + + + + + + + + + From e6ce5b8f0a117f24a732bae72e2fa83ae8b390c9 Mon Sep 17 00:00:00 2001 From: Alexej Kubarev Date: Thu, 16 May 2024 12:42:28 +0200 Subject: [PATCH 4/6] decoder: Adding multi-level nested mixed array test --- decode_test.go | 2 +- testdata/response_array_mixed_with_array.xml | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/decode_test.go b/decode_test.go index 33b5449..022b2b5 100644 --- a/decode_test.go +++ b/decode_test.go @@ -411,7 +411,7 @@ func TestStdDecoder_DecodeRaw_Arrays(t *testing.T) { "Basic mixed array - with nested mixed array (Github #86)": { testFile: "response_array_mixed_with_array.xml", expect: &TestStruct{ - Array: []any{10, "s11", true, []any{"Some String"}}, + Array: []any{10, "s11", true, []any{"Some String", []any{"Nested String", 10, true}}}, }, }, } diff --git a/testdata/response_array_mixed_with_array.xml b/testdata/response_array_mixed_with_array.xml index 095b761..273fb9f 100644 --- a/testdata/response_array_mixed_with_array.xml +++ b/testdata/response_array_mixed_with_array.xml @@ -16,6 +16,15 @@ Nested array in the mixed array decoding issue Some String + + + + Nested String + 10 + 1 + + + From 6120579375a23e4fc31eb1efdbca78a348cb9df7 Mon Sep 17 00:00:00 2001 From: Alexej Kubarev Date: Thu, 16 May 2024 12:43:19 +0200 Subject: [PATCH 5/6] decoder: Adding struct with nested multi-level mixed array test --- decode_test.go | 13 +++++++++++++ testdata/response_struct.xml | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/decode_test.go b/decode_test.go index 022b2b5..ba3d661 100644 --- a/decode_test.go +++ b/decode_test.go @@ -77,6 +77,7 @@ func TestStdDecoder_DecodeRaw(t *testing.T) { WoBleBobble bool WoBleBobble2 int Field2 int `xmlrpc:"2"` + Array []any } }{}, expect: &struct { @@ -86,6 +87,7 @@ func TestStdDecoder_DecodeRaw(t *testing.T) { WoBleBobble bool WoBleBobble2 int Field2 int `xmlrpc:"2"` + Array []any } }{ Struct: struct { @@ -94,12 +96,14 @@ func TestStdDecoder_DecodeRaw(t *testing.T) { WoBleBobble bool WoBleBobble2 int Field2 int `xmlrpc:"2"` + Array []any }{ Foo: "bar", Baz: 2, WoBleBobble: true, WoBleBobble2: 34, Field2: 3, + Array: []any{200, "Some String", []any{"Nested String", 10, true}}, }, }, }, @@ -274,6 +278,7 @@ func TestStdDecoder_DecodeRaw_StructFields(t *testing.T) { WoBleBobble bool WoBleBobble2 int Field2 int `xmlrpc:"2"` + Array []any } }{}, expect: &struct { @@ -283,6 +288,7 @@ func TestStdDecoder_DecodeRaw_StructFields(t *testing.T) { WoBleBobble bool WoBleBobble2 int Field2 int `xmlrpc:"2"` + Array []any } }{ Struct: struct { @@ -291,12 +297,14 @@ func TestStdDecoder_DecodeRaw_StructFields(t *testing.T) { WoBleBobble bool WoBleBobble2 int Field2 int `xmlrpc:"2"` + Array []any }{ Foo: "bar", Baz: 2, WoBleBobble: true, WoBleBobble2: 34, Field2: 3, + Array: []any{200, "Some String", []any{"Nested String", 10, true}}, }, }, }, @@ -310,6 +318,7 @@ func TestStdDecoder_DecodeRaw_StructFields(t *testing.T) { WoBleBobble bool WoBleBobble2 *int Field2 *int `xmlrpc:"2"` + Array []any } }{}, expect: &struct { @@ -319,6 +328,7 @@ func TestStdDecoder_DecodeRaw_StructFields(t *testing.T) { WoBleBobble bool WoBleBobble2 *int Field2 *int `xmlrpc:"2"` + Array []any } }{ Struct: &struct { @@ -327,12 +337,14 @@ func TestStdDecoder_DecodeRaw_StructFields(t *testing.T) { WoBleBobble bool WoBleBobble2 *int Field2 *int `xmlrpc:"2"` + Array []any }{ Foo: sPtr("bar"), Baz: 2, WoBleBobble: true, WoBleBobble2: iPtr(34), Field2: iPtr(3), + Array: []any{200, "Some String", []any{"Nested String", 10, true}}, }, }, }, @@ -463,6 +475,7 @@ func TestStdDecoder_DecodeRaw_Struct_Map(t *testing.T) { "woBleBobble": true, "WoBleBobble2": 34, "2": 3, + "array": []any{200, "Some String", []any{"Nested String", 10, true}}, }, }, }, diff --git a/testdata/response_struct.xml b/testdata/response_struct.xml index 76f40cb..7fcc632 100644 --- a/testdata/response_struct.xml +++ b/testdata/response_struct.xml @@ -24,6 +24,26 @@ 2 3 + + array + + + + 200 + Some String + + + + Nested String + 10 + 1 + + + + + + + From 78203c0c22fad3814e93d77ea33d14b2387982c8 Mon Sep 17 00:00:00 2001 From: Alexej Kubarev Date: Thu, 16 May 2024 12:44:13 +0200 Subject: [PATCH 6/6] changelog: preparing for 0.5.3 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9da5e4a..292f9fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.5.3 + +Bugfixes: +* Decoding an `` of mixed types that contains another set of nested `` (with equally mixed types) (#86). + Outer slice would need to be defined as `[]any` and it's up to the user to cast the inner values (including nested slices) to the desired/expected type. + + ## 0.5.2 Bugfixes: