mirror of
https://github.com/golang/go
synced 2024-11-18 16:44:43 -07:00
encoding/xml: add more EncodeToken tests.
There are no behavior changes in this CL, only specifying the status quo. A follow-up CL, https://go-review.googlesource.com/#/c/2660/, will change the EncodeToken behavior. Change-Id: I6ecbcfb05ae681de71fa1099d054df2826ed4acb Reviewed-on: https://go-review.googlesource.com/4167 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
2978ebbc7b
commit
a9dddb53f7
@ -1194,41 +1194,363 @@ func TestStructPointerMarshal(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var encodeTokenTests = []struct {
|
var encodeTokenTests = []struct {
|
||||||
tok Token
|
desc string
|
||||||
|
toks []Token
|
||||||
want string
|
want string
|
||||||
ok bool
|
err string
|
||||||
}{
|
}{{
|
||||||
{StartElement{Name{"space", "local"}, nil}, "<local xmlns=\"space\">", true},
|
desc: "start element with name space",
|
||||||
{StartElement{Name{"space", ""}, nil}, "", false},
|
toks: []Token{
|
||||||
{EndElement{Name{"space", ""}}, "", false},
|
StartElement{Name{"space", "local"}, nil},
|
||||||
{CharData("foo"), "foo", true},
|
},
|
||||||
{Comment("foo"), "<!--foo-->", true},
|
want: `<local xmlns="space">`,
|
||||||
{Comment("foo-->"), "", false},
|
}, {
|
||||||
{ProcInst{"Target", []byte("Instruction")}, "<?Target Instruction?>", true},
|
desc: "start element with no name",
|
||||||
{ProcInst{"", []byte("Instruction")}, "", false},
|
toks: []Token{
|
||||||
{ProcInst{"Target", []byte("Instruction?>")}, "", false},
|
StartElement{Name{"space", ""}, nil},
|
||||||
{Directive("foo"), "<!foo>", true},
|
},
|
||||||
{Directive("foo>"), "", false},
|
err: "xml: start tag with no name",
|
||||||
}
|
}, {
|
||||||
|
desc: "end element with no name",
|
||||||
|
toks: []Token{
|
||||||
|
EndElement{Name{"space", ""}},
|
||||||
|
},
|
||||||
|
err: "xml: end tag with no name",
|
||||||
|
}, {
|
||||||
|
desc: "char data",
|
||||||
|
toks: []Token{
|
||||||
|
CharData("foo"),
|
||||||
|
},
|
||||||
|
want: `foo`,
|
||||||
|
}, {
|
||||||
|
desc: "char data with escaped chars",
|
||||||
|
toks: []Token{
|
||||||
|
CharData(" \t\n"),
|
||||||
|
},
|
||||||
|
want: ` 	
`,
|
||||||
|
}, {
|
||||||
|
desc: "comment",
|
||||||
|
toks: []Token{
|
||||||
|
Comment("foo"),
|
||||||
|
},
|
||||||
|
want: `<!--foo-->`,
|
||||||
|
}, {
|
||||||
|
desc: "comment with invalid content",
|
||||||
|
toks: []Token{
|
||||||
|
Comment("foo-->"),
|
||||||
|
},
|
||||||
|
err: "xml: EncodeToken of Comment containing --> marker",
|
||||||
|
}, {
|
||||||
|
desc: "proc instruction",
|
||||||
|
toks: []Token{
|
||||||
|
ProcInst{"Target", []byte("Instruction")},
|
||||||
|
},
|
||||||
|
want: `<?Target Instruction?>`,
|
||||||
|
}, {
|
||||||
|
desc: "proc instruction with empty target",
|
||||||
|
toks: []Token{
|
||||||
|
ProcInst{"", []byte("Instruction")},
|
||||||
|
},
|
||||||
|
err: "xml: EncodeToken of ProcInst with invalid Target",
|
||||||
|
}, {
|
||||||
|
desc: "proc instruction with bad content",
|
||||||
|
toks: []Token{
|
||||||
|
ProcInst{"", []byte("Instruction?>")},
|
||||||
|
},
|
||||||
|
err: "xml: EncodeToken of ProcInst with invalid Target",
|
||||||
|
}, {
|
||||||
|
desc: "directive",
|
||||||
|
toks: []Token{
|
||||||
|
Directive("foo"),
|
||||||
|
},
|
||||||
|
want: `<!foo>`,
|
||||||
|
}, {
|
||||||
|
desc: "directive instruction with bad name",
|
||||||
|
toks: []Token{
|
||||||
|
Directive("foo>"),
|
||||||
|
},
|
||||||
|
err: "xml: EncodeToken of Directive containing > marker",
|
||||||
|
}, {
|
||||||
|
desc: "end tag without start tag",
|
||||||
|
toks: []Token{
|
||||||
|
EndElement{Name{"foo", "bar"}},
|
||||||
|
},
|
||||||
|
err: "xml: end tag </bar> without start tag",
|
||||||
|
}, {
|
||||||
|
desc: "mismatching end tag local name",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"", "foo"}, nil},
|
||||||
|
EndElement{Name{"", "bar"}},
|
||||||
|
},
|
||||||
|
err: "xml: end tag </bar> does not match start tag <foo>",
|
||||||
|
want: `<foo>`,
|
||||||
|
}, {
|
||||||
|
desc: "mismatching end tag namespace",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"space", "foo"}, nil},
|
||||||
|
EndElement{Name{"another", "foo"}},
|
||||||
|
},
|
||||||
|
err: "xml: end tag </foo> in namespace another does not match start tag <foo> in namespace space",
|
||||||
|
want: `<foo xmlns="space">`,
|
||||||
|
}, {
|
||||||
|
desc: "start element with explicit namespace",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"space", "local"}, []Attr{
|
||||||
|
{Name{"xmlns", "x"}, "space"},
|
||||||
|
{Name{"space", "foo"}, "value"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<local xmlns="space" xmlns:_xmlns="xmlns" _xmlns:x="space" xmlns:space="space" space:foo="value">`,
|
||||||
|
}, {
|
||||||
|
desc: "start element with explicit namespace and colliding prefix",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"space", "local"}, []Attr{
|
||||||
|
{Name{"xmlns", "x"}, "space"},
|
||||||
|
{Name{"space", "foo"}, "value"},
|
||||||
|
{Name{"x", "bar"}, "other"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<local xmlns="space" xmlns:_xmlns="xmlns" _xmlns:x="space" xmlns:space="space" space:foo="value" xmlns:x="x" x:bar="other">`,
|
||||||
|
}, {
|
||||||
|
desc: "start element using previously defined namespace",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"", "local"}, []Attr{
|
||||||
|
{Name{"xmlns", "x"}, "space"},
|
||||||
|
}},
|
||||||
|
StartElement{Name{"space", "foo"}, []Attr{
|
||||||
|
{Name{"space", "x"}, "y"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<local xmlns:_xmlns="xmlns" _xmlns:x="space"><foo xmlns="space" xmlns:space="space" space:x="y">`,
|
||||||
|
}, {
|
||||||
|
desc: "nested name space with same prefix",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"", "foo"}, []Attr{
|
||||||
|
{Name{"xmlns", "x"}, "space1"},
|
||||||
|
}},
|
||||||
|
StartElement{Name{"", "foo"}, []Attr{
|
||||||
|
{Name{"xmlns", "x"}, "space2"},
|
||||||
|
}},
|
||||||
|
StartElement{Name{"", "foo"}, []Attr{
|
||||||
|
{Name{"space1", "a"}, "space1 value"},
|
||||||
|
{Name{"space2", "b"}, "space2 value"},
|
||||||
|
}},
|
||||||
|
EndElement{Name{"", "foo"}},
|
||||||
|
EndElement{Name{"", "foo"}},
|
||||||
|
StartElement{Name{"", "foo"}, []Attr{
|
||||||
|
{Name{"space1", "a"}, "space1 value"},
|
||||||
|
{Name{"space2", "b"}, "space2 value"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns:_xmlns="xmlns" _xmlns:x="space1"><foo _xmlns:x="space2"><foo xmlns:space1="space1" space1:a="space1 value" xmlns:space2="space2" space2:b="space2 value"></foo></foo><foo xmlns:space1="space1" space1:a="space1 value" xmlns:space2="space2" space2:b="space2 value">`,
|
||||||
|
}, {
|
||||||
|
desc: "start element defining several prefixes for the same name space",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"space", "foo"}, []Attr{
|
||||||
|
{Name{"xmlns", "a"}, "space"},
|
||||||
|
{Name{"xmlns", "b"}, "space"},
|
||||||
|
{Name{"space", "x"}, "value"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns="space" xmlns:_xmlns="xmlns" _xmlns:a="space" _xmlns:b="space" xmlns:space="space" space:x="value">`,
|
||||||
|
}, {
|
||||||
|
desc: "nested element redefines name space",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"", "foo"}, []Attr{
|
||||||
|
{Name{"xmlns", "x"}, "space"},
|
||||||
|
}},
|
||||||
|
StartElement{Name{"space", "foo"}, []Attr{
|
||||||
|
{Name{"xmlns", "y"}, "space"},
|
||||||
|
{Name{"space", "a"}, "value"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns:_xmlns="xmlns" _xmlns:x="space"><foo xmlns="space" _xmlns:y="space" xmlns:space="space" space:a="value">`,
|
||||||
|
}, {
|
||||||
|
desc: "nested element creates alias for default name space",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"space", "foo"}, []Attr{
|
||||||
|
{Name{"", "xmlns"}, "space"},
|
||||||
|
}},
|
||||||
|
StartElement{Name{"space", "foo"}, []Attr{
|
||||||
|
{Name{"xmlns", "y"}, "space"},
|
||||||
|
{Name{"space", "a"}, "value"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns="space" xmlns="space"><foo xmlns="space" xmlns:_xmlns="xmlns" _xmlns:y="space" xmlns:space="space" space:a="value">`,
|
||||||
|
}, {
|
||||||
|
desc: "nested element defines default name space with existing prefix",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"", "foo"}, []Attr{
|
||||||
|
{Name{"xmlns", "x"}, "space"},
|
||||||
|
}},
|
||||||
|
StartElement{Name{"space", "foo"}, []Attr{
|
||||||
|
{Name{"", "xmlns"}, "space"},
|
||||||
|
{Name{"space", "a"}, "value"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns:_xmlns="xmlns" _xmlns:x="space"><foo xmlns="space" xmlns="space" xmlns:space="space" space:a="value">`,
|
||||||
|
}, {
|
||||||
|
desc: "nested element uses empty attribute name space when default ns defined",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"space", "foo"}, []Attr{
|
||||||
|
{Name{"", "xmlns"}, "space"},
|
||||||
|
}},
|
||||||
|
StartElement{Name{"space", "foo"}, []Attr{
|
||||||
|
{Name{"", "attr"}, "value"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns="space" xmlns="space"><foo xmlns="space" attr="value">`,
|
||||||
|
}, {
|
||||||
|
desc: "redefine xmlns",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"", "foo"}, []Attr{
|
||||||
|
{Name{"foo", "xmlns"}, "space"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns:foo="foo" foo:xmlns="space">`,
|
||||||
|
}, {
|
||||||
|
desc: "xmlns with explicit name space #1",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"space", "foo"}, []Attr{
|
||||||
|
{Name{"xml", "xmlns"}, "space"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns="space" xmlns:_xml="xml" _xml:xmlns="space">`,
|
||||||
|
}, {
|
||||||
|
desc: "xmlns with explicit name space #2",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"space", "foo"}, []Attr{
|
||||||
|
{Name{xmlURL, "xmlns"}, "space"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns="space" xml:xmlns="space">`,
|
||||||
|
}, {
|
||||||
|
desc: "empty name space declaration is ignored",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"", "foo"}, []Attr{
|
||||||
|
{Name{"xmlns", "foo"}, ""},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns:_xmlns="xmlns" _xmlns:foo="">`,
|
||||||
|
}, {
|
||||||
|
desc: "attribute with no name is ignored",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"", "foo"}, []Attr{
|
||||||
|
{Name{"", ""}, "value"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo>`,
|
||||||
|
}, {
|
||||||
|
desc: "namespace URL with non-valid name",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"/34", "foo"}, []Attr{
|
||||||
|
{Name{"/34", "x"}, "value"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns="/34" xmlns:_="/34" _:x="value">`,
|
||||||
|
}, {
|
||||||
|
desc: "nested element resets default namespace to empty",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"space", "foo"}, []Attr{
|
||||||
|
{Name{"", "xmlns"}, "space"},
|
||||||
|
}},
|
||||||
|
StartElement{Name{"", "foo"}, []Attr{
|
||||||
|
{Name{"", "xmlns"}, ""},
|
||||||
|
{Name{"", "x"}, "value"},
|
||||||
|
{Name{"space", "x"}, "value"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns="space" xmlns="space"><foo xmlns="" x="value" xmlns:space="space" space:x="value">`,
|
||||||
|
}, {
|
||||||
|
desc: "nested element requires empty default name space",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"space", "foo"}, []Attr{
|
||||||
|
{Name{"", "xmlns"}, "space"},
|
||||||
|
}},
|
||||||
|
StartElement{Name{"", "foo"}, nil},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns="space" xmlns="space"><foo>`,
|
||||||
|
}, {
|
||||||
|
desc: "attribute uses name space from xmlns",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"some/space", "foo"}, []Attr{
|
||||||
|
{Name{"", "attr"}, "value"},
|
||||||
|
{Name{"some/space", "other"}, "other value"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns="some/space" attr="value" xmlns:space="some/space" space:other="other value">`,
|
||||||
|
}, {
|
||||||
|
desc: "default name space should not be used by attributes",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"space", "foo"}, []Attr{
|
||||||
|
{Name{"", "xmlns"}, "space"},
|
||||||
|
{Name{"xmlns", "bar"}, "space"},
|
||||||
|
{Name{"space", "baz"}, "foo"},
|
||||||
|
}},
|
||||||
|
StartElement{Name{"space", "baz"}, nil},
|
||||||
|
EndElement{Name{"space", "baz"}},
|
||||||
|
EndElement{Name{"space", "foo"}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns="space" xmlns="space" xmlns:_xmlns="xmlns" _xmlns:bar="space" xmlns:space="space" space:baz="foo"><baz xmlns="space"></baz></foo>`,
|
||||||
|
}, {
|
||||||
|
desc: "default name space not used by attributes, not explicitly defined",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"space", "foo"}, []Attr{
|
||||||
|
{Name{"", "xmlns"}, "space"},
|
||||||
|
{Name{"space", "baz"}, "foo"},
|
||||||
|
}},
|
||||||
|
StartElement{Name{"space", "baz"}, nil},
|
||||||
|
EndElement{Name{"space", "baz"}},
|
||||||
|
EndElement{Name{"space", "foo"}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns="space" xmlns="space" xmlns:space="space" space:baz="foo"><baz xmlns="space"></baz></foo>`,
|
||||||
|
}, {
|
||||||
|
desc: "impossible xmlns declaration",
|
||||||
|
toks: []Token{
|
||||||
|
StartElement{Name{"", "foo"}, []Attr{
|
||||||
|
{Name{"", "xmlns"}, "space"},
|
||||||
|
}},
|
||||||
|
StartElement{Name{"space", "bar"}, []Attr{
|
||||||
|
{Name{"space", "attr"}, "value"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
want: `<foo xmlns="space"><bar xmlns="space" xmlns:space="space" space:attr="value">`,
|
||||||
|
}}
|
||||||
|
|
||||||
func TestEncodeToken(t *testing.T) {
|
func TestEncodeToken(t *testing.T) {
|
||||||
for _, tt := range encodeTokenTests {
|
loop:
|
||||||
|
for i, tt := range encodeTokenTests {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
enc := NewEncoder(&buf)
|
enc := NewEncoder(&buf)
|
||||||
err := enc.EncodeToken(tt.tok)
|
var err error
|
||||||
|
for j, tok := range tt.toks {
|
||||||
|
err = enc.EncodeToken(tok)
|
||||||
|
if err != nil && j < len(tt.toks)-1 {
|
||||||
|
t.Errorf("#%d %s token #%d: %v", i, tt.desc, j, err)
|
||||||
|
continue loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errorf := func(f string, a ...interface{}) {
|
||||||
|
t.Errorf("#%d %s token #%d:%s", i, tt.desc, len(tt.toks)-1, fmt.Sprintf(f, a...))
|
||||||
|
}
|
||||||
switch {
|
switch {
|
||||||
case !tt.ok && err == nil:
|
case tt.err != "" && err == nil:
|
||||||
t.Errorf("enc.EncodeToken(%#v): expected error; got none", tt.tok)
|
errorf(" expected error; got none")
|
||||||
case tt.ok && err != nil:
|
continue
|
||||||
t.Fatalf("enc.EncodeToken: %v", err)
|
case tt.err == "" && err != nil:
|
||||||
case !tt.ok && err != nil:
|
errorf(" got error: %v", err)
|
||||||
// expected error, got one
|
continue
|
||||||
|
case tt.err != "" && err != nil && tt.err != err.Error():
|
||||||
|
errorf(" error mismatch; got %v, want %v", err, tt.err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
if err := enc.Flush(); err != nil {
|
if err := enc.Flush(); err != nil {
|
||||||
t.Fatalf("enc.EncodeToken: %v", err)
|
errorf(" %v", err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
if got := buf.String(); got != tt.want {
|
if got := buf.String(); got != tt.want {
|
||||||
t.Errorf("enc.EncodeToken = %s; want: %s", got, tt.want)
|
errorf("\ngot %v\nwant %v", got, tt.want)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user