Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: testing/iossim/iossim.mm

Issue 113403002: Move iossim to DVTiPhoneSimulatorRemoteClient. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import <Foundation/Foundation.h> 5 #import <Foundation/Foundation.h>
6 #include <asl.h> 6 #include <asl.h>
7 #include <libgen.h> 7 #include <libgen.h>
8 #include <stdarg.h> 8 #include <stdarg.h>
9 #include <stdio.h> 9 #include <stdio.h>
10 10
(...skipping 10 matching lines...) Expand all
21 // However, there are some forward declarations required to get things to 21 // However, there are some forward declarations required to get things to
22 // compile. Also, the DTiPhoneSimulatorSessionDelegate protocol is referenced 22 // compile. Also, the DTiPhoneSimulatorSessionDelegate protocol is referenced
23 // by the iPhoneSimulatorRemoteClient framework, but not defined in the object 23 // by the iPhoneSimulatorRemoteClient framework, but not defined in the object
24 // file, so it must be defined here before importing the generated 24 // file, so it must be defined here before importing the generated
25 // iPhoneSimulatorRemoteClient.h file. 25 // iPhoneSimulatorRemoteClient.h file.
26 26
27 @class DTiPhoneSimulatorApplicationSpecifier; 27 @class DTiPhoneSimulatorApplicationSpecifier;
28 @class DTiPhoneSimulatorSession; 28 @class DTiPhoneSimulatorSession;
29 @class DTiPhoneSimulatorSessionConfig; 29 @class DTiPhoneSimulatorSessionConfig;
30 @class DTiPhoneSimulatorSystemRoot; 30 @class DTiPhoneSimulatorSystemRoot;
31 @class DVTiPhoneSimulatorMessenger;
32
33 @interface DVTPlatform : NSObject
34 + (BOOL)loadAllPlatformsReturningError:(id *)arg1;
35 @end
36
37 @protocol OS_dispatch_source
38 @end
39 @protocol OS_dispatch_queue
40 @end
41 @class DVTDispatchLock;
42 @class DVTConfinementServiceConnection;
43 @class DVTTask;
31 44
32 @protocol DTiPhoneSimulatorSessionDelegate 45 @protocol DTiPhoneSimulatorSessionDelegate
33 - (void)session:(DTiPhoneSimulatorSession*)session 46 - (void)session:(DTiPhoneSimulatorSession*)session
34 didEndWithError:(NSError*)error; 47 didEndWithError:(NSError*)error;
35 - (void)session:(DTiPhoneSimulatorSession*)session 48 - (void)session:(DTiPhoneSimulatorSession*)session
36 didStart:(BOOL)started 49 didStart:(BOOL)started
37 withError:(NSError*)error; 50 withError:(NSError*)error;
38 @end 51 @end
39 52
40 #import "iPhoneSimulatorRemoteClient.h" 53 #import "DVTiPhoneSimulatorRemoteClient.h"
41 54
42 // An undocumented system log key included in messages from launchd. The value 55 // An undocumented system log key included in messages from launchd. The value
43 // is the PID of the process the message is about (as opposed to launchd's PID). 56 // is the PID of the process the message is about (as opposed to launchd's PID).
44 #define ASL_KEY_REF_PID "RefPID" 57 #define ASL_KEY_REF_PID "RefPID"
45 58
46 namespace { 59 namespace {
47 60
48 // Name of environment variables that control the user's home directory in the 61 // Name of environment variables that control the user's home directory in the
49 // simulator. 62 // simulator.
50 const char* const kUserHomeEnvVariable = "CFFIXED_USER_HOME"; 63 const char* const kUserHomeEnvVariable = "CFFIXED_USER_HOME";
(...skipping 15 matching lines...) Expand all
66 const NSTimeInterval kDefaultSessionStartTimeoutSeconds = 30; 79 const NSTimeInterval kDefaultSessionStartTimeoutSeconds = 30;
67 80
68 // While the simulated app is running, its stdout is redirected to a file which 81 // While the simulated app is running, its stdout is redirected to a file which
69 // is polled by iossim and written to iossim's stdout using the following 82 // is polled by iossim and written to iossim's stdout using the following
70 // polling interval. 83 // polling interval.
71 const NSTimeInterval kOutputPollIntervalSeconds = 0.1; 84 const NSTimeInterval kOutputPollIntervalSeconds = 0.1;
72 85
73 // The path within the developer dir of the private Simulator frameworks. 86 // The path within the developer dir of the private Simulator frameworks.
74 NSString* const kSimulatorFrameworkRelativePath = 87 NSString* const kSimulatorFrameworkRelativePath =
75 @"Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/" 88 @"Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/"
76 @"iPhoneSimulatorRemoteClient.framework"; 89 @"DVTiPhoneSimulatorRemoteClient.framework";
90 NSString* const kDVTFoundationRelativePath =
91 @"../SharedFrameworks/DVTFoundation.framework";
77 NSString* const kDevToolsFoundationRelativePath = 92 NSString* const kDevToolsFoundationRelativePath =
78 @"../OtherFrameworks/DevToolsFoundation.framework"; 93 @"../OtherFrameworks/DevToolsFoundation.framework";
79 NSString* const kSimulatorRelativePath = 94 NSString* const kSimulatorRelativePath =
80 @"Platforms/iPhoneSimulator.platform/Developer/Applications/" 95 @"Platforms/iPhoneSimulator.platform/Developer/Applications/"
81 @"iPhone Simulator.app"; 96 @"iPhone Simulator.app";
82 97
83 // Simulator Error String Key. This can be found by looking in the Simulator's 98 // Simulator Error String Key. This can be found by looking in the Simulator's
84 // Localizable.strings files. 99 // Localizable.strings files.
85 NSString* const kSimulatorAppQuitErrorKey = @"The simulated application quit."; 100 NSString* const kSimulatorAppQuitErrorKey = @"The simulated application quit.";
86 101
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 objectAtIndex:0] intValue]; 308 objectAtIndex:0] intValue];
294 if (majorVersion <= 6) { 309 if (majorVersion <= 6) {
295 // In iOS 6 and before, logging from the simulated apps went to the main 310 // In iOS 6 and before, logging from the simulated apps went to the main
296 // system logs, so use ASL to check if the simulated app exited abnormally 311 // system logs, so use ASL to check if the simulated app exited abnormally
297 // by looking for system log messages from launchd that refer to the 312 // by looking for system log messages from launchd that refer to the
298 // simulated app's PID. Limit query to messages in the last minute since 313 // simulated app's PID. Limit query to messages in the last minute since
299 // PIDs are cyclical. 314 // PIDs are cyclical.
300 aslmsg query = asl_new(ASL_TYPE_QUERY); 315 aslmsg query = asl_new(ASL_TYPE_QUERY);
301 asl_set_query(query, ASL_KEY_SENDER, "launchd", 316 asl_set_query(query, ASL_KEY_SENDER, "launchd",
302 ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_SUBSTRING); 317 ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_SUBSTRING);
303 asl_set_query(query, ASL_KEY_REF_PID, 318 asl_set_query(
304 [[[session simulatedApplicationPID] stringValue] UTF8String], 319 query,
305 ASL_QUERY_OP_EQUAL); 320 ASL_KEY_REF_PID,
321 [[NSString stringWithFormat:@"%d", [session simulatedApplicationPID]]
lliabraa 2013/12/12 15:01:15 why change from stringValue to stringWithFormat?
justincohen 2013/12/12 15:02:03 Because it's not a NSNumber anymore, it's an int.
TVL 2013/12/12 16:08:27 This whole thing would be less scary with a char[2
justincohen 2013/12/16 18:44:37 Done, converted to snprintf. On 2013/12/12 16:08:
322 UTF8String],
323 ASL_QUERY_OP_EQUAL);
306 asl_set_query(query, ASL_KEY_TIME, "-1m", ASL_QUERY_OP_GREATER_EQUAL); 324 asl_set_query(query, ASL_KEY_TIME, "-1m", ASL_QUERY_OP_GREATER_EQUAL);
307 325
308 // Log any messages found, and take note of any messages that may indicate 326 // Log any messages found, and take note of any messages that may indicate
309 // the app crashed or did not exit cleanly. 327 // the app crashed or did not exit cleanly.
310 aslresponse response = asl_search(NULL, query); 328 aslresponse response = asl_search(NULL, query);
311 aslmsg entry; 329 aslmsg entry;
312 while ((entry = aslresponse_next(response)) != NULL) { 330 while ((entry = aslresponse_next(response)) != NULL) {
313 const char* message = asl_get(entry, ASL_KEY_MSG); 331 const char* message = asl_get(entry, ASL_KEY_MSG);
314 LogWarning(@"Console message: %s", message); 332 LogWarning(@"Console message: %s", message);
315 // Some messages are harmless, so don't trigger a failure for them. 333 // Some messages are harmless, so don't trigger a failure for them.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 NSString* output = 404 NSString* output =
387 [[[NSString alloc] initWithData:outputData 405 [[[NSString alloc] initWithData:outputData
388 encoding:NSUTF8StringEncoding] autorelease]; 406 encoding:NSUTF8StringEncoding] autorelease];
389 output = [output stringByTrimmingCharactersInSet: 407 output = [output stringByTrimmingCharactersInSet:
390 [NSCharacterSet whitespaceAndNewlineCharacterSet]]; 408 [NSCharacterSet whitespaceAndNewlineCharacterSet]];
391 if ([output length] == 0) 409 if ([output length] == 0)
392 output = nil; 410 output = nil;
393 return output; 411 return output;
394 } 412 }
395 413
414 // Helper to find a class by name and die if it isn't found.
TVL 2013/12/12 16:08:27 any reason this got moved?
justincohen 2013/12/16 18:44:37 Forward declaration. On 2013/12/12 16:08:27, TVL
415 Class FindClassByName(NSString* nameOfClass) {
416 Class theClass = NSClassFromString(nameOfClass);
417 if (!theClass) {
418 LogError(@"Failed to find class %@ at runtime.", nameOfClass);
419 exit(kExitInitializationFailure);
420 }
421 return theClass;
422 }
423
396 // Loads the Simulator framework from the given developer dir. 424 // Loads the Simulator framework from the given developer dir.
397 NSBundle* LoadSimulatorFramework(NSString* developerDir) { 425 NSBundle* LoadSimulatorFramework(NSString* developerDir) {
398 // The Simulator framework depends on some of the other Xcode private 426 // The Simulator framework depends on some of the other Xcode private
399 // frameworks; manually load them first so everything can be linked up. 427 // frameworks; manually load them first so everything can be linked up.
428 NSString* dvtFoundationPath = [developerDir
429 stringByAppendingPathComponent:kDVTFoundationRelativePath];
430 NSBundle* dvtFoundationBundle =
431 [NSBundle bundleWithPath:dvtFoundationPath];
432 if (![dvtFoundationBundle load])
433 return nil;
434
400 NSString* devToolsFoundationPath = [developerDir 435 NSString* devToolsFoundationPath = [developerDir
401 stringByAppendingPathComponent:kDevToolsFoundationRelativePath]; 436 stringByAppendingPathComponent:kDevToolsFoundationRelativePath];
402 NSBundle* devToolsFoundationBundle = 437 NSBundle* devToolsFoundationBundle =
403 [NSBundle bundleWithPath:devToolsFoundationPath]; 438 [NSBundle bundleWithPath:devToolsFoundationPath];
404 if (![devToolsFoundationBundle load]) 439 if (![devToolsFoundationBundle load])
405 return nil; 440 return nil;
441
442 // Prime DVTPlatform.
443 Class DVTPlatformClass = FindClassByName(@"DVTPlatform");
444 [DVTPlatformClass loadAllPlatformsReturningError:nil];
TVL 2013/12/12 16:08:27 You should check the bool return result, and would
justincohen 2013/12/16 18:44:37 Done.
445
406 NSString* simBundlePath = [developerDir 446 NSString* simBundlePath = [developerDir
407 stringByAppendingPathComponent:kSimulatorFrameworkRelativePath]; 447 stringByAppendingPathComponent:kSimulatorFrameworkRelativePath];
408 NSBundle* simBundle = [NSBundle bundleWithPath:simBundlePath]; 448 NSBundle* simBundle = [NSBundle bundleWithPath:simBundlePath];
409 if (![simBundle load]) 449 if (![simBundle load])
410 return nil; 450 return nil;
411 return simBundle; 451 return simBundle;
412 } 452 }
413 453
414 // Helper to find a class by name and die if it isn't found.
415 Class FindClassByName(NSString* nameOfClass) {
416 Class theClass = NSClassFromString(nameOfClass);
417 if (!theClass) {
418 LogError(@"Failed to find class %@ at runtime.", nameOfClass);
419 exit(kExitInitializationFailure);
420 }
421 return theClass;
422 }
423
424 // Converts the given app path to an application spec, which requires an 454 // Converts the given app path to an application spec, which requires an
425 // absolute path. 455 // absolute path.
426 DTiPhoneSimulatorApplicationSpecifier* BuildAppSpec(NSString* appPath) { 456 DTiPhoneSimulatorApplicationSpecifier* BuildAppSpec(NSString* appPath) {
427 Class applicationSpecifierClass = 457 Class applicationSpecifierClass =
428 FindClassByName(@"DTiPhoneSimulatorApplicationSpecifier"); 458 FindClassByName(@"DTiPhoneSimulatorApplicationSpecifier");
429 if (![appPath isAbsolutePath]) { 459 if (![appPath isAbsolutePath]) {
430 NSString* cwd = [[NSFileManager defaultManager] currentDirectoryPath]; 460 NSString* cwd = [[NSFileManager defaultManager] currentDirectoryPath];
431 appPath = [cwd stringByAppendingPathComponent:appPath]; 461 appPath = [cwd stringByAppendingPathComponent:appPath];
432 } 462 }
433 appPath = [appPath stringByStandardizingPath]; 463 appPath = [appPath stringByStandardizingPath];
(...skipping 13 matching lines...) Expand all
447 } 477 }
448 478
449 // Builds a config object for starting the specified app. 479 // Builds a config object for starting the specified app.
450 DTiPhoneSimulatorSessionConfig* BuildSessionConfig( 480 DTiPhoneSimulatorSessionConfig* BuildSessionConfig(
451 DTiPhoneSimulatorApplicationSpecifier* appSpec, 481 DTiPhoneSimulatorApplicationSpecifier* appSpec,
452 DTiPhoneSimulatorSystemRoot* systemRoot, 482 DTiPhoneSimulatorSystemRoot* systemRoot,
453 NSString* stdoutPath, 483 NSString* stdoutPath,
454 NSString* stderrPath, 484 NSString* stderrPath,
455 NSArray* appArgs, 485 NSArray* appArgs,
456 NSDictionary* appEnv, 486 NSDictionary* appEnv,
457 NSNumber* deviceFamily) { 487 NSNumber* deviceFamily,
488 NSString* deviceName) {
458 Class sessionConfigClass = FindClassByName(@"DTiPhoneSimulatorSessionConfig"); 489 Class sessionConfigClass = FindClassByName(@"DTiPhoneSimulatorSessionConfig");
459 DTiPhoneSimulatorSessionConfig* sessionConfig = 490 DTiPhoneSimulatorSessionConfig* sessionConfig =
460 [[[sessionConfigClass alloc] init] autorelease]; 491 [[[sessionConfigClass alloc] init] autorelease];
461 sessionConfig.applicationToSimulateOnStart = appSpec; 492 sessionConfig.applicationToSimulateOnStart = appSpec;
462 sessionConfig.simulatedSystemRoot = systemRoot; 493 sessionConfig.simulatedSystemRoot = systemRoot;
463 sessionConfig.localizedClientName = @"chromium"; 494 sessionConfig.localizedClientName = @"chromium";
464 sessionConfig.simulatedApplicationStdErrPath = stderrPath; 495 sessionConfig.simulatedApplicationStdErrPath = stderrPath;
465 sessionConfig.simulatedApplicationStdOutPath = stdoutPath; 496 sessionConfig.simulatedApplicationStdOutPath = stdoutPath;
466 sessionConfig.simulatedApplicationLaunchArgs = appArgs; 497 sessionConfig.simulatedApplicationLaunchArgs = appArgs;
467 sessionConfig.simulatedApplicationLaunchEnvironment = appEnv; 498 sessionConfig.simulatedApplicationLaunchEnvironment = appEnv;
499 sessionConfig.simulatedDeviceInfoName = deviceName;
468 sessionConfig.simulatedDeviceFamily = deviceFamily; 500 sessionConfig.simulatedDeviceFamily = deviceFamily;
469 return sessionConfig; 501 return sessionConfig;
470 } 502 }
471 503
472 // Builds a simulator session that will use the given delegate. 504 // Builds a simulator session that will use the given delegate.
473 DTiPhoneSimulatorSession* BuildSession(SimulatorDelegate* delegate) { 505 DTiPhoneSimulatorSession* BuildSession(SimulatorDelegate* delegate) {
474 Class sessionClass = FindClassByName(@"DTiPhoneSimulatorSession"); 506 Class sessionClass = FindClassByName(@"DTiPhoneSimulatorSession");
475 DTiPhoneSimulatorSession* session = 507 DTiPhoneSimulatorSession* session =
476 [[[sessionClass alloc] init] autorelease]; 508 [[[sessionClass alloc] init] autorelease];
477 session.delegate = delegate; 509 session.delegate = delegate;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 } 554 }
523 } 555 }
524 556
525 return YES; 557 return YES;
526 } 558 }
527 559
528 // Creates the necessary directory structure under the given user home directory 560 // Creates the necessary directory structure under the given user home directory
529 // path, then sets the path in the appropriate environment variable. 561 // path, then sets the path in the appropriate environment variable.
530 // Returns YES if successful, NO if unable to create or initialize the given 562 // Returns YES if successful, NO if unable to create or initialize the given
531 // directory. 563 // directory.
532 BOOL InitializeSimulatorUserHome(NSString* userHomePath, NSString* deviceName) { 564 BOOL InitializeSimulatorUserHome(NSString* userHomePath) {
533 if (!CreateHomeDirSubDirs(userHomePath)) 565 if (!CreateHomeDirSubDirs(userHomePath))
534 return NO; 566 return NO;
535 567
536 // Set the device to simulate. Note that the iOS Simulator must not be running
537 // for this setting to take effect.
538 CFStringRef iPhoneSimulatorAppID = CFSTR("com.apple.iphonesimulator");
539 CFPreferencesSetAppValue(CFSTR("SimulateDevice"),
540 deviceName,
541 iPhoneSimulatorAppID);
542 CFPreferencesAppSynchronize(iPhoneSimulatorAppID);
543
544 // Update the environment to use the specified directory as the user home 568 // Update the environment to use the specified directory as the user home
545 // directory. 569 // directory.
546 // Note: the third param of setenv specifies whether or not to overwrite the 570 // Note: the third param of setenv specifies whether or not to overwrite the
547 // variable's value if it has already been set. 571 // variable's value if it has already been set.
548 if ((setenv(kUserHomeEnvVariable, [userHomePath UTF8String], YES) == -1) || 572 if ((setenv(kUserHomeEnvVariable, [userHomePath UTF8String], YES) == -1) ||
549 (setenv(kHomeEnvVariable, [userHomePath UTF8String], YES) == -1)) { 573 (setenv(kHomeEnvVariable, [userHomePath UTF8String], YES) == -1)) {
550 LogError(@"Unable to set environment variables for home directory."); 574 LogError(@"Unable to set environment variables for home directory.");
551 return NO; 575 return NO;
552 } 576 }
553 577
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 if (!simHomePath) { 745 if (!simHomePath) {
722 NSString* dirNameTemplate = 746 NSString* dirNameTemplate =
723 [NSString stringWithFormat:@"iossim-%@-%@-XXXXXX", appName, deviceName]; 747 [NSString stringWithFormat:@"iossim-%@-%@-XXXXXX", appName, deviceName];
724 simHomePath = CreateTempDirectory(dirNameTemplate); 748 simHomePath = CreateTempDirectory(dirNameTemplate);
725 if (!simHomePath) { 749 if (!simHomePath) {
726 LogError(@"Unable to create unique directory for template %@", 750 LogError(@"Unable to create unique directory for template %@",
727 dirNameTemplate); 751 dirNameTemplate);
728 exit(kExitInitializationFailure); 752 exit(kExitInitializationFailure);
729 } 753 }
730 } 754 }
731 if (!InitializeSimulatorUserHome(simHomePath, deviceName)) { 755 if (!InitializeSimulatorUserHome(simHomePath)) {
732 LogError(@"Unable to initialize home directory for simulator: %@", 756 LogError(@"Unable to initialize home directory for simulator: %@",
733 simHomePath); 757 simHomePath);
734 exit(kExitInitializationFailure); 758 exit(kExitInitializationFailure);
735 } 759 }
736 760
737 // Create the config and simulator session. 761 // Create the config and simulator session.
738 DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec, 762 DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec,
739 systemRoot, 763 systemRoot,
740 stdioPath, 764 stdioPath,
741 stdioPath, 765 stdioPath,
742 appArgs, 766 appArgs,
743 appEnv, 767 appEnv,
744 deviceFamily); 768 deviceFamily,
769 deviceName);
745 SimulatorDelegate* delegate = 770 SimulatorDelegate* delegate =
746 [[[SimulatorDelegate alloc] initWithStdioPath:stdioPath 771 [[[SimulatorDelegate alloc] initWithStdioPath:stdioPath
747 developerDir:developerDir 772 developerDir:developerDir
748 simulatorHome:simHomePath] autorelease]; 773 simulatorHome:simHomePath] autorelease];
749 DTiPhoneSimulatorSession* session = BuildSession(delegate); 774 DTiPhoneSimulatorSession* session = BuildSession(delegate);
750 775
751 // Start the simulator session. 776 // Start the simulator session.
752 NSError* error; 777 NSError* error;
753 BOOL started = [session requestStartWithConfig:config 778 BOOL started = [session requestStartWithConfig:config
754 timeout:sessionStartTimeout 779 timeout:sessionStartTimeout
755 error:&error]; 780 error:&error];
756 781
757 // Spin the runtime indefinitely. When the delegate gets the message that the 782 // Spin the runtime indefinitely. When the delegate gets the message that the
758 // app has quit it will exit this program. 783 // app has quit it will exit this program.
759 if (started) { 784 if (started) {
760 [[NSRunLoop mainRunLoop] run]; 785 [[NSRunLoop mainRunLoop] run];
761 } else { 786 } else {
762 LogError(@"Simulator failed request to start: \"%@\" (%@:%ld)", 787 LogError(@"Simulator failed request to start: \"%@\" (%@:%ld)",
763 [error localizedDescription], 788 [error localizedDescription],
764 [error domain], static_cast<long int>([error code])); 789 [error domain], static_cast<long int>([error code]));
765 } 790 }
766 791
767 // Note that this code is only executed if the simulator fails to start 792 // Note that this code is only executed if the simulator fails to start
768 // because once the main run loop is started, only the delegate calling 793 // because once the main run loop is started, only the delegate calling
769 // exit() will end the program. 794 // exit() will end the program.
770 [pool drain]; 795 [pool drain];
771 return kExitFailure; 796 return kExitFailure;
772 } 797 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698