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:
Mikhail Naganov 2021-07-03 00:49:13 +00:00
parent 9f834f1a91
commit 068de276f0
4 changed files with 214 additions and 3 deletions

View file

@ -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"],
}

View file

@ -0,0 +1,7 @@
{
"presubmit": [
{
"name": "android.hardware.audio.common.test.utility_tests"
}
]
}

View file

@ -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();
}

View 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));
}