Commit a9dddb53 authored by Nigel Tao's avatar Nigel Tao

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/4167Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 2978ebbc
......@@ -1194,41 +1194,363 @@ func TestStructPointerMarshal(t *testing.T) {
}
var encodeTokenTests = []struct {
tok Token
desc string
toks []Token
want string
ok bool
}{
{StartElement{Name{"space", "local"}, nil}, "<local xmlns=\"space\">", true},
{StartElement{Name{"space", ""}, nil}, "", false},
{EndElement{Name{"space", ""}}, "", false},
{CharData("foo"), "foo", true},
{Comment("foo"), "<!--foo-->", true},
{Comment("foo-->"), "", false},
{ProcInst{"Target", []byte("Instruction")}, "<?Target Instruction?>", true},
{ProcInst{"", []byte("Instruction")}, "", false},
{ProcInst{"Target", []byte("Instruction?>")}, "", false},
{Directive("foo"), "<!foo>", true},
{Directive("foo>"), "", false},
}
err string
}{{
desc: "start element with name space",
toks: []Token{
StartElement{Name{"space", "local"}, nil},
},
want: `<local xmlns="space">`,
}, {
desc: "start element with no name",
toks: []Token{
StartElement{Name{"space", ""}, nil},
},
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: ` &#x9;&#xA;`,
}, {
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) {
for _, tt := range encodeTokenTests {
loop:
for i, tt := range encodeTokenTests {
var buf bytes.Buffer
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 {
case !tt.ok && err == nil:
t.Errorf("enc.EncodeToken(%#v): expected error; got none", tt.tok)
case tt.ok && err != nil:
t.Fatalf("enc.EncodeToken: %v", err)
case !tt.ok && err != nil:
// expected error, got one
case tt.err != "" && err == nil:
errorf(" expected error; got none")
continue
case tt.err == "" && err != nil:
errorf(" got error: %v", err)
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 {
t.Fatalf("enc.EncodeToken: %v", err)
errorf(" %v", err)
continue
}
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
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment