test_support_android.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file. 4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <stdarg.h> 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <string.h> 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/android/path_utils.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_path.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/logging.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/memory/singleton.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_pump_android.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/path_service.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace { 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)struct RunState { 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RunState(base::MessagePump::Delegate* delegate, int run_depth) 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : delegate(delegate), 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) run_depth(run_depth), 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) should_quit(false) { 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::MessagePump::Delegate* delegate; 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Used to count how many Run() invocations are on the stack. 29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int run_depth; 30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Used to flag that the current Run() invocation should return ASAP. 32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool should_quit; 33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}; 34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)RunState* g_state = NULL; 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// A singleton WaitableEvent wrapper so we avoid a busy loop in 38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// MessagePumpForUIStub. Other platforms use the native event loop which blocks 39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// when there are no pending messages. 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class Waitable { 41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public: 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) static Waitable* GetInstance() { 43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Singleton<Waitable>::get(); 44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Signals that there are more work to do. 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void Signal() { 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) waitable_event_.Signal(); 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Blocks until more work is scheduled. 52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void Block() { 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) waitable_event_.Wait(); 54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void Quit() { 57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) g_state->should_quit = true; 58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Signal(); 59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private: 62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) friend struct DefaultSingletonTraits<Waitable>; 63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Waitable() 65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : waitable_event_(false, false) { 66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::WaitableEvent waitable_event_; 69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Waitable); 71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}; 72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// The MessagePumpForUI implementation for test purpose. 74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class MessagePumpForUIStub : public base::MessagePumpForUI { 75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual ~MessagePumpForUIStub() {} 76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual void Start(base::MessagePump::Delegate* delegate) OVERRIDE { 78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NOTREACHED() << "The Start() method shouldn't be called in test, using" 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) " Run() method should be used."; 80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual void Run(base::MessagePump::Delegate* delegate) OVERRIDE { 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // The following was based on message_pump_glib.cc, except we're using a 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // WaitableEvent since there are no native message loop to use. 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RunState state(delegate, g_state ? g_state->run_depth + 1 : 1); 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RunState* previous_state = g_state; 88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) g_state = &state; 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool more_work_is_plausible = true; 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (;;) { 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!more_work_is_plausible) { 94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Waitable::GetInstance()->Block(); 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (g_state->should_quit) 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 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 136base::MessagePump* CreateMessagePumpForUIStub() { 137 return 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_MODULE: { 144 return base::android::GetExternalStorageDirectory(result); 145 } 146 case base::DIR_ANDROID_APP_DATA: { 147 // For tests, app data is put in external storage. 148 return base::android::GetExternalStorageDirectory(result); 149 } 150 default: 151 return false; 152 } 153} 154 155void InitPathProvider(int key) { 156 base::FilePath path; 157 // If failed to override the key, that means the way has not been registered. 158 if (GetTestProviderPath(key, &path) && !PathService::Override(key, path)) 159 PathService::RegisterProvider(&GetTestProviderPath, key, key + 1); 160} 161 162} // namespace 163 164namespace base { 165 166void InitAndroidTestLogging() { 167 logging::LoggingSettings settings; 168 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; 169 logging::InitLogging(settings); 170 // To view log output with IDs and timestamps use "adb logcat -v threadtime". 171 logging::SetLogItems(false, // Process ID 172 false, // Thread ID 173 false, // Timestamp 174 false); // Tick count 175} 176 177void InitAndroidTestPaths() { 178 InitPathProvider(DIR_MODULE); 179 InitPathProvider(DIR_ANDROID_APP_DATA); 180} 181 182void InitAndroidTestMessageLoop() { 183 if (!MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUIStub)) 184 LOG(INFO) << "MessagePumpForUIFactory already set, unable to override."; 185} 186 187void InitAndroidTest() { 188 InitAndroidTestLogging(); 189 InitAndroidTestPaths(); 190 InitAndroidTestMessageLoop(); 191} 192} // namespace base 193