bootstat: Handle v1 record files which do not contain file contents.
Bug: 27836969 Change-Id: I18fcdab7ca32d00af3f8827f42d47868492ed719
This commit is contained in:
parent
abdb758ef6
commit
84fda19c83
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue