LCOV - code coverage report
Current view: top level - test/unittests/libplatform - default-worker-threads-task-runner-unittest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 166 172 96.5 %
Date: 2019-04-18 Functions: 31 40 77.5 %

          Line data    Source code
       1             : // Copyright 2019 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/libplatform/default-worker-threads-task-runner.h"
       6             : 
       7             : #include <vector>
       8             : 
       9             : #include "include/v8-platform.h"
      10             : #include "src/base/platform/platform.h"
      11             : #include "src/base/platform/semaphore.h"
      12             : #include "src/base/platform/time.h"
      13             : #include "testing/gtest-support.h"
      14             : 
      15             : namespace v8 {
      16             : namespace platform {
      17             : 
      18          46 : class TestTask : public v8::Task {
      19             :  public:
      20          23 :   explicit TestTask(std::function<void()> f) : f_(std::move(f)) {}
      21             : 
      22          40 :   void Run() override { f_(); }
      23             : 
      24             :  private:
      25             :   std::function<void()> f_;
      26             : };
      27             : 
      28          15 : double RealTime() {
      29          45 :   return base::TimeTicks::HighResolutionNow().ToInternalValue() /
      30          30 :          static_cast<double>(base::Time::kMicrosecondsPerSecond);
      31             : }
      32             : 
      33       15418 : TEST(DefaultWorkerThreadsTaskRunnerUnittest, PostTaskOrder) {
      34           2 :   DefaultWorkerThreadsTaskRunner runner(1, RealTime);
      35             : 
      36             :   std::vector<int> order;
      37           2 :   base::Semaphore semaphore(0);
      38             : 
      39             :   std::unique_ptr<TestTask> task1 =
      40           3 :       base::make_unique<TestTask>([&] { order.push_back(1); });
      41             :   std::unique_ptr<TestTask> task2 =
      42           3 :       base::make_unique<TestTask>([&] { order.push_back(2); });
      43           1 :   std::unique_ptr<TestTask> task3 = base::make_unique<TestTask>([&] {
      44           2 :     order.push_back(3);
      45           1 :     semaphore.Signal();
      46           2 :   });
      47             : 
      48           2 :   runner.PostTask(std::move(task1));
      49           2 :   runner.PostTask(std::move(task2));
      50           2 :   runner.PostTask(std::move(task3));
      51             : 
      52           1 :   semaphore.Wait();
      53             : 
      54           1 :   runner.Terminate();
      55           2 :   ASSERT_EQ(3UL, order.size());
      56           2 :   ASSERT_EQ(1, order[0]);
      57           2 :   ASSERT_EQ(2, order[1]);
      58           2 :   ASSERT_EQ(3, order[2]);
      59             : }
      60             : 
      61       15418 : TEST(DefaultWorkerThreadsTaskRunnerUnittest, PostTaskOrderMultipleWorkers) {
      62           2 :   DefaultWorkerThreadsTaskRunner runner(4, RealTime);
      63             : 
      64           2 :   base::Mutex vector_lock;
      65             :   std::vector<int> order;
      66           1 :   std::atomic_int count{0};
      67             : 
      68           1 :   std::unique_ptr<TestTask> task1 = base::make_unique<TestTask>([&] {
      69           1 :     base::MutexGuard guard(&vector_lock);
      70           2 :     order.push_back(1);
      71           1 :     count++;
      72           2 :   });
      73           1 :   std::unique_ptr<TestTask> task2 = base::make_unique<TestTask>([&] {
      74           1 :     base::MutexGuard guard(&vector_lock);
      75           2 :     order.push_back(2);
      76           1 :     count++;
      77           2 :   });
      78           1 :   std::unique_ptr<TestTask> task3 = base::make_unique<TestTask>([&] {
      79           1 :     base::MutexGuard guard(&vector_lock);
      80           2 :     order.push_back(3);
      81           1 :     count++;
      82           2 :   });
      83           1 :   std::unique_ptr<TestTask> task4 = base::make_unique<TestTask>([&] {
      84           1 :     base::MutexGuard guard(&vector_lock);
      85           2 :     order.push_back(4);
      86           1 :     count++;
      87           2 :   });
      88           1 :   std::unique_ptr<TestTask> task5 = base::make_unique<TestTask>([&] {
      89           1 :     base::MutexGuard guard(&vector_lock);
      90           2 :     order.push_back(5);
      91           1 :     count++;
      92           2 :   });
      93             : 
      94           2 :   runner.PostTask(std::move(task1));
      95           2 :   runner.PostTask(std::move(task2));
      96           2 :   runner.PostTask(std::move(task3));
      97           2 :   runner.PostTask(std::move(task4));
      98           2 :   runner.PostTask(std::move(task5));
      99             : 
     100             :   // We can't observe any ordering when there are multiple worker threads. The
     101             :   // tasks are guaranteed to be dispatched to workers in the input order, but
     102             :   // the workers are different threads and can be scheduled arbitrarily. Just
     103             :   // check that all of the tasks were run once.
     104       15556 :   while (count != 5) {
     105             :   }
     106             : 
     107           1 :   runner.Terminate();
     108           2 :   ASSERT_EQ(5UL, order.size());
     109           2 :   ASSERT_EQ(1, std::count(order.begin(), order.end(), 1));
     110           2 :   ASSERT_EQ(1, std::count(order.begin(), order.end(), 2));
     111           2 :   ASSERT_EQ(1, std::count(order.begin(), order.end(), 3));
     112           2 :   ASSERT_EQ(1, std::count(order.begin(), order.end(), 4));
     113           2 :   ASSERT_EQ(1, std::count(order.begin(), order.end(), 5));
     114             : }
     115             : 
     116             : class FakeClock {
     117             :  public:
     118          46 :   static double time() { return time_.load(); }
     119             :   static void set_time(double time) { time_.store(time); }
     120           6 :   static void set_time_and_wake_up_runner(
     121             :       double time, DefaultWorkerThreadsTaskRunner* runner) {
     122             :     time_.store(time);
     123             :     // PostTask will cause the condition variable WaitFor() call to be notified
     124             :     // early, rather than waiting for the real amount of time. WaitFor() listens
     125             :     // to the system clock and not our FakeClock.
     126          24 :     runner->PostTask(base::make_unique<TestTask>([] {}));
     127           6 :   }
     128             : 
     129             :  private:
     130             :   static std::atomic<double> time_;
     131             : };
     132             : 
     133             : std::atomic<double> FakeClock::time_{0.0};
     134             : 
     135       15418 : TEST(DefaultWorkerThreadsTaskRunnerUnittest, PostDelayedTaskOrder) {
     136             :   FakeClock::set_time(0.0);
     137           2 :   DefaultWorkerThreadsTaskRunner runner(1, FakeClock::time);
     138             : 
     139             :   std::vector<int> order;
     140           2 :   base::Semaphore task1_semaphore(0);
     141           2 :   base::Semaphore task3_semaphore(0);
     142             : 
     143           1 :   std::unique_ptr<TestTask> task1 = base::make_unique<TestTask>([&] {
     144           2 :     order.push_back(1);
     145           1 :     task1_semaphore.Signal();
     146           2 :   });
     147             :   std::unique_ptr<TestTask> task2 =
     148           3 :       base::make_unique<TestTask>([&] { order.push_back(2); });
     149           1 :   std::unique_ptr<TestTask> task3 = base::make_unique<TestTask>([&] {
     150           2 :     order.push_back(3);
     151           1 :     task3_semaphore.Signal();
     152           2 :   });
     153             : 
     154           2 :   runner.PostDelayedTask(std::move(task1), 100);
     155           2 :   runner.PostTask(std::move(task2));
     156           2 :   runner.PostTask(std::move(task3));
     157             : 
     158           1 :   FakeClock::set_time_and_wake_up_runner(99, &runner);
     159             : 
     160           1 :   task3_semaphore.Wait();
     161           2 :   ASSERT_EQ(2UL, order.size());
     162           2 :   ASSERT_EQ(2, order[0]);
     163           2 :   ASSERT_EQ(3, order[1]);
     164             : 
     165           1 :   FakeClock::set_time_and_wake_up_runner(101, &runner);
     166           1 :   task1_semaphore.Wait();
     167             : 
     168           1 :   runner.Terminate();
     169           2 :   ASSERT_EQ(3UL, order.size());
     170           2 :   ASSERT_EQ(2, order[0]);
     171           2 :   ASSERT_EQ(3, order[1]);
     172           2 :   ASSERT_EQ(1, order[2]);
     173             : }
     174             : 
     175       15418 : TEST(DefaultWorkerThreadsTaskRunnerUnittest, PostDelayedTaskOrder2) {
     176             :   FakeClock::set_time(0.0);
     177           2 :   DefaultWorkerThreadsTaskRunner runner(1, FakeClock::time);
     178             : 
     179             :   std::vector<int> order;
     180           2 :   base::Semaphore task1_semaphore(0);
     181           2 :   base::Semaphore task2_semaphore(0);
     182           2 :   base::Semaphore task3_semaphore(0);
     183             : 
     184           1 :   std::unique_ptr<TestTask> task1 = base::make_unique<TestTask>([&] {
     185           2 :     order.push_back(1);
     186           1 :     task1_semaphore.Signal();
     187           2 :   });
     188           1 :   std::unique_ptr<TestTask> task2 = base::make_unique<TestTask>([&] {
     189           2 :     order.push_back(2);
     190           1 :     task2_semaphore.Signal();
     191           2 :   });
     192           1 :   std::unique_ptr<TestTask> task3 = base::make_unique<TestTask>([&] {
     193           2 :     order.push_back(3);
     194           1 :     task3_semaphore.Signal();
     195           2 :   });
     196             : 
     197           2 :   runner.PostDelayedTask(std::move(task1), 500);
     198           2 :   runner.PostDelayedTask(std::move(task2), 100);
     199           2 :   runner.PostDelayedTask(std::move(task3), 200);
     200             : 
     201           1 :   FakeClock::set_time_and_wake_up_runner(101, &runner);
     202             : 
     203           1 :   task2_semaphore.Wait();
     204           2 :   ASSERT_EQ(1UL, order.size());
     205           2 :   ASSERT_EQ(2, order[0]);
     206             : 
     207           1 :   FakeClock::set_time_and_wake_up_runner(201, &runner);
     208             : 
     209           1 :   task3_semaphore.Wait();
     210           2 :   ASSERT_EQ(2UL, order.size());
     211           2 :   ASSERT_EQ(2, order[0]);
     212           2 :   ASSERT_EQ(3, order[1]);
     213             : 
     214           1 :   FakeClock::set_time_and_wake_up_runner(501, &runner);
     215             : 
     216           1 :   task1_semaphore.Wait();
     217           1 :   runner.Terminate();
     218           2 :   ASSERT_EQ(3UL, order.size());
     219           2 :   ASSERT_EQ(2, order[0]);
     220           2 :   ASSERT_EQ(3, order[1]);
     221           2 :   ASSERT_EQ(1, order[2]);
     222             : }
     223             : 
     224       15418 : TEST(DefaultWorkerThreadsTaskRunnerUnittest, PostAfterTerminate) {
     225             :   FakeClock::set_time(0.0);
     226           2 :   DefaultWorkerThreadsTaskRunner runner(1, FakeClock::time);
     227             : 
     228             :   std::vector<int> order;
     229           2 :   base::Semaphore task1_semaphore(0);
     230           2 :   base::Semaphore task2_semaphore(0);
     231           2 :   base::Semaphore task3_semaphore(0);
     232             : 
     233           1 :   std::unique_ptr<TestTask> task1 = base::make_unique<TestTask>([&] {
     234           2 :     order.push_back(1);
     235           1 :     task1_semaphore.Signal();
     236           2 :   });
     237           0 :   std::unique_ptr<TestTask> task2 = base::make_unique<TestTask>([&] {
     238           0 :     order.push_back(2);
     239           0 :     task2_semaphore.Signal();
     240           1 :   });
     241           0 :   std::unique_ptr<TestTask> task3 = base::make_unique<TestTask>([&] {
     242           0 :     order.push_back(3);
     243           0 :     task3_semaphore.Signal();
     244           1 :   });
     245             : 
     246           2 :   runner.PostTask(std::move(task1));
     247           2 :   runner.PostDelayedTask(std::move(task2), 100);
     248             : 
     249           1 :   task1_semaphore.Wait();
     250           2 :   ASSERT_EQ(1UL, order.size());
     251           2 :   ASSERT_EQ(1, order[0]);
     252             : 
     253           1 :   runner.Terminate();
     254           1 :   FakeClock::set_time_and_wake_up_runner(201, &runner);
     255             :   // OK, we can't actually prove that this never executes. But wait a bit at
     256             :   // least.
     257             :   bool signalled =
     258           1 :       task2_semaphore.WaitFor(base::TimeDelta::FromMilliseconds(100));
     259           2 :   ASSERT_FALSE(signalled);
     260           2 :   ASSERT_EQ(1UL, order.size());
     261           2 :   ASSERT_EQ(1, order[0]);
     262             : 
     263           2 :   runner.PostTask(std::move(task3));
     264           1 :   signalled = task3_semaphore.WaitFor(base::TimeDelta::FromMilliseconds(100));
     265           2 :   ASSERT_FALSE(signalled);
     266           2 :   ASSERT_EQ(1UL, order.size());
     267           2 :   ASSERT_EQ(1, order[0]);
     268             : }
     269             : 
     270       15418 : TEST(DefaultWorkerThreadsTaskRunnerUnittest, NoIdleTasks) {
     271           2 :   DefaultWorkerThreadsTaskRunner runner(1, FakeClock::time);
     272             : 
     273           2 :   ASSERT_FALSE(runner.IdleTasksEnabled());
     274           1 :   runner.Terminate();
     275             : }
     276             : 
     277             : }  // namespace platform
     278        9249 : }  // namespace v8

Generated by: LCOV version 1.10