Skip to content

encoding/xml: increase test coverage #42043

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
2a43115
new test TestMarshalIndentErrors
charlesjlee Sep 15, 2020
78620db
new struct and test
charlesjlee Sep 15, 2020
3ddbe5e
two new structs MyMarshalerTestErrorMissingName, MyMarshalerTestError…
charlesjlee Sep 15, 2020
952047e
cover (TagPathError)Error
charlesjlee Sep 15, 2020
90444c3
trigger namespace without name in field
charlesjlee Sep 15, 2020
d744d03
new struct BadTag
charlesjlee Sep 15, 2020
d1241c4
add BadTagMultipleNodes struct
charlesjlee Sep 16, 2020
a0a6b24
new struct BadTagTrailingTag
charlesjlee Sep 16, 2020
bc09b36
new struct ServiceErrorNameConflict
charlesjlee Sep 16, 2020
13f5833
new structs BadEmbed, BadInnerEmbed
charlesjlee Sep 16, 2020
620e85f
new TestUnmarshalNonpointer
charlesjlee Sep 16, 2020
4bf70b0
new TestUnmarshalerError
charlesjlee Sep 16, 2020
d9d0d3b
test all cases of CopyToken
charlesjlee Sep 19, 2020
7788df1
add TestTokenAutoClose
charlesjlee Sep 23, 2020
a2992db
test (e *SyntaxError) Error()
charlesjlee Sep 23, 2020
e3640a7
new TestTokenErrors, deleteTestSyntaxErrorLineNum
charlesjlee Sep 26, 2020
bdfb5e6
two new cases for (d *Decoder) rawToken
charlesjlee Oct 3, 2020
1930242
new TestRawTokenAltEncodingErrors, TestRawTokenAltEncodingPanic
charlesjlee Oct 4, 2020
9942b66
new TestNewDecoder
charlesjlee Oct 4, 2020
e739fcd
more coverage
charlesjlee Oct 4, 2020
1b6d31a
test isName
charlesjlee Oct 4, 2020
90e0587
new TestProcInstEncodeTokenBadNameString
charlesjlee Oct 4, 2020
9e67c0b
new EscapeText tests
charlesjlee Oct 4, 2020
fb0d6f1
new TestUnmarshalerTextError
charlesjlee Oct 4, 2020
9a8e2f1
new TestUnmarshalUnknownType
charlesjlee Oct 4, 2020
6930c03
new TestUnmarshalErrors
charlesjlee Oct 4, 2020
7058a0d
new TestSkip, TestSkipErrors
charlesjlee Oct 11, 2020
b1c25b2
cover unmarshal() reflect.Struct cases
charlesjlee Oct 11, 2020
1374b98
gofmt
charlesjlee Oct 17, 2020
c95cbfe
gofmt
charlesjlee Oct 17, 2020
9ec3a79
remove comments
charlesjlee Oct 17, 2020
a828f1f
delete test files
charlesjlee Oct 17, 2020
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
135 changes: 132 additions & 3 deletions src/encoding/xml/marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ type Service struct {
Extra2 interface{} `xml:"host>extra2"`
}

type ServiceErrorNameConflict struct {
XMLName struct{} `xml:"service"`
Domain *Domain `xml:"host>domain"`
Port *Port `xml:"host>portZZZ"`
Extra1 interface{}
Extra2 interface{} `xml:"host>extra2"`
}

var nilStruct *Ship

