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

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

Issue 494583004: Make iossim binary work on Xcode 5 and 6. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: refactored task-running method; exit early if no xcode6 support Created 6 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « testing/iossim/iossim.gyp ('k') | 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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 // If this timeout occurs iossim will likely exit with non-zero status; the 94 // If this timeout occurs iossim will likely exit with non-zero status; the
95 // exception being if the app is invoked and completes execution before the 95 // exception being if the app is invoked and completes execution before the
96 // session is started (this case is handled in session:didStart:withError). 96 // session is started (this case is handled in session:didStart:withError).
97 const NSTimeInterval kDefaultSessionStartTimeoutSeconds = 30; 97 const NSTimeInterval kDefaultSessionStartTimeoutSeconds = 30;
98 98
99 // While the simulated app is running, its stdout is redirected to a file which 99 // While the simulated app is running, its stdout is redirected to a file which
100 // is polled by iossim and written to iossim's stdout using the following 100 // is polled by iossim and written to iossim's stdout using the following
101 // polling interval. 101 // polling interval.
102 const NSTimeInterval kOutputPollIntervalSeconds = 0.1; 102 const NSTimeInterval kOutputPollIntervalSeconds = 0.1;
103 103
104 // The path within the developer dir of the private Simulator frameworks.
105 // TODO(lliabraa): Once all builders are on Xcode 6 this ifdef can be removed
106 // (crbug.com/385030).
107 #if defined(IOSSIM_USE_XCODE_6)
108 NSString* const kSimulatorFrameworkRelativePath =
109 @"../SharedFrameworks/DVTiPhoneSimulatorRemoteClient.framework";
110 NSString* const kCoreSimulatorRelativePath =
111 @"Library/PrivateFrameworks/CoreSimulator.framework";
112 #else
113 NSString* const kSimulatorFrameworkRelativePath =
114 @"Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/"
115 @"DVTiPhoneSimulatorRemoteClient.framework";
116 #endif // IOSSIM_USE_XCODE_6
117 NSString* const kDVTFoundationRelativePath = 104 NSString* const kDVTFoundationRelativePath =
118 @"../SharedFrameworks/DVTFoundation.framework"; 105 @"../SharedFrameworks/DVTFoundation.framework";
119 NSString* const kDevToolsFoundationRelativePath = 106 NSString* const kDevToolsFoundationRelativePath =
120 @"../OtherFrameworks/DevToolsFoundation.framework"; 107 @"../OtherFrameworks/DevToolsFoundation.framework";
121 NSString* const kSimulatorRelativePath = 108 NSString* const kSimulatorRelativePath =
122 @"Platforms/iPhoneSimulator.platform/Developer/Applications/" 109 @"Platforms/iPhoneSimulator.platform/Developer/Applications/"
123 @"iPhone Simulator.app"; 110 @"iPhone Simulator.app";
124 111
125 // Simulator Error String Key. This can be found by looking in the Simulator's 112 // Simulator Error String Key. This can be found by looking in the Simulator's
126 // Localizable.strings files. 113 // Localizable.strings files.
127 NSString* const kSimulatorAppQuitErrorKey = @"The simulated application quit."; 114 NSString* const kSimulatorAppQuitErrorKey = @"The simulated application quit.";
128 115
129 const char* gToolName = "iossim"; 116 const char* gToolName = "iossim";
130 117
131 // Exit status codes. 118 // Exit status codes.
132 const int kExitSuccess = EXIT_SUCCESS; 119 const int kExitSuccess = EXIT_SUCCESS;
133 const int kExitFailure = EXIT_FAILURE; 120 const int kExitFailure = EXIT_FAILURE;
134 const int kExitInvalidArguments = 2; 121 const int kExitInvalidArguments = 2;
135 const int kExitInitializationFailure = 3; 122 const int kExitInitializationFailure = 3;
136 const int kExitAppFailedToStart = 4; 123 const int kExitAppFailedToStart = 4;
137 const int kExitAppCrashed = 5; 124 const int kExitAppCrashed = 5;
125 const int kExitUnsupportedXcodeVersion = 6;
138 126
139 void LogError(NSString* format, ...) { 127 void LogError(NSString* format, ...) {
140 va_list list; 128 va_list list;
141 va_start(list, format); 129 va_start(list, format);
142 130
143 NSString* message = 131 NSString* message =
144 [[[NSString alloc] initWithFormat:format arguments:list] autorelease]; 132 [[[NSString alloc] initWithFormat:format arguments:list] autorelease];
145 133
146 fprintf(stderr, "%s: ERROR: %s\n", gToolName, [message UTF8String]); 134 fprintf(stderr, "%s: ERROR: %s\n", gToolName, [message UTF8String]);
147 fflush(stderr); 135 fflush(stderr);
(...skipping 17 matching lines...) Expand all
165 // Helper to find a class by name and die if it isn't found. 153 // Helper to find a class by name and die if it isn't found.
166 Class FindClassByName(NSString* nameOfClass) { 154 Class FindClassByName(NSString* nameOfClass) {
167 Class theClass = NSClassFromString(nameOfClass); 155 Class theClass = NSClassFromString(nameOfClass);
168 if (!theClass) { 156 if (!theClass) {
169 LogError(@"Failed to find class %@ at runtime.", nameOfClass); 157 LogError(@"Failed to find class %@ at runtime.", nameOfClass);
170 exit(kExitInitializationFailure); 158 exit(kExitInitializationFailure);
171 } 159 }
172 return theClass; 160 return theClass;
173 } 161 }
174 162
163 // Returns the a NSString containing the stdout from running an NSTask that
164 // launches |toolPath| with th given command line |args|.
165 NSString* GetOutputFromTask(NSString* toolPath, NSArray* args) {
166 NSTask* task = [[[NSTask alloc] init] autorelease];
167 [task setLaunchPath:toolPath];
168 [task setArguments:args];
169 NSPipe* outputPipe = [NSPipe pipe];
170 [task setStandardOutput:outputPipe];
171 NSFileHandle* outputFile = [outputPipe fileHandleForReading];
172
173 [task launch];
174 NSData* outputData = [outputFile readDataToEndOfFile];
175 [task waitUntilExit];
176 if ([task isRunning]) {
177 LogError(@"Task '%@ %@' is still running.",
178 toolPath,
179 [args componentsJoinedByString:@" "]);
180 return nil;
181 } else if ([task terminationStatus]) {
182 LogError(@"Task '%@ %@' exited with return code %@.",
TVL 2014/08/25 13:19:03 isn't terminationStatus an int? (you are using %@
lliabraa 2014/08/25 13:28:36 Done. changed to %d
183 toolPath,
184 [args componentsJoinedByString:@" "],
185 [task terminationStatus]);
186 return nil;
187 }
188 return [[[NSString alloc] initWithData:outputData
189 encoding:NSUTF8StringEncoding] autorelease];
190 }
191
192 // Finds the Xcode version via xcodebuild -version. Output from xcodebuild is
193 // expected to look like:
194 // Xcode <version>
195 // Build version 5B130a
196 // where <version> is the string returned by this function (e.g. 6.0).
197 NSString* FindXcodeVersion() {
198 NSString* output = GetOutputFromTask(@"/usr/bin/xcodebuild",
199 @[ @"-version" ]);
200 // Scan past the "Xcode ", then scan the rest of the line into |version|.
201 NSScanner* scanner = [NSScanner scannerWithString:output];
202 BOOL valid = [scanner scanString:@"Xcode " intoString:NULL];
203 NSString* version;
204 valid =
205 [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet]
206 intoString:&version];
207 if (!valid) {
208 LogError(@"Unable to find Xcode version. 'xcodebuild -version' "
209 @"returned \n%@", output);
210 return nil;
211 }
212 return version;
213 }
214
215 // Returns true if iossim is running with Xcode 6 or later installed on the
216 // host.
217 BOOL IsRunningWithXcode6OrLater() {
218 static NSString* xcodeVersion = FindXcodeVersion();
219 if (!xcodeVersion) {
220 return false;
221 }
222 NSArray* components = [xcodeVersion componentsSeparatedByString:@"."];
223 if ([components count] < 1) {
224 return false;
225 }
226 NSInteger majorVersion = [components[0] integerValue];
227 return majorVersion >= 6;
228 }
229
175 // Prints supported devices and SDKs. 230 // Prints supported devices and SDKs.
176 void PrintSupportedDevices() { 231 void PrintSupportedDevices() {
177 // TODO(lliabraa): Once all builders are on Xcode 6 this ifdef can be removed 232 if (IsRunningWithXcode6OrLater()) {
178 // (crbug.com/385030).
179 #if defined(IOSSIM_USE_XCODE_6) 233 #if defined(IOSSIM_USE_XCODE_6)
180 printf("Supported device/SDK combinations:\n"); 234 printf("Supported device/SDK combinations:\n");
181 Class simDeviceSetClass = FindClassByName(@"SimDeviceSet"); 235 Class simDeviceSetClass = FindClassByName(@"SimDeviceSet");
182 id deviceSet = 236 id deviceSet =
183 [simDeviceSetClass setForSetPath:[simDeviceSetClass defaultSetPath]]; 237 [simDeviceSetClass setForSetPath:[simDeviceSetClass defaultSetPath]];
184 for (id simDevice in [deviceSet availableDevices]) { 238 for (id simDevice in [deviceSet availableDevices]) {
185 NSString* deviceInfo = 239 NSString* deviceInfo =
186 [NSString stringWithFormat:@" -d '%@' -s '%@'\n", 240 [NSString stringWithFormat:@" -d '%@' -s '%@'\n",
187 [simDevice name], [[simDevice runtime] versionString]]; 241 [simDevice name], [[simDevice runtime] versionString]];
188 printf("%s", [deviceInfo UTF8String]); 242 printf("%s", [deviceInfo UTF8String]);
243 }
244 #endif // IOSSIM_USE_XCODE_6
245 } else {
246 printf("Supported SDK versions:\n");
247 Class rootClass = FindClassByName(@"DTiPhoneSimulatorSystemRoot");
248 for (id root in [rootClass knownRoots]) {
249 printf(" '%s'\n", [[root sdkVersion] UTF8String]);
250 }
251 // This is the list of devices supported on Xcode 5.1.x.
252 printf("Supported devices:\n");
253 printf(" 'iPhone'\n");
254 printf(" 'iPhone Retina (3.5-inch)'\n");
255 printf(" 'iPhone Retina (4-inch)'\n");
256 printf(" 'iPhone Retina (4-inch 64-bit)'\n");
257 printf(" 'iPad'\n");
258 printf(" 'iPad Retina'\n");
259 printf(" 'iPad Retina (64-bit)'\n");
189 } 260 }
190 #else
191 printf("Supported SDK versions:\n");
192 Class rootClass = FindClassByName(@"DTiPhoneSimulatorSystemRoot");
193 for (id root in [rootClass knownRoots]) {
194 printf(" '%s'\n", [[root sdkVersion] UTF8String]);
195 }
196 printf("Supported devices:\n");
197 printf(" 'iPhone'\n");
198 printf(" 'iPhone Retina (3.5-inch)'\n");
199 printf(" 'iPhone Retina (4-inch)'\n");
200 printf(" 'iPhone Retina (4-inch 64-bit)'\n");
201 printf(" 'iPad'\n");
202 printf(" 'iPad Retina'\n");
203 printf(" 'iPad Retina (64-bit)'\n");
204 #endif // defined(IOSSIM_USE_XCODE_6)
205 } 261 }
206 } // namespace 262 } // namespace
207 263
208 // A delegate that is called when the simulated app is started or ended in the 264 // A delegate that is called when the simulated app is started or ended in the
209 // simulator. 265 // simulator.
210 @interface SimulatorDelegate : NSObject <DTiPhoneSimulatorSessionDelegate> { 266 @interface SimulatorDelegate : NSObject <DTiPhoneSimulatorSessionDelegate> {
211 @private 267 @private
212 NSString* stdioPath_; 268 NSString* stdioPath_;
213 NSString* developerDir_; 269 NSString* developerDir_;
214 NSString* simulatorHome_; 270 NSString* simulatorHome_;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 // Reads data from the simulated app's output and writes it to stdout. This 309 // Reads data from the simulated app's output and writes it to stdout. This
254 // method blocks, so it should be called in a separate thread. The iOS 310 // method blocks, so it should be called in a separate thread. The iOS
255 // Simulator takes a file path for the simulated app's stdout and stderr, but 311 // Simulator takes a file path for the simulated app's stdout and stderr, but
256 // this path isn't always available (e.g. when the stdout is Xcode's build 312 // this path isn't always available (e.g. when the stdout is Xcode's build
257 // window). As a workaround, iossim creates a temp file to hold output, which 313 // window). As a workaround, iossim creates a temp file to hold output, which
258 // this method reads and copies to stdout. 314 // this method reads and copies to stdout.
259 - (void)tailOutputForSession:(DTiPhoneSimulatorSession*)session { 315 - (void)tailOutputForSession:(DTiPhoneSimulatorSession*)session {
260 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 316 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
261 317
262 NSFileHandle* simio = [NSFileHandle fileHandleForReadingAtPath:stdioPath_]; 318 NSFileHandle* simio = [NSFileHandle fileHandleForReadingAtPath:stdioPath_];
263 // TODO(lliabraa): Once all builders are on Xcode 6 this ifdef can be removed 319 if (IsRunningWithXcode6OrLater()) {
264 // (crbug.com/385030).
265 #if defined(IOSSIM_USE_XCODE_6) 320 #if defined(IOSSIM_USE_XCODE_6)
266 // With iOS 8 simulators on Xcode 6, the app output is relative to the 321 // With iOS 8 simulators on Xcode 6, the app output is relative to the
267 // simulator's data directory. 322 // simulator's data directory.
268 if ([session.sessionConfig.simulatedSystemRoot.sdkVersion isEqual:@"8.0"]) { 323 if ([session.sessionConfig.simulatedSystemRoot.sdkVersion isEqual:@"8.0"]) {
269 NSString* dataPath = session.sessionConfig.device.dataPath; 324 NSString* dataPath = session.sessionConfig.device.dataPath;
270 NSString* appOutput = [dataPath stringByAppendingPathComponent:stdioPath_]; 325 NSString* appOutput =
271 simio = [NSFileHandle fileHandleForReadingAtPath:appOutput]; 326 [dataPath stringByAppendingPathComponent:stdioPath_];
327 simio = [NSFileHandle fileHandleForReadingAtPath:appOutput];
328 }
329 #endif // IOSSIM_USE_XCODE_6
272 } 330 }
273 #endif
274 NSFileHandle* standardOutput = [NSFileHandle fileHandleWithStandardOutput]; 331 NSFileHandle* standardOutput = [NSFileHandle fileHandleWithStandardOutput];
275 // Copy data to stdout/stderr while the app is running. 332 // Copy data to stdout/stderr while the app is running.
276 while (appRunning_) { 333 while (appRunning_) {
277 NSAutoreleasePool* innerPool = [[NSAutoreleasePool alloc] init]; 334 NSAutoreleasePool* innerPool = [[NSAutoreleasePool alloc] init];
278 [standardOutput writeData:[simio readDataToEndOfFile]]; 335 [standardOutput writeData:[simio readDataToEndOfFile]];
279 [NSThread sleepForTimeInterval:kOutputPollIntervalSeconds]; 336 [NSThread sleepForTimeInterval:kOutputPollIntervalSeconds];
280 [innerPool drain]; 337 [innerPool drain];
281 } 338 }
282 339
283 // Once the app is no longer running, copy any data that was written during 340 // Once the app is no longer running, copy any data that was written during
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 const char* message = asl_get(entry, ASL_KEY_MSG); 469 const char* message = asl_get(entry, ASL_KEY_MSG);
413 LogWarning(@"Console message: %s", message); 470 LogWarning(@"Console message: %s", message);
414 // Some messages are harmless, so don't trigger a failure for them. 471 // Some messages are harmless, so don't trigger a failure for them.
415 if (strstr(message, "The following job tried to hijack the service")) 472 if (strstr(message, "The following job tried to hijack the service"))
416 continue; 473 continue;
417 badEntryFound = YES; 474 badEntryFound = YES;
418 } 475 }
419 } else { 476 } else {
420 // Otherwise, the iOS Simulator's system logging is sandboxed, so parse the 477 // Otherwise, the iOS Simulator's system logging is sandboxed, so parse the
421 // sandboxed system.log file for known errors. 478 // sandboxed system.log file for known errors.
422 // TODO(lliabraa): Once all builders are on Xcode 6 this ifdef can be removed 479 NSString* path;
423 // (crbug.com/385030). 480 if (IsRunningWithXcode6OrLater()) {
424 #if defined(IOSSIM_USE_XCODE_6) 481 #if defined(IOSSIM_USE_XCODE_6)
425 NSString* dataPath = session.sessionConfig.device.dataPath; 482 NSString* dataPath = session.sessionConfig.device.dataPath;
426 NSString* path = 483 path =
427 [dataPath stringByAppendingPathComponent:@"Library/Logs/system.log"]; 484 [dataPath stringByAppendingPathComponent:@"Library/Logs/system.log"];
428 #else 485 #endif // IOSSIM_USE_XCODE_6
429 NSString* relativePathToSystemLog = 486 } else {
430 [NSString stringWithFormat: 487 NSString* relativePathToSystemLog =
431 @"Library/Logs/iOS Simulator/%@/system.log", versionString]; 488 [NSString stringWithFormat:
432 NSString* path = 489 @"Library/Logs/iOS Simulator/%@/system.log", versionString];
433 [simulatorHome_ stringByAppendingPathComponent:relativePathToSystemLog]; 490 path = [simulatorHome_
434 #endif // defined(IOSSIM_USE_XCODE_6) 491 stringByAppendingPathComponent:relativePathToSystemLog];
492 }
435 NSFileManager* fileManager = [NSFileManager defaultManager]; 493 NSFileManager* fileManager = [NSFileManager defaultManager];
436 if ([fileManager fileExistsAtPath:path]) { 494 if ([fileManager fileExistsAtPath:path]) {
437 NSString* content = 495 NSString* content =
438 [NSString stringWithContentsOfFile:path 496 [NSString stringWithContentsOfFile:path
439 encoding:NSUTF8StringEncoding 497 encoding:NSUTF8StringEncoding
440 error:NULL]; 498 error:NULL];
441 NSArray* lines = [content componentsSeparatedByCharactersInSet: 499 NSArray* lines = [content componentsSeparatedByCharactersInSet:
442 [NSCharacterSet newlineCharacterSet]]; 500 [NSCharacterSet newlineCharacterSet]];
443 NSString* simulatedAppPID = 501 NSString* simulatedAppPID =
444 [NSString stringWithFormat:@"%d", session.simulatedApplicationPID]; 502 [NSString stringWithFormat:@"%d", session.simulatedApplicationPID];
(...skipping 29 matching lines...) Expand all
474 // Finds the developer dir via xcode-select or the DEVELOPER_DIR environment 532 // Finds the developer dir via xcode-select or the DEVELOPER_DIR environment
475 // variable. 533 // variable.
476 NSString* FindDeveloperDir() { 534 NSString* FindDeveloperDir() {
477 // Check the env first. 535 // Check the env first.
478 NSDictionary* env = [[NSProcessInfo processInfo] environment]; 536 NSDictionary* env = [[NSProcessInfo processInfo] environment];
479 NSString* developerDir = [env objectForKey:@"DEVELOPER_DIR"]; 537 NSString* developerDir = [env objectForKey:@"DEVELOPER_DIR"];
480 if ([developerDir length] > 0) 538 if ([developerDir length] > 0)
481 return developerDir; 539 return developerDir;
482 540
483 // Go look for it via xcode-select. 541 // Go look for it via xcode-select.
484 NSTask* xcodeSelectTask = [[[NSTask alloc] init] autorelease]; 542 NSString* output = GetOutputFromTask(@"/usr/bin/xcode-select",
485 [xcodeSelectTask setLaunchPath:@"/usr/bin/xcode-select"]; 543 @[ @"-print-path" ]);
486 [xcodeSelectTask setArguments:[NSArray arrayWithObject:@"-print-path"]];
487
488 NSPipe* outputPipe = [NSPipe pipe];
489 [xcodeSelectTask setStandardOutput:outputPipe];
490 NSFileHandle* outputFile = [outputPipe fileHandleForReading];
491
492 [xcodeSelectTask launch];
493 NSData* outputData = [outputFile readDataToEndOfFile];
494 [xcodeSelectTask terminate];
495
496 NSString* output =
497 [[[NSString alloc] initWithData:outputData
498 encoding:NSUTF8StringEncoding] autorelease];
499 output = [output stringByTrimmingCharactersInSet: 544 output = [output stringByTrimmingCharactersInSet:
500 [NSCharacterSet whitespaceAndNewlineCharacterSet]]; 545 [NSCharacterSet whitespaceAndNewlineCharacterSet]];
501 if ([output length] == 0) 546 if ([output length] == 0)
502 output = nil; 547 output = nil;
503 return output; 548 return output;
504 } 549 }
505 550
506 // Loads the Simulator framework from the given developer dir. 551 // Loads the Simulator framework from the given developer dir.
507 NSBundle* LoadSimulatorFramework(NSString* developerDir) { 552 NSBundle* LoadSimulatorFramework(NSString* developerDir) {
508 // The Simulator framework depends on some of the other Xcode private 553 // The Simulator framework depends on some of the other Xcode private
(...skipping 14 matching lines...) Expand all
523 568
524 // Prime DVTPlatform. 569 // Prime DVTPlatform.
525 NSError* error; 570 NSError* error;
526 Class DVTPlatformClass = FindClassByName(@"DVTPlatform"); 571 Class DVTPlatformClass = FindClassByName(@"DVTPlatform");
527 if (![DVTPlatformClass loadAllPlatformsReturningError:&error]) { 572 if (![DVTPlatformClass loadAllPlatformsReturningError:&error]) {
528 LogError(@"Unable to loadAllPlatformsReturningError. Error: %@", 573 LogError(@"Unable to loadAllPlatformsReturningError. Error: %@",
529 [error localizedDescription]); 574 [error localizedDescription]);
530 return nil; 575 return nil;
531 } 576 }
532 577
533 // TODO(lliabraa): Once all builders are on Xcode 6 this ifdef can be removed 578 // The path within the developer dir of the private Simulator frameworks.
534 // (crbug.com/385030). 579 NSString* simulatorFrameworkRelativePath;
535 #if defined(IOSSIM_USE_XCODE_6) 580 if (IsRunningWithXcode6OrLater()) {
536 NSString* coreSimulatorPath = [developerDir 581 simulatorFrameworkRelativePath =
537 stringByAppendingPathComponent:kCoreSimulatorRelativePath]; 582 @"../SharedFrameworks/DVTiPhoneSimulatorRemoteClient.framework";
538 NSBundle* coreSimulatorBundle = 583 NSString* const kCoreSimulatorRelativePath =
539 [NSBundle bundleWithPath:coreSimulatorPath]; 584 @"Library/PrivateFrameworks/CoreSimulator.framework";
540 if (![coreSimulatorBundle load]) 585 NSString* coreSimulatorPath = [developerDir
541 return nil; 586 stringByAppendingPathComponent:kCoreSimulatorRelativePath];
542 #endif // defined(IOSSIM_USE_XCODE_6) 587 NSBundle* coreSimulatorBundle =
543 588 [NSBundle bundleWithPath:coreSimulatorPath];
589 if (![coreSimulatorBundle load])
590 return nil;
591 } else {
592 simulatorFrameworkRelativePath =
593 @"Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/"
594 @"DVTiPhoneSimulatorRemoteClient.framework";
595 }
544 NSString* simBundlePath = [developerDir 596 NSString* simBundlePath = [developerDir
545 stringByAppendingPathComponent:kSimulatorFrameworkRelativePath]; 597 stringByAppendingPathComponent:simulatorFrameworkRelativePath];
546 NSBundle* simBundle = [NSBundle bundleWithPath:simBundlePath]; 598 NSBundle* simBundle = [NSBundle bundleWithPath:simBundlePath];
547 if (![simBundle load]) 599 if (![simBundle load])
548 return nil; 600 return nil;
549 return simBundle; 601 return simBundle;
550 } 602 }
551 603
552 // Converts the given app path to an application spec, which requires an 604 // Converts the given app path to an application spec, which requires an
553 // absolute path. 605 // absolute path.
554 DTiPhoneSimulatorApplicationSpecifier* BuildAppSpec(NSString* appPath) { 606 DTiPhoneSimulatorApplicationSpecifier* BuildAppSpec(NSString* appPath) {
555 Class applicationSpecifierClass = 607 Class applicationSpecifierClass =
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 sessionConfig.applicationToSimulateOnStart = appSpec; 647 sessionConfig.applicationToSimulateOnStart = appSpec;
596 sessionConfig.simulatedSystemRoot = systemRoot; 648 sessionConfig.simulatedSystemRoot = systemRoot;
597 sessionConfig.localizedClientName = @"chromium"; 649 sessionConfig.localizedClientName = @"chromium";
598 sessionConfig.simulatedApplicationStdErrPath = stderrPath; 650 sessionConfig.simulatedApplicationStdErrPath = stderrPath;
599 sessionConfig.simulatedApplicationStdOutPath = stdoutPath; 651 sessionConfig.simulatedApplicationStdOutPath = stdoutPath;
600 sessionConfig.simulatedApplicationLaunchArgs = appArgs; 652 sessionConfig.simulatedApplicationLaunchArgs = appArgs;
601 sessionConfig.simulatedApplicationLaunchEnvironment = appEnv; 653 sessionConfig.simulatedApplicationLaunchEnvironment = appEnv;
602 sessionConfig.simulatedDeviceInfoName = deviceName; 654 sessionConfig.simulatedDeviceInfoName = deviceName;
603 sessionConfig.simulatedDeviceFamily = deviceFamily; 655 sessionConfig.simulatedDeviceFamily = deviceFamily;
604 656
605 // TODO(lliabraa): Once all builders are on Xcode 6 this ifdef can be removed 657 if (IsRunningWithXcode6OrLater()) {
606 // (crbug.com/385030).
607 #if defined(IOSSIM_USE_XCODE_6) 658 #if defined(IOSSIM_USE_XCODE_6)
608 Class simDeviceTypeClass = FindClassByName(@"SimDeviceType"); 659 Class simDeviceTypeClass = FindClassByName(@"SimDeviceType");
609 id simDeviceType = 660 id simDeviceType =
610 [simDeviceTypeClass supportedDeviceTypesByName][deviceName]; 661 [simDeviceTypeClass supportedDeviceTypesByName][deviceName];
611 Class simRuntimeClass = FindClassByName(@"SimRuntime"); 662 Class simRuntimeClass = FindClassByName(@"SimRuntime");
612 NSString* identifier = systemRoot.runtime.identifier; 663 NSString* identifier = systemRoot.runtime.identifier;
613 id simRuntime = [simRuntimeClass supportedRuntimesByIdentifier][identifier]; 664 id simRuntime = [simRuntimeClass supportedRuntimesByIdentifier][identifier];
614 665
615 // Attempt to use an existing device, but create one if a suitable match can't 666 // Attempt to use an existing device, but create one if a suitable match
616 // be found. For example, if the simulator is running with a non-default home 667 // can't be found. For example, if the simulator is running with a
617 // directory (e.g. via iossim's -u command line arg) then there won't be any 668 // non-default home directory (e.g. via iossim's -u command line arg) then
618 // devices so one will have to be created. 669 // there won't be any devices so one will have to be created.
619 Class simDeviceSetClass = FindClassByName(@"SimDeviceSet"); 670 Class simDeviceSetClass = FindClassByName(@"SimDeviceSet");
620 id deviceSet = 671 id deviceSet =
621 [simDeviceSetClass setForSetPath:[simDeviceSetClass defaultSetPath]]; 672 [simDeviceSetClass setForSetPath:[simDeviceSetClass defaultSetPath]];
622 id simDevice = nil; 673 id simDevice = nil;
623 for (id device in [deviceSet availableDevices]) { 674 for (id device in [deviceSet availableDevices]) {
624 if ([device runtime] == simRuntime && 675 if ([device runtime] == simRuntime &&
625 [device deviceType] == simDeviceType) { 676 [device deviceType] == simDeviceType) {
626 simDevice = device; 677 simDevice = device;
627 break; 678 break;
679 }
628 } 680 }
681 if (!simDevice) {
682 NSError* error = nil;
683 // n.b. only the device name is necessary because the iOS Simulator menu
684 // already splits devices by runtime version.
685 NSString* name = [NSString stringWithFormat:@"iossim - %@ ", deviceName];
686 simDevice = [deviceSet createDeviceWithType:simDeviceType
687 runtime:simRuntime
688 name:name
689 error:&error];
690 if (error) {
691 LogError(@"Failed to create device: %@", error);
692 exit(kExitInitializationFailure);
693 }
694 }
695 sessionConfig.device = simDevice;
696 #endif // IOSSIM_USE_XCODE_6
629 } 697 }
630 if (!simDevice) {
631 NSError* error = nil;
632 // n.b. only the device name is necessary because the iOS Simulator menu
633 // already splits devices by runtime version.
634 NSString* name = [NSString stringWithFormat:@"iossim - %@ ", deviceName];
635 simDevice = [deviceSet createDeviceWithType:simDeviceType
636 runtime:simRuntime
637 name:name
638 error:&error];
639 if (error) {
640 LogError(@"Failed to create device: %@", error);
641 exit(kExitInitializationFailure);
642 }
643 }
644 sessionConfig.device = simDevice;
645 #endif
646 return sessionConfig; 698 return sessionConfig;
647 } 699 }
648 700
649 // Builds a simulator session that will use the given delegate. 701 // Builds a simulator session that will use the given delegate.
650 DTiPhoneSimulatorSession* BuildSession(SimulatorDelegate* delegate) { 702 DTiPhoneSimulatorSession* BuildSession(SimulatorDelegate* delegate) {
651 Class sessionClass = FindClassByName(@"DTiPhoneSimulatorSession"); 703 Class sessionClass = FindClassByName(@"DTiPhoneSimulatorSession");
652 DTiPhoneSimulatorSession* session = 704 DTiPhoneSimulatorSession* session =
653 [[[sessionClass alloc] init] autorelease]; 705 [[[sessionClass alloc] init] autorelease];
654 session.delegate = delegate; 706 session.delegate = delegate;
655 return session; 707 return session;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 " Will create a new directory if not specified.\n" 801 " Will create a new directory if not specified.\n"
750 " -e Specifies an environment key=value pair that will be" 802 " -e Specifies an environment key=value pair that will be"
751 " set in the simulated application's environment.\n" 803 " set in the simulated application's environment.\n"
752 " -t Specifies the session startup timeout (in seconds)." 804 " -t Specifies the session startup timeout (in seconds)."
753 " Defaults to %d.\n" 805 " Defaults to %d.\n"
754 " -l List supported devices and iOS versions.\n", 806 " -l List supported devices and iOS versions.\n",
755 static_cast<int>(kDefaultSessionStartTimeoutSeconds)); 807 static_cast<int>(kDefaultSessionStartTimeoutSeconds));
756 } 808 }
757 } // namespace 809 } // namespace
758 810
811 void EnsureSupportForCurrentXcodeVersion() {
812 if (IsRunningWithXcode6OrLater()) {
813 #if !defined(IOSSIM_USE_XCODE_6)
TVL 2014/08/25 13:19:03 will this ever get defined to zero? i.e. do you j
lliabraa 2014/08/25 13:28:36 Done.
814 LogError(@"Running on Xcode 6, but Xcode 6 support was not compiled in.");
815 exit(kExitUnsupportedXcodeVersion);
816 #endif // IOSSIM_USE_XCODE_6
817 }
818 }
819
759 int main(int argc, char* const argv[]) { 820 int main(int argc, char* const argv[]) {
821 EnsureSupportForCurrentXcodeVersion();
760 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 822 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
TVL 2014/08/25 13:19:03 create the pool first, the do the check.
lliabraa 2014/08/25 13:28:36 Done.
761 823
762 // basename() may modify the passed in string and it returns a pointer to an 824 // basename() may modify the passed in string and it returns a pointer to an
763 // internal buffer. Give it a copy to modify, and copy what it returns. 825 // internal buffer. Give it a copy to modify, and copy what it returns.
764 char* worker = strdup(argv[0]); 826 char* worker = strdup(argv[0]);
765 char* toolName = basename(worker); 827 char* toolName = basename(worker);
766 if (toolName != NULL) { 828 if (toolName != NULL) {
767 toolName = strdup(toolName); 829 toolName = strdup(toolName);
768 if (toolName != NULL) 830 if (toolName != NULL)
769 gToolName = toolName; 831 gToolName = toolName;
770 } 832 }
771 if (worker != NULL) 833 if (worker != NULL)
772 free(worker); 834 free(worker);
773 835
774 NSString* appPath = nil; 836 NSString* appPath = nil;
775 NSString* appName = nil; 837 NSString* appName = nil;
776 NSString* sdkVersion = nil; 838 NSString* sdkVersion = nil;
777 // TODO(lliabraa): Once all builders are on Xcode 6 this ifdef can be removed 839 NSString* deviceName = IsRunningWithXcode6OrLater() ? @"iPhone 5" : @"iPhone";
778 // (crbug.com/385030).
779 #if defined(IOSSIM_USE_XCODE_6)
780 NSString* deviceName = @"iPhone 5";
781 #else
782 NSString* deviceName = @"iPhone";
783 #endif
784 NSString* simHomePath = nil; 840 NSString* simHomePath = nil;
785 NSMutableArray* appArgs = [NSMutableArray array]; 841 NSMutableArray* appArgs = [NSMutableArray array];
786 NSMutableDictionary* appEnv = [NSMutableDictionary dictionary]; 842 NSMutableDictionary* appEnv = [NSMutableDictionary dictionary];
787 NSTimeInterval sessionStartTimeout = kDefaultSessionStartTimeoutSeconds; 843 NSTimeInterval sessionStartTimeout = kDefaultSessionStartTimeoutSeconds;
788 844
789 NSString* developerDir = FindDeveloperDir(); 845 NSString* developerDir = FindDeveloperDir();
790 if (!developerDir) { 846 if (!developerDir) {
791 LogError(@"Unable to find developer directory."); 847 LogError(@"Unable to find developer directory.");
792 exit(kExitInitializationFailure); 848 exit(kExitInitializationFailure);
793 } 849 }
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 exit(kExitInitializationFailure); 936 exit(kExitInitializationFailure);
881 } 937 }
882 938
883 // Get the paths for stdout and stderr so the simulated app's output will show 939 // Get the paths for stdout and stderr so the simulated app's output will show
884 // up in the caller's stdout/stderr. 940 // up in the caller's stdout/stderr.
885 NSString* outputDir = CreateTempDirectory(@"iossim-XXXXXX"); 941 NSString* outputDir = CreateTempDirectory(@"iossim-XXXXXX");
886 NSString* stdioPath = [outputDir stringByAppendingPathComponent:@"stdio.txt"]; 942 NSString* stdioPath = [outputDir stringByAppendingPathComponent:@"stdio.txt"];
887 943
888 // Determine the deviceFamily based on the deviceName 944 // Determine the deviceFamily based on the deviceName
889 NSNumber* deviceFamily = nil; 945 NSNumber* deviceFamily = nil;
890 // TODO(lliabraa): Once all builders are on Xcode 6 this ifdef can be removed 946 if (IsRunningWithXcode6OrLater()) {
891 // (crbug.com/385030).
892 #if defined(IOSSIM_USE_XCODE_6) 947 #if defined(IOSSIM_USE_XCODE_6)
893 Class simDeviceTypeClass = FindClassByName(@"SimDeviceType"); 948 Class simDeviceTypeClass = FindClassByName(@"SimDeviceType");
894 if ([simDeviceTypeClass supportedDeviceTypesByName][deviceName] == nil) { 949 if ([simDeviceTypeClass supportedDeviceTypesByName][deviceName] == nil) {
895 LogError(@"Invalid device name: %@.", deviceName); 950 LogError(@"Invalid device name: %@.", deviceName);
896 PrintSupportedDevices(); 951 PrintSupportedDevices();
897 exit(kExitInvalidArguments); 952 exit(kExitInvalidArguments);
953 }
954 #endif // IOSSIM_USE_XCODE_6
955 } else {
956 if (!deviceName || CaseInsensitivePrefixSearch(deviceName, @"iPhone")) {
957 deviceFamily = [NSNumber numberWithInt:kIPhoneFamily];
958 } else if (CaseInsensitivePrefixSearch(deviceName, @"iPad")) {
959 deviceFamily = [NSNumber numberWithInt:kIPadFamily];
960 }
961 else {
962 LogError(@"Invalid device name: %@. Must begin with 'iPhone' or 'iPad'",
963 deviceName);
964 exit(kExitInvalidArguments);
965 }
898 } 966 }
899 #else
900 if (!deviceName || CaseInsensitivePrefixSearch(deviceName, @"iPhone")) {
901 deviceFamily = [NSNumber numberWithInt:kIPhoneFamily];
902 } else if (CaseInsensitivePrefixSearch(deviceName, @"iPad")) {
903 deviceFamily = [NSNumber numberWithInt:kIPadFamily];
904 }
905 else {
906 LogError(@"Invalid device name: %@. Must begin with 'iPhone' or 'iPad'",
907 deviceName);
908 exit(kExitInvalidArguments);
909 }
910 #endif // !defined(IOSSIM_USE_XCODE_6)
911 967
912 // Set up the user home directory for the simulator only if a non-default 968 // Set up the user home directory for the simulator only if a non-default
913 // value was specified. 969 // value was specified.
914 if (simHomePath) { 970 if (simHomePath) {
915 if (!InitializeSimulatorUserHome(simHomePath)) { 971 if (!InitializeSimulatorUserHome(simHomePath)) {
916 LogError(@"Unable to initialize home directory for simulator: %@", 972 LogError(@"Unable to initialize home directory for simulator: %@",
917 simHomePath); 973 simHomePath);
918 exit(kExitInitializationFailure); 974 exit(kExitInitializationFailure);
919 } 975 }
920 } else { 976 } else {
(...skipping 30 matching lines...) Expand all
951 [error localizedDescription], 1007 [error localizedDescription],
952 [error domain], static_cast<long int>([error code])); 1008 [error domain], static_cast<long int>([error code]));
953 } 1009 }
954 1010
955 // Note that this code is only executed if the simulator fails to start 1011 // Note that this code is only executed if the simulator fails to start
956 // because once the main run loop is started, only the delegate calling 1012 // because once the main run loop is started, only the delegate calling
957 // exit() will end the program. 1013 // exit() will end the program.
958 [pool drain]; 1014 [pool drain];
959 return kExitFailure; 1015 return kExitFailure;
960 } 1016 }
OLDNEW
« no previous file with comments | « testing/iossim/iossim.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698