Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(762)

Unified Diff: log_unit_tests.cc

Issue 5500001: Eliminate the dependency on kernel pseudo-files when running unit tests (Closed) Base URL: http://git.chromium.org/git/bootstat.git@master
Patch Set: Update in response to review comments Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « bootstat_test.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: log_unit_tests.cc
diff --git a/log_unit_tests.cc b/log_unit_tests.cc
index 2d279eef679bd45cde569aea19b20bd30aa6dc7b..b12718a20fad934aa44b3e99f67d9aad510bf8da 100644
--- a/log_unit_tests.cc
+++ b/log_unit_tests.cc
@@ -3,8 +3,13 @@
// found in the LICENSE file.
#include "bootstat.h"
+#include "bootstat_test.h"
#include <errno.h>
+#include <stdlib.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
#include <string>
@@ -16,40 +21,245 @@ namespace {
using std::string;
-static const char kMostVoluminousEventName[] =
- // 16 32 48 64
- "event-6789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 64
- "event-6789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 128
- "event-6789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 191
- "event-6789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 256
- ;
+static void RemoveFile(const string& file_path) {
+ EXPECT_EQ(0, unlink(file_path.c_str()))
+ << "can't unlink file " << file_path << ": "
+ << strerror(errno);
+}
+
+
+// Class to track and test the data associated with a single event.
+// The primary function is TestLogEvent(): This method wraps calls
+// to bootstat_log() with code to track the expected contents of the
+// event files. After logging, the expected content is tested
+// against the actual content.
+class EventTracker {
+ public:
+ EventTracker(const string& name, const string& uptime_prefix,
+ const string& disk_prefix);
+ void TestLogEvent(const string& uptime, const string& diskstats);
+ void Reset();
+
+ private:
+ string event_name_;
+ string uptime_file_name_;
+ string uptime_content_;
+ string diskstats_file_name_;
+ string diskstats_content_;
+};
+
+
+EventTracker::EventTracker(const string& name,
+ const string& uptime_prefix,
+ const string& diskstats_prefix)
+ : event_name_(name),
+ uptime_content_(""),
+ diskstats_content_("") {
+ string truncated_name =
+ event_name_.substr(0, BOOTSTAT_MAX_EVENT_LEN - 1);
+ uptime_file_name_ = uptime_prefix + truncated_name;
+ diskstats_file_name_ = diskstats_prefix + truncated_name;
+}
+
+
+// Basic helper function to test whether the contents of the
+// specified file exactly match the given contents string.
+static void ValidateEventFileContents(const string& file_name,
+ const string& file_contents) {
+ int rv = access(file_name.c_str(), W_OK);
+ EXPECT_EQ(0, rv) << file_name << " is not writable: "
+ << strerror(errno);
+ rv = access(file_name.c_str(), R_OK);
+ ASSERT_EQ(0, rv) << file_name << " is not readable: "
+ << strerror(errno);
+ char *buffer = new char[file_contents.length() + 1];
+ int fd = open(file_name.c_str(), O_RDONLY);
+ rv = read(fd, buffer, file_contents.length());
+ EXPECT_EQ(file_contents.length(), rv);
+ buffer[file_contents.length()] = '\0';
+ string actual_contents(buffer);
+ EXPECT_EQ(file_contents, actual_contents);
+ rv = read(fd, buffer, 1);
+ EXPECT_EQ(0, rv) << "found data in event file past expected EOF";
+ (void)close(fd);
+ delete buffer;
+}
-static const string kUptimeFileNamePrefix("/tmp/uptime-");
-static const string kDiskStatFileNamePrefix("/tmp/disk-");
-static void TestEventFileAccess(const string& file_name) {
- int rv = access(file_name.c_str(), R_OK | W_OK);
- EXPECT_EQ(rv, 0) << "access to " << file_name
- << " failed: " << strerror(errno);
- (void) unlink(file_name.c_str());
+// Call bootstat_log() once, and update the expected content for
+// this event. Test that the new content of the event's files
+// matches the updated expected content.
+void EventTracker::TestLogEvent(const string& uptime,
+ const string& diskstats) {
+ bootstat_log(event_name_.c_str());
+ uptime_content_ += uptime;
+ diskstats_content_ += diskstats;
+ ValidateEventFileContents(uptime_file_name_, uptime_content_);
+ ValidateEventFileContents(diskstats_file_name_, diskstats_content_);
}
-static void TestEventByName(const string& event_name) {
- bootstat_log(event_name.c_str());
- string truncated_event(event_name.substr(0, BOOTSTAT_MAX_EVENT_LEN - 1));
- TestEventFileAccess(kUptimeFileNamePrefix + truncated_event);
- TestEventFileAccess(kDiskStatFileNamePrefix + truncated_event);
+
+// Reset event state back to initial conditions, by deleting the
+// associated event files, and clearing the expected contents.
+void EventTracker::Reset() {
+ uptime_content_.clear();
+ diskstats_content_.clear();
+ RemoveFile(diskstats_file_name_);
+ RemoveFile(uptime_file_name_);
+}
+
+
+// Bootstat test class. We use this class to override the
+// dependencies in bootstat_log() on the file paths for /proc/uptime
+// and /sys/block/<device>/stat.
+//
+// The class uses test-specific interfaces that change the default
+// paths from the kernel statistics psuedo-files to temporary paths
+// selected by this test. This class also redirects the location for
+// the event files created by bootstat_log() to a temporary directory.
+class BootstatTest : public ::testing::Test {
+ protected:
+ virtual void SetUp();
+ virtual void TearDown();
+
+ EventTracker MakeEvent(const string& event_name) {
+ return EventTracker(event_name, uptime_event_prefix_,
+ disk_event_prefix_);
+ }
+
+ void SetStatsContent(const char* uptime_content,
+ const char* disk_content);
+ void TestLogEvent(EventTracker& event);
+
+ private:
+ string stats_output_dir_;
+ string uptime_event_prefix_;
+ string disk_event_prefix_;
+
+ string uptime_stats_file_name_;
+ string uptime_stats_content_;
+ string disk_stats_file_name_;
+ string disk_stats_content_;
+};
+
+
+void BootstatTest::SetUp() {
+ char dir_template[] = "bootstat_test_XXXXXX";
+ stats_output_dir_ = string(mkdtemp(dir_template));
+ uptime_event_prefix_ = stats_output_dir_ + "/uptime-";
+ disk_event_prefix_ = stats_output_dir_ + "/disk-";
+ uptime_stats_file_name_ = stats_output_dir_ + "/proc_uptime";
+ disk_stats_file_name_ = stats_output_dir_ + "/block_stats";
+ bootstat_set_output_directory(stats_output_dir_.c_str());
+ bootstat_set_uptime_file_name(uptime_stats_file_name_.c_str());
+ bootstat_set_disk_file_name(disk_stats_file_name_.c_str());
}
-// Tests that name truncation of logged events works as advertised
-TEST(BoostatTest, EventNameTruncation) {
+
+void BootstatTest::TearDown() {
+ bootstat_set_uptime_file_name(NULL);
+ bootstat_set_disk_file_name(NULL);
+ bootstat_set_output_directory(NULL);
+ RemoveFile(uptime_stats_file_name_);
+ RemoveFile(disk_stats_file_name_);
+ EXPECT_EQ(0, rmdir(stats_output_dir_.c_str()))
+ << "Can't remove directory " << stats_output_dir_
+ << ": " << strerror(errno) << ".";
+}
+
+
+static void WriteStatsContent(const string& content, const string& file_path) {
+ const int kFileOpenFlags = O_WRONLY | O_TRUNC | O_CREAT;
+ const mode_t kFileCreationMode =
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+ int fd = open(file_path.c_str(), kFileOpenFlags, kFileCreationMode);
+ int nwrite = write(fd, content.c_str(), content.length());
+ EXPECT_EQ(content.length(), nwrite)
+ << "write to stats file " << file_path
+ << " failed: " << strerror(errno);
+ (void)close(fd);
+}
+
+
+// Set the content of the files mocking the contents of the kernel's
+// statistics pseudo-files. The strings provided here will be the
+// ones recorded for subsequent calls to bootstat_log() for all
+// events.
+void BootstatTest::SetStatsContent(const char* uptime_stats,
+ const char* disk_stats) {
+ uptime_stats_content_ = string(uptime_stats);
+ WriteStatsContent(uptime_stats_content_, uptime_stats_file_name_);
+ disk_stats_content_ = string(disk_stats);
+ WriteStatsContent(disk_stats_content_, disk_stats_file_name_);
+}
+
+
+void BootstatTest::TestLogEvent(EventTracker& event) {
+ event.TestLogEvent(uptime_stats_content_, disk_stats_content_);
+}
+
+
+// Test data to be used as input to SetStatsContent().
+//
+// The structure of this array is pairs of strings, terminated by a
+// single NULL. The first string in the pair is content for
+// /proc/uptime, the second for /sys/block/<device>/stat.
+//
+// This data is taken directly from a development system, and is
+// representative of valid stats content, though not typical of what
+// would be seen immediately after boot.
+static const char* bootstat_data[] = {
+/* 0 */
+/* uptime */ "691448.42 11020440.26\n",
+/* disk */ " 1417116 14896 55561564 10935990 4267850 78379879"
+ " 661568738 1635920520 158 17856450 1649520570\n",
+/* 1 */
+/* uptime */ "691623.71 11021372.99\n",
+/* disk */ " 1420714 14918 55689988 11006390 4287385 78594261"
+ " 663441564 1651579200 152 17974280 1665255160\n",
+/* EOT */ NULL
+};
+
+
+// Tests that event file content matches expectations when an
+// event is logged multiple times.
+TEST_F(BootstatTest, ContentGeneration) {
+ EventTracker ev = MakeEvent(string("test_event"));
+ int i = 0;
+ while (bootstat_data[i] != NULL) {
+ SetStatsContent(bootstat_data[i], bootstat_data[i+1]);
+ TestLogEvent(ev);
+ i += 2;
+ }
+ ev.Reset();
+}
+
+
+// Tests that name truncation of logged events works as advertised.
+TEST_F(BootstatTest, EventNameTruncation) {
+ static const char kMostVoluminousEventName[] =
+ // 16 32 48 64
+ "event-6789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 64
+ "=064+56789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 128
+ "=128+56789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 191
+ "=191+56789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 256
+ ;
+
string very_long(kMostVoluminousEventName);
+ SetStatsContent(bootstat_data[0], bootstat_data[1]);
- TestEventByName(very_long);
- TestEventByName(very_long.substr(0, 1));
- TestEventByName(very_long.substr(0, 16));
- TestEventByName(very_long.substr(0, BOOTSTAT_MAX_EVENT_LEN - 1));
- TestEventByName(very_long.substr(0, BOOTSTAT_MAX_EVENT_LEN));
+ EventTracker ev = MakeEvent(very_long);
+ TestLogEvent(ev);
+ ev.Reset();
+ ev = MakeEvent(very_long.substr(0, 1));
+ TestLogEvent(ev);
+ ev.Reset();
+ ev = MakeEvent(very_long.substr(0, BOOTSTAT_MAX_EVENT_LEN - 1));
+ TestLogEvent(ev);
+ ev.Reset();
+ ev = MakeEvent(very_long.substr(0, BOOTSTAT_MAX_EVENT_LEN));
+ TestLogEvent(ev);
+ ev.Reset();
}
} // namespace
« no previous file with comments | « bootstat_test.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698