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

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: bcf@ 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
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 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
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_EQ(0, manager.DoWorkLocked());
269 ASSERT_EQ(0, manager.add_entry_return_code()); 269 ASSERT_EQ(0, 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_EQ(0, manager.DoWorkLocked());
280 ASSERT_EQ(0, manager.add_entry_return_code()); 280 ASSERT_EQ(0, 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,
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) { 288 AcquireLockFile_WaitsForOtherThreadWhenBlocking) {
310 // Create some parameters for a minidump. 289 // Create some parameters for a minidump.
311 time_t now = time(0); 290 base::Time now = base::Time::Now();
312 MinidumpParams params; 291 MinidumpParams params;
313 params.process_name = "process"; 292 params.process_name = "process";
314 293
315 // Create a manager that grabs the lock then sleeps. Post a DoWork task to 294 // 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 295 // 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. 296 // |sleep_time_ms|. It will then write a dump and release the lock.
318 const int sleep_time_ms = 100; 297 const int sleep_time_ms = 100;
319 SleepySynchronizedMinidumpManagerSimple sleepy_manager(sleep_time_ms); 298 SleepySynchronizedMinidumpManagerSimple sleepy_manager(sleep_time_ms);
320 sleepy_manager.SetDumpInfoToWrite( 299 sleepy_manager.SetDumpInfoToWrite(
321 base::WrapUnique(new DumpInfo("dump", "log", now, params))); 300 base::WrapUnique(new DumpInfo("dump", "log", now, params)));
322 base::Thread sleepy_thread("sleepy"); 301 base::Thread sleepy_thread("sleepy");
323 sleepy_thread.Start(); 302 sleepy_thread.Start();
324 sleepy_thread.task_runner()->PostTask( 303 sleepy_thread.task_runner()->PostTask(
325 FROM_HERE, 304 FROM_HERE,
326 base::Bind(&DoWorkLockedTask, base::Unretained(&sleepy_manager))); 305 base::Bind(&DoWorkLockedTask, base::Unretained(&sleepy_manager)));
327 306
328 // Meanwhile, this thread should wait brielfy to allow the other thread to 307 // Meanwhile, this thread should wait brielfy to allow the other thread to
329 // grab the lock. 308 // grab the lock.
330 const int concurrency_delay = 50; 309 const int concurrency_delay = 50;
331 base::PlatformThread::Sleep( 310 base::PlatformThread::Sleep(
332 base::TimeDelta::FromMilliseconds(concurrency_delay)); 311 base::TimeDelta::FromMilliseconds(concurrency_delay));
333 312
334 // |sleepy_manager| has the lock by now, but has not released it. Attempt to 313 // |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 314 // grab it. DoWorkLocked() should block until |manager| has a chance to write
336 // the dump. 315 // the dump.
337 SynchronizedMinidumpManagerSimple manager; 316 SynchronizedMinidumpManagerSimple manager;
338 manager.SetDumpInfoToWrite( 317 manager.SetDumpInfoToWrite(
339 base::WrapUnique(new DumpInfo("dump", "log", now, params))); 318 base::WrapUnique(new DumpInfo("dump", "log", now, params)));
340 manager.set_non_blocking(false);
341 319
342 EXPECT_EQ(0, manager.DoWorkLocked()); 320 EXPECT_EQ(0, manager.DoWorkLocked());
343 EXPECT_EQ(0, manager.add_entry_return_code()); 321 EXPECT_EQ(0, manager.add_entry_return_code());
344 EXPECT_TRUE(manager.work_done()); 322 EXPECT_TRUE(manager.work_done());
345 323
346 // Check that the other manager was also successful. 324 // Check that the other manager was also successful.
347 EXPECT_EQ(0, sleepy_manager.add_entry_return_code()); 325 EXPECT_EQ(0, sleepy_manager.add_entry_return_code());
348 EXPECT_TRUE(sleepy_manager.work_done()); 326 EXPECT_TRUE(sleepy_manager.work_done());
349 327
350 // Test that both entries were logged. 328 // Test that both entries were logged.
351 ScopedVector<DumpInfo> dumps; 329 ScopedVector<DumpInfo> dumps;
352 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps)); 330 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps));
353 EXPECT_EQ(2u, dumps.size()); 331 EXPECT_EQ(2u, dumps.size());
354 } 332 }
355 333
356 // TODO(slan): These tests are passing but forking them is creating duplicates 334 // 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 335 // of all tests in this thread. Figure out how to lock the file more cleanly
358 // from another process. 336 // from another process.
359 TEST_F(SynchronizedMinidumpManagerTest, 337 TEST_F(SynchronizedMinidumpManagerTest,
360 DISABLED_AcquireLockFile_FailsWhenNonBlockingAndLockedFromOtherProcess) {
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) { 338 DISABLED_AcquireLockFile_WaitsForOtherProcessWhenBlocking) {
393 // Create some parameters for a minidump. 339 // Create some parameters for a minidump.
394 time_t now = time(0); 340 base::Time now = base::Time::Now();
395 MinidumpParams params; 341 MinidumpParams params;
396 params.process_name = "process"; 342 params.process_name = "process";
397 343
398 // Fork the process. 344 // Fork the process.
399 pid_t pid = base::ForkWithFlags(0u, nullptr, nullptr); 345 pid_t pid = base::ForkWithFlags(0u, nullptr, nullptr);
400 if (pid != 0) { 346 if (pid != 0) {
401 // The child process should instantiate a manager which immediately grabs 347 // 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, 348 // the lock, and falls aleep for some period of time, then writes a dump,
403 // and finally releases the lock. 349 // and finally releases the lock.
404 SleepySynchronizedMinidumpManagerSimple sleepy_manager(100); 350 SleepySynchronizedMinidumpManagerSimple sleepy_manager(100);
405 sleepy_manager.SetDumpInfoToWrite( 351 sleepy_manager.SetDumpInfoToWrite(
406 base::WrapUnique(new DumpInfo("dump", "log", now, params))); 352 base::WrapUnique(new DumpInfo("dump", "log", now, params)));
407 ASSERT_EQ(0, sleepy_manager.DoWorkLocked()); 353 ASSERT_EQ(0, sleepy_manager.DoWorkLocked());
408 ASSERT_TRUE(sleepy_manager.work_done()); 354 ASSERT_TRUE(sleepy_manager.work_done());
409 return; 355 return;
410 } 356 }
411 357
412 // Meanwhile, this process should wait brielfy to allow the other thread to 358 // Meanwhile, this process should wait brielfy to allow the other thread to
413 // grab the lock. 359 // grab the lock.
414 const int concurrency_delay = 50; 360 const int concurrency_delay = 50;
415 base::PlatformThread::Sleep( 361 base::PlatformThread::Sleep(
416 base::TimeDelta::FromMilliseconds(concurrency_delay)); 362 base::TimeDelta::FromMilliseconds(concurrency_delay));
417 363
418 // |sleepy_manager| has the lock by now, but has not released it. Attempt to 364 // |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 365 // grab it. DoWorkLocked() should block until |manager| has a chance to write
420 // the dump. 366 // the dump.
421 SynchronizedMinidumpManagerSimple manager; 367 SynchronizedMinidumpManagerSimple manager;
422 manager.SetDumpInfoToWrite( 368 manager.SetDumpInfoToWrite(
423 base::WrapUnique(new DumpInfo("dump", "log", now, params))); 369 base::WrapUnique(new DumpInfo("dump", "log", now, params)));
424 manager.set_non_blocking(false);
425 370
426 EXPECT_EQ(0, manager.DoWorkLocked()); 371 EXPECT_EQ(0, manager.DoWorkLocked());
427 EXPECT_EQ(0, manager.add_entry_return_code()); 372 EXPECT_EQ(0, manager.add_entry_return_code());
428 EXPECT_TRUE(manager.work_done()); 373 EXPECT_TRUE(manager.work_done());
429 374
430 // Test that both entries were logged. 375 // Test that both entries were logged.
431 ScopedVector<DumpInfo> dumps; 376 ScopedVector<DumpInfo> dumps;
432 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps)); 377 ASSERT_TRUE(FetchDumps(lockfile_.value(), &dumps));
433 EXPECT_EQ(2u, dumps.size()); 378 EXPECT_EQ(2u, dumps.size());
434 } 379 }
435 380
436 TEST_F(SynchronizedMinidumpManagerTest, 381 TEST_F(SynchronizedMinidumpManagerTest,
437 Upload_SucceedsWhenDumpLimitsNotExceeded) { 382 Upload_SucceedsWhenDumpLimitsNotExceeded) {
438 // Sample parameters. 383 // Sample parameters.
439 time_t now = time(0); 384 base::Time now = base::Time::Now();
440 MinidumpParams params; 385 MinidumpParams params;
441 params.process_name = "process"; 386 params.process_name = "process";
442 387
443 FakeSynchronizedMinidumpUploader uploader; 388 FakeSynchronizedMinidumpUploader uploader;
444 SynchronizedMinidumpManagerSimple producer; 389 SynchronizedMinidumpManagerSimple producer;
445 producer.SetDumpInfoToWrite( 390 producer.SetDumpInfoToWrite(
446 base::WrapUnique(new DumpInfo("dump1", "log1", now, params))); 391 base::WrapUnique(new DumpInfo("dump1", "log1", now, params)));
447 392
448 const int max_dumps = SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps; 393 const int max_dumps = SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps;
449 produce_dumps(producer, max_dumps); 394 produce_dumps(producer, max_dumps);
450 consume_dumps(uploader, max_dumps); 395 consume_dumps(uploader, max_dumps);
451 } 396 }
452 397
453 TEST_F(SynchronizedMinidumpManagerTest, Upload_FailsWhenTooManyRecentDumps) { 398 TEST_F(SynchronizedMinidumpManagerTest, Upload_FailsWhenTooManyRecentDumps) {
454 // Sample parameters. 399 // Sample parameters.
455 time_t now = time(0); 400 base::Time now = base::Time::Now();
456 MinidumpParams params; 401 MinidumpParams params;
457 params.process_name = "process"; 402 params.process_name = "process";
458 403
459 FakeSynchronizedMinidumpUploader uploader; 404 FakeSynchronizedMinidumpUploader uploader;
460 SynchronizedMinidumpManagerSimple producer; 405 SynchronizedMinidumpManagerSimple producer;
461 producer.SetDumpInfoToWrite( 406 producer.SetDumpInfoToWrite(
462 base::WrapUnique(new DumpInfo("dump1", "log1", now, params))); 407 base::WrapUnique(new DumpInfo("dump1", "log1", now, params)));
463 408
464 const int max_dumps = SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps; 409 const int max_dumps = SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps;
465 produce_dumps(producer, max_dumps + 1); 410 produce_dumps(producer, max_dumps + 1);
466 consume_dumps(uploader, max_dumps); 411 consume_dumps(uploader, max_dumps);
467 412
468 // Should fail with too many dumps 413 // Should fail with too many dumps
469 ASSERT_EQ(0, uploader.DoWorkLocked()); 414 ASSERT_EQ(0, uploader.DoWorkLocked());
470 ASSERT_FALSE(uploader.can_upload_return_val()); 415 ASSERT_FALSE(uploader.can_upload_return_val());
471 } 416 }
472 417
473 TEST_F(SynchronizedMinidumpManagerTest, UploadSucceedsAfterRateLimitPeriodEnd) { 418 TEST_F(SynchronizedMinidumpManagerTest, UploadSucceedsAfterRateLimitPeriodEnd) {
474 // Sample parameters. 419 // Sample parameters.
475 time_t now = time(0); 420 base::Time now = base::Time::Now();
476 MinidumpParams params; 421 MinidumpParams params;
477 params.process_name = "process"; 422 params.process_name = "process";
478 423
479 FakeSynchronizedMinidumpUploader uploader; 424 FakeSynchronizedMinidumpUploader uploader;
480 SynchronizedMinidumpManagerSimple producer; 425 SynchronizedMinidumpManagerSimple producer;
481 producer.SetDumpInfoToWrite( 426 producer.SetDumpInfoToWrite(
482 base::WrapUnique(new DumpInfo("dump1", "log1", now, params))); 427 base::WrapUnique(new DumpInfo("dump1", "log1", now, params)));
483 428
484 const int iters = 3; 429 const int iters = 3;
485 const int max_dumps = SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps; 430 const int max_dumps = SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps;
486 431
487 for (int i = 0; i < iters; ++i) { 432 for (int i = 0; i < iters; ++i) {
488 produce_dumps(producer, max_dumps + 1); 433 produce_dumps(producer, max_dumps + 1);
489 consume_dumps(uploader, max_dumps); 434 consume_dumps(uploader, max_dumps);
490 435
491 // Should fail with too many dumps 436 // Should fail with too many dumps
492 ASSERT_EQ(0, uploader.DoWorkLocked()); 437 ASSERT_EQ(0, uploader.DoWorkLocked());
493 ASSERT_FALSE(uploader.can_upload_return_val()); 438 ASSERT_FALSE(uploader.can_upload_return_val());
494 439
495 int64_t period = SynchronizedMinidumpManager::kRatelimitPeriodSeconds; 440 int64_t period = SynchronizedMinidumpManager::kRatelimitPeriodSeconds;
441 time_t now_time_t = now.ToTimeT();
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_time_t - period / 2);
500 ASSERT_EQ(0, uploader.DoWorkLocked()); 446 ASSERT_EQ(0, 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_time_t - 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
« chromecast/base/file_utils.cc ('K') | « 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