serial_runner_unittest.cc revision 424c4d7b64af9d0d8fd9624f381f469654d5e3d2
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/debug/stack_trace.h" 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/message_loop/message_loop.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/pipeline_status.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/serial_runner.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace media { 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SerialRunnerTest : public ::testing::Test { 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SerialRunnerTest() 178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : inside_start_(false), done_called_(false), done_status_(PIPELINE_OK) {} 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~SerialRunnerTest() {} 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void RunSerialRunner() { 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_loop_.PostTask(FROM_HERE, base::Bind( 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &SerialRunnerTest::StartRunnerInternal, base::Unretained(this), 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bound_fns_)); 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) message_loop_.RunUntilIdle(); 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Pushes a bound function to the queue that will run its callback with 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // |status|. called(i) returns whether the i'th bound function pushed to the 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // queue was called while running the SerialRunner. 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void PushBoundFunction(PipelineStatus status) { 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bound_fns_.Push(base::Bind(&SerialRunnerTest::RunBoundFunction, 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this), 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) status, 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) called_.size())); 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) called_.push_back(false); 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Push a bound function to the queue that will delete the SerialRunner, 393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // which should cancel all remaining queued work. 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void PushCancellation() { 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bound_fns_.Push(base::Bind(&SerialRunnerTest::CancelSerialRunner, 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Unretained(this))); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Queries final status of pushed functions and done callback. Valid only 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // after calling RunSerialRunner(). 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool called(size_t index) { return called_[index]; } 48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bool done_called() { return done_called_; } 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PipelineStatus done_status() { return done_status_; } 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void RunBoundFunction(PipelineStatus status, 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t index, 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const PipelineStatusCB& status_cb) { 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(index == 0u, inside_start_) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "First bound function should run on same stack as " 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "SerialRunner::Run() while all others should not\n" 58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) << base::debug::StackTrace().ToString(); 59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) called_[index] = true; 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) status_cb.Run(status); 624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) void StartRunnerInternal(const SerialRunner::Queue& bound_fns) { 654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) inside_start_ = true; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) runner_ = SerialRunner::Run(bound_fns_, base::Bind( 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &SerialRunnerTest::DoneCallback, base::Unretained(this))); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) inside_start_ = false; 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void DoneCallback(PipelineStatus status) { 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(inside_start_) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "Done callback should not run on same stack as SerialRunner::Run()\n" 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << base::debug::StackTrace().ToString(); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) done_called_ = true; 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) done_status_ = status; 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_loop_.QuitWhenIdle(); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void CancelSerialRunner(const PipelineStatusCB& status_cb) { 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Tasks run by |runner_| shouldn't reset it, hence we post a task to do so. 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_loop_.PostTask(FROM_HERE, base::Bind( 840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &SerialRunnerTest::ResetSerialRunner, base::Unretained(this))); 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) status_cb.Run(PIPELINE_OK); 863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void ResetSerialRunner() { 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) runner_.reset(); 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::MessageLoop message_loop_; 930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch SerialRunner::Queue bound_fns_; 94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<SerialRunner> runner_; 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Used to enforce calling stack guarantees of the API. 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool inside_start_; 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Tracks whether the i'th bound function was called. 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<bool> called_; 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Tracks whether the final done callback was called + resulting status. 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool done_called_; 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PipelineStatus done_status_; 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SerialRunnerTest); 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SerialRunnerTest, Empty) { 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunSerialRunner(); 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(done_called()); 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(PIPELINE_OK, done_status()); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SerialRunnerTest, Single) { 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PushBoundFunction(PIPELINE_OK); 1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) RunSerialRunner(); 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_TRUE(called(0)); 121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_TRUE(done_called()); 122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_EQ(PIPELINE_OK, done_status()); 1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(SerialRunnerTest, Single_Error) { 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PushBoundFunction(PIPELINE_ERROR_ABORT); 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RunSerialRunner(); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(called(0)); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(done_called()); 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_EQ(PIPELINE_ERROR_ABORT, done_status()); 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SerialRunnerTest, Single_Cancel) { 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PushBoundFunction(PIPELINE_OK); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PushCancellation(); 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RunSerialRunner(); 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(called(0)); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(done_called()); 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SerialRunnerTest, Multiple) { 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PushBoundFunction(PIPELINE_OK); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PushBoundFunction(PIPELINE_OK); 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) RunSerialRunner(); 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_TRUE(called(0)); 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_TRUE(called(1)); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(done_called()); 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(PIPELINE_OK, done_status()); 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SerialRunnerTest, Multiple_Error) { 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PushBoundFunction(PIPELINE_ERROR_ABORT); 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PushBoundFunction(PIPELINE_OK); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RunSerialRunner(); 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_TRUE(called(0)); 1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_FALSE(called(1)); // A bad status cancels remaining work. 161effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_TRUE(done_called()); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(PIPELINE_ERROR_ABORT, done_status()); 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SerialRunnerTest, Multiple_Cancel) { 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PushBoundFunction(PIPELINE_OK); 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PushCancellation(); 168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PushBoundFunction(PIPELINE_OK); 1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) RunSerialRunner(); 1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(called(0)); 1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_FALSE(called(1)); 1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_FALSE(done_called()); 174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace media 177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)