Add tests to RuntimeInfo fetch flags.

Test: libvintf_test
Test: vintf_object_test

Bug: 66960848

Change-Id: I7736760a2cfbd7aa4ebdc030ccf0ae9b2024bccb
diff --git a/VintfObject.cpp b/VintfObject.cpp
index e87dd05..698bf30 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -98,7 +98,7 @@
     }
 
     if (gDeviceRuntimeInfo.object == nullptr) {
-        gDeviceRuntimeInfo.object = std::make_shared<RuntimeInfo>();
+        gDeviceRuntimeInfo.object = details::gRuntimeInfoFactory->make_shared();
     }
 
     status_t status = gDeviceRuntimeInfo.object->fetchAllInformation(flags);
diff --git a/include/vintf/RuntimeInfo.h b/include/vintf/RuntimeInfo.h
index 390e3ed..68b6929 100644
--- a/include/vintf/RuntimeInfo.h
+++ b/include/vintf/RuntimeInfo.h
@@ -38,6 +38,7 @@
 struct RuntimeInfo {
 
     RuntimeInfo() {}
+    virtual ~RuntimeInfo() = default;
 
     // /proc/version
     // utsname.sysname
@@ -87,14 +88,15 @@
         ALL = ((LAST_PLUS_ONE - 1) << 1) - 1,
     };
 
+   protected:
+    virtual status_t fetchAllInformation(FetchFlags flags);
+
    private:
     friend struct RuntimeInfoFetcher;
     friend class VintfObject;
     friend struct LibVintfTest;
     friend std::string dump(const RuntimeInfo &ki);
 
-    status_t fetchAllInformation(FetchFlags flags);
-
     // mKernelVersion = x'.y'.z', minLts = x.y.z,
     // match if x == x' , y == y' , and z <= z'.
     bool matchKernelVersion(const KernelVersion& minLts) const;
diff --git a/test/RuntimeInfo-fake.cpp b/test/RuntimeInfo-fake.cpp
index 4fc568a..c13eac2 100644
--- a/test/RuntimeInfo-fake.cpp
+++ b/test/RuntimeInfo-fake.cpp
@@ -20,7 +20,7 @@
 namespace vintf {
 
 // Fake implementation used for testing.
-status_t RuntimeInfo::fetchAllInformation() {
+status_t RuntimeInfo::fetchAllInformation(RuntimeInfo::FetchFlags) {
     mOsName = "Linux";
     mNodeName = "localhost";
     mOsRelease = "3.18.31-g936f9a479d0f";
diff --git a/test/utils-fake.cpp b/test/utils-fake.cpp
index 3f4f3c1..151b3bf 100644
--- a/test/utils-fake.cpp
+++ b/test/utils-fake.cpp
@@ -26,6 +26,8 @@
 
 PartitionMounter* gPartitionMounter = nullptr;
 
+ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory = nullptr;
+
 }  // namespace details
 }  // namespace vintf
 }  // namespace android
diff --git a/test/utils-fake.h b/test/utils-fake.h
index a3cd3d7..dd93542 100644
--- a/test/utils-fake.h
+++ b/test/utils-fake.h
@@ -78,6 +78,35 @@
     bool vendorMounted_;
 };
 
+class MockRuntimeInfo : public RuntimeInfo {
+   public:
+    MockRuntimeInfo() {
+        ON_CALL(*this, fetchAllInformation(_))
+            .WillByDefault(Invoke(this, &MockRuntimeInfo::doFetch));
+    }
+    MOCK_METHOD1(fetchAllInformation, status_t(RuntimeInfo::FetchFlags));
+    status_t doFetch(RuntimeInfo::FetchFlags flags) {
+        if (failNextFetch_) {
+            failNextFetch_ = false;
+            return android::UNKNOWN_ERROR;
+        }
+        return RuntimeInfo::fetchAllInformation(flags);
+    }
+    void failNextFetch() { failNextFetch_ = true; }
+
+   private:
+    bool failNextFetch_ = false;
+};
+class MockRuntimeInfoFactory : public ObjectFactory<RuntimeInfo> {
+   public:
+    MockRuntimeInfoFactory(const std::shared_ptr<MockRuntimeInfo>& info) { object_ = info; }
+    std::shared_ptr<RuntimeInfo> make_shared() const override { return object_; }
+    std::shared_ptr<MockRuntimeInfo> getInfo() const { return object_; }
+
+   private:
+    std::shared_ptr<MockRuntimeInfo> object_;
+};
+
 }  // namespace details
 }  // namespace vintf
 }  // namespace android
