summaryrefslogtreecommitdiffstats
path: root/bootstat
diff options
context:
space:
mode:
Diffstat (limited to 'bootstat')
-rw-r--r--bootstat/boot_event_record_store.cpp7
-rw-r--r--bootstat/boot_event_record_store.h1
-rw-r--r--bootstat/boot_event_record_store_test.cpp51
3 files changed, 56 insertions, 3 deletions
diff --git a/bootstat/boot_event_record_store.cpp b/bootstat/boot_event_record_store.cpp
index 5d1fae90b..ef4f68ec0 100644
--- a/bootstat/boot_event_record_store.cpp
+++ b/bootstat/boot_event_record_store.cpp
@@ -55,8 +55,11 @@ bool ParseRecordEventTime(const std::string& path, int32_t* uptime) {
return false;
}
- int32_t value = std::stoi(content);
- bootstat::LogHistogram("bootstat_mtime_matches_content", value == *uptime);
+ // Ignore existing bootstat records (which do not contain file content).
+ if (!content.empty()) {
+ int32_t value = std::stoi(content);
+ bootstat::LogHistogram("bootstat_mtime_matches_content", value == *uptime);
+ }
return true;
}
diff --git a/bootstat/boot_event_record_store.h b/bootstat/boot_event_record_store.h
index 4d5deee51..a2b83184e 100644
--- a/bootstat/boot_event_record_store.h
+++ b/bootstat/boot_event_record_store.h
@@ -55,6 +55,7 @@ class BootEventRecordStore {
FRIEND_TEST(BootEventRecordStoreTest, AddMultipleBootEvents);
FRIEND_TEST(BootEventRecordStoreTest, AddBootEventWithValue);
FRIEND_TEST(BootEventRecordStoreTest, GetBootEvent);
+ FRIEND_TEST(BootEventRecordStoreTest, GetBootEventNoFileContent);
// Sets the filesystem path of the record store.
void SetStorePath(const std::string& path);
diff --git a/bootstat/boot_event_record_store_test.cpp b/bootstat/boot_event_record_store_test.cpp
index 343f9d00b..d4f075590 100644
--- a/bootstat/boot_event_record_store_test.cpp
+++ b/bootstat/boot_event_record_store_test.cpp
@@ -17,12 +17,16 @@
#include "boot_event_record_store.h"
#include <dirent.h>
+#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cstdint>
#include <cstdlib>
+#include <fstream>
#include <android-base/file.h>
+#include <android-base/logging.h>
#include <android-base/test_utils.h>
+#include <android-base/unique_fd.h>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "uptime_parser.h"
@@ -31,6 +35,36 @@ using testing::UnorderedElementsAreArray;
namespace {
+// Creates a fake boot event record file at |record_path| containing the boot
+// record |value|. This method is necessary as truncating a
+// BootEventRecordStore-created file would modify the mtime, which would alter
+// the value of the record.
+bool CreateEmptyBootEventRecord(const std::string& record_path, int32_t value) {
+ android::base::unique_fd record_fd(creat(record_path.c_str(), S_IRUSR | S_IWUSR));
+ if (record_fd.get() == -1) {
+ return false;
+ }
+
+ // Writing the value as content in the record file is a debug measure to
+ // ensure the validity of the file mtime value, i.e., to check that the record
+ // file mtime values are not changed once set.
+ // TODO(jhawkins): Remove this block.
+ if (!android::base::WriteStringToFd(std::to_string(value), record_fd.get())) {
+ return false;
+ }
+
+ // Set the |mtime| of the file to store the value of the boot event while
+ // preserving the |atime|.
+ struct timespec atime = {/* tv_sec */ 0, /* tv_usec */ UTIME_OMIT};
+ struct timespec mtime = {/* tv_sec */ value, /* tv_usec */ 0};
+ const struct timespec times[] = {atime, mtime};
+ if (futimens(record_fd.get(), times) != 0) {
+ return false;
+ }
+
+ return true;
+}
+
// Returns true if the time difference between |a| and |b| is no larger
// than 10 seconds. This allow for a relatively large fuzz when comparing
// two timestamps taken back-to-back.
@@ -178,4 +212,19 @@ TEST_F(BootEventRecordStoreTest, GetBootEvent) {
// Null |record|.
EXPECT_DEATH(store.GetBootEvent("carboniferous", nullptr), std::string());
-} \ No newline at end of file
+}
+
+// Tests that the BootEventRecordStore is capable of handling an older record
+// protocol which does not contain file contents.
+TEST_F(BootEventRecordStoreTest, GetBootEventNoFileContent) {
+ BootEventRecordStore store;
+ store.SetStorePath(GetStorePathForTesting());
+
+ EXPECT_TRUE(CreateEmptyBootEventRecord(store.GetBootEventPath("devonian"), 2718));
+
+ BootEventRecordStore::BootEventRecord record;
+ bool result = store.GetBootEvent("devonian", &record);
+ EXPECT_EQ(true, result);
+ EXPECT_EQ("devonian", record.first);
+ EXPECT_EQ(2718, record.second);
+}