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/test/main_hook.h" | |
6 | |
7 #import <UIKit/UIKit.h> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/mac/scoped_nsautorelease_pool.h" | |
11 #include "base/debug/debugger.h" | |
stuartmorgan
2012/07/12 10:59:23
Move this up a line so the headers are in order.
leng
2012/07/12 11:17:31
Two lines. :)
| |
12 | |
13 // Springboard will kill any iOS app that fails to check in after launch within | |
14 // a given time. These two classes prevent this from happening. | |
15 | |
16 // MainHook saves the chrome main() and calls UIApplicationMain(), | |
17 // providing an application delegate class: ChromeUnitTestDelegate. The delegate | |
18 // listens for UIApplicationDidFinishLaunchingNotification. When the | |
19 // notification is received, it fires main() again to have the real work done. | |
20 | |
21 // Since the executable isn't likely to be a real iOS UI, the delegate puts up a | |
22 // window displaying the app name. If a bunch of apps using this are being run | |
23 // in a row, this provides an indication of which one is currently running. | |
24 | |
25 static MainHook::MainType g_main_func = NULL; | |
26 static int g_argc; | |
27 static char** g_argv; | |
28 | |
29 @interface ChromeUnitTestDelegate : NSObject | |
30 - (void)runTests; | |
31 @end | |
32 | |
33 @implementation ChromeUnitTestDelegate | |
34 | |
35 - (BOOL)application:(UIApplication *)application | |
36 didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { | |
37 | |
38 CGRect bounds = [[UIScreen mainScreen] bounds]; | |
39 | |
40 // Yes, this is leaked, it's just to make what's running visible. | |
41 UIWindow* window = [[UIWindow alloc] initWithFrame:bounds]; | |
42 [window makeKeyAndVisible]; | |
43 | |
44 // Add a label with the app name. | |
45 UILabel* label = [[[UILabel alloc] initWithFrame:bounds] autorelease]; | |
46 label.text = [[NSProcessInfo processInfo] processName]; | |
47 label.textAlignment = UITextAlignmentCenter; | |
48 [window addSubview:label]; | |
49 | |
50 // Queue up the test run. | |
51 [self performSelector:@selector(runTests) | |
52 withObject:nil | |
53 afterDelay:0.1]; | |
54 return YES; | |
55 } | |
56 | |
57 - (void)runTests { | |
58 int exitStatus = g_main_func(g_argc, g_argv); | |
59 | |
60 // If a test app is too fast, it will exit before Instruments has has a | |
61 // a chance to initialize and no test results will be seen. | |
62 // TODO(ios): b/6810854 Figure out how much time is actually needed. | |
stuartmorgan
2012/07/12 10:59:23
Sorry, I meant a crbug.com bug; I should have said
leng
2012/07/12 11:17:31
Done.
| |
63 [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]]; | |
64 | |
65 // Use the hidden selector to try and cleanly take down the app (otherwise | |
66 // things can think the app crashed even on a zero exit status). | |
67 UIApplication* application = [UIApplication sharedApplication]; | |
68 if ([application respondsToSelector:@selector(_terminateWithStatus:)]) { | |
69 [application performSelector:@selector(_terminateWithStatus:) | |
70 withObject:(id)exitStatus]; | |
71 } | |
72 exit(exitStatus); | |
73 } | |
74 | |
75 @end | |
76 | |
77 #pragma mark - | |
78 | |
79 MainHook::MainHook(MainType main_func, int argc, char* argv[]) { | |
80 static bool ran_hook = false; | |
81 if (!ran_hook) { | |
82 ran_hook = true; | |
83 | |
84 g_main_func = main_func; | |
85 g_argc = argc; | |
86 g_argv = argv; | |
87 | |
88 base::mac::ScopedNSAutoreleasePool pool; | |
89 int exitStatus = UIApplicationMain(argc, argv, nil, | |
90 @"ChromeUnitTestDelegate"); | |
91 exit(exitStatus); | |
92 } | |
93 } | |
OLD | NEW |