audio: Fix handling of relative XML include paths in VTS
Pass "no fixup base dirs" flag to the XInclude processor
to avoid modifications of the top-level elements from
included XML files as a result of "fixup."
Added tests to ensure that all relevant XInclude scenarios
work.
Bug: 192619060
Test: atest -host android.hardware.audio.common.test.utility_tests
Change-Id: Id595c9fd30be378d76387ee55a8937e0bf28d1cd
(cherry picked from commit 13c6796528
)
Merged-In: Id595c9fd30be378d76387ee55a8937e0bf28d1cd
This commit is contained in:
parent
9f834f1a91
commit
068de276f0
4 changed files with 214 additions and 3 deletions
|
@ -25,7 +25,7 @@ package {
|
|||
|
||||
cc_library_static {
|
||||
name: "android.hardware.audio.common.test.utility",
|
||||
defaults : ["hidl_defaults"],
|
||||
defaults: ["hidl_defaults"],
|
||||
srcs: ["src/ValidateXml.cpp"],
|
||||
cflags: [
|
||||
"-O0",
|
||||
|
@ -34,7 +34,34 @@ cc_library_static {
|
|||
],
|
||||
local_include_dirs: ["include/utility"],
|
||||
export_include_dirs: ["include"],
|
||||
shared_libs: ["libxml2", "liblog"],
|
||||
shared_libs: [
|
||||
"libxml2",
|
||||
"liblog",
|
||||
],
|
||||
static_libs: ["libgtest"],
|
||||
export_static_lib_headers: ["libgtest"],
|
||||
}
|
||||
|
||||
// Note: this isn't a VTS test, but rather a unit test
|
||||
// to verify correctness of test utilities.
|
||||
cc_test {
|
||||
name: "android.hardware.audio.common.test.utility_tests",
|
||||
host_supported: true,
|
||||
local_include_dirs: ["include/utility"],
|
||||
srcs: [
|
||||
"src/ValidateXml.cpp",
|
||||
"tests/utility_tests.cpp",
|
||||
],
|
||||
cflags: [
|
||||
"-Werror",
|
||||
"-Wall",
|
||||
"-g",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libxml2",
|
||||
"liblog",
|
||||
],
|
||||
static_libs: ["libgtest"],
|
||||
test_suites: ["general-tests"],
|
||||
}
|
||||
|
|
7
audio/common/all-versions/test/utility/TEST_MAPPING
Normal file
7
audio/common/all-versions/test/utility/TEST_MAPPING
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"presubmit": [
|
||||
{
|
||||
"name": "android.hardware.audio.common.test.utility_tests"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -112,7 +112,8 @@ struct Libxml2Global {
|
|||
return ::testing::AssertionFailure() << "Failed to parse xml\n" << context();
|
||||
}
|
||||
|
||||
if (xmlXIncludeProcess(doc.get()) == -1) {
|
||||
// Process 'include' directives w/o modifying elements loaded from included files.
|
||||
if (xmlXIncludeProcessFlags(doc.get(), XML_PARSE_NOBASEFIX) == -1) {
|
||||
return ::testing::AssertionFailure() << "Failed to resolve xincludes in xml\n" << context();
|
||||
}
|
||||
|
||||
|
|
176
audio/common/all-versions/test/utility/tests/utility_tests.cpp
Normal file
176
audio/common/all-versions/test/utility/tests/utility_tests.cpp
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <ValidateXml.h>
|
||||
|
||||
using ::android::hardware::audio::common::test::utility::validateXml;
|
||||
|
||||
const char* XSD_SOURCE =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<xs:schema version=\"2.0\""
|
||||
" elementFormDefault=\"qualified\""
|
||||
" attributeFormDefault=\"unqualified\""
|
||||
" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
|
||||
" <xs:element name=\"audioPolicyConfiguration\">"
|
||||
" <xs:complexType>"
|
||||
" <xs:sequence>"
|
||||
" <xs:element name=\"modules\">"
|
||||
" <xs:complexType>"
|
||||
" <xs:sequence>"
|
||||
" <xs:element name=\"module\" maxOccurs=\"unbounded\">"
|
||||
" <xs:complexType>"
|
||||
" <xs:attribute name=\"name\" type=\"xs:string\" use=\"required\"/>"
|
||||
" </xs:complexType>"
|
||||
" </xs:element>"
|
||||
" </xs:sequence>"
|
||||
" </xs:complexType>"
|
||||
" </xs:element>"
|
||||
" </xs:sequence>"
|
||||
" </xs:complexType>"
|
||||
" </xs:element>"
|
||||
"</xs:schema>";
|
||||
|
||||
const char* INVALID_XML_SOURCE =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
|
||||
"<audioPolicyKonfiguration />";
|
||||
|
||||
const char* VALID_XML_SOURCE =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
|
||||
"<audioPolicyConfiguration>"
|
||||
" <modules>"
|
||||
" <module name=\"aaa\" />"
|
||||
" %s"
|
||||
" </modules>"
|
||||
"</audioPolicyConfiguration>";
|
||||
|
||||
const char* MODULE_SOURCE = "<module name=\"bbb\" />";
|
||||
|
||||
const char* XI_INCLUDE = "<xi:include xmlns:xi=\"http://www.w3.org/2001/XInclude\" href=\"%s\" />";
|
||||
|
||||
const char* XML_INCLUDED_SOURCE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>%s";
|
||||
|
||||
namespace {
|
||||
|
||||
std::string substitute(const char* fmt, const char* param) {
|
||||
std::string buffer(static_cast<size_t>(strlen(fmt) + strlen(param)), '\0');
|
||||
snprintf(buffer.data(), buffer.size(), fmt, param);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
std::string substitute(const char* fmt, const std::string& s) {
|
||||
return substitute(fmt, s.c_str());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(ValidateXml, InvalidXml) {
|
||||
TemporaryFile xml;
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(INVALID_XML_SOURCE, xml.path)) << strerror(errno);
|
||||
TemporaryFile xsd;
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
|
||||
EXPECT_FALSE(validateXml("xml", "xsd", xml.path, xsd.path));
|
||||
}
|
||||
|
||||
TEST(ValidateXml, ValidXml) {
|
||||
TemporaryFile xml;
|
||||
ASSERT_TRUE(
|
||||
android::base::WriteStringToFile(substitute(VALID_XML_SOURCE, MODULE_SOURCE), xml.path))
|
||||
<< strerror(errno);
|
||||
TemporaryFile xsd;
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
|
||||
EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
|
||||
}
|
||||
|
||||
TEST(ValidateXml, IncludeAbsolutePath) {
|
||||
TemporaryFile xmlInclude;
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
|
||||
xmlInclude.path))
|
||||
<< strerror(errno);
|
||||
TemporaryFile xml;
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(
|
||||
substitute(VALID_XML_SOURCE, substitute(XI_INCLUDE, xmlInclude.path)), xml.path))
|
||||
<< strerror(errno);
|
||||
TemporaryFile xsd;
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
|
||||
EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
|
||||
}
|
||||
|
||||
TEST(ValidateXml, IncludeSameDirRelativePath) {
|
||||
TemporaryFile xmlInclude;
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
|
||||
xmlInclude.path))
|
||||
<< strerror(errno);
|
||||
TemporaryFile xml;
|
||||
ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlInclude.path));
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(
|
||||
substitute(VALID_XML_SOURCE,
|
||||
substitute(XI_INCLUDE, android::base::Basename(xmlInclude.path))),
|
||||
xml.path))
|
||||
<< strerror(errno);
|
||||
TemporaryFile xsd;
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
|
||||
EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
|
||||
}
|
||||
|
||||
TEST(ValidateXml, IncludeSubdirRelativePath) {
|
||||
TemporaryDir xmlIncludeDir;
|
||||
TemporaryFile xmlInclude(xmlIncludeDir.path);
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
|
||||
xmlInclude.path))
|
||||
<< strerror(errno);
|
||||
TemporaryFile xml;
|
||||
ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlIncludeDir.path));
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(
|
||||
substitute(VALID_XML_SOURCE,
|
||||
substitute(XI_INCLUDE, android::base::Basename(xmlIncludeDir.path) + "/" +
|
||||
android::base::Basename(xmlInclude.path))),
|
||||
xml.path))
|
||||
<< strerror(errno);
|
||||
TemporaryFile xsd;
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
|
||||
EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
|
||||
}
|
||||
|
||||
TEST(ValidateXml, IncludeParentDirRelativePath) {
|
||||
// An XML file from a subdirectory includes a file from the parent directory using '..' syntax.
|
||||
TemporaryFile xmlInclude;
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(substitute(XML_INCLUDED_SOURCE, MODULE_SOURCE),
|
||||
xmlInclude.path))
|
||||
<< strerror(errno);
|
||||
TemporaryDir xmlIncludeDir;
|
||||
TemporaryFile xmlParentInclude(xmlIncludeDir.path);
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(
|
||||
substitute(XML_INCLUDED_SOURCE,
|
||||
substitute(XI_INCLUDE, "../" + android::base::Basename(xmlInclude.path))),
|
||||
xmlParentInclude.path))
|
||||
<< strerror(errno);
|
||||
TemporaryFile xml;
|
||||
ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlInclude.path));
|
||||
ASSERT_EQ(android::base::Dirname(xml.path), android::base::Dirname(xmlIncludeDir.path));
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(
|
||||
substitute(
|
||||
VALID_XML_SOURCE,
|
||||
substitute(XI_INCLUDE, android::base::Basename(xmlIncludeDir.path) + "/" +
|
||||
android::base::Basename(xmlParentInclude.path))),
|
||||
xml.path))
|
||||
<< strerror(errno);
|
||||
TemporaryFile xsd;
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(XSD_SOURCE, xsd.path)) << strerror(errno);
|
||||
EXPECT_TRUE(validateXml("xml", "xsd", xml.path, xsd.path));
|
||||
}
|
Loading…
Reference in a new issue