1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <android-base/file.h>
18 #include <gtest/gtest.h>
19
20 #include <ValidateXml.h>
21
22 using ::android::hardware::audio::common::test::utility::validateXml;
23
24 const char* XSD_SOURCE =
25 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
26 "<xs:schema version=\"2.0\""
27 " elementFormDefault=\"qualified\""
28 " attributeFormDefault=\"unqualified\""
29 " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
30 " <xs:element name=\"audioPolicyConfiguration\">"
31 " <xs:complexType>"
32 " <xs:sequence>"
33 " <xs:element name=\"modules\">"
34 " <xs:complexType>"
35 " <xs:sequence>"
36 " <xs:element name=\"module\" maxOccurs=\"unbounded\">"
37 " <xs:complexType>"
38 " <xs:attribute name=\"name\" type=\"xs:string\" use=\"required\"/>"
39 " </xs:complexType>"
40 " </xs:element>"
41 " </xs:sequence>"
42 " </xs:complexType>"
43 " </xs:element>"
44 " </xs:sequence>"
45 " </xs:complexType>"
46 " </xs:element>"
47 "</xs:schema>";
48
49 const char* INVALID_XML_SOURCE =
50 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
51 "<audioPolicyKonfiguration />";
52
53 const char* VALID_XML_SOURCE =
54 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
55 "<audioPolicyConfiguration>"
56 " <modules>"
57 " <module name=\"aaa\" />"
58 " %s"
59 " </modules>"
60 "</audioPolicyConfiguration>";
61
62 const char* MODULE_SOURCE = "<module name=\"bbb\" />";
63
64 const char* XI_INCLUDE = "<xi:include xmlns:xi=\"http://www.w3.org/2001/XInclude\" href=\"%s\" />";
65
66 const char* XML_INCLUDED_SOURCE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>%s";
67
68 namespace {
69
substitute(const char * fmt,const char * param)70 std::string substitute(const char* fmt, const char* param) {
71 std::string buffer(static_cast<size_t>(strlen(fmt) + strlen(param)), '\0');
72 snprintf(buffer.data(), buffer.size(), fmt, param);
73 buffer.resize(strlen(buffer.c_str()));
74 return buffer;
75 }
76
substitute(const char * fmt,const std::string & s)77 std::string substitute(const char* fmt, const std::string& s) {
78 return substitute(fmt, s.c_str());
79 }
80
81 } // namespace
82
TEST(ValidateXml,InvalidXml)83 TEST(ValidateXml, InvalidXml) {
84 TemporaryFile xml;
85 ASSERT_TRUE(android::base::WriteStringToFile(INVALID_XML_SOURCE, xml.path)) << strerror(errno);
86 TemporaryFile xsd;
87 ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
88 EXPECT_FALSE(validateXml("xml", "xsd", xml.path, xsd.path));
89 }
90
TEST(ValidateXml,ValidXml)91 TEST(ValidateXml, ValidXml) {
92 TemporaryFile xml;
93 ASSERT_TRUE(
94 android::base::WriteStringToFile(substitute(VALID_XML_SOURCE, MODULE_SOURCE), xml.path))
95 << strerror(errno);
96 TemporaryFile xsd;
97 ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
98 EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
99 }
100
TEST(ValidateXml,IncludeAbsolutePath)101 TEST(ValidateXml, IncludeAbsolutePath) {
102 TemporaryFile xmlInclude;
103 ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
104 xmlInclude.path))
105 << strerror(errno);
106 TemporaryFile xml;
107 ASSERT_TRUE(android::base::WriteStringToFile(
108 substitute(VALID_XML_SOURCE, substitute(XI_INCLUDE, xmlInclude.path)), xml.path))
109 << strerror(errno);
110 TemporaryFile xsd;
111 ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
112 EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
113 }
114
TEST(ValidateXml,IncludeSameDirRelativePath)115 TEST(ValidateXml, IncludeSameDirRelativePath) {
116 TemporaryFile xmlInclude;
117 ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
118 xmlInclude.path))
119 << strerror(errno);
120 TemporaryFile xml;
121 ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlInclude.path));
122 ASSERT_TRUE(android::base::WriteStringToFile(
123 substitute(VALID_XML_SOURCE,
124 substitute(XI_INCLUDE, android::base::Basename(xmlInclude.path))),
125 xml.path))
126 << strerror(errno);
127 TemporaryFile xsd;
128 ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
129 EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
130 }
131
TEST(ValidateXml,IncludeSubdirRelativePath)132 TEST(ValidateXml, IncludeSubdirRelativePath) {
133 TemporaryDir xmlIncludeDir;
134 TemporaryFile xmlInclude(xmlIncludeDir.path);
135 ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
136 xmlInclude.path))
137 << strerror(errno);
138 TemporaryFile xml;
139 ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlIncludeDir.path));
140 ASSERT_TRUE(android::base::WriteStringToFile(
141 substitute(VALID_XML_SOURCE,
142 substitute(XI_INCLUDE, android::base::Basename(xmlIncludeDir.path) + "/" +
143 android::base::Basename(xmlInclude.path))),
144 xml.path))
145 << strerror(errno);
146 TemporaryFile xsd;
147 ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
148 EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
149 }
150
TEST(ValidateXml,IncludeParentDirRelativePath)151 TEST(ValidateXml, IncludeParentDirRelativePath) {
152 // An XML file from a subdirectory includes a file from the parent directory using '..' syntax.
153 TemporaryFile xmlInclude;
154 ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
155 xmlInclude.path))
156 << strerror(errno);
157 TemporaryDir xmlIncludeDir;
158 TemporaryFile xmlParentInclude(xmlIncludeDir.path);
159 ASSERT_TRUE(android::base::WriteStringToFile(
160 substitute(XML_INCLUDED_SOURCE,
161 substitute(XI_INCLUDE, "../" + android::base::Basename(xmlInclude.path))),
162 xmlParentInclude.path))
163 << strerror(errno);
164 TemporaryFile xml;
165 ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlInclude.path));
166 ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlIncludeDir.path));
167 ASSERT_TRUE(android::base::WriteStringToFile(
168 substitute(
169 VALID_XML_SOURCE,
170 substitute(XI_INCLUDE, android::base::Basename(xmlIncludeDir.path) + "/" +
171 android::base::Basename(xmlParentInclude.path))),
172 xml.path))
173 << strerror(errno);
174 TemporaryFile xsd;
175 ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
176 EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
177 }
178