// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/threading/worker_pool.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/location.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/synchronization/waitable_event.h" #include "base/test/test_timeouts.h" #include "base/threading/thread_checker_impl.h" #include "base/time/time.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" typedef PlatformTest WorkerPoolTest; namespace base { namespace { class PostTaskAndReplyTester : public base::RefCountedThreadSafe<PostTaskAndReplyTester> { public: PostTaskAndReplyTester() : finished_(false), test_event_(false, false) {} void RunTest() { ASSERT_TRUE(thread_checker_.CalledOnValidThread()); WorkerPool::PostTaskAndReply( FROM_HERE, base::Bind(&PostTaskAndReplyTester::OnWorkerThread, this), base::Bind(&PostTaskAndReplyTester::OnOriginalThread, this), false); test_event_.Wait(); } void OnWorkerThread() { // We're not on the original thread. EXPECT_FALSE(thread_checker_.CalledOnValidThread()); test_event_.Signal(); } void OnOriginalThread() { EXPECT_TRUE(thread_checker_.CalledOnValidThread()); finished_ = true; } bool finished() const { return finished_; } private: friend class base::RefCountedThreadSafe<PostTaskAndReplyTester>; ~PostTaskAndReplyTester() {} bool finished_; WaitableEvent test_event_; // The Impl version performs its checks even in release builds. ThreadCheckerImpl thread_checker_; }; } // namespace TEST_F(WorkerPoolTest, PostTask) { WaitableEvent test_event(false, false); WaitableEvent long_test_event(false, false); WorkerPool::PostTask(FROM_HERE, base::Bind(&WaitableEvent::Signal, base::Unretained(&test_event)), false); WorkerPool::PostTask(FROM_HERE, base::Bind(&WaitableEvent::Signal, base::Unretained(&long_test_event)), true); test_event.Wait(); long_test_event.Wait(); } #if defined(OS_WIN) || defined(OS_LINUX) // Flaky on Windows and Linux (http://crbug.com/130337) #define MAYBE_PostTaskAndReply DISABLED_PostTaskAndReply #else #define MAYBE_PostTaskAndReply PostTaskAndReply #endif TEST_F(WorkerPoolTest, MAYBE_PostTaskAndReply) { MessageLoop message_loop; scoped_refptr<PostTaskAndReplyTester> tester(new PostTaskAndReplyTester()); tester->RunTest(); const TimeDelta kMaxDuration = TestTimeouts::tiny_timeout(); TimeTicks start = TimeTicks::Now(); while (!tester->finished() && TimeTicks::Now() - start < kMaxDuration) { #if defined(OS_IOS) // Ensure that the other thread has a chance to run even on a single-core // device. pthread_yield_np(); #endif RunLoop().RunUntilIdle(); } EXPECT_TRUE(tester->finished()); } } // namespace base