test_support_android.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <stdarg.h> 6#include <string.h> 7 8#include "base/android/path_utils.h" 9#include "base/files/file_path.h" 10#include "base/logging.h" 11#include "base/memory/singleton.h" 12#include "base/message_loop/message_loop.h" 13#include "base/message_loop/message_pump_android.h" 14#include "base/path_service.h" 15#include "base/synchronization/waitable_event.h" 16 17namespace { 18 19struct RunState { 20 RunState(base::MessagePump::Delegate* delegate, int run_depth) 21 : delegate(delegate), 22 run_depth(run_depth), 23 should_quit(false) { 24 } 25 26 base::MessagePump::Delegate* delegate; 27 28 // Used to count how many Run() invocations are on the stack. 29 int run_depth; 30 31 // Used to flag that the current Run() invocation should return ASAP. 32 bool should_quit; 33}; 34 35RunState* g_state = NULL; 36 37// A singleton WaitableEvent wrapper so we avoid a busy loop in 38// MessagePumpForUIStub. Other platforms use the native event loop which blocks 39// when there are no pending messages. 40class Waitable { 41 public: 42 static Waitable* GetInstance() { 43 return Singleton<Waitable>::get(); 44 } 45 46 // Signals that there are more work to do. 47 void Signal() { 48 waitable_event_.Signal(); 49 } 50 51 // Blocks until more work is scheduled. 52 void Block() { 53 waitable_event_.Wait(); 54 } 55 56 void Quit() { 57 g_state->should_quit = true; 58 Signal(); 59 } 60 61 private: 62 friend struct DefaultSingletonTraits<Waitable>; 63 64 Waitable() 65 : waitable_event_(false, false) { 66 } 67 68 base::WaitableEvent waitable_event_; 69 70 DISALLOW_COPY_AND_ASSIGN(Waitable); 71}; 72 73// The MessagePumpForUI implementation for test purpose. 74class MessagePumpForUIStub : public base::MessagePumpForUI { 75 virtual ~MessagePumpForUIStub() {} 76 77 virtual void Start(base::MessagePump::Delegate* delegate) OVERRIDE { 78 NOTREACHED() << "The Start() method shouldn't be called in test, using" 79 " Run() method should be used."; 80 } 81 82 virtual void Run(base::MessagePump::Delegate* delegate) OVERRIDE { 83 // The following was based on message_pump_glib.cc, except we're using a 84 // WaitableEvent since there are no native message loop to use. 85 RunState state(delegate, g_state ? g_state->run_depth + 1 : 1); 86 87 RunState* previous_state = g_state; 88 g_state = &state; 89 90 bool more_work_is_plausible = true; 91 92 for (;;) { 93 if (!more_work_is_plausible) { 94 Waitable::GetInstance()->Block(); 95 if (g_state->should_quit) 96 break; 97 } 98 99 more_work_is_plausible = g_state->delegate->DoWork(); 100 if (g_state->should_quit) 101 break; 102 103 base::TimeTicks delayed_work_time; 104 more_work_is_plausible |= 105 g_state->delegate->DoDelayedWork(&delayed_work_time); 106 if (g_state->should_quit) 107 break; 108 109 if (more_work_is_plausible) 110 continue; 111 112 more_work_is_plausible = g_state->delegate->DoIdleWork(); 113 if (g_state->should_quit) 114 break; 115 116 more_work_is_plausible |= !delayed_work_time.is_null(); 117 } 118 119 g_state = previous_state; 120 } 121 122 virtual void Quit() OVERRIDE { 123 Waitable::GetInstance()->Quit(); 124 } 125 126 virtual void ScheduleWork() OVERRIDE { 127 Waitable::GetInstance()->Signal(); 128 } 129 130 virtual void ScheduleDelayedWork( 131 const base::TimeTicks& delayed_work_time) OVERRIDE { 132 Waitable::GetInstance()->Signal(); 133 } 134}; 135 136scoped_ptr<base::MessagePump> CreateMessagePumpForUIStub() { 137 return scoped_ptr<base::MessagePump>(new MessagePumpForUIStub()); 138}; 139 140// Provides the test path for DIR_MODULE and DIR_ANDROID_APP_DATA. 141bool GetTestProviderPath(int key, base::FilePath* result) { 142 switch (key) { 143 case base::DIR_ANDROID_APP_DATA: { 144 // For tests, app data is put in external storage. 145 return base::android::GetExternalStorageDirectory(result); 146 } 147 default: 148 return false; 149 } 150} 151 152void InitPathProvider(int key) { 153 base::FilePath path; 154 // If failed to override the key, that means the way has not been registered. 155 if (GetTestProviderPath(key, &path) && !PathService::Override(key, path)) 156 PathService::RegisterProvider(&GetTestProviderPath, key, key + 1); 157} 158 159} // namespace 160 161namespace base { 162 163void InitAndroidTestLogging() { 164 logging::LoggingSettings settings; 165 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; 166 logging::InitLogging(settings); 167 // To view log output with IDs and timestamps use "adb logcat -v threadtime". 168 logging::SetLogItems(false, // Process ID 169 false, // Thread ID 170 false, // Timestamp 171 false); // Tick count 172} 173 174void InitAndroidTestPaths() { 175 InitPathProvider(DIR_MODULE); 176 InitPathProvider(DIR_ANDROID_APP_DATA); 177} 178 179void InitAndroidTestMessageLoop() { 180 if (!MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUIStub)) 181 LOG(INFO) << "MessagePumpForUIFactory already set, unable to override."; 182} 183 184void InitAndroidTest() { 185 InitAndroidTestLogging(); 186 InitAndroidTestPaths(); 187 InitAndroidTestMessageLoop(); 188} 189} // namespace base 190