type EmbedA struct {
Expand Down Expand Up @@ -189,6 +197,10 @@ type NameInField struct {
Foo Name `xml:"ns foo"`
}

type NameInFieldError struct {
Foo Name `xml:"ns "`
}

type AttrTest struct {
Int int `xml:",attr"`
Named int `xml:"int,attr"`
Expand Down Expand Up @@ -320,9 +332,22 @@ type MyMarshalerTest struct {
var _ Marshaler = (*MyMarshalerTest)(nil)

func (m *MyMarshalerTest) MarshalXML(e *Encoder, start StartElement) error {
return e.EncodeElement("hello world", start)
}

type MyMarshalerTestErrorMissingName struct {
}

func (m *MyMarshalerTestErrorMissingName) MarshalXML(e *Encoder, _ StartElement) error {
return e.EncodeElement("hello world", StartElement{Name{"", ""}, nil})
}

type MyMarshalerTestErrorNotClosed struct {
}

func (m *MyMarshalerTestErrorNotClosed) MarshalXML(e *Encoder, start StartElement) error {
e.EncodeToken(start)
e.EncodeToken(CharData([]byte("hello world")))
e.EncodeToken(EndElement{start.Name})
e.EncodeToken(CharData("hello world"))
return nil
}

Expand Down Expand Up @@ -791,6 +816,12 @@ var marshalTests = []struct {
`</service>`,
MarshalOnly: true,
},
{
Value: &ServiceErrorNameConflict{Port: &Port{Number: "80"}},
ExpectXML: `<service><host><port>80</port></host></service>`,
MarshalError: `conflicts with name`,
UnmarshalError: `conflicts with name`,
},
{
Value: &struct {
XMLName struct{} `xml:"space top"`
Expand Down Expand Up @@ -955,6 +986,12 @@ var marshalTests = []struct {
ExpectXML: `<NameInField><foo xmlns="ns"><ignore></ignore></foo></NameInField>`,
UnmarshalOnly: true,
},
{
Value: &NameInFieldError{Name{Space: "ns", Local: "foo"}},
ExpectXML: `<NameInField><foo xmlns="ns"></foo></NameInField>`,
MarshalError: "xml: namespace without name in field",
UnmarshalError: "xml: namespace without name in field",
},

// Marshaling zero xml.Name uses the tag or field name.
{
Expand Down Expand Up @@ -1243,6 +1280,16 @@ var marshalTests = []struct {
ExpectXML: `<MyMarshalerTest>hello world</MyMarshalerTest>`,
Value: &MyMarshalerTest{},
},
{
ExpectXML: `<MyMarshalerTest>hello world</MyMarshalerTest>`,
Value: &MyMarshalerTestErrorMissingName{},
MarshalError: "xml: EncodeElement of StartElement with missing name",
},
{
ExpectXML: `<MyMarshalerTest>hello world</MyMarshalerTest>`,
Value: &MyMarshalerTestErrorNotClosed{},
MarshalError: "MarshalXML wrote invalid XML",
},
{
ExpectXML: `<MarshalerStruct Foo="hello world"></MarshalerStruct>`,
Value: &MarshalerStruct{},
Expand Down Expand Up @@ -1694,6 +1741,27 @@ type BadAttr struct {
Name map[string]string `xml:"name,attr"`
}

type BadTag struct {
Comment string `xml:",comment,omitempty"`
}

type BadTagMultipleModes struct {
Comment string `xml:",attr,comment"`
}

type BadTagTrailingTag struct {
Comment string `xml:"comment>"`
}

type BadEmbed struct {
BadInnerEmbed
}

type BadInnerEmbed struct {
Field string `xml:"Field,attr,comment"`
}

// used by both TestMarshalErrors and TestMarshalIndentErrors
var marshalErrorTests = []struct {
Value interface{}
Err string
Expand Down Expand Up @@ -1730,6 +1798,22 @@ var marshalErrorTests = []struct {
Value: BadAttr{map[string]string{"X": "Y"}},
Err: `xml: unsupported type: map[string]string`,
},
{
Value: BadTag{"some comment"},
Err: `xml: invalid tag in field Comment of type xml.BadTag: ",comment,omitempty"`,
},
{
Value: BadTagMultipleModes{"some comment"},
Err: `xml: invalid tag in field Comment of type xml.BadTagMultipleModes: ",attr,comment"`,
},
{
Value: BadTagTrailingTag{"some comment"},
Err: `xml: trailing '>' in field Comment of type xml.BadTagTrailingTag`,
},
{
Value: BadEmbed{},
Err: `xml: invalid tag in field Field of type xml.BadInnerEmbed: "Field,attr,comment"`,
},
}

var marshalIndentTests = []struct {
Expand Down Expand Up @@ -1829,6 +1913,24 @@ func TestMarshalIndent(t *testing.T) {
}
}

func TestMarshalIndentErrors(t *testing.T) {
for idx, test := range marshalErrorTests {
data, err := MarshalIndent(test.Value, "", "")
if err == nil {
t.Errorf("#%d: marshalIndent(%#v) = [success] %q, want error %v", idx, test.Value, data, test.Err)
continue
}
if err.Error() != test.Err {
t.Errorf("#%d: marshalIndent(%#v) = [error] %v, want %v", idx, test.Value, err, test.Err)
}
if test.Kind != reflect.Invalid {
if kind := err.(*UnsupportedTypeError).Type.Kind(); kind != test.Kind {
t.Errorf("#%d: marshalIndent(%#v) = [error kind] %s, want %s", idx, test.Value, kind, test.Kind)
}
}
}
}

type limitedBytesWriter struct {
w io.Writer
remain int // until writes fail
Expand Down Expand Up @@ -2020,6 +2122,12 @@ var encodeTokenTests = []struct {
ProcInst{"", []byte("Instruction?>")},
},
err: "xml: EncodeToken of ProcInst with invalid Target",
}, {
desc: "proc instruction with endProcInst",
toks: []Token{
ProcInst{"Target", []byte("Instruction?>")},
},
err: "xml: EncodeToken of ProcInst containing ?> marker",
}, {
desc: "directive",
toks: []Token{
Expand Down Expand Up @@ -2340,6 +2448,28 @@ func TestProcInstEncodeToken(t *testing.T) {
}
}

func TestProcInstEncodeTokenBadNameString(t *testing.T) {
tests := []struct {
input ProcInst
}{
{ProcInst{"\xe6", []byte("Instruction")}},
{ProcInst{".", []byte("Instruction")}},
{ProcInst{"a\xe6", []byte("Instruction")}},
}
expectedError := `xml: EncodeToken of ProcInst with invalid Target`

for _, test := range tests {
var buf bytes.Buffer
enc := NewEncoder(&buf)

if err := enc.EncodeToken(test.input); err == nil {
t.Fatalf(`expected not receive expected error for input %s`, test.input)
} else if err.Error() != expectedError {
t.Fatalf(`err.Error() = "%s", want "%s"`, err.Error(), expectedError)
}
}
}

func TestDecodeEncode(t *testing.T) {
var in, out bytes.Buffer
in.WriteString(`<?xml version="1.0" encoding="UTF-8"?>
Expand Down Expand Up @@ -2449,7 +2579,6 @@ func TestIssue16158(t *testing.T) {
}

// Issue 20953. Crash on invalid XMLName attribute.

type InvalidXMLName struct {
XMLName Name `xml:"error"`
Type struct {
Expand Down
135 changes: 134 additions & 1 deletion src/encoding/xml/read_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package xml

import (
"errors"
"io"
"reflect"
"strings"
Expand Down Expand Up @@ -332,7 +333,7 @@ var badPathTests = []struct {
func TestUnmarshalBadPaths(t *testing.T) {
for _, tt := range badPathTests {
err := Unmarshal([]byte(pathTestString), tt.v)
if !reflect.DeepEqual(err, tt.e) {
if !strings.Contains(err.Error(), "conflicts with field") || !reflect.DeepEqual(err, tt.e) {
t.Fatalf("Unmarshal with %#v didn't fail properly:\nhave %#v,\nwant %#v", tt.v, err, tt.e)
}
}
Expand All @@ -348,6 +349,18 @@ type TestThree struct {
Attr string `xml:",attr"`
}

func TestUnmarshalNonpointer(t *testing.T) {
var x TestThree
err := Unmarshal([]byte(withoutNameTypeData), x)
errText := "non-pointer passed to Unmarshal"
if err == nil {
t.Errorf("[success], want error %v", errText)
}
if err.Error() != errText {
t.Errorf("[error] %v, want %v", err, errText)
}
}

func TestUnmarshalWithoutNameType(t *testing.T) {
var x TestThree
if err := Unmarshal([]byte(withoutNameTypeData), &x); err != nil {
Expand Down Expand Up @@ -686,6 +699,126 @@ func TestUnmarshaler(t *testing.T) {
}
}

var errText = "UnmarshalXML failed"

type MyBodyError struct {
Body string
}

func (m *MyBodyError) UnmarshalXML(*Decoder, StartElement) error {
return errors.New(errText)
}

func TestUnmarshalerError(t *testing.T) {
xml := `<?xml version="1.0" encoding="utf-8"?><Body>words</Body>`
var m MyBodyError
err := Unmarshal([]byte(xml), &m)

if err == nil {
t.Errorf("[success], want error %v", errText)
}
if err.Error() != errText {
t.Errorf("[error] %v, want %v", err, errText)
}
}

type MyBodyErrorText struct {
Body string
}

func (m MyBodyErrorText) UnmarshalText([]byte) error {
return errors.New(errText)
}

func TestUnmarshalerTextError(t *testing.T) {
xml := `<?xml version="1.0" encoding="utf-8"?><Body>words</Body>`
var m MyBodyErrorText
err := Unmarshal([]byte(xml), &m)

if err == nil {
t.Errorf("[success], want error %v", errText)
}
if err.Error() != errText {
t.Errorf("[error] %v, want %v", err, errText)
}
}

func TestUnmarshalUnknownType(t *testing.T) {
expectedError := `unknown type func()`
var dst func()

if err := Unmarshal([]byte(pathTestString), &dst); err == nil || err.Error() != expectedError {
t.Errorf("have %v, want %v", err, expectedError)
}
}

type XMLNameWithNamespace struct {
XMLName Name `xml:"ns Test3"`
}

func TestUnmarshalErrors(t *testing.T) {
tests := []struct {
input []byte
expectedError string
}{
{[]byte(""), "EOF"},
{[]byte("<a>bbb</a>"), `expected element type <Test3> but have <a>`},
{[]byte(`<Test3 xmlns="namespace">inside</Test3>`), `expected element <Test3> in name space ns but have namespace`},
{[]byte(`<Test3 xmlns="">inside</Test3>`), `expected element <Test3> in name space ns but have no name space`},
}
for _, test := range tests {
var dst XMLNameWithNamespace

if err := Unmarshal(test.input, &dst); err == nil || err.Error() != test.expectedError {
t.Errorf("have %v, want %v", err, test.expectedError)
}
}
}

func TestSkip(t *testing.T) {
xml := "<a>bbb</a><Person><name>nnn</name><uri>uuu</uri>wefwef</Person>"

var dst Person
d := NewDecoder(strings.NewReader(xml))

// consume a start element
if _, err := d.Token(); err != nil {
t.Fatalf("expected d.Token() to succeed but got: :%v", err)
}

// consume the rest until the matching end element
if err := d.Skip(); err != nil {
t.Fatalf("expected d.Skip() to succeed but got: :%v", err)
}

if err := d.Decode(&dst); err != nil {
t.Fatalf("expected d.Decode() to succeed but got: :%v", err)
}
}

func TestSkipErrors(t *testing.T) {
tests := []struct {
input string
expectedError string
}{
{"<a>", `XML syntax error on line 1: unexpected EOF`},
{"<a>bbbb<c>", `XML syntax error on line 1: unexpected EOF`},
}

for _, test := range tests {
d := NewDecoder(strings.NewReader(test.input))

// consume a start element
if _, err := d.Token(); err != nil {
t.Fatalf("expected d.Token() to succeed but got: :%v", err)
}

if err := d.Skip(); err == nil || err.Error() != test.expectedError {
t.Errorf("have %v, want %v", err, test.expectedError)
}
}
}

type Pea struct {
Cotelydon string
}
Expand Down
Loading