1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 23345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Use of this source code is governed by a BSD-style license that can be 33345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// found in the LICENSE file. 43345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 53345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/basictypes.h" 63345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/logging.h" 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 83f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread_checker.h" 93f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/simple_thread.h" 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "testing/gtest/include/gtest/gtest.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsennamespace base { 133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Simple class to exercise the basics of ThreadChecker. 153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Both the destructor and DoStuff should verify that they were 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// called on the same thread as the constructor. 173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass ThreadCheckerClass : public ThreadChecker { 183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public: 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ThreadCheckerClass() {} 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Verifies that it was called on the same thread as the constructor. 223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void DoStuff() { 23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CHECK(CalledOnValidThread()); 243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 26731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick void DetachFromThread() { 27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ThreadChecker::DetachFromThread(); 28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 29731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen static void MethodOnDifferentThreadImpl(); 31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen static void DetachThenCallFromDifferentThreadImpl(); 32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private: 343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DISALLOW_COPY_AND_ASSIGN(ThreadCheckerClass); 353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}; 363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Calls ThreadCheckerClass::DoStuff on another thread. 383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass CallDoStuffOnThread : public base::SimpleThread { 393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public: 403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CallDoStuffOnThread(ThreadCheckerClass* thread_checker_class) 413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick : SimpleThread("call_do_stuff_on_thread"), 423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick thread_checker_class_(thread_checker_class) { 433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void Run() { 463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick thread_checker_class_->DoStuff(); 473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private: 503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ThreadCheckerClass* thread_checker_class_; 513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread); 533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}; 543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Deletes ThreadCheckerClass on a different thread. 563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass DeleteThreadCheckerClassOnThread : public base::SimpleThread { 573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public: 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DeleteThreadCheckerClassOnThread(ThreadCheckerClass* thread_checker_class) 593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick : SimpleThread("delete_thread_checker_class_on_thread"), 603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick thread_checker_class_(thread_checker_class) { 613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick virtual void Run() { 643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick thread_checker_class_.reset(); 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private: 683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_ptr<ThreadCheckerClass> thread_checker_class_; 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DISALLOW_COPY_AND_ASSIGN(DeleteThreadCheckerClassOnThread); 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}; 723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST(ThreadCheckerTest, CallsAllowedOnSameThread) { 743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_ptr<ThreadCheckerClass> thread_checker_class( 753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick new ThreadCheckerClass); 763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Verify that DoStuff doesn't assert. 783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick thread_checker_class->DoStuff(); 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Verify that the destructor doesn't assert. 813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick thread_checker_class.reset(); 823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 843345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTEST(ThreadCheckerTest, DestructorAllowedOnDifferentThread) { 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_ptr<ThreadCheckerClass> thread_checker_class( 863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick new ThreadCheckerClass); 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Verify that the destructor doesn't assert 893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // when called on a different thread. 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DeleteThreadCheckerClassOnThread delete_on_thread( 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick thread_checker_class.release()); 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delete_on_thread.Start(); 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delete_on_thread.Join(); 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 97731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickTEST(ThreadCheckerTest, DetachFromThread) { 98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick scoped_ptr<ThreadCheckerClass> thread_checker_class( 99731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick new ThreadCheckerClass); 100731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 101731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Verify that DoStuff doesn't assert when called on a different thread after 102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // a call to DetachFromThread. 103731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick thread_checker_class->DetachFromThread(); 104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CallDoStuffOnThread call_on_thread(thread_checker_class.get()); 105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 106731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick call_on_thread.Start(); 107731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick call_on_thread.Join(); 108731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if GTEST_HAS_DEATH_TEST || NDEBUG 1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ThreadCheckerClass::MethodOnDifferentThreadImpl() { 113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen scoped_ptr<ThreadCheckerClass> thread_checker_class( 114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen new ThreadCheckerClass); 1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // DoStuff should assert in debug builds only when called on a 117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // different thread. 118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CallDoStuffOnThread call_on_thread(thread_checker_class.get()); 1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen call_on_thread.Start(); 121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen call_on_thread.Join(); 1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#ifndef NDEBUG 125dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST(ThreadCheckerDeathTest, MethodNotAllowedOnDifferentThreadInDebug) { 126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ASSERT_DEBUG_DEATH({ 127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ThreadCheckerClass::MethodOnDifferentThreadImpl(); 128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }, ""); 129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#else 131dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST(ThreadCheckerTest, MethodAllowedOnDifferentThreadInRelease) { 132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ThreadCheckerClass::MethodOnDifferentThreadImpl(); 133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif // NDEBUG 135731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl() { 137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen scoped_ptr<ThreadCheckerClass> thread_checker_class( 138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen new ThreadCheckerClass); 139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // DoStuff doesn't assert when called on a different thread 141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // after a call to DetachFromThread. 142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen thread_checker_class->DetachFromThread(); 143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CallDoStuffOnThread call_on_thread(thread_checker_class.get()); 144731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen call_on_thread.Start(); 146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen call_on_thread.Join(); 147731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // DoStuff should assert in debug builds only after moving to 149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // another thread. 150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen thread_checker_class->DoStuff(); 151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#ifndef NDEBUG 154dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST(ThreadCheckerDeathTest, DetachFromThreadInDebug) { 155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ASSERT_DEBUG_DEATH({ 156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl(); 157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick }, ""); 158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#else 160dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST(ThreadCheckerTest, DetachFromThreadInRelease) { 161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ThreadCheckerClass::DetachThenCallFromDifferentThreadImpl(); 162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif // NDEBUG 164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif // GTEST_HAS_DEATH_TEST || NDEBUG 1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} // namespace base 168