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

Side by Side Diff: chromecast/crash/linux/synchronized_minidump_manager_unittest.cc

Issue 2203123003: [Chromecast] Remove usage of nonreentrant functions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: slan@ comments Created 4 years, 4 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
« no previous file with comments | « chromecast/crash/linux/synchronized_minidump_manager.cc ('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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium 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 "chromecast/crash/linux/synchronized_minidump_manager.h" 5 #include "chromecast/crash/linux/synchronized_minidump_manager.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 #include <stdio.h> // perror 9 #include <stdio.h> // perror
10 #include <stdlib.h> 10 #include <stdlib.h>
(...skipping 30 matching lines...) Expand all
41 const char kMinidumpSubdir[] = "minidumps"; 41 const char kMinidumpSubdir[] = "minidumps";
42 42
43 // A trivial implementation of SynchronizedMinidumpManager, which does no work 43 // A trivial implementation of SynchronizedMinidumpManager, which does no work
44 // to the minidump and exposes its protected members for testing. This simply 44 // to the minidump and exposes its protected members for testing. This simply
45 // adds an entry to the lockfile. 45 // adds an entry to the lockfile.
46 class SynchronizedMinidumpManagerSimple : public SynchronizedMinidumpManager { 46 class SynchronizedMinidumpManagerSimple : public SynchronizedMinidumpManager {
47 public: 47 public:
48 SynchronizedMinidumpManagerSimple() 48 SynchronizedMinidumpManagerSimple()
49 : SynchronizedMinidumpManager(), 49 : SynchronizedMinidumpManager(),
50 work_done_(false), 50 work_done_(false),
51 add_entry_return_code_(-1), 51 add_entry_return_code_(false),
52 lockfile_path_(dump_path_.Append(kLockfileName).value()) {} 52 lockfile_path_(dump_path_.Append(kLockfileName).value()) {}
53 ~SynchronizedMinidumpManagerSimple() override {} 53 ~SynchronizedMinidumpManagerSimple() override {}
54 54
55 void SetDumpInfoToWrite(std::unique_ptr<DumpInfo> dump_info) { 55 void SetDumpInfoToWrite(std::unique_ptr<DumpInfo> dump_info) {
56 dump_info_ = std::move(dump_info); 56 dump_info_ = std::move(dump_info);
57 } 57 }
58 58
59 int DoWorkLocked() { return AcquireLockAndDoWork(); } 59 bool DoWorkLocked() { return AcquireLockAndDoWork(); }
60 60
61 // SynchronizedMinidumpManager implementation: 61 // SynchronizedMinidumpManager implementation:
62 int DoWork() override { 62 bool DoWork() override {
63 if (dump_info_) 63 if (dump_info_)
64 add_entry_return_code_ = AddEntryToLockFile(*dump_info_); 64 add_entry_return_code_ = AddEntryToLockFile(*dump_info_);
65 work_done_ = true; 65 work_done_ = true;
66 return 0; 66 return true;
67 } 67 }
68 68
69 // Accessors for testing. 69 // Accessors for testing.
70 bool HasDumps() { return SynchronizedMinidumpManager::HasDumps(); } 70 bool HasDumps() { return SynchronizedMinidumpManager::HasDumps(); }
71 const std::string& dump_path() { return dump_path_.value(); } 71 const std::string& dump_path() { return dump_path_.value(); }
72 const std::string& lockfile_path() { return lockfile_path_; } 72 const std::string& lockfile_path() { return lockfile_path_; }
73 bool work_done() { return work_done_; } 73 bool work_done() { return work_done_; }
74 int add_entry_return_code() { return add_entry_return_code_; } 74 bool add_entry_return_code() { return add_entry_return_code_; }
75 75
76 private: 76 private:
77 bool work_done_; 77 bool work_done_;
78 int add_entry_return_code_; 78 bool add_entry_return_code_;
79 std::string lockfile_path_; 79 std::string lockfile_path_;
80 std::unique_ptr<DumpInfo> dump_info_; 80 std::unique_ptr<DumpInfo> dump_info_;
81 }; 81 };
82 82
83 void DoWorkLockedTask(SynchronizedMinidumpManagerSimple* manager) { 83 void DoWorkLockedTask(SynchronizedMinidumpManagerSimple* manager) {
84 manager->DoWorkLocked(); 84 manager->DoWorkLocked();
85 } 85 }
86 86
87 // Simple SynchronizedMinidumpManager consumer. Checks if a dump can be uploaded 87 // Simple SynchronizedMinidumpManager consumer. Checks if a dump can be uploaded
88 // then removes it from the lockfile. 88 // then removes it from the lockfile.
89 class FakeSynchronizedMinidumpUploader : public SynchronizedMinidumpManager { 89 class FakeSynchronizedMinidumpUploader : public SynchronizedMinidumpManager {
90 public: 90 public:
91 FakeSynchronizedMinidumpUploader() 91 FakeSynchronizedMinidumpUploader()
92 : SynchronizedMinidumpManager(), can_upload_return_val_(false) {} 92 : SynchronizedMinidumpManager(), can_upload_return_val_(false) {}
93 ~FakeSynchronizedMinidumpUploader() override {} 93 ~FakeSynchronizedMinidumpUploader() override {}
94 94
95 int DoWorkLocked() { return AcquireLockAndDoWork(); } 95 bool DoWorkLocked() { return AcquireLockAndDoWork(); }
96 96
97 // SynchronizedMinidumpManager implementation: 97 // SynchronizedMinidumpManager implementation:
98 int DoWork() override { 98 bool DoWork() override {
99 can_upload_return_val_ = CanUploadDump(); 99 can_upload_return_val_ = CanUploadDump();
100 100
101 if (RemoveEntryFromLockFile(0) < 0) 101 if (!RemoveEntryFromLockFile(0))
102 return -1; 102 return false;
103 103
104 if (IncrementNumDumpsInCurrentPeriod() < 0) 104 if (!IncrementNumDumpsInCurrentPeriod())
105 return -1; 105 return false;
106 106
107 return 0; 107 return true;
108 } 108 }
109 109
110 // Accessors for testing. 110 // Accessors for testing.
111 bool HasDumps() { return SynchronizedMinidumpManager::HasDumps(); } 111 bool HasDumps() { return SynchronizedMinidumpManager::HasDumps(); }
112 bool can_upload_return_val() { return can_upload_return_val_; } 112 bool can_upload_return_val() { return can_upload_return_val_; }
113 113
114 private: 114 private:
115 bool can_upload_return_val_; 115 bool can_upload_return_val_;
116 }; 116 };
117 117
118 class SleepySynchronizedMinidumpManagerSimple 118 class SleepySynchronizedMinidumpManagerSimple
119 : public SynchronizedMinidumpManagerSimple { 119 : public SynchronizedMinidumpManagerSimple {
120 public: 120 public:
121 SleepySynchronizedMinidumpManagerSimple(int sleep_duration_ms) 121 SleepySynchronizedMinidumpManagerSimple(int sleep_duration_ms)
122 : SynchronizedMinidumpManagerSimple(), 122 : SynchronizedMinidumpManagerSimple(),
123 sleep_duration_ms_(sleep_duration_ms) {} 123 sleep_duration_ms_(sleep_duration_ms) {}
124 ~SleepySynchronizedMinidumpManagerSimple() override {} 124 ~SleepySynchronizedMinidumpManagerSimple() override {}
125 125
126 // SynchronizedMinidumpManager implementation: 126 // SynchronizedMinidumpManager implementation:
127 int DoWork() override { 127 bool DoWork() override {
128 // The lock has been acquired. Fall asleep for |kSleepDurationMs|, then 128 // The lock has been acquired. Fall asleep for |kSleepDurationMs|, then
129 // write the file. 129 // write the file.
130 base::PlatformThread::Sleep( 130 base::PlatformThread::Sleep(
131 base::TimeDelta::FromMilliseconds(sleep_duration_ms_)); 131 base::TimeDelta::FromMilliseconds(sleep_duration_ms_));
132 return SynchronizedMinidumpManagerSimple::DoWork(); 132 return SynchronizedMinidumpManagerSimple::DoWork();
133 } 133 }
134 134
135 private: 135 private:
136 const int sleep_duration_ms_; 136 const int sleep_duration_ms_;
137 }; 137 };
(...skipping 29 matching lines...) Expand all
167 base::FilePath metadata_; // Path to the metadata in |minidump_dir_|. 167 base::FilePath metadata_; // Path to the metadata in |minidump_dir_|.
168 168
169 private: 169 private:
170 base::ScopedTempDir fake_home_dir_; 170 base::ScopedTempDir fake_home_dir_;
171 std::unique_ptr<base::ScopedPathOverride> path_override_; 171 std::unique_ptr<base::ScopedPathOverride> path_override_;
172 }; 172 };
173 173
174 // Have |producer| generate |num_dumps| while checking there are no errors. 174 // Have |producer| generate |num_dumps| while checking there are no errors.
175 void produce_dumps(SynchronizedMinidumpManagerSimple& producer, int num_dumps) { 175 void produce_dumps(SynchronizedMinidumpManagerSimple& producer, int num_dumps) {
176 for (int i = 0; i < num_dumps; ++i) { 176 for (int i = 0; i < num_dumps; ++i) {
177 ASSERT_EQ(0, producer.DoWorkLocked()); 177 ASSERT_TRUE(producer.DoWorkLocked());
178 ASSERT_EQ(0, producer.add_entry_return_code()); 178 ASSERT_TRUE(producer.add_entry_return_code());
179 } 179 }
180 } 180 }
181 181
182 // Have |consumer| remove and process |num_dumps| while checking there are no 182 // Have |consumer| remove and process |num_dumps| while checking there are no
183 // errors. 183 // errors.
184 void consume_dumps(FakeSynchronizedMinidumpUploader& consumer, int num_dumps) { 184 void consume_dumps(FakeSynchronizedMinidumpUploader& consumer, int num_dumps) {
185 for (int i = 0; i < num_dumps; ++i) { 185 for (int i = 0; i < num_dumps; ++i) {
186 ASSERT_EQ(0, consumer.DoWorkLocked()); 186 ASSERT_TRUE(consumer.DoWorkLocked());
187 ASSERT_TRUE(consumer.can_upload_return_val()); 187 ASSERT_TRUE(consumer.can_upload_return_val());
188 } 188 }
189 } 189 }
190 190
191 } // namespace 191 } // namespace
192 192
193 TEST_F(SynchronizedMinidumpManagerTest, FilePathsAreCorrect) { 193 TEST_F(SynchronizedMinidumpManagerTest, FilePathsAreCorrect) {
194 SynchronizedMinidumpManagerSimple manager; 194 SynchronizedMinidumpManagerSimple manager;
195 195
196 // Verify file paths for directory and lock file. 196 // Verify file paths for directory and lock file.
197 ASSERT_EQ(minidump_dir_.value(), manager.dump_path()); 197 ASSERT_EQ(minidump_dir_.value(), manager.dump_path());
198 ASSERT_EQ(lockfile_.value(), manager.lockfile_path()); 198 ASSERT_EQ(lockfile_.value(), manager.lockfile_path());
199 } 199 }
200 200
201 TEST_F(SynchronizedMinidumpManagerTest, AcquireLockOnNonExistentDirectory) { 201 TEST_F(SynchronizedMinidumpManagerTest, AcquireLockOnNonExistentDirectory) {
202 // The directory was created in SetUp(). Delete it and its contents. 202 // The directory was created in SetUp(). Delete it and its contents.
203 ASSERT_TRUE(base::DeleteFile(minidump_dir_, true)); 203 ASSERT_TRUE(base::DeleteFile(minidump_dir_, true));
204 ASSERT_FALSE(base::PathExists(minidump_dir_)); 204 ASSERT_FALSE(base::PathExists(minidump_dir_));
205 205
206 SynchronizedMinidumpManagerSimple manager; 206 SynchronizedMinidumpManagerSimple manager;
207 ASSERT_EQ(0, manager.DoWorkLocked()); 207 ASSERT_TRUE(manager.DoWorkLocked());
208 ASSERT_TRUE(manager.work_done()); 208 ASSERT_TRUE(manager.work_done());
209 209
210 // Verify the directory and the lockfile both exist. 210 // Verify the directory and the lockfile both exist.
211 ASSERT_TRUE(base::DirectoryExists(minidump_dir_)); 211 ASSERT_TRUE(base::DirectoryExists(minidump_dir_));
212 ASSERT_TRUE(base::PathExists(lockfile_)); 212 ASSERT_TRUE(base::PathExists(lockfile_));
213 } 213 }
214 214
215 TEST_F(SynchronizedMinidumpManagerTest, AcquireLockOnExistingEmptyDirectory) { 215 TEST_F(SynchronizedMinidumpManagerTest, AcquireLockOnExistingEmptyDirectory) {
216 // The lockfile was created in SetUp(). Delete it. 216 // The lockfile was created in SetUp(). Delete it.
217 ASSERT_TRUE(base::DeleteFile(lockfile_, false)); 217 ASSERT_TRUE(base::DeleteFile(lockfile_, false));
218 ASSERT_FALSE(base::PathExists(lockfile_)); 218 ASSERT_FALSE(base::PathExists(lockfile_));
219 219
220 SynchronizedMinidumpManagerSimple manager; 220 SynchronizedMinidumpManagerSimple manager;
221 ASSERT_EQ(0, manager.DoWorkLocked()); 221 ASSERT_TRUE(manager.DoWorkLocked());
222 ASSERT_TRUE(manager.work_done()); 222 ASSERT_TRUE(manager.work_done());
223 223
224 // Verify the directory and the lockfile both exist. 224 // Verify the directory and the lockfile both exist.
225 ASSERT_TRUE(base::DirectoryExists(minidump_dir_)); 225 ASSERT_TRUE(base::DirectoryExists(minidump_dir_));
226 ASSERT_TRUE(base::PathExists(lockfile_)); 226 ASSERT_TRUE(base::PathExists(lockfile_));
227 } 227 }
228 228
229 TEST_F(SynchronizedMinidumpManagerTest, 229 TEST_F(SynchronizedMinidumpManagerTest,
230 AcquireLockOnExistingDirectoryWithLockfile) { 230 AcquireLockOnExistingDirectoryWithLockfile) {
231 SynchronizedMinidumpManagerSimple manager; 231 SynchronizedMinidumpManagerSimple manager;
232 ASSERT_EQ(0, manager.DoWorkLocked()); 232 ASSERT_TRUE(manager.DoWorkLocked());
233 ASSERT_TRUE(manager.work_done()); 233 ASSERT_TRUE(manager.work_done());
234 234
235 // Verify the directory and the lockfile both exist. 235 // Verify the directory and the lockfile both exist.
236 ASSERT_TRUE(base::DirectoryExists(minidump_dir_)); 236 ASSERT_TRUE(base::DirectoryExists(minidump_dir_));
237 ASSERT_TRUE(base::PathExists(lockfile_)); 237 ASSERT_TRUE(base::PathExists(lockfile_));
238 } 238 }
239 239
240 TEST_F(SynchronizedMinidumpManagerTest, 240 TEST_F(SynchronizedMinidumpManagerTest,
241 AddEntryToLockFile_FailsWithInvalidEntry) { 241 AddEntryToLockFile_FailsWithInvalidEntry) {
242 // Create invalid dump info value 242 // Create invalid dump info value
243 base::DictionaryValue val; 243 base::DictionaryValue val;
244 244
245 // Test that the manager tried to log the entry and failed. 245 // Test that the manager tried to log the entry and failed.
246 SynchronizedMinidumpManagerSimple manager; 246 SynchronizedMinidumpManagerSimple manager;
247 manager.SetDumpInfoToWrite(base::WrapUnique(new DumpInfo(&val))); 247 manager.SetDumpInfoToWrite(base::WrapUnique(new DumpInfo(&val)));
248 ASSERT_EQ(0, manager.DoWorkLocked()); 248 ASSERT_TRUE(manager.DoWorkLocked());
249 ASSERT_EQ(-1, manager.add_entry_return_code()); 249 ASSERT_FALSE(manager.add_entry_return_code());
250 250
251 // Verify the lockfile is untouched. 251 // Verify the lockfile is untouched.
252 ScopedVector<DumpInfo> dumps; 252 ScopedVector<DumpInfo> dumps;
253 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps)); 253 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps));
254 ASSERT_EQ(0u, dumps.size()); 254 ASSERT_EQ(0u, dumps.size());
255 } 255 }
256 256
257 TEST_F(SynchronizedMinidumpManagerTest, 257 TEST_F(SynchronizedMinidumpManagerTest,
258 AddEntryToLockFile_SucceedsWithValidEntries) { 258 AddEntryToLockFile_SucceedsWithValidEntries) {
259 // Sample parameters. 259 // Sample parameters.
260 time_t now = time(0); 260 base::Time now = base::Time::Now();
261 MinidumpParams params; 261 MinidumpParams params;
262 params.process_name = "process"; 262 params.process_name = "process";
263 263
264 // Write the first entry. 264 // Write the first entry.
265 SynchronizedMinidumpManagerSimple manager; 265 SynchronizedMinidumpManagerSimple manager;
266 manager.SetDumpInfoToWrite( 266 manager.SetDumpInfoToWrite(
267 base::WrapUnique(new DumpInfo("dump1", "log1", now, params))); 267 base::WrapUnique(new DumpInfo("dump1", "log1", now, params)));
268 ASSERT_EQ(0, manager.DoWorkLocked()); 268 ASSERT_TRUE(manager.DoWorkLocked());
269 ASSERT_EQ(0, manager.add_entry_return_code()); 269 ASSERT_TRUE(manager.add_entry_return_code());
270 270
271 // Test that the manager was successful in logging the entry. 271 // Test that the manager was successful in logging the entry.
272 ScopedVector<DumpInfo> dumps; 272 ScopedVector<DumpInfo> dumps;
273 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps)); 273 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps));
274 ASSERT_EQ(1u, dumps.size()); 274 ASSERT_EQ(1u, dumps.size());
275 275
276 // Write the second entry. 276 // Write the second entry.
277 manager.SetDumpInfoToWrite( 277 manager.SetDumpInfoToWrite(
278 base::WrapUnique(new DumpInfo("dump2", "log2", now, params))); 278 base::WrapUnique(new DumpInfo("dump2", "log2", now, params)));
279 ASSERT_EQ(0, manager.DoWorkLocked()); 279 ASSERT_TRUE(manager.DoWorkLocked());
280 ASSERT_EQ(0, manager.add_entry_return_code()); 280 ASSERT_TRUE(manager.add_entry_return_code());
281 281
282 // Test that the second entry is also valid. 282 // Test that the second entry is also valid.
283 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps)); 283 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps));
284 ASSERT_EQ(2u, dumps.size()); 284 ASSERT_EQ(2u, dumps.size());
285 } 285 }
286 286
287 TEST_F(SynchronizedMinidumpManagerTest, 287 TEST_F(SynchronizedMinidumpManagerTest, AcquireLockFile_WaitsForOtherThread) {
288 AcquireLockFile_FailsWhenNonBlockingAndFileLocked) {
289 ASSERT_TRUE(CreateFiles(lockfile_.value(), metadata_.value()));
290 // Lock the lockfile here. Note that the Chromium base::File tools permit
291 // multiple locks on the same process to succeed, so we must use POSIX system
292 // calls to accomplish this.
293 int fd = open(lockfile_.value().c_str(), O_RDWR | O_CREAT, 0660);
294 ASSERT_GE(fd, 0);
295 ASSERT_EQ(0, flock(fd, LOCK_EX));
296
297 SynchronizedMinidumpManagerSimple manager;
298 manager.set_non_blocking(true);
299 ASSERT_EQ(-1, manager.DoWorkLocked());
300 ASSERT_FALSE(manager.work_done());
301
302 // Test that the manager was not able to log the crash dump.
303 ScopedVector<DumpInfo> dumps;
304 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps));
305 ASSERT_EQ(0u, dumps.size());
306 }
307
308 TEST_F(SynchronizedMinidumpManagerTest,
309 AcquireLockFile_WaitsForOtherThreadWhenBlocking) {
310 // Create some parameters for a minidump. 288 // Create some parameters for a minidump.
311 time_t now = time(0); 289 base::Time now = base::Time::Now();
312 MinidumpParams params; 290 MinidumpParams params;
313 params.process_name = "process"; 291 params.process_name = "process";
314 292
315 // Create a manager that grabs the lock then sleeps. Post a DoWork task to 293 // Create a manager that grabs the lock then sleeps. Post a DoWork task to
316 // another thread. |sleepy_manager| will grab the lock and hold it for 294 // another thread. |sleepy_manager| will grab the lock and hold it for
317 // |sleep_time_ms|. It will then write a dump and release the lock. 295 // |sleep_time_ms|. It will then write a dump and release the lock.
318 const int sleep_time_ms = 100; 296 const int sleep_time_ms = 100;
319 SleepySynchronizedMinidumpManagerSimple sleepy_manager(sleep_time_ms); 297 SleepySynchronizedMinidumpManagerSimple sleepy_manager(sleep_time_ms);
320 sleepy_manager.SetDumpInfoToWrite( 298 sleepy_manager.SetDumpInfoToWrite(
321 base::WrapUnique(new DumpInfo("dump", "log", now, params))); 299 base::WrapUnique(new DumpInfo("dump", "log", now, params)));
322 base::Thread sleepy_thread("sleepy"); 300 base::Thread sleepy_thread("sleepy");
323 sleepy_thread.Start(); 301 sleepy_thread.Start();
324 sleepy_thread.task_runner()->PostTask( 302 sleepy_thread.task_runner()->PostTask(
325 FROM_HERE, 303 FROM_HERE,
326 base::Bind(&DoWorkLockedTask, base::Unretained(&sleepy_manager))); 304 base::Bind(&DoWorkLockedTask, base::Unretained(&sleepy_manager)));
327 305
328 // Meanwhile, this thread should wait brielfy to allow the other thread to 306 // Meanwhile, this thread should wait brielfy to allow the other thread to
329 // grab the lock. 307 // grab the lock.
330 const int concurrency_delay = 50; 308 const int concurrency_delay = 50;
331 base::PlatformThread::Sleep( 309 base::PlatformThread::Sleep(
332 base::TimeDelta::FromMilliseconds(concurrency_delay)); 310 base::TimeDelta::FromMilliseconds(concurrency_delay));
333 311
334 // |sleepy_manager| has the lock by now, but has not released it. Attempt to 312 // |sleepy_manager| has the lock by now, but has not released it. Attempt to
335 // grab it. DoWorkLocked() should block until |manager| has a chance to write 313 // grab it. DoWorkLocked() should block until |manager| has a chance to write
336 // the dump. 314 // the dump.
337 SynchronizedMinidumpManagerSimple manager; 315 SynchronizedMinidumpManagerSimple manager;
338 manager.SetDumpInfoToWrite( 316 manager.SetDumpInfoToWrite(
339 base::WrapUnique(new DumpInfo("dump", "log", now, params))); 317 base::WrapUnique(new DumpInfo("dump", "log", now, params)));
340 manager.set_non_blocking(false);
341 318
342 EXPECT_EQ(0, manager.DoWorkLocked()); 319 EXPECT_TRUE(manager.DoWorkLocked());
343 EXPECT_EQ(0, manager.add_entry_return_code()); 320 EXPECT_TRUE(manager.add_entry_return_code());
344 EXPECT_TRUE(manager.work_done()); 321 EXPECT_TRUE(manager.work_done());
345 322
346 // Check that the other manager was also successful. 323 // Check that the other manager was also successful.
347 EXPECT_EQ(0, sleepy_manager.add_entry_return_code()); 324 EXPECT_TRUE(sleepy_manager.add_entry_return_code());
348 EXPECT_TRUE(sleepy_manager.work_done()); 325 EXPECT_TRUE(sleepy_manager.work_done());
349 326
350 // Test that both entries were logged. 327 // Test that both entries were logged.
351 ScopedVector<DumpInfo> dumps; 328 ScopedVector<DumpInfo> dumps;
352 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps)); 329 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps));
353 EXPECT_EQ(2u, dumps.size()); 330 EXPECT_EQ(2u, dumps.size());
354 } 331 }
355 332
356 // TODO(slan): These tests are passing but forking them is creating duplicates 333 // TODO(slan): These tests are passing but forking them is creating duplicates
357 // of all tests in this thread. Figure out how to lock the file more cleanly 334 // of all tests in this thread. Figure out how to lock the file more cleanly
358 // from another process. 335 // from another process.
359 TEST_F(SynchronizedMinidumpManagerTest, 336 TEST_F(SynchronizedMinidumpManagerTest,
360 DISABLED_AcquireLockFile_FailsWhenNonBlockingAndLockedFromOtherProcess) { 337 DISABLED_AcquireLockFile_WaitsForOtherProcess) {
361 // Fork the process.
362 pid_t pid = base::ForkWithFlags(0u, nullptr, nullptr);
363 if (pid != 0) {
364 // The child process should instantiate a manager which immediately grabs
365 // the lock, and falls aleep for some period of time, then writes a dump,
366 // and finally releases the lock.
367 SleepySynchronizedMinidumpManagerSimple sleepy_manager(100);
368 ASSERT_EQ(0, sleepy_manager.DoWorkLocked());
369 ASSERT_TRUE(sleepy_manager.work_done());
370 return;
371 }
372
373 // Meanwhile, this process should wait brielfy to allow the other thread to
374 // grab the lock.
375 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50));
376
377 SynchronizedMinidumpManagerSimple manager;
378 manager.set_non_blocking(true);
379 ASSERT_EQ(-1, manager.DoWorkLocked());
380 ASSERT_FALSE(manager.work_done());
381
382 // Test that the manager was not able to log the crash dump.
383 ScopedVector<DumpInfo> dumps;
384 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps));
385 ASSERT_EQ(0u, dumps.size());
386 }
387
388 // TODO(slan): These tests are passing but forking them is creating duplicates
389 // of all tests in this thread. Figure out how to lock the file more cleanly
390 // from another process.
391 TEST_F(SynchronizedMinidumpManagerTest,
392 DISABLED_AcquireLockFile_WaitsForOtherProcessWhenBlocking) {
393 // Create some parameters for a minidump. 338 // Create some parameters for a minidump.
394 time_t now = time(0); 339 base::Time now = base::Time::Now();
395 MinidumpParams params; 340 MinidumpParams params;
396 params.process_name = "process"; 341 params.process_name = "process";
397 342
398 // Fork the process. 343 // Fork the process.
399 pid_t pid = base::ForkWithFlags(0u, nullptr, nullptr); 344 pid_t pid = base::ForkWithFlags(0u, nullptr, nullptr);
400 if (pid != 0) { 345 if (pid != 0) {
401 // The child process should instantiate a manager which immediately grabs 346 // The child process should instantiate a manager which immediately grabs
402 // the lock, and falls aleep for some period of time, then writes a dump, 347 // the lock, and falls aleep for some period of time, then writes a dump,
403 // and finally releases the lock. 348 // and finally releases the lock.
404 SleepySynchronizedMinidumpManagerSimple sleepy_manager(100); 349 SleepySynchronizedMinidumpManagerSimple sleepy_manager(100);
405 sleepy_manager.SetDumpInfoToWrite( 350 sleepy_manager.SetDumpInfoToWrite(
406 base::WrapUnique(new DumpInfo("dump", "log", now, params))); 351 base::WrapUnique(new DumpInfo("dump", "log", now, params)));
407 ASSERT_EQ(0, sleepy_manager.DoWorkLocked()); 352 ASSERT_TRUE(sleepy_manager.DoWorkLocked());
408 ASSERT_TRUE(sleepy_manager.work_done()); 353 ASSERT_TRUE(sleepy_manager.work_done());
409 return; 354 return;
410 } 355 }
411 356
412 // Meanwhile, this process should wait brielfy to allow the other thread to 357 // Meanwhile, this process should wait brielfy to allow the other thread to
413 // grab the lock. 358 // grab the lock.
414 const int concurrency_delay = 50; 359 const int concurrency_delay = 50;
415 base::PlatformThread::Sleep( 360 base::PlatformThread::Sleep(
416 base::TimeDelta::FromMilliseconds(concurrency_delay)); 361 base::TimeDelta::FromMilliseconds(concurrency_delay));
417 362
418 // |sleepy_manager| has the lock by now, but has not released it. Attempt to 363 // |sleepy_manager| has the lock by now, but has not released it. Attempt to
419 // grab it. DoWorkLocked() should block until |manager| has a chance to write 364 // grab it. DoWorkLocked() should block until |manager| has a chance to write
420 // the dump. 365 // the dump.
421 SynchronizedMinidumpManagerSimple manager; 366 SynchronizedMinidumpManagerSimple manager;
422 manager.SetDumpInfoToWrite( 367 manager.SetDumpInfoToWrite(
423 base::WrapUnique(new DumpInfo("dump", "log", now, params))); 368 base::WrapUnique(new DumpInfo("dump", "log", now, params)));
424 manager.set_non_blocking(false);
425 369
426 EXPECT_EQ(0, manager.DoWorkLocked()); 370 EXPECT_TRUE(manager.DoWorkLocked());
427 EXPECT_EQ(0, manager.add_entry_return_code()); 371 EXPECT_TRUE(manager.add_entry_return_code());
428 EXPECT_TRUE(manager.work_done()); 372 EXPECT_TRUE(manager.work_done());
429 373
430 // Test that both entries were logged. 374 // Test that both entries were logged.
431 ScopedVector<DumpInfo> dumps; 375 ScopedVector<DumpInfo> dumps;
432 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps)); 376 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps));
433 EXPECT_EQ(2u, dumps.size()); 377 EXPECT_EQ(2u, dumps.size());
434 } 378 }
435 379
436 TEST_F(SynchronizedMinidumpManagerTest, 380 TEST_F(SynchronizedMinidumpManagerTest,
437 Upload_SucceedsWhenDumpLimitsNotExceeded) { 381 Upload_SucceedsWhenDumpLimitsNotExceeded) {
438 // Sample parameters. 382 // Sample parameters.
439 time_t now = time(0); 383 base::Time now = base::Time::Now();
440 MinidumpParams params; 384 MinidumpParams params;
441 params.process_name = "process"; 385 params.process_name = "process";
442 386
443 FakeSynchronizedMinidumpUploader uploader; 387 FakeSynchronizedMinidumpUploader uploader;
444 SynchronizedMinidumpManagerSimple producer; 388 SynchronizedMinidumpManagerSimple producer;
445 producer.SetDumpInfoToWrite( 389 producer.SetDumpInfoToWrite(
446 base::WrapUnique(new DumpInfo("dump1", "log1", now, params))); 390 base::WrapUnique(new DumpInfo("dump1", "log1", now, params)));
447 391
448 const int max_dumps = SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps; 392 const int max_dumps = SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps;
449 produce_dumps(producer, max_dumps); 393 produce_dumps(producer, max_dumps);
450 consume_dumps(uploader, max_dumps); 394 consume_dumps(uploader, max_dumps);
451 } 395 }
452 396
453 TEST_F(SynchronizedMinidumpManagerTest, Upload_FailsWhenTooManyRecentDumps) { 397 TEST_F(SynchronizedMinidumpManagerTest, Upload_FailsWhenTooManyRecentDumps) {
454 // Sample parameters. 398 // Sample parameters.
455 time_t now = time(0); 399 base::Time now = base::Time::Now();
456 MinidumpParams params; 400 MinidumpParams params;
457 params.process_name = "process"; 401 params.process_name = "process";
458 402
459 FakeSynchronizedMinidumpUploader uploader; 403 FakeSynchronizedMinidumpUploader uploader;
460 SynchronizedMinidumpManagerSimple producer; 404 SynchronizedMinidumpManagerSimple producer;
461 producer.SetDumpInfoToWrite( 405 producer.SetDumpInfoToWrite(
462 base::WrapUnique(new DumpInfo("dump1", "log1", now, params))); 406 base::WrapUnique(new DumpInfo("dump1", "log1", now, params)));
463 407
464 const int max_dumps = SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps; 408 const int max_dumps = SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps;
465 produce_dumps(producer, max_dumps + 1); 409 produce_dumps(producer, max_dumps + 1);
466 consume_dumps(uploader, max_dumps); 410 consume_dumps(uploader, max_dumps);
467 411
468 // Should fail with too many dumps 412 // Should fail with too many dumps
469 ASSERT_EQ(0, uploader.DoWorkLocked()); 413 ASSERT_TRUE(uploader.DoWorkLocked());
470 ASSERT_FALSE(uploader.can_upload_return_val()); 414 ASSERT_FALSE(uploader.can_upload_return_val());
471 } 415 }
472 416
473 TEST_F(SynchronizedMinidumpManagerTest, UploadSucceedsAfterRateLimitPeriodEnd) { 417 TEST_F(SynchronizedMinidumpManagerTest, UploadSucceedsAfterRateLimitPeriodEnd) {
474 // Sample parameters. 418 // Sample parameters.
475 time_t now = time(0); 419 base::Time now = base::Time::Now();
476 MinidumpParams params; 420 MinidumpParams params;
477 params.process_name = "process"; 421 params.process_name = "process";
478 422
479 FakeSynchronizedMinidumpUploader uploader; 423 FakeSynchronizedMinidumpUploader uploader;
480 SynchronizedMinidumpManagerSimple producer; 424 SynchronizedMinidumpManagerSimple producer;
481 producer.SetDumpInfoToWrite( 425 producer.SetDumpInfoToWrite(
482 base::WrapUnique(new DumpInfo("dump1", "log1", now, params))); 426 base::WrapUnique(new DumpInfo("dump1", "log1", now, params)));
483 427
484 const int iters = 3; 428 const int iters = 3;
485 const int max_dumps = SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps; 429 const int max_dumps = SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps;
486 430
487 for (int i = 0; i < iters; ++i) { 431 for (int i = 0; i < iters; ++i) {
488 produce_dumps(producer, max_dumps + 1); 432 produce_dumps(producer, max_dumps + 1);
489 consume_dumps(uploader, max_dumps); 433 consume_dumps(uploader, max_dumps);
490 434
491 // Should fail with too many dumps 435 // Should fail with too many dumps
492 ASSERT_EQ(0, uploader.DoWorkLocked()); 436 ASSERT_TRUE(uploader.DoWorkLocked());
493 ASSERT_FALSE(uploader.can_upload_return_val()); 437 ASSERT_FALSE(uploader.can_upload_return_val());
494 438
495 int64_t period = SynchronizedMinidumpManager::kRatelimitPeriodSeconds; 439 base::TimeDelta period = base::TimeDelta::FromSeconds(
440 SynchronizedMinidumpManager::kRatelimitPeriodSeconds);
441 base::Time now = base::Time::Now();
496 442
497 // Half period shouldn't trigger reset 443 // Half period shouldn't trigger reset
498 produce_dumps(producer, 1); 444 produce_dumps(producer, 1);
499 SetRatelimitPeriodStart(metadata_.value(), now - period / 2); 445 SetRatelimitPeriodStart(metadata_.value(), now - period / 2);
500 ASSERT_EQ(0, uploader.DoWorkLocked()); 446 ASSERT_TRUE(uploader.DoWorkLocked());
501 ASSERT_FALSE(uploader.can_upload_return_val()); 447 ASSERT_FALSE(uploader.can_upload_return_val());
502 448
503 // Set period starting time to trigger a reset 449 // Set period starting time to trigger a reset
504 SetRatelimitPeriodStart(metadata_.value(), now - period); 450 SetRatelimitPeriodStart(metadata_.value(), now - period);
505 } 451 }
506 452
507 produce_dumps(producer, 1); 453 produce_dumps(producer, 1);
508 consume_dumps(uploader, 1); 454 consume_dumps(uploader, 1);
509 } 455 }
510 456
511 TEST_F(SynchronizedMinidumpManagerTest, HasDumpsWithoutDumps) { 457 TEST_F(SynchronizedMinidumpManagerTest, HasDumpsWithoutDumps) {
512 FakeSynchronizedMinidumpUploader uploader; 458 FakeSynchronizedMinidumpUploader uploader;
513 ASSERT_FALSE(uploader.HasDumps()); 459 ASSERT_FALSE(uploader.HasDumps());
514 } 460 }
515 461
516 TEST_F(SynchronizedMinidumpManagerTest, HasDumpsWithDumps) { 462 TEST_F(SynchronizedMinidumpManagerTest, HasDumpsWithDumps) {
517 // Sample parameters. 463 // Sample parameters.
518 time_t now = time(0); 464 base::Time now = base::Time::Now();
519 MinidumpParams params; 465 MinidumpParams params;
520 params.process_name = "process"; 466 params.process_name = "process";
521 467
522 SynchronizedMinidumpManagerSimple producer; 468 SynchronizedMinidumpManagerSimple producer;
523 FakeSynchronizedMinidumpUploader uploader; 469 FakeSynchronizedMinidumpUploader uploader;
524 470
525 producer.SetDumpInfoToWrite( 471 producer.SetDumpInfoToWrite(
526 base::WrapUnique(new DumpInfo("dump1", "log1", now, params))); 472 base::WrapUnique(new DumpInfo("dump1", "log1", now, params)));
527 473
528 const int kNumDumps = 3; 474 const int kNumDumps = 3;
(...skipping 18 matching lines...) Expand all
547 const base::FilePath path = 493 const base::FilePath path =
548 base::FilePath(manager.dump_path()).Append("hello123"); 494 base::FilePath(manager.dump_path()).Append("hello123");
549 const char kFileContents[] = "foobar"; 495 const char kFileContents[] = "foobar";
550 ASSERT_EQ(static_cast<int>(sizeof(kFileContents)), 496 ASSERT_EQ(static_cast<int>(sizeof(kFileContents)),
551 WriteFile(path, kFileContents, sizeof(kFileContents))); 497 WriteFile(path, kFileContents, sizeof(kFileContents)));
552 498
553 ASSERT_TRUE(manager.HasDumps()); 499 ASSERT_TRUE(manager.HasDumps());
554 } 500 }
555 501
556 } // namespace chromecast 502 } // namespace chromecast
OLDNEW
« no previous file with comments | « chromecast/crash/linux/synchronized_minidump_manager.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698