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

Side by Side Diff: log_unit_tests.cc

Issue 6870023: Add "bootstat --output-dir" option. Base URL: ssh://gitrw.chromium.org:9222/bootstat.git@master
Patch Set: Get bootstat.c to where it actually compiles. Created 9 years, 8 months 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) 2011 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 #include "bootstat_test.h"
7 7
8 #include <errno.h> 8 #include <errno.h>
9 #include <stdio.h>
9 #include <stdlib.h> 10 #include <stdlib.h>
10 #include <sys/fcntl.h> 11 #include <sys/fcntl.h>
11 #include <sys/stat.h> 12 #include <sys/stat.h>
12 #include <sys/types.h> 13 #include <sys/types.h>
13 #include <unistd.h> 14 #include <unistd.h>
14 15
15 #include <string> 16 #include <string>
16 #include <iostream> 17 #include <iostream>
17 18
18 #include <gtest/gtest.h> 19 #include <gtest/gtest.h>
19 20
20 namespace { 21 namespace {
21 22
22 using std::string; 23 using std::string;
23 24
24 static void RemoveFile(const string& file_path) { 25 static void RemoveFile(const string& file_path) {
25 EXPECT_EQ(0, unlink(file_path.c_str())) 26 EXPECT_EQ(0, unlink(file_path.c_str()))
26 << "can't unlink file " << file_path << ": " 27 << "can't unlink file " << file_path << ": "
27 << strerror(errno); 28 << strerror(errno);
28 } 29 }
29 30
30 31
31 // Class to track and test the data associated with a single event. 32 // Class to track and test the data associated with a single event.
32 // The primary function is TestLogEvent(): This method wraps calls 33 // The methods TestEventContent() and TestEventCreation() wrap calls
33 // to bootstat_log() with code to track the expected contents of the 34 // to bootstat_log() to test various assertions regarding the
34 // event files. After logging, the expected content is tested 35 // function.
35 // against the actual content.
36 class EventTracker { 36 class EventTracker {
37 public: 37 public:
38 EventTracker(const string& name, const string& uptime_prefix, 38 EventTracker(const string& name, const string& output_dir);
39 const string& disk_prefix); 39 void TestEventContent(const char* uptime, const char* diskstats);
40 void TestLogEvent(const string& uptime, const string& diskstats); 40 void TestEventCreation(bool expect_success);
41 void Reset(); 41 void Reset();
42 42
43 private: 43 private:
44 string event_name_; 44 string event_name_;
45 string uptime_file_name_; 45 string uptime_file_name_;
46 string uptime_content_; 46 string uptime_content_;
47 string diskstats_file_name_; 47 string diskstats_file_name_;
48 string diskstats_content_; 48 string diskstats_content_;
49 }; 49 };
50 50
51 51
52 EventTracker::EventTracker(const string& name, 52 EventTracker::EventTracker(const string& name,
53 const string& uptime_prefix, 53 const string& output_dir)
54 const string& diskstats_prefix)
55 : event_name_(name), 54 : event_name_(name),
56 uptime_content_(""), 55 uptime_content_(""),
57 diskstats_content_("") { 56 diskstats_content_("") {
58 string truncated_name = 57 string truncated_name =
59 event_name_.substr(0, BOOTSTAT_MAX_EVENT_LEN - 1); 58 event_name_.substr(0, BOOTSTAT_MAX_EVENT_LEN - 1);
60 uptime_file_name_ = uptime_prefix + truncated_name; 59 uptime_file_name_ = output_dir + "/uptime-" + truncated_name;
61 diskstats_file_name_ = diskstats_prefix + truncated_name; 60 diskstats_file_name_ = output_dir + "/disk-" + truncated_name;
62 } 61 }
63 62
64 63
65 // Basic helper function to test whether the contents of the 64 // Basic helper function to test whether the contents of the
66 // specified file exactly match the given contents string. 65 // specified file exactly match the given contents string.
67 static void ValidateEventFileContents(const string& file_name, 66 static void ValidateEventFileContent(const string& file_name,
68 const string& file_contents) { 67 const string& file_contents) {
69 int rv = access(file_name.c_str(), W_OK); 68 int rv = access(file_name.c_str(), W_OK);
70 EXPECT_EQ(0, rv) << file_name << " is not writable: " 69 EXPECT_EQ(0, rv) << file_name << " is not writable: "
71 << strerror(errno); 70 << strerror(errno) << ".";
72 rv = access(file_name.c_str(), R_OK); 71 rv = access(file_name.c_str(), R_OK);
73 ASSERT_EQ(0, rv) << file_name << " is not readable: " 72 ASSERT_EQ(0, rv) << file_name << " is not readable: "
74 << strerror(errno); 73 << strerror(errno) << ".";
75 char *buffer = new char[file_contents.length() + 1]; 74 char *buffer = new char[file_contents.length() + 1];
76 int fd = open(file_name.c_str(), O_RDONLY); 75 int fd = open(file_name.c_str(), O_RDONLY);
77 rv = read(fd, buffer, file_contents.length()); 76 rv = read(fd, buffer, file_contents.length());
78 EXPECT_EQ(file_contents.length(), rv); 77 EXPECT_EQ(file_contents.length(), rv);
79 buffer[file_contents.length()] = '\0'; 78 buffer[file_contents.length()] = '\0';
80 string actual_contents(buffer); 79 string actual_contents(buffer);
81 EXPECT_EQ(file_contents, actual_contents); 80 EXPECT_EQ(file_contents, actual_contents);
82 rv = read(fd, buffer, 1); 81 rv = read(fd, buffer, 1);
83 EXPECT_EQ(0, rv) << "found data in event file past expected EOF"; 82 EXPECT_EQ(0, rv) << "found data in event file past expected EOF";
84 (void)close(fd); 83 (void)close(fd);
85 delete buffer; 84 delete buffer;
86 } 85 }
87 86
88 87
89 // Call bootstat_log() once, and update the expected content for 88 // Call bootstat_log() once, and update the expected content for
90 // this event. Test that the new content of the event's files 89 // this event. Test that the new content of the event's files
91 // matches the updated expected content. 90 // matches the updated expected content.
92 void EventTracker::TestLogEvent(const string& uptime, 91 void EventTracker::TestEventContent(const char* uptime,
93 const string& diskstats) { 92 const char* diskstats) {
94 bootstat_log(event_name_.c_str()); 93 bootstat_log(event_name_.c_str());
95 uptime_content_ += uptime; 94 uptime_content_ += string(uptime);
96 diskstats_content_ += diskstats; 95 diskstats_content_ += string(diskstats);
97 ValidateEventFileContents(uptime_file_name_, uptime_content_); 96 ValidateEventFileContent(uptime_file_name_, uptime_content_);
98 ValidateEventFileContents(diskstats_file_name_, diskstats_content_); 97 ValidateEventFileContent(diskstats_file_name_, diskstats_content_);
99 } 98 }
100 99
101 100
102 // Reset event state back to initial conditions, by deleting the 101 // Basic helper function to test whether the contents of the
103 // associated event files, and clearing the expected contents. 102 // specified file exactly match the given contents string.
103 // A return value of true indicates that the file contents can
104 // be read.
105 static void ValidateEventFileExistence(const string& file_name,
106 bool expect_success) {
107 int rv = access(file_name.c_str(), F_OK);
108 if (expect_success) {
109 EXPECT_EQ(0, rv) << "Cannot verify existence of " << file_name
110 << ": " << strerror(errno) << ".";
111 } else {
112 EXPECT_LT(rv, 0) << file_name << " exists, but it shouldn't.";
113 }
114
115 if (rv >= 0) {
116 RemoveFile(file_name);
117 }
118 }
119
120
121 // Call bootstat_log() once, and confirm creation of the event
122 // files. The content of the files isn't checked.
123 void EventTracker::TestEventCreation(bool expect_success) {
124 bootstat_log(event_name_.c_str());
125 ValidateEventFileExistence(uptime_file_name_, expect_success);
126 ValidateEventFileExistence(diskstats_file_name_, expect_success);
127 }
128
129
130 // Reset event state back to initial conditions by deleting the
131 // associated event files and clearing the expected contents.
104 void EventTracker::Reset() { 132 void EventTracker::Reset() {
105 uptime_content_.clear(); 133 uptime_content_.clear();
106 diskstats_content_.clear(); 134 diskstats_content_.clear();
107 RemoveFile(diskstats_file_name_); 135 RemoveFile(diskstats_file_name_);
108 RemoveFile(uptime_file_name_); 136 RemoveFile(uptime_file_name_);
109 } 137 }
110 138
111 139
112 // Bootstat test class. We use this class to override the 140 // Bootstat test class. We use this class to override the
113 // dependencies in bootstat_log() on the file paths for /proc/uptime 141 // dependencies in bootstat_log() on the file paths for /proc/uptime
114 // and /sys/block/<device>/stat. 142 // and /sys/block/<device>/stat.
115 // 143 //
116 // The class uses test-specific interfaces that change the default 144 // The class uses test-specific interfaces that change the default
117 // paths from the kernel statistics psuedo-files to temporary paths 145 // paths from the kernel statistics psuedo-files to temporary paths
118 // selected by this test. This class also redirects the location for 146 // selected by this test. This class also redirects the location for
119 // the event files created by bootstat_log() to a temporary directory. 147 // the event files created by bootstat_log() to a temporary directory.
120 class BootstatTest : public ::testing::Test { 148 class BootstatTest : public ::testing::Test {
121 protected: 149 protected:
122 virtual void SetUp(); 150 virtual void SetUp();
123 virtual void TearDown(); 151 virtual void TearDown();
124 152
153 EventTracker MakeEvent(const string& event_name,
154 const string& output_dir_name) {
155 return EventTracker(event_name, output_dir_name);
156 }
125 EventTracker MakeEvent(const string& event_name) { 157 EventTracker MakeEvent(const string& event_name) {
126 return EventTracker(event_name, uptime_event_prefix_, 158 return EventTracker(event_name, stats_output_dir_);
127 disk_event_prefix_);
128 } 159 }
129 160
130 void SetStatsContent(const char* uptime_content, 161 void SetStatsContent(const char* uptime_content,
131 const char* disk_content); 162 const char* disk_content);
132 void TestLogEvent(EventTracker& event); 163 void ClearStatsContent();
164 void TestSetOutputDirectory(const string& testdir,
165 const string& testevent,
166 bool expect_success,
167 int expected_errno);
168 void TestSetOutputDirectoryAccess(const string& testdir, mode_t testmode);
169 void TestLogAccess(const string& testdir, mode_t testmode);
133 170
134 private: 171 private:
135 string stats_output_dir_; 172 string stats_output_dir_;
136 string uptime_event_prefix_;
137 string disk_event_prefix_;
138 173
139 string uptime_stats_file_name_; 174 string uptime_stats_file_name_;
140 string uptime_stats_content_;
141 string disk_stats_file_name_; 175 string disk_stats_file_name_;
142 string disk_stats_content_;
143 }; 176 };
144 177
145 178
146 void BootstatTest::SetUp() { 179 void BootstatTest::SetUp() {
147 char dir_template[] = "bootstat_test_XXXXXX"; 180 char dir_template[] = "bootstat_test_XXXXXX";
148 stats_output_dir_ = string(mkdtemp(dir_template)); 181 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"; 182 uptime_stats_file_name_ = stats_output_dir_ + "/proc_uptime";
152 disk_stats_file_name_ = stats_output_dir_ + "/block_stats"; 183 disk_stats_file_name_ = stats_output_dir_ + "/block_stats";
153 bootstat_set_output_directory(stats_output_dir_.c_str()); 184 EXPECT_EQ(0, bootstat_set_output_directory(stats_output_dir_.c_str()))
154 bootstat_set_uptime_file_name(uptime_stats_file_name_.c_str()); 185 << "Failed to select output directory " << stats_output_dir_
155 bootstat_set_disk_file_name(disk_stats_file_name_.c_str()); 186 << ": " << strerror(errno) << ".";
156 } 187 }
157 188
158 189
159 void BootstatTest::TearDown() { 190 void BootstatTest::TearDown() {
160 bootstat_set_uptime_file_name(NULL); 191 EXPECT_EQ(0, bootstat_set_output_directory(NULL))
161 bootstat_set_disk_file_name(NULL); 192 << "Failed to set output directory back to default: "
162 bootstat_set_output_directory(NULL); 193 << strerror(errno) << ".";
163 RemoveFile(uptime_stats_file_name_);
164 RemoveFile(disk_stats_file_name_);
165 EXPECT_EQ(0, rmdir(stats_output_dir_.c_str())) 194 EXPECT_EQ(0, rmdir(stats_output_dir_.c_str()))
166 << "Can't remove directory " << stats_output_dir_ 195 << "Can't remove directory " << stats_output_dir_
167 << ": " << strerror(errno) << "."; 196 << ": " << strerror(errno) << ".";
168 } 197 }
169 198
170 199
171 static void WriteStatsContent(const string& content, const string& file_path) { 200 static void WriteStatsContent(const char *content, const string& file_path) {
172 const int kFileOpenFlags = O_WRONLY | O_TRUNC | O_CREAT; 201 const int kFileOpenFlags = O_WRONLY | O_TRUNC | O_CREAT;
173 const mode_t kFileCreationMode = 202 const mode_t kFileCreationMode =
174 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; 203 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
175 int fd = open(file_path.c_str(), kFileOpenFlags, kFileCreationMode); 204 int fd = open(file_path.c_str(), kFileOpenFlags, kFileCreationMode);
176 int nwrite = write(fd, content.c_str(), content.length()); 205 int nwrite = write(fd, content, strlen(content));
177 EXPECT_EQ(content.length(), nwrite) 206 EXPECT_EQ(strlen(content), nwrite)
178 << "write to stats file " << file_path 207 << "write to stats file " << file_path
179 << " failed: " << strerror(errno); 208 << " failed: " << strerror(errno);
180 (void)close(fd); 209 (void)close(fd);
181 } 210 }
182 211
183 212
184 // Set the content of the files mocking the contents of the kernel's 213 // Set the content of the files mocking the contents of the kernel's
185 // statistics pseudo-files. The strings provided here will be the 214 // statistics pseudo-files. The strings provided here will be the
186 // ones recorded for subsequent calls to bootstat_log() for all 215 // ones recorded for subsequent calls to bootstat_log() for all
187 // events. 216 // events.
188 void BootstatTest::SetStatsContent(const char* uptime_stats, 217 void BootstatTest::SetStatsContent(const char* uptime_stats,
189 const char* disk_stats) { 218 const char* disk_stats) {
190 uptime_stats_content_ = string(uptime_stats); 219 WriteStatsContent(uptime_stats, uptime_stats_file_name_);
191 WriteStatsContent(uptime_stats_content_, uptime_stats_file_name_); 220 WriteStatsContent(disk_stats, disk_stats_file_name_);
192 disk_stats_content_ = string(disk_stats); 221 bootstat_set_uptime_file_name(uptime_stats_file_name_.c_str());
193 WriteStatsContent(disk_stats_content_, disk_stats_file_name_); 222 bootstat_set_disk_file_name(disk_stats_file_name_.c_str());
194 } 223 }
195 224
196 225
197 void BootstatTest::TestLogEvent(EventTracker& event) { 226 void BootstatTest::ClearStatsContent() {
198 event.TestLogEvent(uptime_stats_content_, disk_stats_content_); 227 bootstat_set_uptime_file_name(NULL);
228 bootstat_set_disk_file_name(NULL);
229 RemoveFile(uptime_stats_file_name_);
230 RemoveFile(disk_stats_file_name_);
199 } 231 }
200 232
201 233
202 // Test data to be used as input to SetStatsContent(). 234 // Test data to be used as input to SetStatsContent().
203 // 235 //
204 // The structure of this array is pairs of strings, terminated by a 236 // The structure of this array is pairs of strings, terminated by a
205 // single NULL. The first string in the pair is content for 237 // single NULL. The first string in the pair is content for
206 // /proc/uptime, the second for /sys/block/<device>/stat. 238 // /proc/uptime, the second for /sys/block/<device>/stat.
207 // 239 //
208 // This data is taken directly from a development system, and is 240 // This data is taken directly from a development system, and is
209 // representative of valid stats content, though not typical of what 241 // representative of valid stats content, though not typical of what
210 // would be seen immediately after boot. 242 // would be seen immediately after boot.
211 static const char* bootstat_data[] = { 243 static const char* bootstat_data[] = {
212 /* 0 */ 244 /* 0 */
213 /* uptime */ "691448.42 11020440.26\n", 245 /* uptime */ "691448.42 11020440.26\n",
214 /* disk */ " 1417116 14896 55561564 10935990 4267850 78379879" 246 /* disk */ " 1417116 14896 55561564 10935990 4267850 78379879"
215 " 661568738 1635920520 158 17856450 1649520570\n", 247 " 661568738 1635920520 158 17856450 1649520570\n",
216 /* 1 */ 248 /* 1 */
217 /* uptime */ "691623.71 11021372.99\n", 249 /* uptime */ "691623.71 11021372.99\n",
218 /* disk */ " 1420714 14918 55689988 11006390 4287385 78594261" 250 /* disk */ " 1420714 14918 55689988 11006390 4287385 78594261"
219 " 663441564 1651579200 152 17974280 1665255160\n", 251 " 663441564 1651579200 152 17974280 1665255160\n",
220 /* EOT */ NULL 252 /* EOT */ NULL
221 }; 253 };
222 254
223 255
224 // Tests that event file content matches expectations when an 256 // This is to test that event file content matches expectations when
225 // event is logged multiple times. 257 // an event is logged multiple times.
226 TEST_F(BootstatTest, ContentGeneration) { 258 TEST_F(BootstatTest, ContentGeneration) {
227 EventTracker ev = MakeEvent(string("test_event")); 259 EventTracker ev = MakeEvent(string("test_event"));
228 int i = 0; 260 int i = 0;
229 while (bootstat_data[i] != NULL) { 261 while (bootstat_data[i] != NULL) {
230 SetStatsContent(bootstat_data[i], bootstat_data[i+1]); 262 SetStatsContent(bootstat_data[i], bootstat_data[i+1]);
231 TestLogEvent(ev); 263 ev.TestEventContent(bootstat_data[i], bootstat_data[i+1]);
232 i += 2; 264 i += 2;
233 } 265 }
266 ClearStatsContent();
234 ev.Reset(); 267 ev.Reset();
235 } 268 }
236 269
237 270
238 // Tests that name truncation of logged events works as advertised. 271 // This is to test that name truncation of logged events works as
272 // advertised.
239 TEST_F(BootstatTest, EventNameTruncation) { 273 TEST_F(BootstatTest, EventNameTruncation) {
240 static const char kMostVoluminousEventName[] = 274 static const char kMostVoluminousEventName[] =
241 // 16 32 48 64 275 // 16 32 48 64
242 "event-6789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 64 276 "event-6789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 64
243 "=064+56789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 128 277 "=064+56789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 128
244 "=128+56789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 191 278 "=128+56789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 191
245 "=191+56789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 256 279 "=191+56789abcdef_123456789ABCDEF.123456789abcdef0123456789abcdef" // 256
246 ; 280 ;
247 281
248 string very_long(kMostVoluminousEventName); 282 string very_long(kMostVoluminousEventName);
249 SetStatsContent(bootstat_data[0], bootstat_data[1]); 283 SetStatsContent(bootstat_data[0], bootstat_data[1]);
250 284
251 EventTracker ev = MakeEvent(very_long); 285 EventTracker ev = MakeEvent(very_long);
252 TestLogEvent(ev); 286 ev.TestEventContent(bootstat_data[0], bootstat_data[1]);
253 ev.Reset(); 287 ev.Reset();
254 ev = MakeEvent(very_long.substr(0, 1)); 288 ev = MakeEvent(very_long.substr(0, 1));
255 TestLogEvent(ev); 289 ev.TestEventContent(bootstat_data[0], bootstat_data[1]);
256 ev.Reset(); 290 ev.Reset();
257 ev = MakeEvent(very_long.substr(0, BOOTSTAT_MAX_EVENT_LEN - 1)); 291 ev = MakeEvent(very_long.substr(0, BOOTSTAT_MAX_EVENT_LEN - 1));
258 TestLogEvent(ev); 292 ev.TestEventContent(bootstat_data[0], bootstat_data[1]);
259 ev.Reset(); 293 ev.Reset();
260 ev = MakeEvent(very_long.substr(0, BOOTSTAT_MAX_EVENT_LEN)); 294 ev = MakeEvent(very_long.substr(0, BOOTSTAT_MAX_EVENT_LEN));
261 TestLogEvent(ev); 295 ev.TestEventContent(bootstat_data[0], bootstat_data[1]);
262 ev.Reset(); 296 ev.Reset();
297
298 ClearStatsContent();
263 } 299 }
264 300
301
302 // Test a call to bootstat_set_output_directory(). Check that the
303 // operation succeeds or fails as indicated by the input parameters.
304 // Also tests that bootstat_log() logs in the expected place after
305 // the call: after success, logging should go to the new directory;
306 // after a failure, logging should continue to go to the previous
307 // directory.
308 void BootstatTest::TestSetOutputDirectory(const string& testdir,
309 const string& testevent,
310 bool expect_success,
311 int expected_errno) {
312 ASSERT_EQ(0, bootstat_set_output_directory(stats_output_dir_.c_str()))
313 << "bootstat_set_output_directory() failed for " << stats_output_dir_
314 << ": " << strerror(errno) << ".";
315 bool set_output_success =
316 (bootstat_set_output_directory(testdir.c_str()) == 0);
317
318 if (expect_success) {
319 ASSERT_TRUE(set_output_success)
320 << "bootstat_set_output_directory() failed unexpectedly for "
321 << testdir << ": " << strerror(errno) << ".";
322 } else {
323 ASSERT_FALSE(set_output_success)
324 << "bootstat_set_output_directory() succeeded for "
325 << testdir << "; expected error: " << strerror(expected_errno) << ".";
326 EXPECT_EQ(expected_errno, errno);
327 }
328
329 string eventdir;
330 if (set_output_success) {
331 eventdir = testdir;
332 } else {
333 eventdir = stats_output_dir_;
334 }
335 string eventname = string("test-set-directory-") + testevent;
336 EventTracker ev = MakeEvent(eventname, eventdir);
337 ev.TestEventCreation(true);
338 ASSERT_EQ(0, bootstat_set_output_directory(NULL))
339 << "bootstat_set_output_directory(NULL) failed: "
340 << strerror(errno) << ".";
341 }
342
343
344 // Test that bootstat_set_output_directory() will return ENOENT
345 // when required.
346 TEST_F(BootstatTest, SetOutputDirectoryEnoent) {
347 TestSetOutputDirectory(string("/this-directory-does-not-exist"),
348 string("ENOENT"), false, ENOENT);
349 }
350
351
352 // Test that bootstat_set_output_directory() will return ENOTDIR
353 // when required.
354 TEST_F(BootstatTest, SetOutputDirectoryEnotdir) {
355 string ordinary_file_name = string("ordinary-file");
356 const mode_t kFileCreationMode =
357 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
358 int fd = creat(ordinary_file_name.c_str(), kFileCreationMode);
359 EXPECT_GE(fd, 0)
360 << "failed to create test file " << ordinary_file_name
361 << ": " << strerror(errno) << ".";
362 if (fd >= 0) {
363 TestSetOutputDirectory(ordinary_file_name, string("ENOTDIR"),
364 false, ENOTDIR);
365 (void) close(fd);
366 RemoveFile(ordinary_file_name);
367 }
368 }
369
370
371 // Test that bootstat_set_output_directory() succeeds or fails with
372 // EACCES as expected.
373 void BootstatTest::TestSetOutputDirectoryAccess(const string& testdir,
374 mode_t testmode) {
375 char buffer[8];
376 sprintf(buffer, "0%03o", testmode);
377 string modestring = string(buffer);
378 bool expect_success =
379 ((testmode & (S_IWUSR | S_IXUSR)) == (S_IWUSR | S_IXUSR));
380
381 ASSERT_EQ(0, chmod(testdir.c_str(), testmode))
382 << "Unable to change directory mode for " << testdir
383 << " to " << modestring << ": " << strerror(errno) << ".";
384 string eventname = string("EACCES-") + modestring;
385 TestSetOutputDirectory(testdir, eventname, expect_success, EACCES);
386 }
387
388
389 // Test that the actual access mode requirements enforced by
390 // bootstat_log() match the requirements enforced by
391 // bootstat_set_output_directory().
392 void BootstatTest::TestLogAccess(const string& testdir,
393 mode_t testmode) {
394 char buffer[8];
395 sprintf(buffer, "0%03o", testmode);
396 string modestring = string(buffer);
397 bool expect_success =
398 ((testmode & (S_IWUSR | S_IXUSR)) == (S_IWUSR | S_IXUSR));
399
400 ASSERT_EQ(0, chmod(testdir.c_str(), S_IRUSR | S_IWUSR | S_IXUSR))
401 << "Unable to change directory mode for " << testdir
402 << " to 0700: " << strerror(errno) << ".";
403 ASSERT_EQ(0, bootstat_set_output_directory(testdir.c_str()))
404 << "bootstat_set_output_directory() failed for " << testdir
405 << ": " << strerror(errno) << ".";
406 ASSERT_EQ(0, chmod(testdir.c_str(), testmode))
407 << "Unable to change directory mode for " << testdir
408 << " to " << modestring << ": " << strerror(errno) << ".";
409
410 string event_name = string("test-log-access-") + modestring;
411 EventTracker ev = MakeEvent(event_name, testdir);
412 ev.TestEventCreation(expect_success);
413
414 ASSERT_EQ(0, bootstat_set_output_directory(NULL))
415 << "bootstat_set_output_directory(NULL) failed: "
416 << strerror(errno) << ".";
417 }
418
419
420 // Test that bootstat_set_output_directory() will return EACCES
421 // as expected for all directory modes. The test here is
422 // two-pronged. First, the test confirms that EACCES is
423 // returned exactly when the caller has both W and X access.
424 // Second, the test confirms that bootstat_log() fails when
425 // EACCES is returned, but not when it isn't.
426 TEST_F(BootstatTest, SetOutputDirectoryEacces) {
427 char dir_template[] = "bootstat_access_test_XXXXXX";
428 string testdir = string(mkdtemp(dir_template));
429 mode_t lobit = ((S_IRUSR - 1) & (S_IWUSR - 1) & (S_IXUSR - 1)) + 1;
430 mode_t allbits = (S_IRUSR | S_IWUSR | S_IXUSR);
431 mode_t dirmode = allbits + lobit;
432 while (dirmode > 0) {
433 dirmode -= lobit;
434 TestSetOutputDirectoryAccess(testdir, dirmode);
435 TestLogAccess(testdir, dirmode);
436 }
437 EXPECT_EQ(0, rmdir(testdir.c_str()))
438 << "Can't remove directory " << testdir
439 << ": " << strerror(errno) << ".";
440 }
441
442
265 } // namespace 443 } // namespace
266 444
267 int main(int argc, char** argv) { 445 int main(int argc, char** argv) {
268 testing::InitGoogleTest(&argc, argv); 446 testing::InitGoogleTest(&argc, argv);
269 return RUN_ALL_TESTS(); 447 return RUN_ALL_TESTS();
270 } 448 }
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