]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/xml: add more EncodeToken tests.
authorNigel Tao <nigeltao@golang.org>
Mon, 9 Feb 2015 02:42:45 +0000 (13:42 +1100)
committerNigel Tao <nigeltao@golang.org>
Mon, 9 Feb 2015 04:02:45 +0000 (04:02 +0000)
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>
src/encoding/xml/marshal_test.go

index cdd52ff97fb45981ca2412df44a6d1de043dc77b..d8507ce81401e5a08aa178091f1db3265feaadb9 100644 (file)
@@ -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
                }
        }
 }