OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/logging.h" | |
6 #include "base/test/main_hook.h" | |
7 #include "base/debug/debugger.h" | |
8 | |
9 #import <UIKit/UIKit.h> | |
10 | |
11 // Springboard will kill any iOS app that fails to check in after launch within | |
12 // a given time. These two classes prevent this from happening. | |
13 | |
14 // MainHook saves the chrome main() and calls UIApplicationMain(), | |
15 // providing an application delegate class: ChromeUnitTestDelegate. The delegate | |
16 // listens for UIApplicationDidFinishLaunchingNotification. When the | |
17 // notification is received, it fires main() again to have the real work done. | |
18 | |
19 // Since the executable isn't likely to be a real iOS UI, the delegate puts up a | |
20 // window displaying the app name. If a bunch of apps using this are being run | |
21 // in a row, this provides an indication of which one is currently running. | |
22 // (i.e.-Run All Tests) | |
stuartmorgan
2012/07/12 09:36:31
Remove this last line since it's subject to becomi
leng
2012/07/12 10:44:42
Done.
| |
23 | |
24 // NOTE: This takes care of one of the iOS timers, but the watchdog can still | |
25 // kill the app if the messageloop is starved too long. A potential solution to | |
26 // this second problem would be to break the running of the main logic | |
27 // (unittest, etc.) into chunks via a timer so the iOS eventloop can drive it. | |
stuartmorgan
2012/07/12 09:36:31
I think this comment predates test_listener_ios; i
leng
2012/07/12 10:44:42
Done.
| |
28 | |
29 static MainHook::MainType g_main_func = NULL; | |
30 static int g_argc; | |
31 static char** g_argv; | |
32 | |
33 @interface ChromeUnitTestDelegate : NSObject | |
34 - (void)runTests; | |
35 @end | |
36 | |
37 @implementation ChromeUnitTestDelegate | |
38 | |
39 - (BOOL)application:(UIApplication *)application | |
40 didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { | |
41 | |
42 CGRect bounds = [[UIScreen mainScreen] bounds]; | |
43 | |
44 // Yes, this is leaked, it's just to make what's running visible. | |
45 UIWindow* window = [[UIWindow alloc] initWithFrame:bounds]; | |
46 [window makeKeyAndVisible]; | |
47 | |
48 // Add a label with the app name. | |
49 UILabel* label = [[[UILabel alloc] initWithFrame:bounds] autorelease]; | |
50 label.text = [[NSProcessInfo processInfo] processName]; | |
51 label.textAlignment = UITextAlignmentCenter; | |
52 [window addSubview:label]; | |
53 | |
54 // Queue up the test run. | |
55 [self performSelector:@selector(runTests) | |
56 withObject:nil | |
57 afterDelay:0.1]; | |
58 return YES; | |
59 } | |
60 | |
61 - (void)runTests { | |
62 int exitStatus = g_main_func(g_argc, g_argv); | |
63 | |
64 // If a test app is too fast, it will exit before Instruments has has a | |
65 // a chance to initialize and no test results will be seen. | |
66 [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow:2.0]]; | |
stuartmorgan
2012/07/12 09:36:31
Remove the space after :
We should add a TODO: wi
leng
2012/07/12 10:44:42
Done.
| |
67 | |
68 // Use the hidden selector to try and cleanly take down the app (otherwise | |
69 // things can think the app crashed even on a zero exit status). | |
70 UIApplication* application = [UIApplication sharedApplication]; | |
71 if ([application respondsToSelector:@selector(_terminateWithStatus:)]) { | |
72 [application performSelector:@selector(_terminateWithStatus:) | |
73 withObject:(id)exitStatus]; | |
74 } | |
75 exit(exitStatus); | |
76 } | |
77 | |
78 @end | |
79 | |
80 #pragma mark - | |
81 | |
82 MainHook::MainHook(MainType main_func, int argc, char* argv[]) { | |
83 static bool ran_hook; | |
stuartmorgan
2012/07/12 09:36:31
= false
leng
2012/07/12 10:44:42
Done.
| |
84 if (!ran_hook) { | |
85 ran_hook = true; | |
86 | |
87 g_main_func = main_func; | |
88 g_argc = argc; | |
89 g_argv = argv; | |
90 | |
91 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; | |
stuartmorgan
2012/07/12 09:36:31
We may as well use a scoped autorelease pool here.
leng
2012/07/12 10:44:42
Done.
| |
92 int exitStatus = UIApplicationMain(argc, argv, nil, | |
93 @"ChromeUnitTestDelegate"); | |
94 [pool release]; | |
95 exit(exitStatus); | |
96 } | |
97 } | |
OLD | NEW |