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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « bootstat_test.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "bootstat.h" 5 #include "bootstat.h"
6 #include "bootstat_test.h"
6 7
7 #include <errno.h> 8 #include <errno.h>
9 #include <stdlib.h>
10 #include <sys/fcntl.h>
11 #include <sys/stat.h>
12 #include <sys/types.h>
8 #include <unistd.h> 13 #include <unistd.h>
9 14
10 #include <string> 15 #include <string>
11 #include <iostream> 16 #include <iostream>
12 17
13 #include <gtest/gtest.h> 18 #include <gtest/gtest.h>
14 19
15 namespace { 20 namespace {
16 21
17 using std::string; 22 using std::string;
18 23
19 static const char kMostVoluminousEventName[] = 24 static void RemoveFile(const string& file_path) {
20 // 16 32 48 64 25 EXPECT_EQ(0, unlink(file_path.c_str()))
21 "event-6789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 64 26 << "can't unlink file " << file_path << ": "
22 "event-6789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 128 27 << strerror(errno);
23 "event-6789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 191 28 }
24 "event-6789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 256 29
25 ; 30
26 31 // Class to track and test the data associated with a single event.
27 static const string kUptimeFileNamePrefix("/tmp/uptime-"); 32 // The primary function is TestLogEvent(): This method wraps calls
28 static const string kDiskStatFileNamePrefix("/tmp/disk-"); 33 // to bootstat_log() with code to track the expected contents of the
29 34 // event files. After logging, the expected content is tested
30 static void TestEventFileAccess(const string& file_name) { 35 // against the actual content.
31 int rv = access(file_name.c_str(), R_OK | W_OK); 36 class EventTracker {
32 EXPECT_EQ(rv, 0) << "access to " << file_name 37 public:
33 << " failed: " << strerror(errno); 38 EventTracker(const string& name, const string& uptime_prefix,
34 (void) unlink(file_name.c_str()); 39 const string& disk_prefix);
35 } 40 void TestLogEvent(const string& uptime, const string& diskstats);
36 41 void Reset();
37 static void TestEventByName(const string& event_name) { 42
38 bootstat_log(event_name.c_str()); 43 private:
39 string truncated_event(event_name.substr(0, BOOTSTAT_MAX_EVENT_LEN - 1)); 44 string event_name_;
40 TestEventFileAccess(kUptimeFileNamePrefix + truncated_event); 45 string uptime_file_name_;
41 TestEventFileAccess(kDiskStatFileNamePrefix + truncated_event); 46 string uptime_content_;
42 } 47 string diskstats_file_name_;
43 48 string diskstats_content_;
44 // Tests that name truncation of logged events works as advertised 49 };
45 TEST(BoostatTest, EventNameTruncation) { 50
51
52 EventTracker::EventTracker(const string& name,
53 const string& uptime_prefix,
54 const string& diskstats_prefix)
55 : event_name_(name),
56 uptime_content_(""),
57 diskstats_content_("") {
58 string truncated_name =
59 event_name_.substr(0, BOOTSTAT_MAX_EVENT_LEN - 1);
60 uptime_file_name_ = uptime_prefix + truncated_name;
61 diskstats_file_name_ = diskstats_prefix + truncated_name;
62 }
63
64
65 // Basic helper function to test whether the contents of the
66 // specified file exactly match the given contents string.
67 static void ValidateEventFileContents(const string& file_name,
68 const string& file_contents) {
69 int rv = access(file_name.c_str(), W_OK);
70 EXPECT_EQ(0, rv) << file_name << " is not writable: "
71 << strerror(errno);
72 rv = access(file_name.c_str(), R_OK);
73 ASSERT_EQ(0, rv) << file_name << " is not readable: "
74 << strerror(errno);
75 char *buffer = new char[file_contents.length() + 1];
76 int fd = open(file_name.c_str(), O_RDONLY);
77 rv = read(fd, buffer, file_contents.length());
78 EXPECT_EQ(file_contents.length(), rv);
79 buffer[file_contents.length()] = '\0';
80 string actual_contents(buffer);
81 EXPECT_EQ(file_contents, actual_contents);
82 rv = read(fd, buffer, 1);
83 EXPECT_EQ(0, rv) << "found data in event file past expected EOF";
84 (void)close(fd);
85 delete buffer;
86 }
87
88
89 // Call bootstat_log() once, and update the expected content for
90 // this event. Test that the new content of the event's files
91 // matches the updated expected content.
92 void EventTracker::TestLogEvent(const string& uptime,
93 const string& diskstats) {
94 bootstat_log(event_name_.c_str());
95 uptime_content_ += uptime;
96 diskstats_content_ += diskstats;
97 ValidateEventFileContents(uptime_file_name_, uptime_content_);
98 ValidateEventFileContents(diskstats_file_name_, diskstats_content_);
99 }
100
101
102 // Reset event state back to initial conditions, by deleting the
103 // associated event files, and clearing the expected contents.
104 void EventTracker::Reset() {
105 uptime_content_.clear();
106 diskstats_content_.clear();
107 RemoveFile(diskstats_file_name_);
108 RemoveFile(uptime_file_name_);
109 }
110
111
112 // Bootstat test class. We use this class to override the
113 // dependencies in bootstat_log() on the file paths for /proc/uptime
114 // and /sys/block/<device>/stat.
115 //
116 // The class uses test-specific interfaces that change the default
117 // paths from the kernel statistics psuedo-files to temporary paths
118 // selected by this test. This class also redirects the location for
119 // the event files created by bootstat_log() to a temporary directory.
120 class BootstatTest : public ::testing::Test {
121 protected:
122 virtual void SetUp();
123 virtual void TearDown();
124
125 EventTracker MakeEvent(const string& event_name) {
126 return EventTracker(event_name, uptime_event_prefix_,
127 disk_event_prefix_);
128 }
129
130 void SetStatsContent(const char* uptime_content,
131 const char* disk_content);
132 void TestLogEvent(EventTracker& event);
133
134 private:
135 string stats_output_dir_;
136 string uptime_event_prefix_;
137 string disk_event_prefix_;
138
139 string uptime_stats_file_name_;
140 string uptime_stats_content_;
141 string disk_stats_file_name_;
142 string disk_stats_content_;
143 };
144
145
146 void BootstatTest::SetUp() {
147 char dir_template[] = "bootstat_test_XXXXXX";
148 stats_output_dir_ = string(mkdtemp(dir_template));
149 uptime_event_prefix_ = stats_output_dir_ + "/uptime-";
150 disk_event_prefix_ = stats_output_dir_ + "/disk-";
151 uptime_stats_file_name_ = stats_output_dir_ + "/proc_uptime";
152 disk_stats_file_name_ = stats_output_dir_ + "/block_stats";
153 bootstat_set_output_directory(stats_output_dir_.c_str());
154 bootstat_set_uptime_file_name(uptime_stats_file_name_.c_str());
155 bootstat_set_disk_file_name(disk_stats_file_name_.c_str());
156 }
157
158
159 void BootstatTest::TearDown() {
160 bootstat_set_uptime_file_name(NULL);
161 bootstat_set_disk_file_name(NULL);
162 bootstat_set_output_directory(NULL);
163 RemoveFile(uptime_stats_file_name_);
164 RemoveFile(disk_stats_file_name_);
165 EXPECT_EQ(0, rmdir(stats_output_dir_.c_str()))
166 << "Can't remove directory " << stats_output_dir_
167 << ": " << strerror(errno) << ".";
168 }
169
170
171 static void WriteStatsContent(const string& content, const string& file_path) {
172 const int kFileOpenFlags = O_WRONLY | O_TRUNC | O_CREAT;
173 const mode_t kFileCreationMode =
174 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
175 int fd = open(file_path.c_str(), kFileOpenFlags, kFileCreationMode);
176 int nwrite = write(fd, content.c_str(), content.length());
177 EXPECT_EQ(content.length(), nwrite)
178 << "write to stats file " << file_path
179 << " failed: " << strerror(errno);
180 (void)close(fd);
181 }
182
183
184 // Set the content of the files mocking the contents of the kernel's
185 // statistics pseudo-files. The strings provided here will be the
186 // ones recorded for subsequent calls to bootstat_log() for all
187 // events.
188 void BootstatTest::SetStatsContent(const char* uptime_stats,
189 const char* disk_stats) {
190 uptime_stats_content_ = string(uptime_stats);
191 WriteStatsContent(uptime_stats_content_, uptime_stats_file_name_);
192 disk_stats_content_ = string(disk_stats);
193 WriteStatsContent(disk_stats_content_, disk_stats_file_name_);
194 }
195
196
197 void BootstatTest::TestLogEvent(EventTracker& event) {
198 event.TestLogEvent(uptime_stats_content_, disk_stats_content_);
199 }
200
201
202 // Test data to be used as input to SetStatsContent().
203 //
204 // The structure of this array is pairs of strings, terminated by a
205 // single NULL. The first string in the pair is content for
206 // /proc/uptime, the second for /sys/block/<device>/stat.
207 //
208 // This data is taken directly from a development system, and is
209 // representative of valid stats content, though not typical of what
210 // would be seen immediately after boot.
211 static const char* bootstat_data[] = {
212 /* 0 */
213 /* uptime */ "691448.42 11020440.26\n",
214 /* disk */ " 1417116 14896 55561564 10935990 4267850 78379879"
215 " 661568738 1635920520 158 17856450 1649520570\n",
216 /* 1 */
217 /* uptime */ "691623.71 11021372.99\n",
218 /* disk */ " 1420714 14918 55689988 11006390 4287385 78594261"
219 " 663441564 1651579200 152 17974280 1665255160\n",
220 /* EOT */ NULL
221 };
222
223
224 // Tests that event file content matches expectations when an
225 // event is logged multiple times.
226 TEST_F(BootstatTest, ContentGeneration) {
227 EventTracker ev = MakeEvent(string("test_event"));
228 int i = 0;
229 while (bootstat_data[i] != NULL) {
230 SetStatsContent(bootstat_data[i], bootstat_data[i+1]);
231 TestLogEvent(ev);
232 i += 2;
233 }
234 ev.Reset();
235 }
236
237
238 // Tests that name truncation of logged events works as advertised.
239 TEST_F(BootstatTest, EventNameTruncation) {
240 static const char kMostVoluminousEventName[] =
241 // 16 32 48 64
242 "event-6789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 64
243 "=064+56789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 128
244 "=128+56789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 191
245 "=191+56789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 256
246 ;
247
46 string very_long(kMostVoluminousEventName); 248 string very_long(kMostVoluminousEventName);
47 249 SetStatsContent(bootstat_data[0], bootstat_data[1]);
48 TestEventByName(very_long); 250
49 TestEventByName(very_long.substr(0, 1)); 251 EventTracker ev = MakeEvent(very_long);
50 TestEventByName(very_long.substr(0, 16)); 252 TestLogEvent(ev);
51 TestEventByName(very_long.substr(0, BOOTSTAT_MAX_EVENT_LEN - 1)); 253 ev.Reset();
52 TestEventByName(very_long.substr(0, BOOTSTAT_MAX_EVENT_LEN)); 254 ev = MakeEvent(very_long.substr(0, 1));
255 TestLogEvent(ev);
256 ev.Reset();
257 ev = MakeEvent(very_long.substr(0, BOOTSTAT_MAX_EVENT_LEN - 1));
258 TestLogEvent(ev);
259 ev.Reset();
260 ev = MakeEvent(very_long.substr(0, BOOTSTAT_MAX_EVENT_LEN));
261 TestLogEvent(ev);
262 ev.Reset();
53 } 263 }
54 264
55 } // namespace 265 } // namespace
56 266
57 int main(int argc, char** argv) { 267 int main(int argc, char** argv) {
58 testing::InitGoogleTest(&argc, argv); 268 testing::InitGoogleTest(&argc, argv);
59 return RUN_ALL_TESTS(); 269 return RUN_ALL_TESTS();
60 } 270 }
OLDNEW
« 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