Invoke the iOS hook from TestSuite so each run_all_unittests.cc file does not
have to remember to install MainHook. BUG=None Review URL: https://chromiumcodereview.appspot.com/12321117 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188376 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@ -817,9 +817,6 @@
|
||||
'test/expectations/expectation.h',
|
||||
'test/expectations/parser.cc',
|
||||
'test/expectations/parser.h',
|
||||
'test/main_hook.cc',
|
||||
'test/main_hook.h',
|
||||
'test/main_hook_ios.mm',
|
||||
'test/mock_chrome_application_mac.h',
|
||||
'test/mock_chrome_application_mac.mm',
|
||||
'test/mock_devices_changed_observer.cc',
|
||||
|
@ -1,9 +0,0 @@
|
||||
// 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 "base/test/main_hook.h"
|
||||
|
||||
#if !defined(OS_IOS)
|
||||
MainHook::MainHook(MainType main_func, int argc, char* argv[]) {}
|
||||
#endif
|
@ -1,17 +0,0 @@
|
||||
// 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 "build/build_config.h"
|
||||
#include "base/basictypes.h"
|
||||
|
||||
// Provides a way of running code before gtest-based tests with access to
|
||||
// argv and argc.
|
||||
class MainHook {
|
||||
public:
|
||||
typedef int (*MainType)(int, char*[]);
|
||||
MainHook(MainType main_func, int argc, char* argv[]);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(MainHook);
|
||||
};
|
@ -1,108 +0,0 @@
|
||||
// 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 "base/test/main_hook.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#include "base/debug/debugger.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/mac/scoped_nsautorelease_pool.h"
|
||||
#include "base/memory/scoped_nsobject.h"
|
||||
|
||||
// Springboard will kill any iOS app that fails to check in after launch within
|
||||
// a given time. These two classes prevent this from happening.
|
||||
|
||||
// MainHook saves the chrome main() and calls UIApplicationMain(),
|
||||
// providing an application delegate class: ChromeUnitTestDelegate. The delegate
|
||||
// listens for UIApplicationDidFinishLaunchingNotification. When the
|
||||
// notification is received, it fires main() again to have the real work done.
|
||||
|
||||
// Example usage:
|
||||
// int main(int argc, char** argv) {
|
||||
// MainHook hook(main, argc, argv);
|
||||
// // Testing code goes here. There should be no code above MainHook. If
|
||||
// // there is, it will be run twice.
|
||||
// }
|
||||
|
||||
// Since the executable isn't likely to be a real iOS UI, the delegate puts up a
|
||||
// window displaying the app name. If a bunch of apps using MainHook are being
|
||||
// run in a row, this provides an indication of which one is currently running.
|
||||
|
||||
static MainHook::MainType g_main_func = NULL;
|
||||
static int g_argc;
|
||||
static char** g_argv;
|
||||
|
||||
@interface UIApplication (Testing)
|
||||
- (void) _terminateWithStatus:(int)status;
|
||||
@end
|
||||
|
||||
@interface ChromeUnitTestDelegate : NSObject {
|
||||
@private
|
||||
scoped_nsobject<UIWindow> window_;
|
||||
}
|
||||
- (void)runTests;
|
||||
@end
|
||||
|
||||
@implementation ChromeUnitTestDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
|
||||
CGRect bounds = [[UIScreen mainScreen] bounds];
|
||||
|
||||
// Yes, this is leaked, it's just to make what's running visible.
|
||||
window_.reset([[UIWindow alloc] initWithFrame:bounds]);
|
||||
[window_ makeKeyAndVisible];
|
||||
|
||||
// Add a label with the app name.
|
||||
UILabel* label = [[[UILabel alloc] initWithFrame:bounds] autorelease];
|
||||
label.text = [[NSProcessInfo processInfo] processName];
|
||||
label.textAlignment = NSTextAlignmentCenter;
|
||||
[window_ addSubview:label];
|
||||
|
||||
// Queue up the test run.
|
||||
[self performSelector:@selector(runTests)
|
||||
withObject:nil
|
||||
afterDelay:0.1];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)runTests {
|
||||
int exitStatus = g_main_func(g_argc, g_argv);
|
||||
|
||||
// If a test app is too fast, it will exit before Instruments has has a
|
||||
// a chance to initialize and no test results will be seen.
|
||||
// TODO(ios): crbug.com/137010 Figure out how much time is actually needed,
|
||||
// and sleep only to make sure that much time has elapsed since launch.
|
||||
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
|
||||
window_.reset();
|
||||
|
||||
// Use the hidden selector to try and cleanly take down the app (otherwise
|
||||
// things can think the app crashed even on a zero exit status).
|
||||
UIApplication* application = [UIApplication sharedApplication];
|
||||
[application _terminateWithStatus:exitStatus];
|
||||
|
||||
exit(exitStatus);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
MainHook::MainHook(MainType main_func, int argc, char* argv[]) {
|
||||
static bool ran_hook = false;
|
||||
if (!ran_hook) {
|
||||
ran_hook = true;
|
||||
|
||||
g_main_func = main_func;
|
||||
g_argc = argc;
|
||||
g_argv = argv;
|
||||
|
||||
base::mac::ScopedNSAutoreleasePool pool;
|
||||
int exit_status = UIApplicationMain(argc, argv, nil,
|
||||
@"ChromeUnitTestDelegate");
|
||||
exit(exit_status);
|
||||
}
|
||||
}
|
@ -2,10 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/test/main_hook.h"
|
||||
#include "base/test/perf_test_suite.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
MainHook hook(main, argc, argv);
|
||||
return base::PerfTestSuite(argc, argv).Run();
|
||||
}
|
||||
|
@ -2,10 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/test/main_hook.h"
|
||||
#include "base/test/test_suite.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
MainHook hook(main, argc, argv);
|
||||
return base::TestSuite(argc, argv).Run();
|
||||
}
|
||||
|
@ -116,6 +116,10 @@ void TestSuite::PreInitialize(int argc, char** argv,
|
||||
at_exit_manager_.reset(new base::AtExitManager);
|
||||
#endif
|
||||
|
||||
#if defined(OS_IOS)
|
||||
InitIOSRunHook(this, argc, argv);
|
||||
#endif
|
||||
|
||||
// Don't add additional code to this function. Instead add it to
|
||||
// Initialize(). See bug 6436.
|
||||
}
|
||||
@ -141,6 +145,10 @@ void TestSuite::ResetCommandLine() {
|
||||
// Don't add additional code to this method. Instead add it to
|
||||
// Initialize(). See bug 6436.
|
||||
int TestSuite::Run() {
|
||||
#if defined(OS_IOS)
|
||||
RunTestsFromIOSApp();
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
base::mac::ScopedNSAutoreleasePool scoped_pool;
|
||||
#endif
|
||||
|
@ -5,11 +5,20 @@
|
||||
#ifndef BASE_TEST_TEST_SUPPORT_IOS_H_
|
||||
#define BASE_TEST_TEST_SUPPORT_IOS_H_
|
||||
|
||||
#include "base/test/test_suite.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
// Init the message loop for tests on iOS.
|
||||
// Inits the message loop for tests on iOS.
|
||||
void InitIOSTestMessageLoop();
|
||||
|
||||
// Inits the run hook for tests on iOS.
|
||||
void InitIOSRunHook(TestSuite* suite, int argc, char* argv[]);
|
||||
|
||||
// Launches an iOS app that runs the tests in the suite passed to
|
||||
// InitIOSRunHook.
|
||||
void RunTestsFromIOSApp();
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_TEST_TEST_SUPPORT_IOS_H_
|
||||
|
@ -2,8 +2,88 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#include "base/debug/debugger.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/mac/scoped_nsautorelease_pool.h"
|
||||
#include "base/memory/scoped_nsobject.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "base/message_pump_default.h"
|
||||
#include "base/test/test_suite.h"
|
||||
|
||||
// Springboard will kill any iOS app that fails to check in after launch within
|
||||
// a given time. Starting a UIApplication before invoking TestSuite::Run
|
||||
// prevents this from happening.
|
||||
|
||||
// InitIOSRunHook saves the TestSuite and argc/argv, then invoking
|
||||
// RunTestsFromIOSApp calls UIApplicationMain(), providing an application
|
||||
// delegate class: ChromeUnitTestDelegate. The delegate implements
|
||||
// application:didFinishLaunchingWithOptions: to invoke the TestSuite's Run
|
||||
// method.
|
||||
|
||||
// Since the executable isn't likely to be a real iOS UI, the delegate puts up a
|
||||
// window displaying the app name. If a bunch of apps using MainHook are being
|
||||
// run in a row, this provides an indication of which one is currently running.
|
||||
|
||||
static base::TestSuite* g_test_suite = NULL;
|
||||
static int g_argc;
|
||||
static char** g_argv;
|
||||
|
||||
@interface UIApplication (Testing)
|
||||
- (void) _terminateWithStatus:(int)status;
|
||||
@end
|
||||
|
||||
@interface ChromeUnitTestDelegate : NSObject {
|
||||
@private
|
||||
scoped_nsobject<UIWindow> window_;
|
||||
}
|
||||
- (void)runTests;
|
||||
@end
|
||||
|
||||
@implementation ChromeUnitTestDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
|
||||
CGRect bounds = [[UIScreen mainScreen] bounds];
|
||||
|
||||
// Yes, this is leaked, it's just to make what's running visible.
|
||||
window_.reset([[UIWindow alloc] initWithFrame:bounds]);
|
||||
[window_ makeKeyAndVisible];
|
||||
|
||||
// Add a label with the app name.
|
||||
UILabel* label = [[[UILabel alloc] initWithFrame:bounds] autorelease];
|
||||
label.text = [[NSProcessInfo processInfo] processName];
|
||||
label.textAlignment = UITextAlignmentCenter;
|
||||
[window_ addSubview:label];
|
||||
|
||||
// Queue up the test run.
|
||||
[self performSelector:@selector(runTests)
|
||||
withObject:nil
|
||||
afterDelay:0.1];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)runTests {
|
||||
int exitStatus = g_test_suite->Run();
|
||||
|
||||
// If a test app is too fast, it will exit before Instruments has has a
|
||||
// a chance to initialize and no test results will be seen.
|
||||
// TODO(ios): crbug.com/137010 Figure out how much time is actually needed,
|
||||
// and sleep only to make sure that much time has elapsed since launch.
|
||||
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
|
||||
window_.reset();
|
||||
|
||||
// Use the hidden selector to try and cleanly take down the app (otherwise
|
||||
// things can think the app crashed even on a zero exit status).
|
||||
UIApplication* application = [UIApplication sharedApplication];
|
||||
[application _terminateWithStatus:exitStatus];
|
||||
|
||||
exit(exitStatus);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
namespace {
|
||||
|
||||
@ -20,4 +100,29 @@ void InitIOSTestMessageLoop() {
|
||||
MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUIForTests);
|
||||
}
|
||||
|
||||
void InitIOSRunHook(TestSuite* suite, int argc, char* argv[]) {
|
||||
g_test_suite = suite;
|
||||
g_argc = argc;
|
||||
g_argv = argv;
|
||||
}
|
||||
|
||||
void RunTestsFromIOSApp() {
|
||||
// When TestSuite::Run is invoked it calls RunTestsFromIOSApp(). On the first
|
||||
// invocation, this method fires up an iOS app via UIApplicationMain. Since
|
||||
// UIApplicationMain does not return until the app exits, control does not
|
||||
// return to the initial TestSuite::Run invocation, so the app invokes
|
||||
// TestSuite::Run a second time and since |ran_hook| is true at this point,
|
||||
// this method is a no-op and control returns to TestSuite:Run so that test
|
||||
// are executed. Once the app exits, RunTestsFromIOSApp calls exit() so that
|
||||
// control is not returned to the initial invocation of TestSuite::Run.
|
||||
static bool ran_hook = false;
|
||||
if (!ran_hook) {
|
||||
ran_hook = true;
|
||||
mac::ScopedNSAutoreleasePool pool;
|
||||
int exit_status = UIApplicationMain(g_argc, g_argv, nil,
|
||||
@"ChromeUnitTestDelegate");
|
||||
exit(exit_status);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
@ -2,11 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/test/main_hook.h"
|
||||
#include "chrome/test/base/chrome_test_suite.h"
|
||||
#include "content/public/test/unittest_test_suite.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
MainHook hook(main, argc, argv);
|
||||
return content::UnitTestTestSuite(new ChromeTestSuite(argc, argv)).Run();
|
||||
}
|
||||
|
@ -2,13 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/test/main_hook.h"
|
||||
#include "base/test/test_suite.h"
|
||||
#include "crypto/nss_util.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
MainHook hook(main, argc, argv);
|
||||
|
||||
#if defined(USE_NSS)
|
||||
// This is most likely not needed, but it basically replaces a similar call
|
||||
// that was performed on test_support_base.
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/test/main_hook.h"
|
||||
#include "base/test/test_suite.h"
|
||||
#include "media/base/media.h"
|
||||
|
||||
@ -23,6 +22,5 @@ void TestSuiteNoAtExit::Initialize() {
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
MainHook hook(main, argc, argv);
|
||||
return TestSuiteNoAtExit(argc, argv).Run();
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/metrics/statistics_recorder.h"
|
||||
#include "base/test/main_hook.h"
|
||||
#include "build/build_config.h"
|
||||
#include "crypto/nss_util.h"
|
||||
#include "net/base/net_test_suite.h"
|
||||
@ -24,8 +23,6 @@ using net::internal::ClientSocketPoolBaseHelper;
|
||||
using net::SpdySession;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
MainHook hook(main, argc, argv);
|
||||
|
||||
// Record histograms, so we can get histograms data in tests.
|
||||
base::StatisticsRecorder::Initialize();
|
||||
|
||||
|
@ -2,10 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/test/main_hook.h"
|
||||
#include "base/test/test_suite.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
MainHook hook(main, argc, argv);
|
||||
return base::TestSuite(argc, argv).Run();
|
||||
}
|
||||
|
@ -2,10 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/test/main_hook.h"
|
||||
#include "ui/test/test_suite.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
MainHook hook(main, argc, argv);
|
||||
return ui::test::UITestSuite(argc, argv).Run();
|
||||
}
|
||||
|
Reference in New Issue
Block a user