1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/deferred_sequenced_task_runner.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/basictypes.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind_helpers.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/ref_counted.h"
11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/threading/non_thread_safe.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/threading/thread.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class DeferredSequencedTaskRunnerTest : public testing::Test,
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        public base::NonThreadSafe {
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  class ExecuteTaskOnDestructor :
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      public base::RefCounted<ExecuteTaskOnDestructor> {
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   public:
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ExecuteTaskOnDestructor(
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        DeferredSequencedTaskRunnerTest* executor,
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        int task_id)
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        : executor_(executor),
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          task_id_(task_id) {
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  private:
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    friend class base::RefCounted<ExecuteTaskOnDestructor>;
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    virtual ~ExecuteTaskOnDestructor() {
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      executor_->ExecuteTask(task_id_);
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DeferredSequencedTaskRunnerTest* executor_;
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int task_id_;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void ExecuteTask(int task_id) {
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::AutoLock lock(lock_);
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    executed_task_ids_.push_back(task_id);
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void PostExecuteTask(int task_id) {
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    runner_->PostTask(FROM_HERE,
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      base::Bind(&DeferredSequencedTaskRunnerTest::ExecuteTask,
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 base::Unretained(this),
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 task_id));
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void StartRunner() {
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    runner_->Start();
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void DoNothing(ExecuteTaskOnDestructor* object) {
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DeferredSequencedTaskRunnerTest() :
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      loop_(),
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      runner_(
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          new base::DeferredSequencedTaskRunner(loop_.message_loop_proxy())) {
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoop loop_;
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<base::DeferredSequencedTaskRunner> runner_;
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  mutable base::Lock lock_;
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<int> executed_task_ids_;
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(DeferredSequencedTaskRunnerTest, Stopped) {
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PostExecuteTask(1);
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop_.RunUntilIdle();
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(DeferredSequencedTaskRunnerTest, Start) {
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartRunner();
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PostExecuteTask(1);
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop_.RunUntilIdle();
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1));
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(DeferredSequencedTaskRunnerTest, StartWithMultipleElements) {
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartRunner();
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (int i = 1; i < 5; ++i)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PostExecuteTask(i);
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop_.RunUntilIdle();
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2, 3, 4));
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(DeferredSequencedTaskRunnerTest, DeferredStart) {
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PostExecuteTask(1);
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop_.RunUntilIdle();
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartRunner();
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop_.RunUntilIdle();
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1));
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PostExecuteTask(2);
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop_.RunUntilIdle();
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2));
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(DeferredSequencedTaskRunnerTest, DeferredStartWithMultipleElements) {
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (int i = 1; i < 5; ++i)
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PostExecuteTask(i);
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop_.RunUntilIdle();
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StartRunner();
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (int i = 5; i < 9; ++i)
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PostExecuteTask(i);
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop_.RunUntilIdle();
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2, 3, 4, 5, 6, 7, 8));
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(DeferredSequencedTaskRunnerTest, DeferredStartWithMultipleThreads) {
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  {
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::Thread thread1("DeferredSequencedTaskRunnerTestThread1");
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::Thread thread2("DeferredSequencedTaskRunnerTestThread2");
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    thread1.Start();
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    thread2.Start();
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (int i = 0; i < 5; ++i) {
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      thread1.message_loop()->PostTask(
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          FROM_HERE,
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::Bind(&DeferredSequencedTaskRunnerTest::PostExecuteTask,
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     base::Unretained(this),
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     2 * i));
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      thread2.message_loop()->PostTask(
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          FROM_HERE,
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          base::Bind(&DeferredSequencedTaskRunnerTest::PostExecuteTask,
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     base::Unretained(this),
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     2 * i + 1));
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (i == 2) {
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        thread1.message_loop()->PostTask(
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            FROM_HERE,
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            base::Bind(&DeferredSequencedTaskRunnerTest::StartRunner,
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       base::Unretained(this)));
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop_.RunUntilIdle();
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_THAT(executed_task_ids_,
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      testing::WhenSorted(testing::ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)));
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(DeferredSequencedTaskRunnerTest, ObjectDestructionOrder) {
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  {
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::Thread thread("DeferredSequencedTaskRunnerTestThread");
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    thread.Start();
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    runner_ =
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        new base::DeferredSequencedTaskRunner(thread.message_loop_proxy());
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (int i = 0; i < 5; ++i) {
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      {
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Use a block to ensure that no reference to |short_lived_object|
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // is kept on the main thread after it is posted to |runner_|.
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        scoped_refptr<ExecuteTaskOnDestructor> short_lived_object =
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            new ExecuteTaskOnDestructor(this, 2 * i);
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        runner_->PostTask(
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            FROM_HERE,
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            base::Bind(&DeferredSequencedTaskRunnerTest::DoNothing,
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       base::Unretained(this),
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       short_lived_object));
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // |short_lived_object| with id |2 * i| should be destroyed before the
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // task |2 * i + 1| is executed.
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      PostExecuteTask(2 * i + 1);
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StartRunner();
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // All |short_lived_object| with id |2 * i| are destroyed before the task
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |2 * i + 1| is executed.
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_THAT(executed_task_ids_,
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              testing::ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
185