xref: /aosp_15_r20/external/bazelbuild-rules_android/src/common/golang/marshal_test.go (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
1// Copyright 2018 The Bazel Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package xml2
16
17import (
18	"bufio"
19	"bytes"
20	"encoding/xml"
21	"io"
22	"strings"
23	"testing"
24)
25
26func TestEncoderEncodeToken(t *testing.T) {
27	tests := []struct {
28		name    string
29		in      string
30		want    string
31		wantErr string
32	}{
33		{
34			name: "xmlnsPrefixForElement",
35			in:   "<foo:bar xmlns:foo=\"baz\"></foo:bar>",
36			want: "<foo:bar xmlns:foo=\"baz\"></foo:bar>",
37		},
38		{
39			name: "xmlnsPrefixForAttribute",
40			in:   "<foo bar:baz=\"qux\" xmlns:bar=\"quux\"></foo>",
41			want: "<foo bar:baz=\"qux\" xmlns:bar=\"quux\"></foo>",
42		},
43		{
44			name: "defaultXmlnsAttribute",
45			in:   "<foo xmlns=\"bar\"></foo>",
46			want: "<foo xmlns=\"bar\"></foo>",
47		},
48		{
49			// The return value of Decoder.Token() makes it
50			// impossible for a decode then encode of an xml file
51			// be isomorphic. This is mainly due to the fact that
52			// xml.Name.Space contains the uri, and xml.Name does
53			// not store the prefix. Instead, make sure that the
54			// behavior remains consistent.
55			//
56			// That is, the last prefix defined for the space is the
57			// one applied when encoding the token.
58			name: "multipleDefsXmlnsPrefixesSameUri",
59			in: `
60<foo xmlns:bar="bar">
61  <bar:baz xmlns:qux="bar">
62    <qux:quux></qux:quux>
63  </bar:baz>
64</foo>`,
65			want: `
66<foo xmlns:bar="bar">
67  <qux:baz xmlns:qux="bar">
68    <qux:quux></qux:quux>
69  </qux:baz>
70</foo>`,
71		},
72		{
73			name:    "xmlnsPrefixUsedOnElementButNotDefined",
74			in:      "<foo:bar></foo:bar>",
75			wantErr: "unknown namespace: foo",
76		},
77		{
78			name:    "xmlnsPrefixUsedOnAttrButNotDefined",
79			in:      "<foo bar:baz=\"qux\"></foo>",
80			wantErr: "unknown namespace: bar",
81		},
82		{
83			name: "xmlnsPrefixUsedOutsideOfDefiningTag",
84			in: `
85<foo xmlns:bar="baz" bar:qux="quux">corge</foo>
86<grault bar:garply="waldo"></grault>`,
87			wantErr: "unknown namespace: bar",
88		},
89	}
90	for _, test := range tests {
91		t.Run(test.name, func(t *testing.T) {
92			var b bytes.Buffer
93			e := NewEncoder(bufio.NewWriter(&b))
94			d := xml.NewDecoder(strings.NewReader(test.in))
95			for {
96				tkn, err := d.Token()
97				if err != nil {
98					if err == io.EOF {
99						break
100					}
101					t.Fatalf("Unexpected error got: %v while reading: %s", err, test.in)
102				}
103				if err := e.EncodeToken(tkn); err != nil {
104					if test.wantErr != "" && strings.Contains(err.Error(), test.wantErr) {
105						// Do nothing, error is expected.
106					} else {
107						t.Errorf("Unexpected error during encode: %v", err)
108					}
109					return
110				}
111			}
112			e.Flush()
113			if b.String() != test.want {
114				t.Errorf("got: <%s> expected: <%s>", b.String(), test.want)
115			}
116		})
117	}
118}
119
120func TestChildEncoder(t *testing.T) {
121	// Setup the parent Encoder with the namespace "bar".
122	d := xml.NewDecoder(strings.NewReader("<foo xmlns:bar=\"bar\"><bar:baz>Hello World</bar:baz></foo>"))
123	tkn, err := d.Token()
124	if err != nil {
125		t.Fatalf("Error occurred during decoding, got: %v", err)
126	}
127	parentEnc := NewEncoder(&bytes.Buffer{})
128	if err := parentEnc.EncodeToken(tkn); err != nil {
129		t.Fatalf("Error occurred while the parent encoder was encoding token %q got: %v", tkn, err)
130	}
131
132	// Without instantiating the Encoder as a child, the "bar" namespace will be unknown and cause an
133	// error to occur when trying to encode the "bar" namespaced element "<bar:baz>".
134	tkn, err = d.Token()
135	if err != nil {
136		t.Fatalf("Error occurred during decoding, got: %v", err)
137	}
138	b := &bytes.Buffer{}
139	childEnc := ChildEncoder(b, parentEnc)
140	if err := childEnc.EncodeToken(tkn); err != nil {
141		t.Fatalf("Error occurred while the child encoder was encoding token %q got: %v", tkn, err)
142	}
143	childEnc.Flush()
144
145	// Verify that the token is not mangled.
146	if want := "<bar:baz>"; b.String() != want {
147		t.Errorf("Error, got %q, wanted %q", b.String(), want)
148	}
149}
150