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

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

Issue 11578072: Add error codes to iossim. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 11 months 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 NSString* const kSimulatorRelativePath = 79 NSString* const kSimulatorRelativePath =
80 @"Platforms/iPhoneSimulator.platform/Developer/Applications/" 80 @"Platforms/iPhoneSimulator.platform/Developer/Applications/"
81 @"iPhone Simulator.app"; 81 @"iPhone Simulator.app";
82 82
83 // Simulator Error String Key. This can be found by looking in the Simulator's 83 // Simulator Error String Key. This can be found by looking in the Simulator's
84 // Localizable.strings files. 84 // Localizable.strings files.
85 NSString* const kSimulatorAppQuitErrorKey = @"The simulated application quit."; 85 NSString* const kSimulatorAppQuitErrorKey = @"The simulated application quit.";
86 86
87 const char* gToolName = "iossim"; 87 const char* gToolName = "iossim";
88 88
89 // Exit status codes.
90 const int kExitSuccess = EXIT_SUCCESS;
91 const int kExitFailure = EXIT_FAILURE;
92 const int kExitInvalidArguments = 2;
93 const int kExitInitializationFailure = 3;
94 const int kExitAppFailedToStart = 4;
95 const int kExitAppCrashed = 5;
96
89 void LogError(NSString* format, ...) { 97 void LogError(NSString* format, ...) {
90 va_list list; 98 va_list list;
91 va_start(list, format); 99 va_start(list, format);
92 100
93 NSString* message = 101 NSString* message =
94 [[[NSString alloc] initWithFormat:format arguments:list] autorelease]; 102 [[[NSString alloc] initWithFormat:format arguments:list] autorelease];
95 103
96 fprintf(stderr, "%s: ERROR: %s\n", gToolName, [message UTF8String]); 104 fprintf(stderr, "%s: ERROR: %s\n", gToolName, [message UTF8String]);
97 fflush(stderr); 105 fflush(stderr);
98 106
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 appRunning_ = NO; 224 appRunning_ = NO;
217 [self tailOutput]; 225 [self tailOutput];
218 // Note that exiting in this state leaves a process running 226 // Note that exiting in this state leaves a process running
219 // (e.g. /.../iPhoneSimulator4.3.sdk/usr/libexec/installd -t 30) that will 227 // (e.g. /.../iPhoneSimulator4.3.sdk/usr/libexec/installd -t 30) that will
220 // prevent future simulator sessions from being started for 30 seconds 228 // prevent future simulator sessions from being started for 30 seconds
221 // unless the iOS Simulator application is killed altogether. 229 // unless the iOS Simulator application is killed altogether.
222 [self session:session didEndWithError:nil]; 230 [self session:session didEndWithError:nil];
223 231
224 // session:didEndWithError should not return (because it exits) so 232 // session:didEndWithError should not return (because it exits) so
225 // the execution path should never get here. 233 // the execution path should never get here.
226 exit(EXIT_FAILURE); 234 exit(kExitFailure);
227 } 235 }
228 236
229 LogError(@"Simulator failed to start: \"%@\" (%@:%ld)", 237 LogError(@"Simulator failed to start: \"%@\" (%@:%ld)",
230 [error localizedDescription], 238 [error localizedDescription],
231 [error domain], static_cast<long int>([error code])); 239 [error domain], static_cast<long int>([error code]));
232 exit(EXIT_FAILURE); 240 exit(kExitAppFailedToStart);
233 } 241 }
234 242
235 // Start a thread to write contents of outputPath to stdout. 243 // Start a thread to write contents of outputPath to stdout.
236 appRunning_ = YES; 244 appRunning_ = YES;
237 outputThread_ = [[NSThread alloc] initWithTarget:self 245 outputThread_ = [[NSThread alloc] initWithTarget:self
238 selector:@selector(tailOutput) 246 selector:@selector(tailOutput)
239 object:nil]; 247 object:nil];
240 [outputThread_ start]; 248 [outputThread_ start];
241 } 249 }
242 250
(...skipping 18 matching lines...) Expand all
261 NSString* ignorableErrorStr = 269 NSString* ignorableErrorStr =
262 [self localizedSimulatorErrorString:kSimulatorAppQuitErrorKey]; 270 [self localizedSimulatorErrorString:kSimulatorAppQuitErrorKey];
263 if ([ignorableErrorStr isEqual:localizedDescription]) { 271 if ([ignorableErrorStr isEqual:localizedDescription]) {
264 LogWarning(@"Ignoring that Simulator ended with: \"%@\" (%@:%ld)", 272 LogWarning(@"Ignoring that Simulator ended with: \"%@\" (%@:%ld)",
265 localizedDescription, [error domain], 273 localizedDescription, [error domain],
266 static_cast<long int>([error code])); 274 static_cast<long int>([error code]));
267 } else { 275 } else {
268 LogError(@"Simulator ended with error: \"%@\" (%@:%ld)", 276 LogError(@"Simulator ended with error: \"%@\" (%@:%ld)",
269 localizedDescription, [error domain], 277 localizedDescription, [error domain],
270 static_cast<long int>([error code])); 278 static_cast<long int>([error code]));
271 exit(EXIT_FAILURE); 279 exit(kExitFailure);
272 } 280 }
273 } 281 }
274 282
275 // Check if the simulated app exited abnormally by looking for system log 283 // Check if the simulated app exited abnormally by looking for system log
276 // messages from launchd that refer to the simulated app's PID. Limit query 284 // messages from launchd that refer to the simulated app's PID. Limit query
277 // to messages in the last minute since PIDs are cyclical. 285 // to messages in the last minute since PIDs are cyclical.
278 aslmsg query = asl_new(ASL_TYPE_QUERY); 286 aslmsg query = asl_new(ASL_TYPE_QUERY);
279 asl_set_query(query, ASL_KEY_SENDER, "launchd", 287 asl_set_query(query, ASL_KEY_SENDER, "launchd",
280 ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_SUBSTRING); 288 ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_SUBSTRING);
281 asl_set_query(query, ASL_KEY_REF_PID, 289 asl_set_query(query, ASL_KEY_REF_PID,
282 [[[session simulatedApplicationPID] stringValue] UTF8String], 290 [[[session simulatedApplicationPID] stringValue] UTF8String],
283 ASL_QUERY_OP_EQUAL); 291 ASL_QUERY_OP_EQUAL);
284 asl_set_query(query, ASL_KEY_TIME, "-1m", ASL_QUERY_OP_GREATER_EQUAL); 292 asl_set_query(query, ASL_KEY_TIME, "-1m", ASL_QUERY_OP_GREATER_EQUAL);
285 293
286 // Log any messages found. 294 // Log any messages found.
287 aslresponse response = asl_search(NULL, query); 295 aslresponse response = asl_search(NULL, query);
288 BOOL entryFound = NO; 296 BOOL entryFound = NO;
289 aslmsg entry; 297 aslmsg entry;
290 while ((entry = aslresponse_next(response)) != NULL) { 298 while ((entry = aslresponse_next(response)) != NULL) {
291 entryFound = YES; 299 entryFound = YES;
292 LogWarning(@"Console message: %s", asl_get(entry, ASL_KEY_MSG)); 300 LogWarning(@"Console message: %s", asl_get(entry, ASL_KEY_MSG));
293 } 301 }
294 302
295 // launchd only sends messages if the process crashed or exits with a 303 // launchd only sends messages if the process crashed or exits with a
296 // non-zero status, so if the query returned any results iossim should exit 304 // non-zero status, so if the query returned any results iossim should exit
297 // with non-zero status. 305 // with non-zero status.
298 if (entryFound) { 306 if (entryFound) {
299 LogError(@"Simulated app crashed or exited with non-zero status"); 307 LogError(@"Simulated app crashed or exited with non-zero status");
300 exit(EXIT_FAILURE); 308 exit(kExitAppCrashed);
301 } 309 }
302 exit(EXIT_SUCCESS); 310 exit(kExitSuccess);
303 } 311 }
304 @end 312 @end
305 313
306 namespace { 314 namespace {
307 315
308 // Finds the developer dir via xcode-select or the DEVELOPER_DIR environment 316 // Finds the developer dir via xcode-select or the DEVELOPER_DIR environment
309 // variable. 317 // variable.
310 NSString* FindDeveloperDir() { 318 NSString* FindDeveloperDir() {
311 // Check the env first. 319 // Check the env first.
312 NSDictionary* env = [[NSProcessInfo processInfo] environment]; 320 NSDictionary* env = [[NSProcessInfo processInfo] environment];
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 if (![simBundle load]) 361 if (![simBundle load])
354 return nil; 362 return nil;
355 return simBundle; 363 return simBundle;
356 } 364 }
357 365
358 // Helper to find a class by name and die if it isn't found. 366 // Helper to find a class by name and die if it isn't found.
359 Class FindClassByName(NSString* nameOfClass) { 367 Class FindClassByName(NSString* nameOfClass) {
360 Class theClass = NSClassFromString(nameOfClass); 368 Class theClass = NSClassFromString(nameOfClass);
361 if (!theClass) { 369 if (!theClass) {
362 LogError(@"Failed to find class %@ at runtime.", nameOfClass); 370 LogError(@"Failed to find class %@ at runtime.", nameOfClass);
363 exit(EXIT_FAILURE); 371 exit(kExitInitializationFailure);
364 } 372 }
365 return theClass; 373 return theClass;
366 } 374 }
367 375
368 // Converts the given app path to an application spec, which requires an 376 // Converts the given app path to an application spec, which requires an
369 // absolute path. 377 // absolute path.
370 DTiPhoneSimulatorApplicationSpecifier* BuildAppSpec(NSString* appPath) { 378 DTiPhoneSimulatorApplicationSpecifier* BuildAppSpec(NSString* appPath) {
371 Class applicationSpecifierClass = 379 Class applicationSpecifierClass =
372 FindClassByName(@"DTiPhoneSimulatorApplicationSpecifier"); 380 FindClassByName(@"DTiPhoneSimulatorApplicationSpecifier");
373 if (![appPath isAbsolutePath]) { 381 if (![appPath isAbsolutePath]) {
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 case 'u': 577 case 'u':
570 simHomePath = [[NSFileManager defaultManager] 578 simHomePath = [[NSFileManager defaultManager]
571 stringWithFileSystemRepresentation:optarg length:strlen(optarg)]; 579 stringWithFileSystemRepresentation:optarg length:strlen(optarg)];
572 break; 580 break;
573 case 'e': { 581 case 'e': {
574 NSString* envLine = [NSString stringWithUTF8String:optarg]; 582 NSString* envLine = [NSString stringWithUTF8String:optarg];
575 NSRange range = [envLine rangeOfString:@"="]; 583 NSRange range = [envLine rangeOfString:@"="];
576 if (range.location == NSNotFound) { 584 if (range.location == NSNotFound) {
577 LogError(@"Invalid key=value argument for -e."); 585 LogError(@"Invalid key=value argument for -e.");
578 PrintUsage(); 586 PrintUsage();
579 exit(EXIT_FAILURE); 587 exit(kExitInvalidArguments);
580 } 588 }
581 NSString* key = [envLine substringToIndex:range.location]; 589 NSString* key = [envLine substringToIndex:range.location];
582 NSString* value = [envLine substringFromIndex:(range.location + 1)]; 590 NSString* value = [envLine substringFromIndex:(range.location + 1)];
583 [appEnv setObject:value forKey:key]; 591 [appEnv setObject:value forKey:key];
584 } 592 }
585 break; 593 break;
586 case 't': { 594 case 't': {
587 int timeout = atoi(optarg); 595 int timeout = atoi(optarg);
588 if (timeout > 0) { 596 if (timeout > 0) {
589 sessionStartTimeout = static_cast<NSTimeInterval>(timeout); 597 sessionStartTimeout = static_cast<NSTimeInterval>(timeout);
590 } else { 598 } else {
591 LogError(@"Invalid startup timeout (%s).", optarg); 599 LogError(@"Invalid startup timeout (%s).", optarg);
592 PrintUsage(); 600 PrintUsage();
593 exit(EXIT_FAILURE); 601 exit(kExitInvalidArguments);
594 } 602 }
595 } 603 }
596 break; 604 break;
597 case 'h': 605 case 'h':
598 PrintUsage(); 606 PrintUsage();
599 exit(EXIT_SUCCESS); 607 exit(kExitSuccess);
600 default: 608 default:
601 PrintUsage(); 609 PrintUsage();
602 exit(EXIT_FAILURE); 610 exit(kExitInvalidArguments);
603 } 611 }
604 } 612 }
605 613
606 // There should be at least one arg left, specifying the app path. Any 614 // There should be at least one arg left, specifying the app path. Any
607 // additional args are passed as arguments to the app. 615 // additional args are passed as arguments to the app.
608 if (optind < argc) { 616 if (optind < argc) {
609 appPath = [[NSFileManager defaultManager] 617 appPath = [[NSFileManager defaultManager]
610 stringWithFileSystemRepresentation:argv[optind] 618 stringWithFileSystemRepresentation:argv[optind]
611 length:strlen(argv[optind])]; 619 length:strlen(argv[optind])];
612 appName = [appPath lastPathComponent]; 620 appName = [appPath lastPathComponent];
613 while (++optind < argc) { 621 while (++optind < argc) {
614 [appArgs addObject:[NSString stringWithUTF8String:argv[optind]]]; 622 [appArgs addObject:[NSString stringWithUTF8String:argv[optind]]];
615 } 623 }
616 } else { 624 } else {
617 LogError(@"Unable to parse command line arguments."); 625 LogError(@"Unable to parse command line arguments.");
618 PrintUsage(); 626 PrintUsage();
619 exit(EXIT_FAILURE); 627 exit(kExitInvalidArguments);
620 } 628 }
621 629
622 NSString* developerDir = FindDeveloperDir(); 630 NSString* developerDir = FindDeveloperDir();
623 if (!developerDir) { 631 if (!developerDir) {
624 LogError(@"Unable to find developer directory."); 632 LogError(@"Unable to find developer directory.");
625 exit(EXIT_FAILURE); 633 exit(kExitInitializationFailure);
626 } 634 }
627 635
628 NSBundle* simulatorFramework = LoadSimulatorFramework(developerDir); 636 NSBundle* simulatorFramework = LoadSimulatorFramework(developerDir);
629 if (!simulatorFramework) { 637 if (!simulatorFramework) {
630 LogError(@"Failed to load the Simulator Framework."); 638 LogError(@"Failed to load the Simulator Framework.");
631 exit(EXIT_FAILURE); 639 exit(kExitInitializationFailure);
632 } 640 }
633 641
634 // Make sure the app path provided is legit. 642 // Make sure the app path provided is legit.
635 DTiPhoneSimulatorApplicationSpecifier* appSpec = BuildAppSpec(appPath); 643 DTiPhoneSimulatorApplicationSpecifier* appSpec = BuildAppSpec(appPath);
636 if (!appSpec) { 644 if (!appSpec) {
637 LogError(@"Invalid app path: %@", appPath); 645 LogError(@"Invalid app path: %@", appPath);
638 exit(EXIT_FAILURE); 646 exit(kExitInitializationFailure);
639 } 647 }
640 648
641 // Make sure the SDK path provided is legit (or nil). 649 // Make sure the SDK path provided is legit (or nil).
642 DTiPhoneSimulatorSystemRoot* systemRoot = BuildSystemRoot(sdkVersion); 650 DTiPhoneSimulatorSystemRoot* systemRoot = BuildSystemRoot(sdkVersion);
643 if (!systemRoot) { 651 if (!systemRoot) {
644 LogError(@"Invalid SDK version: %@", sdkVersion); 652 LogError(@"Invalid SDK version: %@", sdkVersion);
645 exit(EXIT_FAILURE); 653 exit(kExitInitializationFailure);
646 } 654 }
647 655
648 // Get the paths for stdout and stderr so the simulated app's output will show 656 // Get the paths for stdout and stderr so the simulated app's output will show
649 // up in the caller's stdout/stderr. 657 // up in the caller's stdout/stderr.
650 NSString* outputDir = CreateTempDirectory(@"iossim-XXXXXX"); 658 NSString* outputDir = CreateTempDirectory(@"iossim-XXXXXX");
651 NSString* stdioPath = [outputDir stringByAppendingPathComponent:@"stdio.txt"]; 659 NSString* stdioPath = [outputDir stringByAppendingPathComponent:@"stdio.txt"];
652 660
653 // Determine the deviceFamily based on the deviceName 661 // Determine the deviceFamily based on the deviceName
654 NSNumber* deviceFamily = nil; 662 NSNumber* deviceFamily = nil;
655 if (!deviceName || CaseInsensitivePrefixSearch(deviceName, @"iPhone")) { 663 if (!deviceName || CaseInsensitivePrefixSearch(deviceName, @"iPhone")) {
656 deviceFamily = [NSNumber numberWithInt:kIPhoneFamily]; 664 deviceFamily = [NSNumber numberWithInt:kIPhoneFamily];
657 } else if (CaseInsensitivePrefixSearch(deviceName, @"iPad")) { 665 } else if (CaseInsensitivePrefixSearch(deviceName, @"iPad")) {
658 deviceFamily = [NSNumber numberWithInt:kIPadFamily]; 666 deviceFamily = [NSNumber numberWithInt:kIPadFamily];
659 } else { 667 } else {
660 LogError(@"Invalid device name: %@. Must begin with 'iPhone' or 'iPad'", 668 LogError(@"Invalid device name: %@. Must begin with 'iPhone' or 'iPad'",
661 deviceName); 669 deviceName);
662 exit(EXIT_FAILURE); 670 exit(kExitInvalidArguments);
663 } 671 }
664 672
665 // Set up the user home directory for the simulator 673 // Set up the user home directory for the simulator
666 if (!simHomePath) { 674 if (!simHomePath) {
667 NSString* dirNameTemplate = 675 NSString* dirNameTemplate =
668 [NSString stringWithFormat:@"iossim-%@-%@-XXXXXX", appName, deviceName]; 676 [NSString stringWithFormat:@"iossim-%@-%@-XXXXXX", appName, deviceName];
669 simHomePath = CreateTempDirectory(dirNameTemplate); 677 simHomePath = CreateTempDirectory(dirNameTemplate);
670 if (!simHomePath) { 678 if (!simHomePath) {
671 LogError(@"Unable to create unique directory for template %@", 679 LogError(@"Unable to create unique directory for template %@",
672 dirNameTemplate); 680 dirNameTemplate);
673 exit(EXIT_FAILURE); 681 exit(kExitInitializationFailure);
674 } 682 }
675 } 683 }
676 if (!InitializeSimulatorUserHome(simHomePath, deviceName)) { 684 if (!InitializeSimulatorUserHome(simHomePath, deviceName)) {
677 LogError(@"Unable to initialize home directory for simulator: %@", 685 LogError(@"Unable to initialize home directory for simulator: %@",
678 simHomePath); 686 simHomePath);
679 exit(EXIT_FAILURE); 687 exit(kExitInitializationFailure);
680 } 688 }
681 689
682 // Create the config and simulator session. 690 // Create the config and simulator session.
683 DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec, 691 DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec,
684 systemRoot, 692 systemRoot,
685 stdioPath, 693 stdioPath,
686 stdioPath, 694 stdioPath,
687 appArgs, 695 appArgs,
688 appEnv, 696 appEnv,
689 deviceFamily); 697 deviceFamily);
(...skipping 15 matching lines...) Expand all
705 } else { 713 } else {
706 LogError(@"Simulator failed request to start: \"%@\" (%@:%ld)", 714 LogError(@"Simulator failed request to start: \"%@\" (%@:%ld)",
707 [error localizedDescription], 715 [error localizedDescription],
708 [error domain], static_cast<long int>([error code])); 716 [error domain], static_cast<long int>([error code]));
709 } 717 }
710 718
711 // Note that this code is only executed if the simulator fails to start 719 // Note that this code is only executed if the simulator fails to start
712 // because once the main run loop is started, only the delegate calling 720 // because once the main run loop is started, only the delegate calling
713 // exit() will end the program. 721 // exit() will end the program.
714 [pool drain]; 722 [pool drain];
715 return EXIT_FAILURE; 723 return kExitFailure;
716 } 724 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698