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

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

Powered by Google App Engine
This is Rietveld 408576698