OLD | NEW |
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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 | 56 |
57 // Max number of seconds to wait for the simulator session to start. | 57 // Max number of seconds to wait for the simulator session to start. |
58 // This timeout must allow time to start up iOS Simulator, install the app | 58 // This timeout must allow time to start up iOS Simulator, install the app |
59 // and perform any other black magic that is encoded in the | 59 // and perform any other black magic that is encoded in the |
60 // iPhoneSimulatorRemoteClient framework to kick things off. Normal start up | 60 // iPhoneSimulatorRemoteClient framework to kick things off. Normal start up |
61 // time is only a couple seconds but machine load, disk caches, etc., can all | 61 // time is only a couple seconds but machine load, disk caches, etc., can all |
62 // affect startup time in the wild so the timeout needs to be fairly generous. | 62 // affect startup time in the wild so the timeout needs to be fairly generous. |
63 // If this timeout occurs iossim will likely exit with non-zero status; the | 63 // If this timeout occurs iossim will likely exit with non-zero status; the |
64 // exception being if the app is invoked and completes execution before the | 64 // exception being if the app is invoked and completes execution before the |
65 // session is started (this case is handled in session:didStart:withError). | 65 // session is started (this case is handled in session:didStart:withError). |
66 const NSTimeInterval kSessionStartTimeoutSeconds = 30; | 66 const NSTimeInterval kDefaultSessionStartTimeoutSeconds = 30; |
67 | 67 |
68 // While the simulated app is running, its stdout is redirected to a file which | 68 // 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 | 69 // is polled by iossim and written to iossim's stdout using the following |
70 // polling interval. | 70 // polling interval. |
71 const NSTimeInterval kOutputPollIntervalSeconds = 0.1; | 71 const NSTimeInterval kOutputPollIntervalSeconds = 0.1; |
72 | 72 |
73 // The path within the developer dir of the private Simulator frameworks. | 73 // The path within the developer dir of the private Simulator frameworks. |
74 NSString* const kSimulatorFrameworkRelativePath = | 74 NSString* const kSimulatorFrameworkRelativePath = |
75 @"Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/" | 75 @"Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/" |
76 @"iPhoneSimulatorRemoteClient.framework"; | 76 @"iPhoneSimulatorRemoteClient.framework"; |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 LogError(@"Unable to set environment variables for home directory."); | 485 LogError(@"Unable to set environment variables for home directory."); |
486 return NO; | 486 return NO; |
487 } | 487 } |
488 | 488 |
489 return YES; | 489 return YES; |
490 } | 490 } |
491 | 491 |
492 // Prints the usage information to stderr. | 492 // Prints the usage information to stderr. |
493 void PrintUsage() { | 493 void PrintUsage() { |
494 fprintf(stderr, "Usage: iossim [-d device] [-s sdkVersion] [-u homeDir] " | 494 fprintf(stderr, "Usage: iossim [-d device] [-s sdkVersion] [-u homeDir] " |
495 "[-e envKey=value]* <appPath> [<appArgs>]\n" | 495 "[-e envKey=value]* [-t startupTimeout] <appPath> [<appArgs>]\n" |
496 " where <appPath> is the path to the .app directory and appArgs are any" | 496 " where <appPath> is the path to the .app directory and appArgs are any" |
497 " arguments to send the simulated app.\n" | 497 " arguments to send the simulated app.\n" |
498 "\n" | 498 "\n" |
499 "Options:\n" | 499 "Options:\n" |
500 " -d Specifies the device (either 'iPhone' or 'iPad')." | 500 " -d Specifies the device (either 'iPhone' or 'iPad')." |
501 " Defaults to 'iPhone'.\n" | 501 " Defaults to 'iPhone'.\n" |
502 " -s Specifies the SDK version to use (e.g '4.3')." | 502 " -s Specifies the SDK version to use (e.g '4.3')." |
503 " Will use system default if not specified.\n" | 503 " Will use system default if not specified.\n" |
504 " -u Specifies a user home directory for the simulator." | 504 " -u Specifies a user home directory for the simulator." |
505 " Will create a new directory if not specified.\n" | 505 " Will create a new directory if not specified.\n" |
506 " -e Specifies an environment key=value pair that will be" | 506 " -e Specifies an environment key=value pair that will be" |
507 " set in the simulated application's environment.\n"); | 507 " set in the simulated application's environment.\n" |
| 508 " -t Specifies the session startup timeout (in seconds)." |
| 509 " Defaults to %d.\n", |
| 510 static_cast<int>(kDefaultSessionStartTimeoutSeconds)); |
508 } | 511 } |
509 | 512 |
510 } // namespace | 513 } // namespace |
511 | 514 |
512 int main(int argc, char* const argv[]) { | 515 int main(int argc, char* const argv[]) { |
513 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; | 516 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; |
514 | 517 |
515 // basename() may modify the passed in string and it returns a pointer to an | 518 // basename() may modify the passed in string and it returns a pointer to an |
516 // internal buffer. Give it a copy to modify, and copy what it returns. | 519 // internal buffer. Give it a copy to modify, and copy what it returns. |
517 char* worker = strdup(argv[0]); | 520 char* worker = strdup(argv[0]); |
518 char* toolName = basename(worker); | 521 char* toolName = basename(worker); |
519 if (toolName != NULL) { | 522 if (toolName != NULL) { |
520 toolName = strdup(toolName); | 523 toolName = strdup(toolName); |
521 if (toolName != NULL) | 524 if (toolName != NULL) |
522 gToolName = toolName; | 525 gToolName = toolName; |
523 } | 526 } |
524 if (worker != NULL) | 527 if (worker != NULL) |
525 free(worker); | 528 free(worker); |
526 | 529 |
527 NSString* appPath = nil; | 530 NSString* appPath = nil; |
528 NSString* appName = nil; | 531 NSString* appName = nil; |
529 NSString* sdkVersion = nil; | 532 NSString* sdkVersion = nil; |
530 NSString* deviceName = @"iPhone"; | 533 NSString* deviceName = @"iPhone"; |
531 NSString* simHomePath = nil; | 534 NSString* simHomePath = nil; |
532 NSMutableArray* appArgs = [NSMutableArray array]; | 535 NSMutableArray* appArgs = [NSMutableArray array]; |
533 NSMutableDictionary* appEnv = [NSMutableDictionary dictionary]; | 536 NSMutableDictionary* appEnv = [NSMutableDictionary dictionary]; |
| 537 NSTimeInterval sessionStartTimeout = kDefaultSessionStartTimeoutSeconds; |
534 | 538 |
535 // Parse the optional arguments | 539 // Parse the optional arguments |
536 int c; | 540 int c; |
537 while ((c = getopt(argc, argv, "hs:d:u:e:")) != -1) { | 541 while ((c = getopt(argc, argv, "hs:d:u:e:t:")) != -1) { |
538 switch (c) { | 542 switch (c) { |
539 case 's': | 543 case 's': |
540 sdkVersion = [NSString stringWithUTF8String:optarg]; | 544 sdkVersion = [NSString stringWithUTF8String:optarg]; |
541 break; | 545 break; |
542 case 'd': | 546 case 'd': |
543 deviceName = [NSString stringWithUTF8String:optarg]; | 547 deviceName = [NSString stringWithUTF8String:optarg]; |
544 break; | 548 break; |
545 case 'u': | 549 case 'u': |
546 simHomePath = [[NSFileManager defaultManager] | 550 simHomePath = [[NSFileManager defaultManager] |
547 stringWithFileSystemRepresentation:optarg length:strlen(optarg)]; | 551 stringWithFileSystemRepresentation:optarg length:strlen(optarg)]; |
548 break; | 552 break; |
549 case 'e': { | 553 case 'e': { |
550 NSString* envLine = [NSString stringWithUTF8String:optarg]; | 554 NSString* envLine = [NSString stringWithUTF8String:optarg]; |
551 NSRange range = [envLine rangeOfString:@"="]; | 555 NSRange range = [envLine rangeOfString:@"="]; |
552 if (range.location == NSNotFound) { | 556 if (range.location == NSNotFound) { |
553 LogError(@"Invalid key=value argument for -e."); | 557 LogError(@"Invalid key=value argument for -e."); |
554 PrintUsage(); | 558 PrintUsage(); |
555 exit(EXIT_FAILURE); | 559 exit(EXIT_FAILURE); |
556 } | 560 } |
557 NSString* key = [envLine substringToIndex:range.location]; | 561 NSString* key = [envLine substringToIndex:range.location]; |
558 NSString* value = [envLine substringFromIndex:(range.location + 1)]; | 562 NSString* value = [envLine substringFromIndex:(range.location + 1)]; |
559 [appEnv setObject:value forKey:key]; | 563 [appEnv setObject:value forKey:key]; |
560 } | 564 } |
561 break; | 565 break; |
| 566 case 't': { |
| 567 int timeout = atoi(optarg); |
| 568 if (timeout > 0) { |
| 569 sessionStartTimeout = static_cast<NSTimeInterval>(timeout); |
| 570 } else { |
| 571 LogError(@"Invalid startup timeout (%s).", optarg); |
| 572 PrintUsage(); |
| 573 exit(EXIT_FAILURE); |
| 574 } |
| 575 } |
| 576 break; |
562 case 'h': | 577 case 'h': |
563 PrintUsage(); | 578 PrintUsage(); |
564 exit(EXIT_SUCCESS); | 579 exit(EXIT_SUCCESS); |
565 default: | 580 default: |
566 PrintUsage(); | 581 PrintUsage(); |
567 exit(EXIT_FAILURE); | 582 exit(EXIT_FAILURE); |
568 } | 583 } |
569 } | 584 } |
570 | 585 |
571 // There should be at least one arg left, specifying the app path. Any | 586 // There should be at least one arg left, specifying the app path. Any |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
653 appEnv, | 668 appEnv, |
654 deviceFamily); | 669 deviceFamily); |
655 SimulatorDelegate* delegate = | 670 SimulatorDelegate* delegate = |
656 [[[SimulatorDelegate alloc] initWithStdioPath:stdioPath | 671 [[[SimulatorDelegate alloc] initWithStdioPath:stdioPath |
657 developerDir:developerDir] autorelease]; | 672 developerDir:developerDir] autorelease]; |
658 DTiPhoneSimulatorSession* session = BuildSession(delegate); | 673 DTiPhoneSimulatorSession* session = BuildSession(delegate); |
659 | 674 |
660 // Start the simulator session. | 675 // Start the simulator session. |
661 NSError* error; | 676 NSError* error; |
662 BOOL started = [session requestStartWithConfig:config | 677 BOOL started = [session requestStartWithConfig:config |
663 timeout:kSessionStartTimeoutSeconds | 678 timeout:sessionStartTimeout |
664 error:&error]; | 679 error:&error]; |
665 | 680 |
666 // Spin the runtime indefinitely. When the delegate gets the message that the | 681 // Spin the runtime indefinitely. When the delegate gets the message that the |
667 // app has quit it will exit this program. | 682 // app has quit it will exit this program. |
668 if (started) { | 683 if (started) { |
669 [[NSRunLoop mainRunLoop] run]; | 684 [[NSRunLoop mainRunLoop] run]; |
670 } else { | 685 } else { |
671 LogError(@"Simulator failed request to start: \"%@\" (%@:%ld)", | 686 LogError(@"Simulator failed request to start: \"%@\" (%@:%ld)", |
672 [error localizedDescription], | 687 [error localizedDescription], |
673 [error domain], static_cast<long int>([error code])); | 688 [error domain], static_cast<long int>([error code])); |
674 } | 689 } |
675 | 690 |
676 // Note that this code is only executed if the simulator fails to start | 691 // Note that this code is only executed if the simulator fails to start |
677 // because once the main run loop is started, only the delegate calling | 692 // because once the main run loop is started, only the delegate calling |
678 // exit() will end the program. | 693 // exit() will end the program. |
679 [pool drain]; | 694 [pool drain]; |
680 return EXIT_FAILURE; | 695 return EXIT_FAILURE; |
681 } | 696 } |
OLD | NEW |