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 return buffer;
74 }
75
substitute(const char * fmt,const std::string & s)76 std::string substitute(const char* fmt, const std::string& s) {
77 return substitute(fmt, s.c_str());
78 }
79
80 } // namespace
81
TEST(ValidateXml,InvalidXml)82 TEST(ValidateXml, InvalidXml) {
83 TemporaryFile xml;
84 ASSERT_TRUE(android::base::WriteStringToFile(INVALID_XML_SOURCE, xml.path)) << strerror(errno);
85 TemporaryFile xsd;
86 ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
87 EXPECT_FALSE(validateXml("xml", "xsd", xml.path, xsd.path));
88 }
89
TEST(ValidateXml,ValidXml)90 TEST(ValidateXml, ValidXml) {
91 TemporaryFile xml;
92 ASSERT_TRUE(
93 android::base::WriteStringToFile(substitute(VALID_XML_SOURCE, MODULE_SOURCE), xml.path))
94 << strerror(errno);
95 TemporaryFile xsd;
96 ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
97 EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
98 }
99
TEST(ValidateXml,IncludeAbsolutePath)100 TEST(ValidateXml, IncludeAbsolutePath) {
101 TemporaryFile xmlInclude;
102 ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
103 xmlInclude.path))
104 << strerror(errno);
105 TemporaryFile xml;
106 ASSERT_TRUE(android::base::WriteStringToFile(
107 substitute(VALID_XML_SOURCE, substitute(XI_INCLUDE, xmlInclude.path)), xml.path))
108 << strerror(errno);
109 TemporaryFile xsd;
110 ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
111 EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
112 }
113
TEST(ValidateXml,IncludeSameDirRelativePath)114 TEST(ValidateXml, IncludeSameDirRelativePath) {
115 TemporaryFile xmlInclude;
116 ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
117 xmlInclude.path))
118 << strerror(errno);
119 TemporaryFile xml;
120 ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlInclude.path));
121 ASSERT_TRUE(android::base::WriteStringToFile(
122 substitute(VALID_XML_SOURCE,
123 substitute(XI_INCLUDE, android::base::Basename(xmlInclude.path))),
124 xml.path))
125 << strerror(errno);
126 TemporaryFile xsd;
127 ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
128 EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
129 }
130
TEST(ValidateXml,IncludeSubdirRelativePath)131 TEST(ValidateXml, IncludeSubdirRelativePath) {
132 TemporaryDir xmlIncludeDir;
133 TemporaryFile xmlInclude(xmlIncludeDir.path);
134 ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
135 xmlInclude.path))
136 << strerror(errno);
137 TemporaryFile xml;
138 ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlIncludeDir.path));
139 ASSERT_TRUE(android::base::WriteStringToFile(
140 substitute(VALID_XML_SOURCE,
141 substitute(XI_INCLUDE, android::base::Basename(xmlIncludeDir.path) + "/" +
142 android::base::Basename(xmlInclude.path))),
143 xml.path))
144 << strerror(errno);
145 TemporaryFile xsd;
146 ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
147 EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
148 }
149
TEST(ValidateXml,IncludeParentDirRelativePath)150 TEST(ValidateXml, IncludeParentDirRelativePath) {
151 // An XML file from a subdirectory includes a file from the parent directory using '..' syntax.
152 TemporaryFile xmlInclude;
153 ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
154 xmlInclude.path))
155 << strerror(errno);
156 TemporaryDir xmlIncludeDir;
157 TemporaryFile xmlParentInclude(xmlIncludeDir.path);
158 ASSERT_TRUE(android::base::WriteStringToFile(
159 substitute(XML_INCLUDED_SOURCE,
160 substitute(XI_INCLUDE, "../" + android::base::Basename(xmlInclude.path))),
161 xmlParentInclude.path))
162 << strerror(errno);
163 TemporaryFile xml;
164 ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlInclude.path));
165 ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlIncludeDir.path));
166 ASSERT_TRUE(android::base::WriteStringToFile(
167 substitute(
168 VALID_XML_SOURCE,
169 substitute(XI_INCLUDE, android::base::Basename(xmlIncludeDir.path) + "/" +
170 android::base::Basename(xmlParentInclude.path))),
171 xml.path))
172 << strerror(errno);
173 TemporaryFile xsd;
174 ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
175 EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
176 }
177