VintfObject::verify() will fetch data from device
- If no info is provided then all data is fetched from device.
- Add hook to mock retrieving files from device.
- Add test.
- Print more detailed messages on AVB failures.
Test: Ran vintf_object_test and libvintf_test
Bug: 37863689
Bug: 36814984
Change-Id: Ia33f4e2e73c863bc0f8f68f5ed61c30df8eff53d
Merged-In: Ia33f4e2e73c863bc0f8f68f5ed61c30df8eff53d
diff --git a/Android.bp b/Android.bp
index 728efc0..47b9863 100644
--- a/Android.bp
+++ b/Android.bp
@@ -46,6 +46,7 @@
"MatrixKernel.cpp",
"TransportArch.cpp",
"VintfObject.cpp",
+ "utils.cpp",
],
target: {
@@ -89,3 +90,43 @@
"assemble_vintf.cpp"
],
}
+
+cc_library {
+ name: "libvintftest",
+ host_supported: true,
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libselinux",
+ "libtinyxml2",
+ ],
+ export_include_dirs: ["include/vintf", "include", "test", "."],
+ local_include_dirs: ["include/vintf", "test", "."],
+
+ srcs: [
+ "parse_string.cpp",
+ "parse_xml.cpp",
+ "CompatibilityMatrix.cpp",
+ "HalManifest.cpp",
+ "KernelConfigTypedValue.cpp",
+ "RuntimeInfo.cpp",
+ "ManifestHal.cpp",
+ "MatrixHal.cpp",
+ "MatrixKernel.cpp",
+ "TransportArch.cpp",
+ "VintfObject.cpp",
+ "test/RuntimeInfo-fake.cpp",
+ "test/utils-fake.cpp",
+ ],
+
+ target: {
+ android: {
+ shared_libs: [
+ "libcutils",
+ "libutils",
+ "libz"
+ ],
+ cflags: ["-DLIBVINTF_TARGET"],
+ },
+ }
+}
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 1ef6edc..342f032 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -176,9 +176,9 @@
const RuntimeInfo *runtimeInfo;
};
-// Parse all information from package;
-// Get missing information from the device;
-// Do compatibility check.
+// Checks given compatibility info against info on the device. If no
+// compatability info is given then the device info will be checked against
+// itself.
int32_t checkCompatibility(const std::vector<std::string> &xmls, bool mount,
std::function<status_t(void)> mountSystem,
std::function<status_t(void)> umountSystem,
@@ -194,11 +194,6 @@
PackageInfo pkg; // All information from package.
UpdatedInfo updated; // All files and runtime info after the update.
- if (xmls.empty()) {
- ADD_MESSAGE("nothing to update");
- return BAD_VALUE;
- }
-
// parse all information from package
for (const auto &xml : xmls) {
parseStatus = tryParse(xml, gHalManifestConverter, &pkg.fwk.manifest, &pkg.dev.manifest);
@@ -232,10 +227,18 @@
std::bind(GetDeviceHalManifest, true /* skipCache */))) != OK) {
return status;
}
+ if ((status = getMissing(
+ pkg.fwk.matrix.get(), mount, mountVendor, umountVendor, &updated.fwk.matrix,
+ std::bind(VintfObject::GetFrameworkCompatibilityMatrix, true /* skipCache */))) !=
+ OK) {
+ return status;
+ }
+ if ((status = getMissing(
+ pkg.dev.matrix.get(), mount, mountSystem, umountSystem, &updated.dev.matrix,
+ std::bind(VintfObject::GetDeviceCompatibilityMatrix, true /* skipCache */))) != OK) {
+ return status;
+ }
updated.runtimeInfo = GetRuntimeInfo(true /* skipCache */);
- // TODO(b/37321309) get matrices from the device as well.
- updated.fwk.matrix = pkg.fwk.matrix.get();
- updated.dev.matrix = pkg.dev.matrix.get();
// null checks for files and runtime info after the update
// TODO(b/37321309) if a compat mat is missing, it is not matched and considered compatible.
diff --git a/test/Android.bp b/test/Android.bp
index 2895ebc..f6053ea 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -30,3 +30,26 @@
"-g",
],
}
+
+cc_test {
+ name: "vintf_object_test",
+ host_supported: true,
+ native_coverage: true,
+ srcs: [
+ "vintf_object_tests.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "liblog",
+ "libvintftest",
+ ],
+ static_libs: [
+ "libgtest",
+ "libgmock",
+ ],
+ cflags: [
+ "-O0",
+ "-g",
+ ],
+}
diff --git a/test/AndroidTest.xml b/test/AndroidTest.xml
new file mode 100644
index 0000000..41f408a
--- /dev/null
+++ b/test/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for vintf_object_test">
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="vintf_object_test->/data/local/tmp/vintf_object_test" />
+ </target_preparer>
+ <option name="test-suite-tag" value="apct" />
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="vintf_object_test" />
+ </test>
+</configuration>
diff --git a/test/RuntimeInfo-fake.cpp b/test/RuntimeInfo-fake.cpp
new file mode 100644
index 0000000..4fc568a
--- /dev/null
+++ b/test/RuntimeInfo-fake.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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 "RuntimeInfo.h"
+
+namespace android {
+namespace vintf {
+
+// Fake implementation used for testing.
+status_t RuntimeInfo::fetchAllInformation() {
+ mOsName = "Linux";
+ mNodeName = "localhost";
+ mOsRelease = "3.18.31-g936f9a479d0f";
+ mKernelVersion = {3, 18, 31};
+ mOsVersion = "#4 SMP PREEMPT Wed Feb 1 18:10:52 PST 2017";
+ mHardwareId = "aarch64";
+ mKernelSepolicyVersion = 30;
+ mKernelConfigs = {{"CONFIG_64BIT", "y"},
+ {"CONFIG_ANDROID_BINDER_DEVICES", "\"binder,hwbinder\""},
+ {"CONFIG_ARCH_MMAP_RND_BITS", "24"},
+ {"CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE_NAMES", "\"\""},
+ {"CONFIG_ILLEGAL_POINTER_VALUE", "0xdead000000000000"}};
+
+ return OK;
+}
+
+} // namespace vintf
+} // namespace android
diff --git a/test/utils-fake.cpp b/test/utils-fake.cpp
new file mode 100644
index 0000000..586017e
--- /dev/null
+++ b/test/utils-fake.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 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 "utils.h"
+
+namespace android {
+namespace vintf {
+namespace details {
+
+// Do not create the MockFileFetcher here as InitGoogleMock must be called
+// first.
+FileFetcher* gFetcher = nullptr;
+
+} // namespace details
+} // namespace vintf
+} // namespace android
diff --git a/test/utils-fake.h b/test/utils-fake.h
new file mode 100644
index 0000000..d0c687e
--- /dev/null
+++ b/test/utils-fake.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 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 <gmock/gmock.h>
+
+#include "utils.h"
+
+using ::testing::_;
+using ::testing::AtLeast;
+using ::testing::Invoke;
+
+namespace android {
+namespace vintf {
+namespace details {
+
+class MockFileFetcher : public FileFetcher {
+ public:
+ MockFileFetcher() {
+ // By default call through to the original.
+ ON_CALL(*this, fetch(_, _)).WillByDefault(Invoke(&real_, &FileFetcher::fetch));
+ }
+
+ MOCK_METHOD2(fetch, status_t(const std::string& path, std::string& fetched));
+
+ private:
+ FileFetcher real_;
+};
+
+} // namespace details
+} // namespace vintf
+} // namespace android
diff --git a/test/vintf_object_tests.cpp b/test/vintf_object_tests.cpp
new file mode 100644
index 0000000..27b3f0a
--- /dev/null
+++ b/test/vintf_object_tests.cpp
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2017 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "utils-fake.h"
+#include "vintf/VintfObject.h"
+
+using namespace ::testing;
+using namespace ::android::vintf;
+using namespace ::android::vintf::details;
+
+//
+// Set of Xml1 metadata compatible with each other.
+//
+
+const std::string systemMatrixXml1 =
+ "<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
+ " <hal format=\"hidl\" optional=\"false\">\n"
+ " <name>android.hardware.camera</name>\n"
+ " <version>2.0-5</version>\n"
+ " <version>3.4-16</version>\n"
+ " </hal>\n"
+ " <hal format=\"hidl\" optional=\"false\">\n"
+ " <name>android.hardware.nfc</name>\n"
+ " <version>1.0</version>\n"
+ " <version>2.0</version>\n"
+ " </hal>\n"
+ " <hal format=\"hidl\" optional=\"true\">\n"
+ " <name>android.hardware.foo</name>\n"
+ " <version>1.0</version>\n"
+ " </hal>\n"
+ " <kernel version=\"3.18.31\"></kernel>\n"
+ " <sepolicy>\n"
+ " <kernel-sepolicy-version>30</kernel-sepolicy-version>\n"
+ " <sepolicy-version>25.5</sepolicy-version>\n"
+ " <sepolicy-version>26.0-3</sepolicy-version>\n"
+ " </sepolicy>\n"
+ " <avb>\n"
+ " <vbmeta-version>0.0</vbmeta-version>\n"
+ " </avb>\n"
+ "</compatibility-matrix>\n";
+
+const std::string vendorManifestXml1 =
+ "<manifest version=\"1.0\" type=\"device\">\n"
+ " <hal format=\"hidl\">\n"
+ " <name>android.hardware.camera</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <version>3.5</version>\n"
+ " <interface>\n"
+ " <name>IBetterCamera</name>\n"
+ " <instance>camera</instance>\n"
+ " </interface>\n"
+ " <interface>\n"
+ " <name>ICamera</name>\n"
+ " <instance>default</instance>\n"
+ " <instance>legacy/0</instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ " <hal format=\"hidl\">\n"
+ " <name>android.hardware.nfc</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <version>1.0</version>\n"
+ " <version>2.0</version>\n"
+ " <interface>\n"
+ " <name>INfc</name>\n"
+ " <instance>nfc_nci</instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ " <hal format=\"hidl\">\n"
+ " <name>android.hardware.nfc</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <version>2.0</version>\n"
+ " <interface>\n"
+ " <name>INfc</name>\n"
+ " <instance>default</instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ " <sepolicy>\n"
+ " <version>25.5</version>\n"
+ " </sepolicy>\n"
+ "</manifest>\n";
+
+const std::string systemManifestXml1 =
+ "<manifest version=\"1.0\" type=\"framework\">\n"
+ " <hal format=\"hidl\">\n"
+ " <name>android.hidl.manager</name>\n"
+ " <transport>hwbinder</transport>\n"
+ " <version>1.0</version>\n"
+ " <interface>\n"
+ " <name>IServiceManager</name>\n"
+ " <instance>default</instance>\n"
+ " </interface>\n"
+ " </hal>\n"
+ " <vndk>\n"
+ " <version>25.0.5</version>\n"
+ " <library>libbase.so</library>\n"
+ " <library>libjpeg.so</library>\n"
+ " </vndk>\n"
+ "</manifest>\n";
+
+const std::string vendorMatrixXml1 =
+ "<compatibility-matrix version=\"1.0\" type=\"device\">\n"
+ " <hal format=\"hidl\" optional=\"false\">\n"
+ " <name>android.hidl.manager</name>\n"
+ " <version>1.0</version>\n"
+ " </hal>\n"
+ " <vndk>\n"
+ " <version>25.0.1-5</version>\n"
+ " <library>libbase.so</library>\n"
+ " <library>libjpeg.so</library>\n"
+ " </vndk>\n"
+ "</compatibility-matrix>\n";
+
+//
+// Set of Xml2 metadata compatible with each other.
+//
+
+const std::string systemMatrixXml2 =
+ "<compatibility-matrix version=\"1.0\" type=\"framework\">\n"
+ " <hal format=\"hidl\">\n"
+ " <name>android.hardware.foo</name>\n"
+ " <version>1.0</version>\n"
+ " </hal>\n"
+ " <kernel version=\"3.18.31\"></kernel>\n"
+ " <sepolicy>\n"
+ " <kernel-sepolicy-version>30</kernel-sepolicy-version>\n"
+ " <sepolicy-version>25.5</sepolicy-version>\n"
+ " <sepolicy-version>26.0-3</sepolicy-version>\n"
+ " </sepolicy>\n"
+ " <avb>\n"
+ " <vbmeta-version>0.0</vbmeta-version>\n"
+ " </avb>\n"
+ "</compatibility-matrix>\n";
+
+const std::string vendorManifestXml2 =
+ "<manifest version=\"1.0\" type=\"device\">"
+ " <hal>"
+ " <name>android.hardware.foo</name>"
+ " <transport>hwbinder</transport>"
+ " <version>1.0</version>"
+ " </hal>"
+ " <sepolicy>\n"
+ " <version>25.5</version>\n"
+ " </sepolicy>\n"
+ "</manifest>";
+
+// Setup the MockFileFetcher used by the fetchAllInformation template
+// so it returns the given metadata info instead of fetching from device.
+void setupMockFetcher(const std::string& vendorManifestXml, const std::string& systemMatrixXml,
+ const std::string& systemManifestXml, const std::string& vendorMatrixXml) {
+ MockFileFetcher* fetcher = static_cast<MockFileFetcher*>(gFetcher);
+
+ ON_CALL(*fetcher, fetch(StrEq("/vendor/manifest.xml"), _))
+ .WillByDefault(Invoke([vendorManifestXml](const std::string& path, std::string& fetched) {
+ (void)path;
+ fetched = vendorManifestXml;
+ return 0;
+ }));
+ ON_CALL(*fetcher, fetch(StrEq("/system/manifest.xml"), _))
+ .WillByDefault(Invoke([systemManifestXml](const std::string& path, std::string& fetched) {
+ (void)path;
+ fetched = systemManifestXml;
+ return 0;
+ }));
+ ON_CALL(*fetcher, fetch(StrEq("/vendor/compatibility_matrix.xml"), _))
+ .WillByDefault(Invoke([vendorMatrixXml](const std::string& path, std::string& fetched) {
+ (void)path;
+ fetched = vendorMatrixXml;
+ return 0;
+ }));
+ ON_CALL(*fetcher, fetch(StrEq("/system/compatibility_matrix.xml"), _))
+ .WillByDefault(Invoke([systemMatrixXml](const std::string& path, std::string& fetched) {
+ (void)path;
+ fetched = systemMatrixXml;
+ return 0;
+ }));
+}
+
+// Test fixture that provides compatible metadata from the mock device.
+class VintfObjectCompatibleTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ setupMockFetcher(vendorManifestXml1, systemMatrixXml1, systemManifestXml1,
+ vendorMatrixXml1);
+ }
+};
+
+// Tests that local info is checked.
+TEST_F(VintfObjectCompatibleTest, TestDeviceCompatibility) {
+ std::string error;
+ std::vector<std::string> packageInfo;
+
+ int result = VintfObject::CheckCompatibility(packageInfo, &error);
+
+ ASSERT_EQ(result, 0) << "Fail message:" << error.c_str();
+ // Check that nothing was ignored.
+ ASSERT_STREQ(error.c_str(), "");
+}
+
+// Tests that input info is checked against device and passes.
+TEST_F(VintfObjectCompatibleTest, TestInputVsDeviceSuccess) {
+ std::string error;
+ std::vector<std::string> packageInfo = {systemMatrixXml1};
+
+ int result = VintfObject::CheckCompatibility(packageInfo, &error);
+
+ ASSERT_EQ(result, 0) << "Fail message:" << error.c_str();
+ ASSERT_STREQ(error.c_str(), "");
+}
+
+// Tests that input info is checked against device and fails.
+TEST_F(VintfObjectCompatibleTest, TestInputVsDeviceFail) {
+ std::string error;
+ std::vector<std::string> packageInfo = {systemMatrixXml2};
+
+ int result = VintfObject::CheckCompatibility(packageInfo, &error);
+
+ ASSERT_EQ(result, 1) << "Should have failed:" << error.c_str();
+ ASSERT_STREQ(error.c_str(),
+ "Device manifest and framework compatibility matrix are incompatible: HALs "
+ "incompatible. android.hardware.foo");
+}
+
+// Tests that complementary info is checked against itself.
+TEST_F(VintfObjectCompatibleTest, TestInputSuccess) {
+ std::string error;
+ std::vector<std::string> packageInfo = {systemMatrixXml2, vendorManifestXml2};
+
+ int result = VintfObject::CheckCompatibility(packageInfo, &error);
+
+ ASSERT_EQ(result, 0) << "Failed message:" << error.c_str();
+ ASSERT_STREQ(error.c_str(), "");
+}
+
+// Test fixture that provides incompatible metadata from the mock device.
+class VintfObjectIncompatibleTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ setupMockFetcher(vendorManifestXml1, systemMatrixXml2, systemManifestXml1,
+ vendorMatrixXml1);
+ }
+};
+
+// Fetch all metadata from device and ensure that it fails.
+TEST_F(VintfObjectIncompatibleTest, TestDeviceCompatibility) {
+ std::string error;
+ std::vector<std::string> packageInfo;
+
+ MockFileFetcher* fetcher = static_cast<MockFileFetcher*>(gFetcher);
+ EXPECT_CALL(*fetcher, fetch(StrEq("/vendor/manifest.xml"), _));
+ EXPECT_CALL(*fetcher, fetch(StrEq("/system/manifest.xml"), _));
+ EXPECT_CALL(*fetcher, fetch(StrEq("/vendor/compatibility_matrix.xml"), _));
+ EXPECT_CALL(*fetcher, fetch(StrEq("/system/compatibility_matrix.xml"), _));
+
+ int result = VintfObject::CheckCompatibility(packageInfo, &error);
+
+ ASSERT_EQ(result, 1) << "Should have failed:" << error.c_str();
+}
+
+// Pass in new metadata that fixes the incompatibility.
+TEST_F(VintfObjectIncompatibleTest, TestInputVsDeviceSuccess) {
+ std::string error;
+ std::vector<std::string> packageInfo = {systemMatrixXml1};
+
+ MockFileFetcher* fetcher = static_cast<MockFileFetcher*>(gFetcher);
+ EXPECT_CALL(*fetcher, fetch(StrEq("/vendor/manifest.xml"), _));
+ EXPECT_CALL(*fetcher, fetch(StrEq("/system/manifest.xml"), _));
+ EXPECT_CALL(*fetcher, fetch(StrEq("/vendor/compatibility_matrix.xml"), _));
+ EXPECT_CALL(*fetcher, fetch(StrEq("/system/compatibility_matrix.xml"), _)).Times(0);
+
+ int result = VintfObject::CheckCompatibility(packageInfo, &error);
+
+ ASSERT_EQ(result, 0) << "Failed message:" << error.c_str();
+ ASSERT_STREQ(error.c_str(), "");
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleMock(&argc, argv);
+
+ NiceMock<MockFileFetcher> fetcher;
+ gFetcher = static_cast<FileFetcher*>(&fetcher);
+
+ return RUN_ALL_TESTS();
+}
diff --git a/utils.cpp b/utils.cpp
new file mode 100644
index 0000000..3c4d2e7
--- /dev/null
+++ b/utils.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 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 "utils.h"
+
+namespace android {
+namespace vintf {
+namespace details {
+
+FileFetcher fetcher;
+FileFetcher* gFetcher = &fetcher;
+
+} // namespace details
+} // namespace vintf
+} // namespace android
diff --git a/utils.h b/utils.h
index 3c06817..2c5f813 100644
--- a/utils.h
+++ b/utils.h
@@ -30,18 +30,48 @@
namespace vintf {
namespace details {
-template<typename T>
-status_t fetchAllInformation(const std::string &path,
- const XmlConverter<T> &converter, T *outObject) {
- std::ifstream in;
- in.open(path);
- if (!in.is_open()) {
- LOG(WARNING) << "Cannot open " << path;
- return INVALID_OPERATION;
+// Return the file from the given location as a string.
+//
+// This class can be used to create a mock for overriding.
+class FileFetcher {
+ public:
+ virtual ~FileFetcher() {}
+ virtual status_t fetch(const std::string& path, std::string& fetched) {
+ std::ifstream in;
+
+ in.open(path);
+ if (!in.is_open()) {
+ LOG(WARNING) << "Cannot open " << path;
+ return INVALID_OPERATION;
+ }
+
+ std::stringstream ss;
+ ss << in.rdbuf();
+ fetched = ss.str();
+
+ return OK;
}
- std::stringstream ss;
- ss << in.rdbuf();
- bool success = converter(outObject, ss.str());
+};
+
+extern FileFetcher* gFetcher;
+
+template <typename T>
+status_t fetchAllInformation(const std::string& path, const XmlConverter<T>& converter,
+ T* outObject) {
+ std::string info;
+
+ if (gFetcher == nullptr) {
+ // Should never happen.
+ return NO_INIT;
+ }
+
+ status_t result = gFetcher->fetch(path, info);
+
+ if (result != OK) {
+ return result;
+ }
+
+ bool success = converter(outObject, info);
if (!success) {
LOG(ERROR) << "Illformed file: " << path << ": "
<< converter.lastError();