LCOV - code coverage report
Current view: top level - test/unittests - cancelable-tasks-unittest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 148 151 98.0 %
Date: 2017-10-20 Functions: 29 43 67.4 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/base/atomicops.h"
       6             : #include "src/base/platform/platform.h"
       7             : #include "src/cancelable-task.h"
       8             : #include "testing/gtest/include/gtest/gtest.h"
       9             : 
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : 
      14             : namespace {
      15             : 
      16          26 : class TestTask : public Task, public Cancelable {
      17             :  public:
      18             :   enum Mode { kDoNothing, kWaitTillCanceledAgain, kCheckNotRun };
      19             : 
      20             :   TestTask(CancelableTaskManager* parent, base::AtomicWord* result,
      21             :            Mode mode = kDoNothing)
      22          13 :       : Cancelable(parent), result_(result), mode_(mode) {}
      23             : 
      24             :   // Task overrides.
      25          13 :   void Run() final {
      26          13 :     if (TryRun()) {
      27           6 :       RunInternal();
      28             :     }
      29          13 :   }
      30             : 
      31             :  private:
      32           6 :   void RunInternal() {
      33           6 :     base::Release_Store(result_, id());
      34             : 
      35           6 :     switch (mode_) {
      36             :       case kWaitTillCanceledAgain:
      37             :         // Simple busy wait until the main thread tried to cancel.
      38     6706936 :         while (CancelAttempts() == 0) {
      39             :         }
      40             :         break;
      41             :       case kCheckNotRun:
      42             :         // Check that we never execute {RunInternal}.
      43           0 :         EXPECT_TRUE(false);
      44           0 :         break;
      45             :       default:
      46             :         break;
      47             :     }
      48           0 :   }
      49             : 
      50             :   base::AtomicWord* result_;
      51             :   Mode mode_;
      52             : };
      53             : 
      54             : 
      55             : class SequentialRunner {
      56             :  public:
      57           2 :   explicit SequentialRunner(TestTask* task) : task_(task) {}
      58             : 
      59           3 :   void Run() {
      60           3 :     task_->Run();
      61           3 :     delete task_;
      62           3 :   }
      63             : 
      64             :  private:
      65             :   TestTask* task_;
      66             : };
      67             : 
      68             : 
      69           6 : class ThreadedRunner final : public base::Thread {
      70             :  public:
      71             :   explicit ThreadedRunner(TestTask* task)
      72          10 :       : Thread(Options("runner thread")), task_(task) {}
      73             : 
      74          10 :   virtual void Run() {
      75          10 :     task_->Run();
      76          10 :     delete task_;
      77          10 :   }
      78             : 
      79             :  private:
      80             :   TestTask* task_;
      81             : };
      82             : 
      83             : 
      84             : typedef base::AtomicWord ResultType;
      85             : 
      86             : 
      87             : intptr_t GetValue(ResultType* result) { return base::Acquire_Load(result); }
      88             : 
      89             : }  // namespace
      90             : 
      91             : 
      92       13158 : TEST(CancelableTask, EmptyCancelableTaskManager) {
      93           1 :   CancelableTaskManager manager;
      94           1 :   manager.CancelAndWait();
      95           1 : }
      96             : 
      97             : 
      98       13158 : TEST(CancelableTask, SequentialCancelAndWait) {
      99           1 :   CancelableTaskManager manager;
     100           1 :   ResultType result1 = 0;
     101             :   SequentialRunner runner1(
     102           1 :       new TestTask(&manager, &result1, TestTask::kCheckNotRun));
     103           3 :   EXPECT_EQ(GetValue(&result1), 0);
     104           1 :   manager.CancelAndWait();
     105           3 :   EXPECT_EQ(GetValue(&result1), 0);
     106           1 :   runner1.Run();  // Run to avoid leaking the Task.
     107           4 :   EXPECT_EQ(GetValue(&result1), 0);
     108           1 : }
     109             : 
     110             : 
     111       13158 : TEST(CancelableTask, SequentialMultipleTasks) {
     112           1 :   CancelableTaskManager manager;
     113           1 :   ResultType result1 = 0;
     114           1 :   ResultType result2 = 0;
     115           1 :   TestTask* task1 = new TestTask(&manager, &result1);
     116           1 :   TestTask* task2 = new TestTask(&manager, &result2);
     117             :   SequentialRunner runner1(task1);
     118             :   SequentialRunner runner2(task2);
     119           2 :   EXPECT_EQ(task1->id(), 1u);
     120           2 :   EXPECT_EQ(task2->id(), 2u);
     121             : 
     122           3 :   EXPECT_EQ(GetValue(&result1), 0);
     123           1 :   runner1.Run();  // Don't touch task1 after running it.
     124           3 :   EXPECT_EQ(GetValue(&result1), 1);
     125             : 
     126           3 :   EXPECT_EQ(GetValue(&result2), 0);
     127           1 :   runner2.Run();  // Don't touch task2 after running it.
     128           3 :   EXPECT_EQ(GetValue(&result2), 2);
     129             : 
     130           1 :   manager.CancelAndWait();
     131           2 :   EXPECT_FALSE(manager.TryAbort(1));
     132           3 :   EXPECT_FALSE(manager.TryAbort(2));
     133           1 : }
     134             : 
     135             : 
     136       13158 : TEST(CancelableTask, ThreadedMultipleTasksStarted) {
     137           1 :   CancelableTaskManager manager;
     138           1 :   ResultType result1 = 0;
     139           1 :   ResultType result2 = 0;
     140             :   TestTask* task1 =
     141           1 :       new TestTask(&manager, &result1, TestTask::kWaitTillCanceledAgain);
     142             :   TestTask* task2 =
     143           1 :       new TestTask(&manager, &result2, TestTask::kWaitTillCanceledAgain);
     144             :   ThreadedRunner runner1(task1);
     145             :   ThreadedRunner runner2(task2);
     146           1 :   runner1.Start();
     147           1 :   runner2.Start();
     148             :   // Busy wait on result to make sure both tasks are done.
     149    11388944 :   while ((GetValue(&result1) == 0) || (GetValue(&result2) == 0)) {
     150             :   }
     151           1 :   manager.CancelAndWait();
     152           1 :   runner1.Join();
     153           1 :   runner2.Join();
     154           3 :   EXPECT_EQ(GetValue(&result1), 1);
     155           4 :   EXPECT_EQ(GetValue(&result2), 2);
     156           1 : }
     157             : 
     158             : 
     159       13158 : TEST(CancelableTask, ThreadedMultipleTasksNotRun) {
     160           1 :   CancelableTaskManager manager;
     161           1 :   ResultType result1 = 0;
     162           1 :   ResultType result2 = 0;
     163           1 :   TestTask* task1 = new TestTask(&manager, &result1, TestTask::kCheckNotRun);
     164           1 :   TestTask* task2 = new TestTask(&manager, &result2, TestTask::kCheckNotRun);
     165             :   ThreadedRunner runner1(task1);
     166             :   ThreadedRunner runner2(task2);
     167           1 :   manager.CancelAndWait();
     168             :   // Tasks are canceled, hence the runner will bail out and not update result.
     169           1 :   runner1.Start();
     170           1 :   runner2.Start();
     171           1 :   runner1.Join();
     172           1 :   runner2.Join();
     173           3 :   EXPECT_EQ(GetValue(&result1), 0);
     174           4 :   EXPECT_EQ(GetValue(&result2), 0);
     175           1 : }
     176             : 
     177             : 
     178       13158 : TEST(CancelableTask, RemoveBeforeCancelAndWait) {
     179           1 :   CancelableTaskManager manager;
     180           1 :   ResultType result1 = 0;
     181           1 :   TestTask* task1 = new TestTask(&manager, &result1, TestTask::kCheckNotRun);
     182             :   ThreadedRunner runner1(task1);
     183           1 :   CancelableTaskManager::Id id = task1->id();
     184           2 :   EXPECT_EQ(id, 1u);
     185           2 :   EXPECT_TRUE(manager.TryAbort(id));
     186           1 :   runner1.Start();
     187           1 :   runner1.Join();
     188           1 :   manager.CancelAndWait();
     189           4 :   EXPECT_EQ(GetValue(&result1), 0);
     190           1 : }
     191             : 
     192             : 
     193       13158 : TEST(CancelableTask, RemoveAfterCancelAndWait) {
     194           1 :   CancelableTaskManager manager;
     195           1 :   ResultType result1 = 0;
     196           1 :   TestTask* task1 = new TestTask(&manager, &result1);
     197             :   ThreadedRunner runner1(task1);
     198           1 :   CancelableTaskManager::Id id = task1->id();
     199           2 :   EXPECT_EQ(id, 1u);
     200           1 :   runner1.Start();
     201           1 :   runner1.Join();
     202           1 :   manager.CancelAndWait();
     203           2 :   EXPECT_FALSE(manager.TryAbort(id));
     204           4 :   EXPECT_EQ(GetValue(&result1), 1);
     205           1 : }
     206             : 
     207             : 
     208       13158 : TEST(CancelableTask, RemoveUnmanagedId) {
     209           1 :   CancelableTaskManager manager;
     210           2 :   EXPECT_FALSE(manager.TryAbort(1));
     211           2 :   EXPECT_FALSE(manager.TryAbort(2));
     212           1 :   manager.CancelAndWait();
     213           2 :   EXPECT_FALSE(manager.TryAbort(1));
     214           3 :   EXPECT_FALSE(manager.TryAbort(3));
     215           1 : }
     216             : 
     217       13158 : TEST(CancelableTask, EmptyTryAbortAll) {
     218           1 :   CancelableTaskManager manager;
     219           3 :   EXPECT_EQ(manager.TryAbortAll(), CancelableTaskManager::kTaskRemoved);
     220           1 : }
     221             : 
     222       13158 : TEST(CancelableTask, ThreadedMultipleTasksNotRunTryAbortAll) {
     223           1 :   CancelableTaskManager manager;
     224           1 :   ResultType result1 = 0;
     225           1 :   ResultType result2 = 0;
     226           1 :   TestTask* task1 = new TestTask(&manager, &result1, TestTask::kCheckNotRun);
     227           1 :   TestTask* task2 = new TestTask(&manager, &result2, TestTask::kCheckNotRun);
     228             :   ThreadedRunner runner1(task1);
     229             :   ThreadedRunner runner2(task2);
     230           2 :   EXPECT_EQ(manager.TryAbortAll(), CancelableTaskManager::kTaskAborted);
     231             :   // Tasks are canceled, hence the runner will bail out and not update result.
     232           1 :   runner1.Start();
     233           1 :   runner2.Start();
     234           1 :   runner1.Join();
     235           1 :   runner2.Join();
     236           3 :   EXPECT_EQ(GetValue(&result1), 0);
     237           4 :   EXPECT_EQ(GetValue(&result2), 0);
     238           1 : }
     239             : 
     240       13158 : TEST(CancelableTask, ThreadedMultipleTasksStartedTryAbortAll) {
     241           1 :   CancelableTaskManager manager;
     242           1 :   ResultType result1 = 0;
     243           1 :   ResultType result2 = 0;
     244             :   TestTask* task1 =
     245           1 :       new TestTask(&manager, &result1, TestTask::kWaitTillCanceledAgain);
     246             :   TestTask* task2 =
     247           1 :       new TestTask(&manager, &result2, TestTask::kWaitTillCanceledAgain);
     248             :   ThreadedRunner runner1(task1);
     249             :   ThreadedRunner runner2(task2);
     250           1 :   runner1.Start();
     251             :   // Busy wait on result to make sure task1 is done.
     252     2878159 :   while (GetValue(&result1) == 0) {
     253             :   }
     254           2 :   EXPECT_EQ(manager.TryAbortAll(), CancelableTaskManager::kTaskRunning);
     255           1 :   runner2.Start();
     256           1 :   runner1.Join();
     257           1 :   runner2.Join();
     258           3 :   EXPECT_EQ(GetValue(&result1), 1);
     259           4 :   EXPECT_EQ(GetValue(&result2), 0);
     260           1 : }
     261             : 
     262             : }  // namespace internal
     263        7893 : }  // namespace v8

Generated by: LCOV version 1.10