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

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: Address TVL and lliabraa comments 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 char session_id[20];
304 [[[session simulatedApplicationPID] stringValue] UTF8String], 319 snprintf(session_id, 20, "%d", [session simulatedApplicationPID]);
TVL 2013/12/16 18:50:28 check the result & error out?
justincohen 2013/12/16 18:59:52 Done.
305 ASL_QUERY_OP_EQUAL); 320 asl_set_query(query, ASL_KEY_REF_PID, session_id, ASL_QUERY_OP_EQUAL);
306 asl_set_query(query, ASL_KEY_TIME, "-1m", ASL_QUERY_OP_GREATER_EQUAL); 321 asl_set_query(query, ASL_KEY_TIME, "-1m", ASL_QUERY_OP_GREATER_EQUAL);
307 322
308 // Log any messages found, and take note of any messages that may indicate 323 // Log any messages found, and take note of any messages that may indicate
309 // the app crashed or did not exit cleanly. 324 // the app crashed or did not exit cleanly.
310 aslresponse response = asl_search(NULL, query); 325 aslresponse response = asl_search(NULL, query);
311 aslmsg entry; 326 aslmsg entry;
312 while ((entry = aslresponse_next(response)) != NULL) { 327 while ((entry = aslresponse_next(response)) != NULL) {
313 const char* message = asl_get(entry, ASL_KEY_MSG); 328 const char* message = asl_get(entry, ASL_KEY_MSG);
314 LogWarning(@"Console message: %s", message); 329 LogWarning(@"Console message: %s", message);
315 // Some messages are harmless, so don't trigger a failure for them. 330 // 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 = 401 NSString* output =
387 [[[NSString alloc] initWithData:outputData 402 [[[NSString alloc] initWithData:outputData
388 encoding:NSUTF8StringEncoding] autorelease]; 403 encoding:NSUTF8StringEncoding] autorelease];
389 output = [output stringByTrimmingCharactersInSet: 404 output = [output stringByTrimmingCharactersInSet:
390 [NSCharacterSet whitespaceAndNewlineCharacterSet]]; 405 [NSCharacterSet whitespaceAndNewlineCharacterSet]];
391 if ([output length] == 0) 406 if ([output length] == 0)
392 output = nil; 407 output = nil;
393 return output; 408 return output;
394 } 409 }
395 410
411 // Helper to find a class by name and die if it isn't found.
412 Class FindClassByName(NSString* nameOfClass) {
413 Class theClass = NSClassFromString(nameOfClass);
414 if (!theClass) {
415 LogError(@"Failed to find class %@ at runtime.", nameOfClass);
416 exit(kExitInitializationFailure);
417 }
418 return theClass;
419 }
420
396 // Loads the Simulator framework from the given developer dir. 421 // Loads the Simulator framework from the given developer dir.
397 NSBundle* LoadSimulatorFramework(NSString* developerDir) { 422 NSBundle* LoadSimulatorFramework(NSString* developerDir) {
398 // The Simulator framework depends on some of the other Xcode private 423 // The Simulator framework depends on some of the other Xcode private
399 // frameworks; manually load them first so everything can be linked up. 424 // frameworks; manually load them first so everything can be linked up.
425 NSString* dvtFoundationPath = [developerDir
426 stringByAppendingPathComponent:kDVTFoundationRelativePath];
427 NSBundle* dvtFoundationBundle =
428 [NSBundle bundleWithPath:dvtFoundationPath];
429 if (![dvtFoundationBundle load])
430 return nil;
431
400 NSString* devToolsFoundationPath = [developerDir 432 NSString* devToolsFoundationPath = [developerDir
401 stringByAppendingPathComponent:kDevToolsFoundationRelativePath]; 433 stringByAppendingPathComponent:kDevToolsFoundationRelativePath];
402 NSBundle* devToolsFoundationBundle = 434 NSBundle* devToolsFoundationBundle =
403 [NSBundle bundleWithPath:devToolsFoundationPath]; 435 [NSBundle bundleWithPath:devToolsFoundationPath];
404 if (![devToolsFoundationBundle load]) 436 if (![devToolsFoundationBundle load])
405 return nil; 437 return nil;
438
439 // Prime DVTPlatform.
440 NSError* error;
441 Class DVTPlatformClass = FindClassByName(@"DVTPlatform");
442 if (![DVTPlatformClass loadAllPlatformsReturningError:&error]) {
443 LogError(@"Unable to loadAllPlatformsReturningError. Error: %@",
444 [error localizedDescription]);
445 return nil;
446 }
447
406 NSString* simBundlePath = [developerDir 448 NSString* simBundlePath = [developerDir
407 stringByAppendingPathComponent:kSimulatorFrameworkRelativePath]; 449 stringByAppendingPathComponent:kSimulatorFrameworkRelativePath];
408 NSBundle* simBundle = [NSBundle bundleWithPath:simBundlePath]; 450 NSBundle* simBundle = [NSBundle bundleWithPath:simBundlePath];
409 if (![simBundle load]) 451 if (![simBundle load])
410 return nil; 452 return nil;
411 return simBundle; 453 return simBundle;
412 } 454 }
413 455
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 456 // Converts the given app path to an application spec, which requires an
425 // absolute path. 457 // absolute path.
426 DTiPhoneSimulatorApplicationSpecifier* BuildAppSpec(NSString* appPath) { 458 DTiPhoneSimulatorApplicationSpecifier* BuildAppSpec(NSString* appPath) {
427 Class applicationSpecifierClass = 459 Class applicationSpecifierClass =
428 FindClassByName(@"DTiPhoneSimulatorApplicationSpecifier"); 460 FindClassByName(@"DTiPhoneSimulatorApplicationSpecifier");
429 if (![appPath isAbsolutePath]) { 461 if (![appPath isAbsolutePath]) {
430 NSString* cwd = [[NSFileManager defaultManager] currentDirectoryPath]; 462 NSString* cwd = [[NSFileManager defaultManager] currentDirectoryPath];
431 appPath = [cwd stringByAppendingPathComponent:appPath]; 463 appPath = [cwd stringByAppendingPathComponent:appPath];
432 } 464 }
433 appPath = [appPath stringByStandardizingPath]; 465 appPath = [appPath stringByStandardizingPath];
(...skipping 13 matching lines...) Expand all
447 } 479 }
448 480
449 // Builds a config object for starting the specified app. 481 // Builds a config object for starting the specified app.
450 DTiPhoneSimulatorSessionConfig* BuildSessionConfig( 482 DTiPhoneSimulatorSessionConfig* BuildSessionConfig(
451 DTiPhoneSimulatorApplicationSpecifier* appSpec, 483 DTiPhoneSimulatorApplicationSpecifier* appSpec,
452 DTiPhoneSimulatorSystemRoot* systemRoot, 484 DTiPhoneSimulatorSystemRoot* systemRoot,
453 NSString* stdoutPath, 485 NSString* stdoutPath,
454 NSString* stderrPath, 486 NSString* stderrPath,
455 NSArray* appArgs, 487 NSArray* appArgs,
456 NSDictionary* appEnv, 488 NSDictionary* appEnv,
457 NSNumber* deviceFamily) { 489 NSNumber* deviceFamily,
490 NSString* deviceName) {
458 Class sessionConfigClass = FindClassByName(@"DTiPhoneSimulatorSessionConfig"); 491 Class sessionConfigClass = FindClassByName(@"DTiPhoneSimulatorSessionConfig");
459 DTiPhoneSimulatorSessionConfig* sessionConfig = 492 DTiPhoneSimulatorSessionConfig* sessionConfig =
460 [[[sessionConfigClass alloc] init] autorelease]; 493 [[[sessionConfigClass alloc] init] autorelease];
461 sessionConfig.applicationToSimulateOnStart = appSpec; 494 sessionConfig.applicationToSimulateOnStart = appSpec;
462 sessionConfig.simulatedSystemRoot = systemRoot; 495 sessionConfig.simulatedSystemRoot = systemRoot;
463 sessionConfig.localizedClientName = @"chromium"; 496 sessionConfig.localizedClientName = @"chromium";
464 sessionConfig.simulatedApplicationStdErrPath = stderrPath; 497 sessionConfig.simulatedApplicationStdErrPath = stderrPath;
465 sessionConfig.simulatedApplicationStdOutPath = stdoutPath; 498 sessionConfig.simulatedApplicationStdOutPath = stdoutPath;
466 sessionConfig.simulatedApplicationLaunchArgs = appArgs; 499 sessionConfig.simulatedApplicationLaunchArgs = appArgs;
467 sessionConfig.simulatedApplicationLaunchEnvironment = appEnv; 500 sessionConfig.simulatedApplicationLaunchEnvironment = appEnv;
501 sessionConfig.simulatedDeviceInfoName = deviceName;
468 sessionConfig.simulatedDeviceFamily = deviceFamily; 502 sessionConfig.simulatedDeviceFamily = deviceFamily;
469 return sessionConfig; 503 return sessionConfig;
470 } 504 }
471 505
472 // Builds a simulator session that will use the given delegate. 506 // Builds a simulator session that will use the given delegate.
473 DTiPhoneSimulatorSession* BuildSession(SimulatorDelegate* delegate) { 507 DTiPhoneSimulatorSession* BuildSession(SimulatorDelegate* delegate) {
474 Class sessionClass = FindClassByName(@"DTiPhoneSimulatorSession"); 508 Class sessionClass = FindClassByName(@"DTiPhoneSimulatorSession");
475 DTiPhoneSimulatorSession* session = 509 DTiPhoneSimulatorSession* session =
476 [[[sessionClass alloc] init] autorelease]; 510 [[[sessionClass alloc] init] autorelease];
477 session.delegate = delegate; 511 session.delegate = delegate;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 } 556 }
523 } 557 }
524 558
525 return YES; 559 return YES;
526 } 560 }
527 561
528 // Creates the necessary directory structure under the given user home directory 562 // Creates the necessary directory structure under the given user home directory
529 // path, then sets the path in the appropriate environment variable. 563 // path, then sets the path in the appropriate environment variable.
530 // Returns YES if successful, NO if unable to create or initialize the given 564 // Returns YES if successful, NO if unable to create or initialize the given
531 // directory. 565 // directory.
532 BOOL InitializeSimulatorUserHome(NSString* userHomePath, NSString* deviceName) { 566 BOOL InitializeSimulatorUserHome(NSString* userHomePath) {
533 if (!CreateHomeDirSubDirs(userHomePath)) 567 if (!CreateHomeDirSubDirs(userHomePath))
534 return NO; 568 return NO;
535 569
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 570 // Update the environment to use the specified directory as the user home
545 // directory. 571 // directory.
546 // Note: the third param of setenv specifies whether or not to overwrite the 572 // Note: the third param of setenv specifies whether or not to overwrite the
547 // variable's value if it has already been set. 573 // variable's value if it has already been set.
548 if ((setenv(kUserHomeEnvVariable, [userHomePath UTF8String], YES) == -1) || 574 if ((setenv(kUserHomeEnvVariable, [userHomePath UTF8String], YES) == -1) ||
549 (setenv(kHomeEnvVariable, [userHomePath UTF8String], YES) == -1)) { 575 (setenv(kHomeEnvVariable, [userHomePath UTF8String], YES) == -1)) {
550 LogError(@"Unable to set environment variables for home directory."); 576 LogError(@"Unable to set environment variables for home directory.");
551 return NO; 577 return NO;
552 } 578 }
553 579
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 if (!simHomePath) { 747 if (!simHomePath) {
722 NSString* dirNameTemplate = 748 NSString* dirNameTemplate =
723 [NSString stringWithFormat:@"iossim-%@-%@-XXXXXX", appName, deviceName]; 749 [NSString stringWithFormat:@"iossim-%@-%@-XXXXXX", appName, deviceName];
724 simHomePath = CreateTempDirectory(dirNameTemplate); 750 simHomePath = CreateTempDirectory(dirNameTemplate);
725 if (!simHomePath) { 751 if (!simHomePath) {
726 LogError(@"Unable to create unique directory for template %@", 752 LogError(@"Unable to create unique directory for template %@",
727 dirNameTemplate); 753 dirNameTemplate);
728 exit(kExitInitializationFailure); 754 exit(kExitInitializationFailure);
729 } 755 }
730 } 756 }
731 if (!InitializeSimulatorUserHome(simHomePath, deviceName)) { 757 if (!InitializeSimulatorUserHome(simHomePath)) {
732 LogError(@"Unable to initialize home directory for simulator: %@", 758 LogError(@"Unable to initialize home directory for simulator: %@",
733 simHomePath); 759 simHomePath);
734 exit(kExitInitializationFailure); 760 exit(kExitInitializationFailure);
735 } 761 }
736 762
737 // Create the config and simulator session. 763 // Create the config and simulator session.
738 DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec, 764 DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec,
739 systemRoot, 765 systemRoot,
740 stdioPath, 766 stdioPath,
741 stdioPath, 767 stdioPath,
742 appArgs, 768 appArgs,
743 appEnv, 769 appEnv,
744 deviceFamily); 770 deviceFamily,
771 deviceName);
745 SimulatorDelegate* delegate = 772 SimulatorDelegate* delegate =
746 [[[SimulatorDelegate alloc] initWithStdioPath:stdioPath 773 [[[SimulatorDelegate alloc] initWithStdioPath:stdioPath
747 developerDir:developerDir 774 developerDir:developerDir
748 simulatorHome:simHomePath] autorelease]; 775 simulatorHome:simHomePath] autorelease];
749 DTiPhoneSimulatorSession* session = BuildSession(delegate); 776 DTiPhoneSimulatorSession* session = BuildSession(delegate);
750 777
751 // Start the simulator session. 778 // Start the simulator session.
752 NSError* error; 779 NSError* error;
753 BOOL started = [session requestStartWithConfig:config 780 BOOL started = [session requestStartWithConfig:config
754 timeout:sessionStartTimeout 781 timeout:sessionStartTimeout
755 error:&error]; 782 error:&error];
756 783
757 // Spin the runtime indefinitely. When the delegate gets the message that the 784 // Spin the runtime indefinitely. When the delegate gets the message that the
758 // app has quit it will exit this program. 785 // app has quit it will exit this program.
759 if (started) { 786 if (started) {
760 [[NSRunLoop mainRunLoop] run]; 787 [[NSRunLoop mainRunLoop] run];
761 } else { 788 } else {
762 LogError(@"Simulator failed request to start: \"%@\" (%@:%ld)", 789 LogError(@"Simulator failed request to start: \"%@\" (%@:%ld)",
763 [error localizedDescription], 790 [error localizedDescription],
764 [error domain], static_cast<long int>([error code])); 791 [error domain], static_cast<long int>([error code]));
765 } 792 }
766 793
767 // Note that this code is only executed if the simulator fails to start 794 // 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 795 // because once the main run loop is started, only the delegate calling
769 // exit() will end the program. 796 // exit() will end the program.
770 [pool drain]; 797 [pool drain];
771 return kExitFailure; 798 return kExitFailure;
772 } 799 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698