Commit 13d89167 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

Modernize unittest for cancelable tasks

1) Use own test fixture {CancelableTaskManagerTest}.
2) Avoid base::AtomicWord.
3) Use unique_ptr.
4) Fix order of expected and actual values in EXPECT_EQ.

R=mstarzinger@chromium.org

Bug: v8:8238
Change-Id: I3d29785864bbf3de58c5d9d5384b9e0065255e99
Reviewed-on: https://chromium-review.googlesource.com/c/1325967
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57378}
parent 6b8c7148
...@@ -13,13 +13,14 @@ namespace internal { ...@@ -13,13 +13,14 @@ namespace internal {
namespace { namespace {
using ResultType = std::atomic<CancelableTaskManager::Id>;
class TestTask : public Task, public Cancelable { class TestTask : public Task, public Cancelable {
public: public:
enum Mode { kDoNothing, kWaitTillCanceledAgain, kCheckNotRun }; enum Mode { kDoNothing, kWaitTillCanceledAgain, kCheckNotRun };
TestTask(CancelableTaskManager* parent, base::AtomicWord* result, TestTask(CancelableTaskManager* manager, ResultType* result, Mode mode)
Mode mode = kDoNothing) : Cancelable(manager), result_(result), mode_(mode) {}
: Cancelable(parent), result_(result), mode_(mode) {}
// Task overrides. // Task overrides.
void Run() final { void Run() final {
...@@ -30,7 +31,7 @@ class TestTask : public Task, public Cancelable { ...@@ -30,7 +31,7 @@ class TestTask : public Task, public Cancelable {
private: private:
void RunInternal() { void RunInternal() {
base::Release_Store(result_, id()); result_->store(id());
switch (mode_) { switch (mode_) {
case kWaitTillCanceledAgain: case kWaitTillCanceledAgain:
...@@ -47,216 +48,194 @@ class TestTask : public Task, public Cancelable { ...@@ -47,216 +48,194 @@ class TestTask : public Task, public Cancelable {
} }
} }
base::AtomicWord* result_; ResultType* const result_;
Mode mode_; const Mode mode_;
}; };
class SequentialRunner { class SequentialRunner {
public: public:
explicit SequentialRunner(TestTask* task) : task_(task) {} explicit SequentialRunner(std::unique_ptr<TestTask> task)
: task_(std::move(task)), task_id_(task_->id()) {}
void Run() { void Run() {
task_->Run(); task_->Run();
delete task_; task_.reset();
} }
CancelableTaskManager::Id task_id() const { return task_id_; }
private: private:
TestTask* task_; std::unique_ptr<TestTask> task_;
const CancelableTaskManager::Id task_id_;
}; };
class ThreadedRunner final : public base::Thread { class ThreadedRunner final : public base::Thread {
public: public:
explicit ThreadedRunner(TestTask* task) explicit ThreadedRunner(std::unique_ptr<TestTask> task)
: Thread(Options("runner thread")), task_(task) {} : Thread(Options("runner thread")),
task_(std::move(task)),
task_id_(task_->id()) {}
void Run() override { void Run() override {
task_->Run(); task_->Run();
delete task_; task_.reset();
} }
CancelableTaskManager::Id task_id() const { return task_id_; }
private: private:
TestTask* task_; std::unique_ptr<TestTask> task_;
const CancelableTaskManager::Id task_id_;
}; };
class CancelableTaskManagerTest : public ::testing::Test {
public:
CancelableTaskManager* manager() { return &manager_; }
typedef base::AtomicWord ResultType; std::unique_ptr<TestTask> NewTask(
ResultType* result, TestTask::Mode mode = TestTask::kDoNothing) {
return base::make_unique<TestTask>(&manager_, result, mode);
}
intptr_t GetValue(ResultType* result) { return base::Acquire_Load(result); } private:
CancelableTaskManager manager_;
};
} // namespace } // namespace
TEST_F(CancelableTaskManagerTest, EmptyCancelableTaskManager) {
TEST(CancelableTask, EmptyCancelableTaskManager) { manager()->CancelAndWait();
CancelableTaskManager manager;
manager.CancelAndWait();
} }
TEST_F(CancelableTaskManagerTest, SequentialCancelAndWait) {
TEST(CancelableTask, SequentialCancelAndWait) { ResultType result1{0};
CancelableTaskManager manager; SequentialRunner runner1(NewTask(&result1, TestTask::kCheckNotRun));
ResultType result1 = 0; EXPECT_EQ(0u, result1);
SequentialRunner runner1( manager()->CancelAndWait();
new TestTask(&manager, &result1, TestTask::kCheckNotRun)); EXPECT_EQ(0u, result1);
EXPECT_EQ(GetValue(&result1), 0); runner1.Run();
manager.CancelAndWait(); EXPECT_EQ(0u, result1);
EXPECT_EQ(GetValue(&result1), 0);
runner1.Run(); // Run to avoid leaking the Task.
EXPECT_EQ(GetValue(&result1), 0);
} }
TEST_F(CancelableTaskManagerTest, SequentialMultipleTasks) {
TEST(CancelableTask, SequentialMultipleTasks) { ResultType result1{0};
CancelableTaskManager manager; ResultType result2{0};
ResultType result1 = 0; SequentialRunner runner1(NewTask(&result1));
ResultType result2 = 0; SequentialRunner runner2(NewTask(&result2));
TestTask* task1 = new TestTask(&manager, &result1); EXPECT_EQ(1u, runner1.task_id());
TestTask* task2 = new TestTask(&manager, &result2); EXPECT_EQ(2u, runner2.task_id());
SequentialRunner runner1(task1);
SequentialRunner runner2(task2); EXPECT_EQ(0u, result1);
EXPECT_EQ(task1->id(), 1u); runner1.Run();
EXPECT_EQ(task2->id(), 2u); EXPECT_EQ(1u, result1);
EXPECT_EQ(GetValue(&result1), 0); EXPECT_EQ(0u, result2);
runner1.Run(); // Don't touch task1 after running it. runner2.Run();
EXPECT_EQ(GetValue(&result1), 1); EXPECT_EQ(2u, result2);
EXPECT_EQ(GetValue(&result2), 0); manager()->CancelAndWait();
runner2.Run(); // Don't touch task2 after running it. EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(1));
EXPECT_EQ(GetValue(&result2), 2); EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(2));
manager.CancelAndWait();
EXPECT_EQ(TryAbortResult::kTaskRemoved, manager.TryAbort(1));
EXPECT_EQ(TryAbortResult::kTaskRemoved, manager.TryAbort(2));
} }
TEST_F(CancelableTaskManagerTest, ThreadedMultipleTasksStarted) {
TEST(CancelableTask, ThreadedMultipleTasksStarted) { ResultType result1{0};
CancelableTaskManager manager; ResultType result2{0};
ResultType result1 = 0; ThreadedRunner runner1(NewTask(&result1, TestTask::kWaitTillCanceledAgain));
ResultType result2 = 0; ThreadedRunner runner2(NewTask(&result2, TestTask::kWaitTillCanceledAgain));
TestTask* task1 =
new TestTask(&manager, &result1, TestTask::kWaitTillCanceledAgain);
TestTask* task2 =
new TestTask(&manager, &result2, TestTask::kWaitTillCanceledAgain);
ThreadedRunner runner1(task1);
ThreadedRunner runner2(task2);
runner1.Start(); runner1.Start();
runner2.Start(); runner2.Start();
// Busy wait on result to make sure both tasks are done. // Busy wait on result to make sure both tasks are done.
while ((GetValue(&result1) == 0) || (GetValue(&result2) == 0)) { while (result1.load() == 0 || result2.load() == 0) {
} }
manager.CancelAndWait(); manager()->CancelAndWait();
runner1.Join(); runner1.Join();
runner2.Join(); runner2.Join();
EXPECT_EQ(GetValue(&result1), 1); EXPECT_EQ(1u, result1);
EXPECT_EQ(GetValue(&result2), 2); EXPECT_EQ(2u, result2);
} }
TEST_F(CancelableTaskManagerTest, ThreadedMultipleTasksNotRun) {
TEST(CancelableTask, ThreadedMultipleTasksNotRun) { ResultType result1{0};
CancelableTaskManager manager; ResultType result2{0};
ResultType result1 = 0; ThreadedRunner runner1(NewTask(&result1, TestTask::kCheckNotRun));
ResultType result2 = 0; ThreadedRunner runner2(NewTask(&result2, TestTask::kCheckNotRun));
TestTask* task1 = new TestTask(&manager, &result1, TestTask::kCheckNotRun); manager()->CancelAndWait();
TestTask* task2 = new TestTask(&manager, &result2, TestTask::kCheckNotRun);
ThreadedRunner runner1(task1);
ThreadedRunner runner2(task2);
manager.CancelAndWait();
// Tasks are canceled, hence the runner will bail out and not update result. // Tasks are canceled, hence the runner will bail out and not update result.
runner1.Start(); runner1.Start();
runner2.Start(); runner2.Start();
runner1.Join(); runner1.Join();
runner2.Join(); runner2.Join();
EXPECT_EQ(GetValue(&result1), 0); EXPECT_EQ(0u, result1);
EXPECT_EQ(GetValue(&result2), 0); EXPECT_EQ(0u, result2);
} }
TEST_F(CancelableTaskManagerTest, RemoveBeforeCancelAndWait) {
TEST(CancelableTask, RemoveBeforeCancelAndWait) { ResultType result1{0};
CancelableTaskManager manager; ThreadedRunner runner1(NewTask(&result1, TestTask::kCheckNotRun));
ResultType result1 = 0; CancelableTaskManager::Id id = runner1.task_id();
TestTask* task1 = new TestTask(&manager, &result1, TestTask::kCheckNotRun); EXPECT_EQ(1u, id);
ThreadedRunner runner1(task1); EXPECT_EQ(TryAbortResult::kTaskAborted, manager()->TryAbort(id));
CancelableTaskManager::Id id = task1->id();
EXPECT_EQ(id, 1u);
EXPECT_EQ(TryAbortResult::kTaskAborted, manager.TryAbort(id));
runner1.Start(); runner1.Start();
runner1.Join(); runner1.Join();
manager.CancelAndWait(); manager()->CancelAndWait();
EXPECT_EQ(GetValue(&result1), 0); EXPECT_EQ(0u, result1);
} }
TEST_F(CancelableTaskManagerTest, RemoveAfterCancelAndWait) {
TEST(CancelableTask, RemoveAfterCancelAndWait) { ResultType result1{0};
CancelableTaskManager manager; ThreadedRunner runner1(NewTask(&result1));
ResultType result1 = 0; CancelableTaskManager::Id id = runner1.task_id();
TestTask* task1 = new TestTask(&manager, &result1); EXPECT_EQ(1u, id);
ThreadedRunner runner1(task1);
CancelableTaskManager::Id id = task1->id();
EXPECT_EQ(id, 1u);
runner1.Start(); runner1.Start();
runner1.Join(); runner1.Join();
manager.CancelAndWait(); manager()->CancelAndWait();
EXPECT_EQ(TryAbortResult::kTaskRemoved, manager.TryAbort(id)); EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(id));
EXPECT_EQ(GetValue(&result1), 1); EXPECT_EQ(1u, result1);
} }
TEST_F(CancelableTaskManagerTest, RemoveUnmanagedId) {
TEST(CancelableTask, RemoveUnmanagedId) { EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(1));
CancelableTaskManager manager; EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(2));
EXPECT_EQ(TryAbortResult::kTaskRemoved, manager.TryAbort(1)); manager()->CancelAndWait();
EXPECT_EQ(TryAbortResult::kTaskRemoved, manager.TryAbort(2)); EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(1));
manager.CancelAndWait(); EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(3));
EXPECT_EQ(TryAbortResult::kTaskRemoved, manager.TryAbort(1));
EXPECT_EQ(TryAbortResult::kTaskRemoved, manager.TryAbort(3));
} }
TEST(CancelableTask, EmptyTryAbortAll) { TEST_F(CancelableTaskManagerTest, EmptyTryAbortAll) {
CancelableTaskManager manager; EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbortAll());
EXPECT_EQ(TryAbortResult::kTaskRemoved, manager.TryAbortAll());
} }
TEST(CancelableTask, ThreadedMultipleTasksNotRunTryAbortAll) { TEST_F(CancelableTaskManagerTest, ThreadedMultipleTasksNotRunTryAbortAll) {
CancelableTaskManager manager; ResultType result1{0};
ResultType result1 = 0; ResultType result2{0};
ResultType result2 = 0; ThreadedRunner runner1(NewTask(&result1, TestTask::kCheckNotRun));
TestTask* task1 = new TestTask(&manager, &result1, TestTask::kCheckNotRun); ThreadedRunner runner2(NewTask(&result2, TestTask::kCheckNotRun));
TestTask* task2 = new TestTask(&manager, &result2, TestTask::kCheckNotRun); EXPECT_EQ(TryAbortResult::kTaskAborted, manager()->TryAbortAll());
ThreadedRunner runner1(task1);
ThreadedRunner runner2(task2);
EXPECT_EQ(TryAbortResult::kTaskAborted, manager.TryAbortAll());
// Tasks are canceled, hence the runner will bail out and not update result. // Tasks are canceled, hence the runner will bail out and not update result.
runner1.Start(); runner1.Start();
runner2.Start(); runner2.Start();
runner1.Join(); runner1.Join();
runner2.Join(); runner2.Join();
EXPECT_EQ(GetValue(&result1), 0); EXPECT_EQ(0u, result1);
EXPECT_EQ(GetValue(&result2), 0); EXPECT_EQ(0u, result2);
} }
TEST(CancelableTask, ThreadedMultipleTasksStartedTryAbortAll) { TEST_F(CancelableTaskManagerTest, ThreadedMultipleTasksStartedTryAbortAll) {
CancelableTaskManager manager; ResultType result1{0};
ResultType result1 = 0; ResultType result2{0};
ResultType result2 = 0; ThreadedRunner runner1(NewTask(&result1, TestTask::kWaitTillCanceledAgain));
TestTask* task1 = ThreadedRunner runner2(NewTask(&result2, TestTask::kWaitTillCanceledAgain));
new TestTask(&manager, &result1, TestTask::kWaitTillCanceledAgain);
TestTask* task2 =
new TestTask(&manager, &result2, TestTask::kWaitTillCanceledAgain);
ThreadedRunner runner1(task1);
ThreadedRunner runner2(task2);
runner1.Start(); runner1.Start();
// Busy wait on result to make sure task1 is done. // Busy wait on result to make sure task1 is done.
while (GetValue(&result1) == 0) { while (result1.load() == 0) {
} }
EXPECT_EQ(TryAbortResult::kTaskRunning, manager.TryAbortAll()); EXPECT_EQ(TryAbortResult::kTaskRunning, manager()->TryAbortAll());
runner2.Start(); runner2.Start();
runner1.Join(); runner1.Join();
runner2.Join(); runner2.Join();
EXPECT_EQ(GetValue(&result1), 1); EXPECT_EQ(1u, result1);
EXPECT_EQ(GetValue(&result2), 0); EXPECT_EQ(0u, result2);
} }
} // namespace internal } // namespace internal
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment