15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/condition_variable.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/sequenced_task_runner_test_template.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/test/sequenced_worker_pool_owner.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/task_runner_test_template.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/test/test_timeouts.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/tracked_objects.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IMPORTANT NOTE:
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Many of these tests have failure modes where they'll hang forever. These
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// tests should not be flaky, and hanging indicates a type of failure. Do not
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mark as flaky if they're hanging, it's likely an actual bug.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kNumWorkerThreads = 3;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Allows a number of threads to all be blocked on the same event, and
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// provides a way to unblock a certain number of them.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadBlocker {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadBlocker() : lock_(), cond_var_(&lock_), unblock_counter_(0) {}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Block() {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock lock(lock_);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (unblock_counter_ == 0)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cond_var_.Wait();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unblock_counter_--;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cond_var_.Signal();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Unblock(size_t count) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock lock(lock_);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(unblock_counter_ == 0);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unblock_counter_ = count;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cond_var_.Signal();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock lock_;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ConditionVariable cond_var_;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t unblock_counter_;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestTracker : public base::RefCountedThreadSafe<TestTracker> {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestTracker()
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : lock_(),
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cond_var_(&lock_),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        started_events_(0) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Each of these tasks appends the argument to the complete sequence vector
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so calling code can see what order they finished in.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FastTask(int id) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SignalWorkerDone(id);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SlowTask(int id) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SignalWorkerDone(id);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BlockTask(int id, ThreadBlocker* blocker) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that this task has started and signal anybody waiting for that
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to happen.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock lock(lock_);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      started_events_++;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cond_var_.Signal();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocker->Block();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SignalWorkerDone(id);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void PostAdditionalTasks(
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        int id, SequencedWorkerPool* pool,
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bool expected_return_value) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Closure fast_task = base::Bind(&TestTracker::FastTask, this, 100);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(expected_return_value,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              pool->PostWorkerTaskWithShutdownBehavior(
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  FROM_HERE, fast_task,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  SequencedWorkerPool::CONTINUE_ON_SHUTDOWN));
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(expected_return_value,
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              pool->PostWorkerTaskWithShutdownBehavior(
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  FROM_HERE, fast_task,
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  SequencedWorkerPool::SKIP_ON_SHUTDOWN));
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pool->PostWorkerTaskWithShutdownBehavior(
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE, fast_task,
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SequencedWorkerPool::BLOCK_SHUTDOWN);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SignalWorkerDone(id);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Waits until the given number of tasks have started executing.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitUntilTasksBlocked(size_t count) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock lock(lock_);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (started_events_ < count)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cond_var_.Wait();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cond_var_.Signal();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Blocks the current thread until at least the given number of tasks are in
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the completed vector, and then returns a copy.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int> WaitUntilTasksComplete(size_t num_tasks) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<int> ret;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock lock(lock_);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (complete_sequence_.size() < num_tasks)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cond_var_.Wait();
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ret = complete_sequence_;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cond_var_.Signal();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t GetTasksCompletedCount() {
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::AutoLock lock(lock_);
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return complete_sequence_.size();
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearCompleteSequence() {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(lock_);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    complete_sequence_.clear();
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    started_events_ = 0;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<TestTracker>;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~TestTracker() {}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SignalWorkerDone(int id) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock lock(lock_);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      complete_sequence_.push_back(id);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cond_var_.Signal();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Protects the complete_sequence.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock lock_;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::ConditionVariable cond_var_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Protected by lock_.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int> complete_sequence_;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Counter of the number of "block" workers that have started.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t started_events_;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SequencedWorkerPoolTest : public testing::Test {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPoolTest()
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : tracker_(new TestTracker) {
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ResetPool();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SequencedWorkerPoolTest() {}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool()->Shutdown();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const scoped_refptr<SequencedWorkerPool>& pool() {
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return pool_owner_->pool();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestTracker* tracker() { return tracker_.get(); }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Destroys the SequencedWorkerPool instance, blocking until it is fully shut
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // down, and creates a new instance.
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ResetPool() {
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pool_owner_.reset(new SequencedWorkerPoolOwner(kNumWorkerThreads, "test"));
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetWillWaitForShutdownCallback(const Closure& callback) {
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pool_owner_->SetWillWaitForShutdownCallback(callback);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensures that the given number of worker threads is created by adding
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // tasks and waiting until they complete. Worker thread creation is
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // serialized, can happen on background threads asynchronously, and doesn't
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // happen any more at shutdown. This means that if a test posts a bunch of
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // tasks and calls shutdown, fewer workers will be created than the test may
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // expect.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This function ensures that this condition can't happen so tests can make
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // assumptions about the number of workers active. See the comment in
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PrepareToStartAdditionalThreadIfNecessary in the .cc file for more
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // details.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It will post tasks to the queue with id -1. It also assumes this is the
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // first thing called in a test since it will clear the complete_sequence_.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EnsureAllWorkersCreated() {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create a bunch of threads, all waiting. This will cause that may
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // workers to be created.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ThreadBlocker blocker;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < kNumWorkerThreads; i++) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pool()->PostWorkerTask(FROM_HERE,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             base::Bind(&TestTracker::BlockTask,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        tracker(), -1, &blocker));
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tracker()->WaitUntilTasksBlocked(kNumWorkerThreads);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Now wake them up and wait until they're done.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocker.Unblock(kNumWorkerThreads);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tracker()->WaitUntilTasksComplete(kNumWorkerThreads);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Clean up the task IDs we added.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tracker()->ClearCompleteSequence();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int has_work_call_count() const {
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return pool_owner_->has_work_call_count();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop message_loop_;
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SequencedWorkerPoolOwner> pool_owner_;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const scoped_refptr<TestTracker> tracker_;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks that the given number of entries are in the tasks to complete of
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the given tracker, and then signals the given event the given number of
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// times. This is used to wakt up blocked background threads before blocking
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on shutdown.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnsureTasksToCompleteCountAndUnblock(scoped_refptr<TestTracker> tracker,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          size_t expected_tasks_to_complete,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          ThreadBlocker* blocker,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          size_t threads_to_awake) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expected_tasks_to_complete,
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tracker->WaitUntilTasksComplete(expected_tasks_to_complete).size());
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocker->Unblock(threads_to_awake);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DeletionHelper : public base::RefCountedThreadSafe<DeletionHelper> {
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit DeletionHelper(
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const scoped_refptr<base::RefCountedData<bool> >& deleted_flag)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : deleted_flag_(deleted_flag) {
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  friend class base::RefCountedThreadSafe<DeletionHelper>;
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~DeletionHelper() { deleted_flag_->data = true; }
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const scoped_refptr<base::RefCountedData<bool> > deleted_flag_;
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DeletionHelper);
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HoldPoolReference(const scoped_refptr<base::SequencedWorkerPool>& pool,
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const scoped_refptr<DeletionHelper>& helper) {
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ADD_FAILURE() << "Should never run";
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests that delayed tasks are deleted upon shutdown of the pool.
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SequencedWorkerPoolTest, DelayedTaskDuringShutdown) {
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Post something to verify the pool is started up.
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pool()->PostTask(
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 1)));
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::RefCountedData<bool> > deleted_flag(
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new base::RefCountedData<bool>(false));
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Time posted_at(base::Time::Now());
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Post something that shouldn't run.
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(pool()->PostDelayedTask(
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&HoldPoolReference,
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 pool(),
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 make_scoped_refptr(new DeletionHelper(deleted_flag))),
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TestTimeouts::action_timeout()));
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<int> completion_sequence = tracker()->WaitUntilTasksComplete(1);
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1u, completion_sequence.size());
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1, completion_sequence[0]);
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pool()->Shutdown();
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Shutdown is asynchronous, so use ResetPool() to block until the pool is
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // fully destroyed (and thus shut down).
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResetPool();
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify that we didn't block until the task was due.
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_LT(base::Time::Now() - posted_at, TestTimeouts::action_timeout());
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Verify that the deferred task has not only not run, but has also been
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // destroyed.
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(deleted_flag->data);
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that same-named tokens have the same ID.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, NamedTokens) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string name1("hello");
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPool::SequenceToken token1 =
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pool()->GetNamedSequenceToken(name1);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken();
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string name3("goodbye");
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPool::SequenceToken token3 =
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pool()->GetNamedSequenceToken(name3);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All 3 tokens should be different.
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(token1.Equals(token2));
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(token1.Equals(token3));
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(token2.Equals(token3));
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Requesting the same name again should give the same value.
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPool::SequenceToken token1again =
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pool()->GetNamedSequenceToken(name1);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(token1.Equals(token1again));
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPool::SequenceToken token3again =
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pool()->GetNamedSequenceToken(name3);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(token3.Equals(token3again));
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that posting a bunch of tasks (many more than the number of worker
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// threads) runs them all.
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, LotsOfTasks) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->PostWorkerTask(FROM_HERE,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         base::Bind(&TestTracker::SlowTask, tracker(), 0));
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kNumTasks = 20;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 1; i < kNumTasks; i++) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool()->PostWorkerTask(FROM_HERE,
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           base::Bind(&TestTracker::FastTask, tracker(), i));
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int> result = tracker()->WaitUntilTasksComplete(kNumTasks);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNumTasks, result.size());
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that posting a bunch of tasks (many more than the number of
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// worker threads) to two pools simultaneously runs them all twice.
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test is meant to shake out any concurrency issues between
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pools (like histograms).
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, LotsOfTasksTwoPools) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPoolOwner pool1(kNumWorkerThreads, "test1");
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPoolOwner pool2(kNumWorkerThreads, "test2");
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure slow_task = base::Bind(&TestTracker::SlowTask, tracker(), 0);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool1.pool()->PostWorkerTask(FROM_HERE, slow_task);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool2.pool()->PostWorkerTask(FROM_HERE, slow_task);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kNumTasks = 20;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 1; i < kNumTasks; i++) {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Closure fast_task =
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&TestTracker::FastTask, tracker(), i);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool1.pool()->PostWorkerTask(FROM_HERE, fast_task);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool2.pool()->PostWorkerTask(FROM_HERE, fast_task);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int> result =
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tracker()->WaitUntilTasksComplete(2*kNumTasks);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2 * kNumTasks, result.size());
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool2.pool()->Shutdown();
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool1.pool()->Shutdown();
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that tasks with the same sequence token are executed in order but don't
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// affect other tasks.
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, Sequence) {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill all the worker threads except one.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kNumBackgroundTasks = kNumWorkerThreads - 1;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadBlocker background_blocker;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < kNumBackgroundTasks; i++) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool()->PostWorkerTask(FROM_HERE,
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           base::Bind(&TestTracker::BlockTask,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      tracker(), i, &background_blocker));
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tracker()->WaitUntilTasksBlocked(kNumBackgroundTasks);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create two tasks with the same sequence token, one that will block on the
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // event, and one which will just complete quickly when it's run. Since there
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is one worker thread free, the first task will start and then block, and
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the second task should be waiting.
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadBlocker blocker;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPool::SequenceToken token1 = pool()->GetSequenceToken();
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->PostSequencedWorkerTask(
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      token1, FROM_HERE,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TestTracker::BlockTask, tracker(), 100, &blocker));
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->PostSequencedWorkerTask(
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      token1, FROM_HERE,
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TestTracker::FastTask, tracker(), 101));
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size());
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create another two tasks as above with a different token. These will be
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // blocked since there are no slots to run.
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken();
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->PostSequencedWorkerTask(
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      token2, FROM_HERE,
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TestTracker::FastTask, tracker(), 200));
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->PostSequencedWorkerTask(
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      token2, FROM_HERE,
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TestTracker::FastTask, tracker(), 201));
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size());
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Let one background task complete. This should then let both tasks of
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // token2 run to completion in order. The second task of token1 should still
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be blocked.
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background_blocker.Unblock(1);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int> result = tracker()->WaitUntilTasksComplete(3);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(3u, result.size());
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(200, result[1]);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(201, result[2]);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Finish the rest of the background tasks. This should leave some workers
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // free with the second token1 task still blocked on the first.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  background_blocker.Unblock(kNumBackgroundTasks - 1);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNumBackgroundTasks + 2,
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            tracker()->WaitUntilTasksComplete(kNumBackgroundTasks + 2).size());
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allow the first task of token1 to complete. This should run the second.
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocker.Unblock(1);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = tracker()->WaitUntilTasksComplete(kNumBackgroundTasks + 4);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(kNumBackgroundTasks + 4, result.size());
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(100, result[result.size() - 2]);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(101, result[result.size() - 1]);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that any tasks posted after Shutdown are ignored.
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Disabled for flakiness.  See http://crbug.com/166451.
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SequencedWorkerPoolTest, DISABLED_IgnoresAfterShutdown) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start tasks to take all the threads and block them.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureAllWorkersCreated();
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadBlocker blocker;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < kNumWorkerThreads; i++) {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool()->PostWorkerTask(FROM_HERE,
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           base::Bind(&TestTracker::BlockTask,
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      tracker(), i, &blocker));
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tracker()->WaitUntilTasksBlocked(kNumWorkerThreads);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetWillWaitForShutdownCallback(
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&EnsureTasksToCompleteCountAndUnblock,
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 scoped_refptr<TestTracker>(tracker()), 0,
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 &blocker, kNumWorkerThreads));
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Shutdown the worker pool. This should discard all non-blocking tasks.
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kMaxNewBlockingTasksAfterShutdown = 100;
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pool()->Shutdown(kMaxNewBlockingTasksAfterShutdown);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int old_has_work_call_count = has_work_call_count();
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int> result =
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tracker()->WaitUntilTasksComplete(kNumWorkerThreads);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The kNumWorkerThread items should have completed, in no particular order.
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(kNumWorkerThreads, result.size());
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < kNumWorkerThreads; i++) {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(std::find(result.begin(), result.end(), static_cast<int>(i)) !=
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                result.end());
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No further tasks, regardless of shutdown mode, should be allowed.
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior(
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TestTracker::FastTask, tracker(), 100),
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SequencedWorkerPool::CONTINUE_ON_SHUTDOWN));
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior(
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TestTracker::FastTask, tracker(), 101),
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SequencedWorkerPool::SKIP_ON_SHUTDOWN));
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior(
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TestTracker::FastTask, tracker(), 102),
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SequencedWorkerPool::BLOCK_SHUTDOWN));
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(old_has_work_call_count, has_work_call_count());
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SequencedWorkerPoolTest, AllowsAfterShutdown) {
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Test that <n> new blocking tasks are allowed provided they're posted
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // by a running tasks.
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnsureAllWorkersCreated();
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ThreadBlocker blocker;
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start tasks to take all the threads and block them.
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kNumBlockTasks = static_cast<int>(kNumWorkerThreads);
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < kNumBlockTasks; ++i) {
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(pool()->PostWorkerTask(
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker)));
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tracker()->WaitUntilTasksBlocked(kNumWorkerThreads);
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Queue up shutdown blocking tasks behind those which will attempt to post
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // additional tasks when run, PostAdditionalTasks attemtps to post 3
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // new FastTasks, one for each shutdown_behavior.
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kNumQueuedTasks = static_cast<int>(kNumWorkerThreads);
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < kNumQueuedTasks; ++i) {
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(pool()->PostWorkerTaskWithShutdownBehavior(
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FROM_HERE,
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&TestTracker::PostAdditionalTasks, tracker(), i, pool(),
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   false),
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SequencedWorkerPool::BLOCK_SHUTDOWN));
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Setup to open the floodgates from within Shutdown().
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetWillWaitForShutdownCallback(
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&EnsureTasksToCompleteCountAndUnblock,
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 scoped_refptr<TestTracker>(tracker()),
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 0, &blocker, kNumBlockTasks));
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Allow half of the additional blocking tasks thru.
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kNumNewBlockingTasksToAllow = kNumWorkerThreads / 2;
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pool()->Shutdown(kNumNewBlockingTasksToAllow);
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure that the correct number of tasks actually got run.
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tracker()->WaitUntilTasksComplete(static_cast<size_t>(
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kNumBlockTasks + kNumQueuedTasks + kNumNewBlockingTasksToAllow));
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Clean up the task IDs we added and go home.
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tracker()->ClearCompleteSequence();
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that unrun tasks are discarded properly according to their shutdown
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mode.
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, DiscardOnShutdown) {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start tasks to take all the threads and block them.
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureAllWorkersCreated();
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadBlocker blocker;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < kNumWorkerThreads; i++) {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool()->PostWorkerTask(FROM_HERE,
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           base::Bind(&TestTracker::BlockTask,
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      tracker(), i, &blocker));
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tracker()->WaitUntilTasksBlocked(kNumWorkerThreads);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create some tasks with different shutdown modes.
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->PostWorkerTaskWithShutdownBehavior(
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TestTracker::FastTask, tracker(), 100),
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->PostWorkerTaskWithShutdownBehavior(
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TestTracker::FastTask, tracker(), 101),
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SequencedWorkerPool::SKIP_ON_SHUTDOWN);
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->PostWorkerTaskWithShutdownBehavior(
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TestTracker::FastTask, tracker(), 102),
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SequencedWorkerPool::BLOCK_SHUTDOWN);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shutdown the worker pool. This should discard all non-blocking tasks.
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetWillWaitForShutdownCallback(
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&EnsureTasksToCompleteCountAndUnblock,
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 scoped_refptr<TestTracker>(tracker()), 0,
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 &blocker, kNumWorkerThreads));
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->Shutdown();
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int> result =
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tracker()->WaitUntilTasksComplete(kNumWorkerThreads + 1);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The kNumWorkerThread items should have completed, plus the BLOCK_SHUTDOWN
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // one, in no particular order.
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(kNumWorkerThreads + 1, result.size());
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < kNumWorkerThreads; i++) {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(std::find(result.begin(), result.end(), static_cast<int>(i)) !=
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                result.end());
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(std::find(result.begin(), result.end(), 102) != result.end());
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that CONTINUE_ON_SHUTDOWN tasks don't block shutdown.
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, ContinueOnShutdown) {
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<TaskRunner> runner(pool()->GetTaskRunnerWithShutdownBehavior(
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SequencedWorkerPool::CONTINUE_ON_SHUTDOWN));
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SequencedTaskRunner> sequenced_runner(
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pool()->GetSequencedTaskRunnerWithShutdownBehavior(
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pool()->GetSequenceToken(),
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SequencedWorkerPool::CONTINUE_ON_SHUTDOWN));
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureAllWorkersCreated();
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadBlocker blocker;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->PostWorkerTaskWithShutdownBehavior(
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TestTracker::BlockTask,
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 tracker(), 0, &blocker),
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  runner->PostTask(
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TestTracker::BlockTask,
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 tracker(), 1, &blocker));
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sequenced_runner->PostTask(
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TestTracker::BlockTask,
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 tracker(), 2, &blocker));
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tracker()->WaitUntilTasksBlocked(3);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should not block. If this test hangs, it means it failed.
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->Shutdown();
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The task should not have completed yet.
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size());
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Posting more tasks should fail.
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(pool()->PostWorkerTaskWithShutdownBehavior(
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0),
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SequencedWorkerPool::CONTINUE_ON_SHUTDOWN));
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(runner->PostTask(
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0)));
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(sequenced_runner->PostTask(
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&TestTracker::FastTask, tracker(), 0)));
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Continue the background thread and make sure the tasks can complete.
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocker.Unblock(3);
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int> result = tracker()->WaitUntilTasksComplete(3);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3u, result.size());
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that SKIP_ON_SHUTDOWN tasks that have been started block Shutdown
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// until they stop, but tasks not yet started do not.
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, SkipOnShutdown) {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start tasks to take all the threads and block them.
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureAllWorkersCreated();
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadBlocker blocker;
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now block all the threads with SKIP_ON_SHUTDOWN. Shutdown() should not
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // return until these tasks have completed.
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < kNumWorkerThreads; i++) {
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool()->PostWorkerTaskWithShutdownBehavior(
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&TestTracker::BlockTask, tracker(), i, &blocker),
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SequencedWorkerPool::SKIP_ON_SHUTDOWN);
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tracker()->WaitUntilTasksBlocked(kNumWorkerThreads);
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now post an additional task as SKIP_ON_SHUTDOWN, which should not be
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // executed once Shutdown() has been called.
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->PostWorkerTaskWithShutdownBehavior(
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&TestTracker::BlockTask,
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 tracker(), 0, &blocker),
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SequencedWorkerPool::SKIP_ON_SHUTDOWN);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This callback will only be invoked if SKIP_ON_SHUTDOWN tasks that have
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // been started block shutdown.
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetWillWaitForShutdownCallback(
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&EnsureTasksToCompleteCountAndUnblock,
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 scoped_refptr<TestTracker>(tracker()), 0,
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 &blocker, kNumWorkerThreads));
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No tasks should have completed yet.
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, tracker()->WaitUntilTasksComplete(0).size());
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should not block. If this test hangs, it means it failed.
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->Shutdown();
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shutdown should not return until all of the tasks have completed.
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int> result =
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tracker()->WaitUntilTasksComplete(kNumWorkerThreads);
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only tasks marked SKIP_ON_SHUTDOWN that were already started should be
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // allowed to complete. No additional non-blocking tasks should have been
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // started.
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(kNumWorkerThreads, result.size());
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < kNumWorkerThreads; i++) {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(std::find(result.begin(), result.end(), static_cast<int>(i)) !=
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                result.end());
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ensure all worker threads are created, and then trigger a spurious
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// work signal. This shouldn't cause any other work signals to be
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// triggered. This is a regression test for http://crbug.com/117469.
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, SpuriousWorkSignal) {
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureAllWorkersCreated();
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int old_has_work_call_count = has_work_call_count();
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->SignalHasWorkForTesting();
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is inherently racy, but can only produce false positives.
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(old_has_work_call_count + 1, has_work_call_count());
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void IsRunningOnCurrentThreadTask(
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SequencedWorkerPool::SequenceToken test_positive_token,
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SequencedWorkerPool::SequenceToken test_negative_token,
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SequencedWorkerPool* pool,
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SequencedWorkerPool* unused_pool) {
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(pool->RunsTasksOnCurrentThread());
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(pool->IsRunningSequenceOnCurrentThread(test_positive_token));
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(pool->IsRunningSequenceOnCurrentThread(test_negative_token));
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(unused_pool->RunsTasksOnCurrentThread());
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unused_pool->IsRunningSequenceOnCurrentThread(test_positive_token));
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unused_pool->IsRunningSequenceOnCurrentThread(test_negative_token));
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify correctness of the IsRunningSequenceOnCurrentThread method.
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SequencedWorkerPoolTest, IsRunningOnCurrentThread) {
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPool::SequenceToken token1 = pool()->GetSequenceToken();
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPool::SequenceToken token2 = pool()->GetSequenceToken();
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPool::SequenceToken unsequenced_token;
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SequencedWorkerPool> unused_pool =
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SequencedWorkerPool(2, "unused_pool");
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(pool()->RunsTasksOnCurrentThread());
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(token1));
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(token2));
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(pool()->IsRunningSequenceOnCurrentThread(unsequenced_token));
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(unused_pool->RunsTasksOnCurrentThread());
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(unused_pool->IsRunningSequenceOnCurrentThread(token1));
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(unused_pool->IsRunningSequenceOnCurrentThread(token2));
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unused_pool->IsRunningSequenceOnCurrentThread(unsequenced_token));
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->PostSequencedWorkerTask(
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      token1, FROM_HERE,
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&IsRunningOnCurrentThreadTask,
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 token1, token2, pool(), unused_pool));
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->PostSequencedWorkerTask(
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      token2, FROM_HERE,
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&IsRunningOnCurrentThreadTask,
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 token2, unsequenced_token, pool(), unused_pool));
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->PostWorkerTask(
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&IsRunningOnCurrentThreadTask,
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 unsequenced_token, token1, pool(), unused_pool));
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pool()->Shutdown();
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unused_pool->Shutdown();
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Verify that FlushForTesting works as intended.
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SequencedWorkerPoolTest, FlushForTesting) {
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Should be fine to call on a new instance.
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pool()->FlushForTesting();
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Queue up a bunch of work, including  a long delayed task and
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a task that produces additional tasks as an artifact.
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pool()->PostDelayedWorkerTask(
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&TestTracker::FastTask, tracker(), 0),
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TimeDelta::FromMinutes(5));
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pool()->PostWorkerTask(FROM_HERE,
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         base::Bind(&TestTracker::SlowTask, tracker(), 0));
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t kNumFastTasks = 20;
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < kNumFastTasks; i++) {
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pool()->PostWorkerTask(FROM_HERE,
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           base::Bind(&TestTracker::FastTask, tracker(), 0));
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pool()->PostWorkerTask(
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&TestTracker::PostAdditionalTasks, tracker(), 0, pool(),
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 true));
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We expect all except the delayed task to have been run. We verify all
782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // closures have been deleted by looking at the refcount of the
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // tracker.
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(tracker()->HasOneRef());
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pool()->FlushForTesting();
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(tracker()->HasOneRef());
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1 + kNumFastTasks + 1 + 3, tracker()->GetTasksCompletedCount());
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Should be fine to call on an idle instance with all threads created, and
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // spamming the method shouldn't deadlock or confuse the class.
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pool()->FlushForTesting();
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pool()->FlushForTesting();
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Should be fine to call after shutdown too.
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pool()->Shutdown();
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pool()->FlushForTesting();
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
799c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(SequencedWorkerPoolRefPtrTest, ShutsDownCleanWithContinueOnShutdown) {
800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MessageLoop loop;
801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<SequencedWorkerPool> pool(new SequencedWorkerPool(3, "Pool"));
802c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<SequencedTaskRunner> task_runner =
803c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pool->GetSequencedTaskRunnerWithShutdownBehavior(
804c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          pool->GetSequenceToken(),
805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
807c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Upon test exit, should shut down without hanging.
808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pool->Shutdown();
809c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
810c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SequencedWorkerPoolTaskRunnerTestDelegate {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPoolTaskRunnerTestDelegate() {}
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~SequencedWorkerPoolTaskRunnerTestDelegate() {}
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartTaskRunner() {
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool_owner_.reset(
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new SequencedWorkerPoolOwner(10, "SequencedWorkerPoolTaskRunnerTest"));
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SequencedWorkerPool> GetTaskRunner() {
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return pool_owner_->pool();
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StopTaskRunner() {
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Make sure all tasks are run before shutting down. Delayed tasks are
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // not run, they're simply deleted.
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool_owner_->pool()->FlushForTesting();
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool_owner_->pool()->Shutdown();
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't reset |pool_owner_| here, as the test may still hold a
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // reference to the pool.
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop message_loop_;
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SequencedWorkerPoolOwner> pool_owner_;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TYPED_TEST_CASE_P(
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SequencedWorkerPool, TaskRunnerTest,
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SequencedWorkerPoolTaskRunnerTestDelegate);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SequencedWorkerPoolTaskRunnerWithShutdownBehaviorTestDelegate {
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPoolTaskRunnerWithShutdownBehaviorTestDelegate() {}
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~SequencedWorkerPoolTaskRunnerWithShutdownBehaviorTestDelegate() {
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartTaskRunner() {
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool_owner_.reset(
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new SequencedWorkerPoolOwner(10, "SequencedWorkerPoolTaskRunnerTest"));
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    task_runner_ = pool_owner_->pool()->GetTaskRunnerWithShutdownBehavior(
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SequencedWorkerPool::BLOCK_SHUTDOWN);
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<TaskRunner> GetTaskRunner() {
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return task_runner_;
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StopTaskRunner() {
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Make sure all tasks are run before shutting down. Delayed tasks are
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // not run, they're simply deleted.
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool_owner_->pool()->FlushForTesting();
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool_owner_->pool()->Shutdown();
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't reset |pool_owner_| here, as the test may still hold a
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // reference to the pool.
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop message_loop_;
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SequencedWorkerPoolOwner> pool_owner_;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<TaskRunner> task_runner_;
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TYPED_TEST_CASE_P(
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SequencedWorkerPoolTaskRunner, TaskRunnerTest,
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SequencedWorkerPoolTaskRunnerWithShutdownBehaviorTestDelegate);
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SequencedWorkerPoolSequencedTaskRunnerTestDelegate {
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SequencedWorkerPoolSequencedTaskRunnerTestDelegate() {}
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~SequencedWorkerPoolSequencedTaskRunnerTestDelegate() {
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartTaskRunner() {
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool_owner_.reset(new SequencedWorkerPoolOwner(
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        10, "SequencedWorkerPoolSequencedTaskRunnerTest"));
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    task_runner_ = pool_owner_->pool()->GetSequencedTaskRunner(
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pool_owner_->pool()->GetSequenceToken());
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SequencedTaskRunner> GetTaskRunner() {
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return task_runner_;
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StopTaskRunner() {
9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Make sure all tasks are run before shutting down. Delayed tasks are
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // not run, they're simply deleted.
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool_owner_->pool()->FlushForTesting();
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pool_owner_->pool()->Shutdown();
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't reset |pool_owner_| here, as the test may still hold a
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // reference to the pool.
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop message_loop_;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SequencedWorkerPoolOwner> pool_owner_;
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SequencedTaskRunner> task_runner_;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TYPED_TEST_CASE_P(
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SequencedWorkerPoolSequencedTaskRunner, TaskRunnerTest,
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SequencedWorkerPoolSequencedTaskRunnerTestDelegate);
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TYPED_TEST_CASE_P(
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SequencedWorkerPoolSequencedTaskRunner, SequencedTaskRunnerTest,
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SequencedWorkerPoolSequencedTaskRunnerTestDelegate);
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
925