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