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/expectation.h',
|
||||||
'test/expectations/parser.cc',
|
'test/expectations/parser.cc',
|
||||||
'test/expectations/parser.h',
|
'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.h',
|
||||||
'test/mock_chrome_application_mac.mm',
|
'test/mock_chrome_application_mac.mm',
|
||||||
'test/mock_devices_changed_observer.cc',
|
'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
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "base/test/main_hook.h"
|
|
||||||
#include "base/test/perf_test_suite.h"
|
#include "base/test/perf_test_suite.h"
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
MainHook hook(main, argc, argv);
|
|
||||||
return base::PerfTestSuite(argc, argv).Run();
|
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
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "base/test/main_hook.h"
|
|
||||||
#include "base/test/test_suite.h"
|
#include "base/test/test_suite.h"
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
MainHook hook(main, argc, argv);
|
|
||||||
return base::TestSuite(argc, argv).Run();
|
return base::TestSuite(argc, argv).Run();
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,10 @@ void TestSuite::PreInitialize(int argc, char** argv,
|
|||||||
at_exit_manager_.reset(new base::AtExitManager);
|
at_exit_manager_.reset(new base::AtExitManager);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(OS_IOS)
|
||||||
|
InitIOSRunHook(this, argc, argv);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Don't add additional code to this function. Instead add it to
|
// Don't add additional code to this function. Instead add it to
|
||||||
// Initialize(). See bug 6436.
|
// Initialize(). See bug 6436.
|
||||||
}
|
}
|
||||||
@ -141,6 +145,10 @@ void TestSuite::ResetCommandLine() {
|
|||||||
// Don't add additional code to this method. Instead add it to
|
// Don't add additional code to this method. Instead add it to
|
||||||
// Initialize(). See bug 6436.
|
// Initialize(). See bug 6436.
|
||||||
int TestSuite::Run() {
|
int TestSuite::Run() {
|
||||||
|
#if defined(OS_IOS)
|
||||||
|
RunTestsFromIOSApp();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(OS_MACOSX)
|
#if defined(OS_MACOSX)
|
||||||
base::mac::ScopedNSAutoreleasePool scoped_pool;
|
base::mac::ScopedNSAutoreleasePool scoped_pool;
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,11 +5,20 @@
|
|||||||
#ifndef BASE_TEST_TEST_SUPPORT_IOS_H_
|
#ifndef BASE_TEST_TEST_SUPPORT_IOS_H_
|
||||||
#define BASE_TEST_TEST_SUPPORT_IOS_H_
|
#define BASE_TEST_TEST_SUPPORT_IOS_H_
|
||||||
|
|
||||||
|
#include "base/test/test_suite.h"
|
||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
|
|
||||||
// Init the message loop for tests on iOS.
|
// Inits the message loop for tests on iOS.
|
||||||
void InitIOSTestMessageLoop();
|
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
|
} // namespace base
|
||||||
|
|
||||||
#endif // BASE_TEST_TEST_SUPPORT_IOS_H_
|
#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
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// 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_loop.h"
|
||||||
#include "base/message_pump_default.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 {
|
namespace {
|
||||||
|
|
||||||
@ -20,4 +100,29 @@ void InitIOSTestMessageLoop() {
|
|||||||
MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUIForTests);
|
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
|
} // namespace base
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "base/test/main_hook.h"
|
|
||||||
#include "chrome/test/base/chrome_test_suite.h"
|
#include "chrome/test/base/chrome_test_suite.h"
|
||||||
#include "content/public/test/unittest_test_suite.h"
|
#include "content/public/test/unittest_test_suite.h"
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
MainHook hook(main, argc, argv);
|
|
||||||
return content::UnitTestTestSuite(new ChromeTestSuite(argc, argv)).Run();
|
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
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "base/test/main_hook.h"
|
|
||||||
#include "base/test/test_suite.h"
|
#include "base/test/test_suite.h"
|
||||||
#include "crypto/nss_util.h"
|
#include "crypto/nss_util.h"
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
MainHook hook(main, argc, argv);
|
|
||||||
|
|
||||||
#if defined(USE_NSS)
|
#if defined(USE_NSS)
|
||||||
// This is most likely not needed, but it basically replaces a similar call
|
// This is most likely not needed, but it basically replaces a similar call
|
||||||
// that was performed on test_support_base.
|
// 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
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "base/test/main_hook.h"
|
|
||||||
#include "base/test/test_suite.h"
|
#include "base/test/test_suite.h"
|
||||||
#include "media/base/media.h"
|
#include "media/base/media.h"
|
||||||
|
|
||||||
@ -23,6 +22,5 @@ void TestSuiteNoAtExit::Initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
MainHook hook(main, argc, argv);
|
|
||||||
return TestSuiteNoAtExit(argc, argv).Run();
|
return TestSuiteNoAtExit(argc, argv).Run();
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "base/metrics/statistics_recorder.h"
|
#include "base/metrics/statistics_recorder.h"
|
||||||
#include "base/test/main_hook.h"
|
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
#include "crypto/nss_util.h"
|
#include "crypto/nss_util.h"
|
||||||
#include "net/base/net_test_suite.h"
|
#include "net/base/net_test_suite.h"
|
||||||
@ -24,8 +23,6 @@ using net::internal::ClientSocketPoolBaseHelper;
|
|||||||
using net::SpdySession;
|
using net::SpdySession;
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
MainHook hook(main, argc, argv);
|
|
||||||
|
|
||||||
// Record histograms, so we can get histograms data in tests.
|
// Record histograms, so we can get histograms data in tests.
|
||||||
base::StatisticsRecorder::Initialize();
|
base::StatisticsRecorder::Initialize();
|
||||||
|
|
||||||
|
@ -2,10 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "base/test/main_hook.h"
|
|
||||||
#include "base/test/test_suite.h"
|
#include "base/test/test_suite.h"
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
MainHook hook(main, argc, argv);
|
|
||||||
return base::TestSuite(argc, argv).Run();
|
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
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "base/test/main_hook.h"
|
|
||||||
#include "ui/test/test_suite.h"
|
#include "ui/test/test_suite.h"
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
MainHook hook(main, argc, argv);
|
|
||||||
return ui::test::UITestSuite(argc, argv).Run();
|
return ui::test::UITestSuite(argc, argv).Run();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user