diff --git a/test/vintf_object_tests.cpp b/test/vintf_object_tests.cpp
index ef65e52..aa11b6f 100644
--- a/test/vintf_object_tests.cpp
+++ b/test/vintf_object_tests.cpp
@@ -201,7 +201,6 @@
 static MockFileFetcher &fetcher() {
     return *static_cast<MockFileFetcher*>(gFetcher);
 }
-
 // Test fixture that provides compatible metadata from the mock device.
 class VintfObjectCompatibleTest : public testing::Test {
    protected:
@@ -439,6 +438,46 @@
     ASSERT_STREQ(error.c_str(), "");
 }
 
+static MockRuntimeInfoFactory& runtimeInfoFactory() {
+    return *static_cast<MockRuntimeInfoFactory*>(gRuntimeInfoFactory);
+}
+
+// Test fixture that provides compatible metadata from the mock device.
+class VintfObjectRuntimeInfoTest : public testing::Test {
+   protected:
+    virtual void SetUp() {
+        // clear fetch flags
+        runtimeInfoFactory().getInfo()->failNextFetch();
+        VintfObject::GetRuntimeInfo(true /* skipCache */, RuntimeInfo::FetchFlag::ALL);
+    }
+    virtual void TearDown() {
+        Mock::VerifyAndClear(&runtimeInfoFactory());
+        Mock::VerifyAndClear(runtimeInfoFactory().getInfo().get());
+    }
+};
+
+TEST_F(VintfObjectRuntimeInfoTest, GetRuntimeInfo) {
+    InSequence s;
+
+    EXPECT_CALL(*runtimeInfoFactory().getInfo(),
+                fetchAllInformation(RuntimeInfo::FetchFlag::CPU_VERSION));
+    EXPECT_CALL(*runtimeInfoFactory().getInfo(), fetchAllInformation(RuntimeInfo::FetchFlag::NONE));
+    EXPECT_CALL(*runtimeInfoFactory().getInfo(),
+                fetchAllInformation(RuntimeInfo::FetchFlag::CPU_VERSION));
+    EXPECT_CALL(
+        *runtimeInfoFactory().getInfo(),
+        fetchAllInformation(RuntimeInfo::FetchFlag::ALL & ~RuntimeInfo::FetchFlag::CPU_VERSION));
+    EXPECT_CALL(*runtimeInfoFactory().getInfo(), fetchAllInformation(RuntimeInfo::FetchFlag::ALL));
+    EXPECT_CALL(*runtimeInfoFactory().getInfo(), fetchAllInformation(RuntimeInfo::FetchFlag::NONE));
+
+    VintfObject::GetRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::CPU_VERSION);
+    VintfObject::GetRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::CPU_VERSION);
+    VintfObject::GetRuntimeInfo(true /* skipCache */, RuntimeInfo::FetchFlag::CPU_VERSION);
+    VintfObject::GetRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::ALL);
+    VintfObject::GetRuntimeInfo(true /* skipCache */, RuntimeInfo::FetchFlag::ALL);
+    VintfObject::GetRuntimeInfo(false /* skipCache */, RuntimeInfo::FetchFlag::ALL);
+}
+
 int main(int argc, char** argv) {
     ::testing::InitGoogleMock(&argc, argv);
 
@@ -448,5 +487,9 @@
     NiceMock<MockPartitionMounter> mounter;
     gPartitionMounter = &mounter;
 
+    NiceMock<MockRuntimeInfoFactory> runtimeInfoFactory(
+        std::make_shared<NiceMock<MockRuntimeInfo>>());
+    gRuntimeInfoFactory = &runtimeInfoFactory;
+
     return RUN_ALL_TESTS();
 }
diff --git a/utils.cpp b/utils.cpp
index 9b20b01..2b0cb37 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -25,6 +25,10 @@
 
 static PartitionMounter partitionMounter;
 PartitionMounter* gPartitionMounter = &partitionMounter;
+
+static ObjectFactory<RuntimeInfo> runtimeInfoFactory;
+ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory = &runtimeInfoFactory;
+
 }  // namespace details
 }  // namespace vintf
 }  // namespace android
diff --git a/utils.h b/utils.h
index 9208b6a..973c524 100644
--- a/utils.h
+++ b/utils.h
@@ -24,6 +24,7 @@
 #include <android-base/logging.h>
 #include <utils/Errors.h>
 
+#include "RuntimeInfo.h"
 #include "parse_xml.h"
 
 namespace android {
@@ -91,6 +92,14 @@
     return OK;
 }
 
+template <typename T>
+class ObjectFactory {
+   public:
+    virtual ~ObjectFactory() = default;
+    virtual std::shared_ptr<T> make_shared() const { return std::make_shared<T>(); }
+};
+extern ObjectFactory<RuntimeInfo>* gRuntimeInfoFactory;
+
 }  // namespace details
 }  // namespace vintf
 }  // namespace android