| Index: chromecast/crash/linux/minidump_manager_unittest.cc
|
| diff --git a/chromecast/crash/linux/minidump_manager_unittest.cc b/chromecast/crash/linux/minidump_manager_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b871c8db1be157e1922c4236e94a90ccca3dec18
|
| --- /dev/null
|
| +++ b/chromecast/crash/linux/minidump_manager_unittest.cc
|
| @@ -0,0 +1,169 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <stdlib.h>
|
| +#include <sys/stat.h> // mkdir
|
| +#include <stdio.h> // perror
|
| +#include <time.h>
|
| +
|
| +#include "base/base_paths.h"
|
| +#include "base/files/file.h"
|
| +#include "base/files/file_util.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "base/process/launch.h"
|
| +#include "base/test/scoped_path_override.h"
|
| +#include "base/threading/platform_thread.h"
|
| +#include "chromecast/crash/linux/minidump_manager.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace chromecast {
|
| +namespace {
|
| +
|
| +const char kLockfileName[] = "lockfile";
|
| +const char kMinidumpSubdir[] = "minidumps";
|
| +
|
| +// A trivial implementation of MinidumpManager, which does no work to the
|
| +// minidump and exposes its protected members for testing.
|
| +class MinidumpManagerSimple : public MinidumpManager {
|
| + public:
|
| + MinidumpManagerSimple() : MinidumpManager(), work_done_(false) {}
|
| + ~MinidumpManagerSimple() override {}
|
| +
|
| + // MinidumpManager implementation:
|
| + int DoWork() override {
|
| + work_done_ = true;
|
| + return 0;
|
| + }
|
| +
|
| + // Accessors for testing.
|
| + const std::string& dump_path() { return dump_path_; }
|
| + const std::string& lockfile_path() { return lockfile_path_; }
|
| + bool work_done() { return work_done_; }
|
| +
|
| + private:
|
| + bool work_done_;
|
| +};
|
| +
|
| +class MinidumpManagerTest : public testing::Test {
|
| + public:
|
| + MinidumpManagerTest() {}
|
| + ~MinidumpManagerTest() override {}
|
| +
|
| + void SetUp() override {
|
| + // Set up a temporary directory which will be used as our fake home dir.
|
| + ASSERT_TRUE(base::CreateNewTempDirectory("", &fake_home_dir_));
|
| + path_override_.reset(
|
| + new base::ScopedPathOverride(base::DIR_HOME, fake_home_dir_));
|
| + minidump_dir_ = fake_home_dir_.Append(kMinidumpSubdir);
|
| + }
|
| +
|
| + void TearDown() override {
|
| + // Remove the temp directory.
|
| + path_override_.reset();
|
| + ASSERT_TRUE(base::DeleteFile(fake_home_dir_, true));
|
| + }
|
| +
|
| + protected:
|
| + base::FilePath
|
| + fake_home_dir_; // Path to the home directory used for the test.
|
| + base::FilePath minidump_dir_; // Path the the minidump directory.
|
| +
|
| + private:
|
| + scoped_ptr<base::ScopedPathOverride> path_override_;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +TEST_F(MinidumpManagerTest, FilePathsAreCorrect) {
|
| + MinidumpManagerSimple manager;
|
| +
|
| + // Verify file paths for directory and lock file.
|
| + ASSERT_EQ(minidump_dir_.value(), manager.dump_path());
|
| + ASSERT_EQ(minidump_dir_.Append(kLockfileName).value(),
|
| + manager.lockfile_path());
|
| +}
|
| +
|
| +TEST_F(MinidumpManagerTest, AcquireLockOnNonExistentDirectory) {
|
| + // Create the manager and do the minidump work.
|
| + MinidumpManagerSimple manager;
|
| + ASSERT_EQ(0, manager.DoWorkLocked());
|
| + ASSERT_TRUE(manager.work_done());
|
| +
|
| + // Verify the directory and the lockfile both exist.
|
| + ASSERT_TRUE(base::DirectoryExists(minidump_dir_));
|
| + ASSERT_TRUE(base::PathExists(minidump_dir_.Append(kLockfileName)));
|
| +}
|
| +
|
| +TEST_F(MinidumpManagerTest, AcquireLockOnExistingEmptyDirectory) {
|
| + // Create the empty minidump directory.
|
| + ASSERT_TRUE(base::CreateDirectory(minidump_dir_));
|
| + ASSERT_TRUE(base::IsDirectoryEmpty(minidump_dir_));
|
| +
|
| + MinidumpManagerSimple manager;
|
| + ASSERT_EQ(0, manager.DoWorkLocked());
|
| + ASSERT_TRUE(manager.work_done());
|
| +
|
| + // Verify the directory and the lockfile both exist.
|
| + ASSERT_TRUE(base::DirectoryExists(minidump_dir_));
|
| + ASSERT_TRUE(base::PathExists(minidump_dir_.Append(kLockfileName)));
|
| +}
|
| +
|
| +TEST_F(MinidumpManagerTest, AcquireLockOnExistingDirectoryWithLockfile) {
|
| + // Create a minidump directory.
|
| + ASSERT_TRUE(base::CreateDirectory(minidump_dir_));
|
| + ASSERT_TRUE(base::IsDirectoryEmpty(minidump_dir_));
|
| +
|
| + // Create a lockfile in that directory.
|
| + base::File lockfile(minidump_dir_.Append(kLockfileName),
|
| + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
|
| + ASSERT_TRUE(lockfile.IsValid());
|
| +
|
| + MinidumpManagerSimple manager;
|
| + ASSERT_EQ(0, manager.DoWorkLocked());
|
| + ASSERT_TRUE(manager.work_done());
|
| +
|
| + // Verify the directory and the lockfile both exist.
|
| + ASSERT_TRUE(base::DirectoryExists(minidump_dir_));
|
| + ASSERT_TRUE(base::PathExists(minidump_dir_.Append(kLockfileName)));
|
| +}
|
| +
|
| +TEST_F(MinidumpManagerTest, DISABLED_DoNotBlockOnAcquiringLock) {
|
| + // TODO(slan): Determine how to lock the lockfile before attempting to
|
| + // aquire lock on it from this process, and test that this thread does not
|
| + // block.
|
| +
|
| + // Create a minidump directory.
|
| + ASSERT_TRUE(base::CreateDirectory(minidump_dir_));
|
| + ASSERT_TRUE(base::IsDirectoryEmpty(minidump_dir_));
|
| +
|
| + // Create a lockfile in that directory.
|
| + base::File lockfile(minidump_dir_.Append(kLockfileName),
|
| + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
|
| + ASSERT_TRUE(lockfile.IsValid());
|
| +
|
| + // Fork the process.
|
| + pid_t pid = base::ForkWithFlags(0u, nullptr, nullptr);
|
| + if (pid != 0) {
|
| + // The child process should hold a lock on the file for 20ms then exit.
|
| + lockfile.Lock();
|
| + base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1000));
|
| + lockfile.Unlock();
|
| + return;
|
| + }
|
| +
|
| + // The parent process should attempt to grab the lock after 10ms, fail
|
| + // immediately, and exit imediately.
|
| + base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(500));
|
| +
|
| + MinidumpManagerSimple manager;
|
| + manager.SetNonblocking(true);
|
| + ASSERT_EQ(-1, manager.DoWorkLocked());
|
| + ASSERT_FALSE(manager.work_done());
|
| +
|
| + // Verify the directory and the lockfile both exist.
|
| + ASSERT_TRUE(base::DirectoryExists(minidump_dir_));
|
| + ASSERT_TRUE(base::PathExists(minidump_dir_.Append(kLockfileName)));
|
| +}
|
| +
|
| +} // namespace chromecast
|
|
|