Support UpdateTimestamp log entry property

The UpdateTimestamp property says when an event log property was last
updated.  On log creation, this field is initialized with the time that
the log was created.

The only other time a log entry property can change is when the Resolved
property changes, so also added support there to update the new
UpdateTimestamp property.

While technically every property of the Entry interface is writeable,
there is no use case nor code for changing those in the field, so
UpdateTimestamp does not support those.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I9b1360b9c5424e130947045cee7b64ede6264829
diff --git a/test/elog_update_ts_test.cpp b/test/elog_update_ts_test.cpp
new file mode 100644
index 0000000..ece0b80
--- /dev/null
+++ b/test/elog_update_ts_test.cpp
@@ -0,0 +1,73 @@
+#include "config.h"
+
+#include "elog_entry.hpp"
+#include "elog_serialize.hpp"
+#include "log_manager.hpp"
+
+#include <filesystem>
+#include <thread>
+
+#include <gtest/gtest.h>
+
+namespace phosphor
+{
+namespace logging
+{
+namespace test
+{
+
+using namespace std::chrono_literals;
+
+// Test that the update timestamp changes when the resolved property changes
+TEST(TestUpdateTS, testChangeResolved)
+{
+    // Setting resolved will serialize, so need this directory.
+    std::filesystem::create_directory(ERRLOG_PERSIST_PATH);
+
+    auto bus = sdbusplus::bus::new_default();
+    phosphor::logging::internal::Manager manager(bus, OBJ_INTERNAL);
+
+    uint32_t id = 99;
+    uint64_t timestamp{100};
+    std::string message{"test error"};
+    std::string fwLevel{"level42"};
+    std::vector<std::string> testData{"additional", "data"};
+    phosphor::logging::AssociationList associations{};
+
+    Entry elog{bus,
+               std::string(OBJ_ENTRY) + '/' + std::to_string(id),
+               id,
+               timestamp,
+               Entry::Level::Informational,
+               std::move(message),
+               std::move(testData),
+               std::move(associations),
+               fwLevel,
+               manager};
+
+    EXPECT_EQ(elog.timestamp(), elog.updateTimestamp());
+
+    std::this_thread::sleep_for(1ms);
+
+    elog.resolved(true);
+    auto updateTS = elog.updateTimestamp();
+    EXPECT_NE(updateTS, elog.timestamp());
+
+    std::this_thread::sleep_for(1ms);
+
+    elog.resolved(false);
+    EXPECT_NE(updateTS, elog.updateTimestamp());
+    updateTS = elog.updateTimestamp();
+
+    std::this_thread::sleep_for(1ms);
+
+    // No change
+    elog.resolved(false);
+    EXPECT_EQ(updateTS, elog.updateTimestamp());
+
+    std::filesystem::remove_all(ERRLOG_PERSIST_PATH);
+}
+
+} // namespace test
+} // namespace logging
+} // namespace phosphor