root/base/test/test_support_android.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GetInstance
  2. Signal
  3. Block
  4. Quit
  5. Start
  6. Run
  7. Quit
  8. ScheduleWork
  9. ScheduleDelayedWork
  10. CreateMessagePumpForUIStub
  11. GetTestProviderPath
  12. InitPathProvider
  13. InitAndroidTestLogging
  14. InitAndroidTestPaths
  15. InitAndroidTestMessageLoop
  16. InitAndroidTest

// 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 <stdarg.h>
#include <string.h>

#include "base/android/path_utils.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_pump_android.h"
#include "base/path_service.h"
#include "base/synchronization/waitable_event.h"

namespace {

struct RunState {
  RunState(base::MessagePump::Delegate* delegate, int run_depth)
      : delegate(delegate),
        run_depth(run_depth),
        should_quit(false) {
  }

  base::MessagePump::Delegate* delegate;

  // Used to count how many Run() invocations are on the stack.
  int run_depth;

  // Used to flag that the current Run() invocation should return ASAP.
  bool should_quit;
};

RunState* g_state = NULL;

// A singleton WaitableEvent wrapper so we avoid a busy loop in
// MessagePumpForUIStub. Other platforms use the native event loop which blocks
// when there are no pending messages.
class Waitable {
 public:
   static Waitable* GetInstance() {
     return Singleton<Waitable>::get();
   }

   // Signals that there are more work to do.
   void Signal() {
     waitable_event_.Signal();
   }

   // Blocks until more work is scheduled.
   void Block() {
     waitable_event_.Wait();
   }

   void Quit() {
     g_state->should_quit = true;
     Signal();
   }

 private:
  friend struct DefaultSingletonTraits<Waitable>;

  Waitable()
      : waitable_event_(false, false) {
  }

  base::WaitableEvent waitable_event_;

  DISALLOW_COPY_AND_ASSIGN(Waitable);
};

// The MessagePumpForUI implementation for test purpose.
class MessagePumpForUIStub : public base::MessagePumpForUI {
  virtual ~MessagePumpForUIStub() {}

  virtual void Start(base::MessagePump::Delegate* delegate) OVERRIDE {
    NOTREACHED() << "The Start() method shouldn't be called in test, using"
        " Run() method should be used.";
  }

  virtual void Run(base::MessagePump::Delegate* delegate) OVERRIDE {
    // The following was based on message_pump_glib.cc, except we're using a
    // WaitableEvent since there are no native message loop to use.
    RunState state(delegate, g_state ? g_state->run_depth + 1 : 1);

    RunState* previous_state = g_state;
    g_state = &state;

    bool more_work_is_plausible = true;

    for (;;) {
      if (!more_work_is_plausible) {
        Waitable::GetInstance()->Block();
        if (g_state->should_quit)
          break;
      }

      more_work_is_plausible = g_state->delegate->DoWork();
      if (g_state->should_quit)
        break;

      base::TimeTicks delayed_work_time;
      more_work_is_plausible |=
          g_state->delegate->DoDelayedWork(&delayed_work_time);
      if (g_state->should_quit)
        break;

      if (more_work_is_plausible)
        continue;

      more_work_is_plausible = g_state->delegate->DoIdleWork();
      if (g_state->should_quit)
        break;

      more_work_is_plausible |= !delayed_work_time.is_null();
    }

    g_state = previous_state;
  }

  virtual void Quit() OVERRIDE {
    Waitable::GetInstance()->Quit();
  }

  virtual void ScheduleWork() OVERRIDE {
    Waitable::GetInstance()->Signal();
  }

  virtual void ScheduleDelayedWork(
      const base::TimeTicks& delayed_work_time) OVERRIDE {
    Waitable::GetInstance()->Signal();
  }
};

scoped_ptr<base::MessagePump> CreateMessagePumpForUIStub() {
  return scoped_ptr<base::MessagePump>(new MessagePumpForUIStub());
};

// Provides the test path for DIR_MODULE and DIR_ANDROID_APP_DATA.
bool GetTestProviderPath(int key, base::FilePath* result) {
  switch (key) {
    case base::DIR_MODULE: {
      return base::android::GetExternalStorageDirectory(result);
    }
    case base::DIR_ANDROID_APP_DATA: {
      // For tests, app data is put in external storage.
      return base::android::GetExternalStorageDirectory(result);
    }
    default:
      return false;
  }
}

void InitPathProvider(int key) {
  base::FilePath path;
  // If failed to override the key, that means the way has not been registered.
  if (GetTestProviderPath(key, &path) && !PathService::Override(key, path))
    PathService::RegisterProvider(&GetTestProviderPath, key, key + 1);
}

}  // namespace

namespace base {

void InitAndroidTestLogging() {
  logging::LoggingSettings settings;
  settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
  logging::InitLogging(settings);
  // To view log output with IDs and timestamps use "adb logcat -v threadtime".
  logging::SetLogItems(false,    // Process ID
                       false,    // Thread ID
                       false,    // Timestamp
                       false);   // Tick count
}

void InitAndroidTestPaths() {
  InitPathProvider(DIR_MODULE);
  InitPathProvider(DIR_ANDROID_APP_DATA);
}

void InitAndroidTestMessageLoop() {
  if (!MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUIStub))
    LOG(INFO) << "MessagePumpForUIFactory already set, unable to override.";
}

void InitAndroidTest() {
  InitAndroidTestLogging();
  InitAndroidTestPaths();
  InitAndroidTestMessageLoop();
}
}  // namespace base

/* [<][>][^][v][top][bottom][index][help] */