// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import <Foundation/Foundation.h>
#include <asl.h>
#include <libgen.h>
#include <stdarg.h>
#include <stdio.h>

// An executable (iossim) that runs an app in the iOS Simulator.
// Run 'iossim -h' for usage information.
//
// For best results, the iOS Simulator application should not be running when
// iossim is invoked.
//
// Headers for the iPhoneSimulatorRemoteClient framework used in this tool are
// generated by class-dump, via GYP.
// (class-dump is available at http://www.codethecode.com/projects/class-dump/)
//
// However, there are some forward declarations required to get things to
// compile. Also, the DTiPhoneSimulatorSessionDelegate protocol is referenced
// by the iPhoneSimulatorRemoteClient framework, but not defined in the object
// file, so it must be defined here before importing the generated
// iPhoneSimulatorRemoteClient.h file.

@class DTiPhoneSimulatorApplicationSpecifier;
@class DTiPhoneSimulatorSession;
@class DTiPhoneSimulatorSessionConfig;
@class DTiPhoneSimulatorSystemRoot;

@protocol DTiPhoneSimulatorSessionDelegate
- (void)session:(DTiPhoneSimulatorSession*)session
    didEndWithError:(NSError*)error;
- (void)session:(DTiPhoneSimulatorSession*)session
       didStart:(BOOL)started
      withError:(NSError*)error;
@end

#import "iPhoneSimulatorRemoteClient.h"

// An undocumented system log key included in messages from launchd. The value
// is the PID of the process the message is about (as opposed to launchd's PID).
#define ASL_KEY_REF_PID "RefPID"

namespace {

// Name of environment variables that control the user's home directory in the
// simulator.
const char* const kUserHomeEnvVariable = "CFFIXED_USER_HOME";
const char* const kHomeEnvVariable = "HOME";

// Device family codes for iPhone and iPad.
const int kIPhoneFamily = 1;
const int kIPadFamily = 2;

// Max number of seconds to wait for the simulator session to start.
// This timeout must allow time to start up iOS Simulator, install the app
// and perform any other black magic that is encoded in the
// iPhoneSimulatorRemoteClient framework to kick things off. Normal start up
// time is only a couple seconds but machine load, disk caches, etc., can all
// affect startup time in the wild so the timeout needs to be fairly generous.
// If this timeout occurs iossim will likely exit with non-zero status; the
// exception being if the app is invoked and completes execution before the
// session is started (this case is handled in session:didStart:withError).
const NSTimeInterval kDefaultSessionStartTimeoutSeconds = 30;

// While the simulated app is running, its stdout is redirected to a file which
// is polled by iossim and written to iossim's stdout using the following
// polling interval.
const NSTimeInterval kOutputPollIntervalSeconds = 0.1;

// The path within the developer dir of the private Simulator frameworks.
NSString* const kSimulatorFrameworkRelativePath =
    @"Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/"
    @"iPhoneSimulatorRemoteClient.framework";
NSString* const kDevToolsFoundationRelativePath =
    @"../OtherFrameworks/DevToolsFoundation.framework";
NSString* const kSimulatorRelativePath =
    @"Platforms/iPhoneSimulator.platform/Developer/Applications/"
    @"iPhone Simulator.app";

// Simulator Error String Key. This can be found by looking in the Simulator's
// Localizable.strings files.
NSString* const kSimulatorAppQuitErrorKey = @"The simulated application quit.";

const char* gToolName = "iossim";

void LogError(NSString* format, ...) {
  va_list list;
  va_start(list, format);

  NSString* message =
      [[[NSString alloc] initWithFormat:format arguments:list] autorelease];

  fprintf(stderr, "%s: ERROR: %s\n", gToolName, [message UTF8String]);
  fflush(stderr);

  va_end(list);
}

void LogWarning(NSString* format, ...) {
  va_list list;
  va_start(list, format);

  NSString* message =
      [[[NSString alloc] initWithFormat:format arguments:list] autorelease];

  fprintf(stderr, "%s: WARNING: %s\n", gToolName, [message UTF8String]);
  fflush(stderr);

  va_end(list);
}

}  // namespace

// A delegate that is called when the simulated app is started or ended in the
// simulator.
@interface SimulatorDelegate : NSObject <DTiPhoneSimulatorSessionDelegate> {
 @private
  NSString* stdioPath_;
  NSString* developerDir_;
  NSThread* outputThread_;
  NSBundle* simulatorBundle_;
  BOOL appRunning_;
}
@end

// An implementation that copies the simulated app's stdio to stdout of this
// executable. While it would be nice to get stdout and stderr independently
// from iOS Simulator, issues like I/O buffering and interleaved output
// between iOS Simulator and the app would cause iossim to display things out
// of order here. Printing all output to a single file keeps the order correct.
// Instances of this classe should be initialized with the location of the
// simulated app's output file. When the simulated app starts, a thread is
// started which handles copying data from the simulated app's output file to
// the stdout of this executable.
@implementation SimulatorDelegate

// Specifies the file locations of the simulated app's stdout and stderr.
- (SimulatorDelegate*)initWithStdioPath:(NSString*)stdioPath
                           developerDir:(NSString*)developerDir {
  self = [super init];
  if (self) {
    stdioPath_ = [stdioPath copy];
    developerDir_ = [developerDir copy];
  }

  return self;
}

- (void)dealloc {
  [stdioPath_ release];
  [developerDir_ release];
  [simulatorBundle_ release];
  [super dealloc];
}

// Reads data from the simulated app's output and writes it to stdout. This
// method blocks, so it should be called in a separate thread. The iOS
// Simulator takes a file path for the simulated app's stdout and stderr, but
// this path isn't always available (e.g. when the stdout is Xcode's build
// window). As a workaround, iossim creates a temp file to hold output, which
// this method reads and copies to stdout.
- (void)tailOutput {
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

  // Copy data to stdout/stderr while the app is running.
  NSFileHandle* simio = [NSFileHandle fileHandleForReadingAtPath:stdioPath_];
  NSFileHandle* standardOutput = [NSFileHandle fileHandleWithStandardOutput];
  while (appRunning_) {
    NSAutoreleasePool* innerPool = [[NSAutoreleasePool alloc] init];
    [standardOutput writeData:[simio readDataToEndOfFile]];
    [NSThread sleepForTimeInterval:kOutputPollIntervalSeconds];
    [innerPool drain];
  }

  // Once the app is no longer running, copy any data that was written during
  // the last sleep cycle.
  [standardOutput writeData:[simio readDataToEndOfFile]];

  [pool drain];
}

// Fetches a localized error string from the Simulator.
- (NSString *)localizedSimulatorErrorString:(NSString*)stringKey {
  // Lazy load of the simulator bundle.
  if (simulatorBundle_ == nil) {
    NSString* simulatorPath = [developerDir_
        stringByAppendingPathComponent:kSimulatorRelativePath];
    simulatorBundle_ = [NSBundle bundleWithPath:simulatorPath];
  }
  NSString *localizedStr =
      [simulatorBundle_ localizedStringForKey:stringKey
                                        value:nil
                                        table:nil];
  if ([localizedStr length])
    return localizedStr;
  // Failed to get a value, follow Cocoa conventions and use the key as the
  // string.
  return stringKey;
}

- (void)session:(DTiPhoneSimulatorSession*)session
       didStart:(BOOL)started
      withError:(NSError*)error {
  if (!started) {
    // If the test executes very quickly (<30ms), the SimulatorDelegate may not
    // get the initial session:started:withError: message indicating successful
    // startup of the simulated app. Instead the delegate will get a
    // session:started:withError: message after the timeout has elapsed. To
    // account for this case, check if the simulated app's stdio file was
    // ever created and if it exists dump it to stdout and return success.
    NSFileManager* fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:stdioPath_]) {
      appRunning_ = NO;
      [self tailOutput];
      // Note that exiting in this state leaves a process running
      // (e.g. /.../iPhoneSimulator4.3.sdk/usr/libexec/installd -t 30) that will
      // prevent future simulator sessions from being started for 30 seconds
      // unless the iOS Simulator application is killed altogether.
      [self session:session didEndWithError:nil];

      // session:didEndWithError should not return (because it exits) so
      // the execution path should never get here.
      exit(EXIT_FAILURE);
    }

    LogError(@"Simulator failed to start: \"%@\" (%@:%ld)",
             [error localizedDescription],
             [error domain], static_cast<long int>([error code]));
    exit(EXIT_FAILURE);
  }

  // Start a thread to write contents of outputPath to stdout.
  appRunning_ = YES;
  outputThread_ = [[NSThread alloc] initWithTarget:self
                                          selector:@selector(tailOutput)
                                            object:nil];
  [outputThread_ start];
}

- (void)session:(DTiPhoneSimulatorSession*)session
    didEndWithError:(NSError*)error {
  appRunning_ = NO;
  // Wait for the output thread to finish copying data to stdout.
  if (outputThread_) {
    while (![outputThread_ isFinished]) {
      [NSThread sleepForTimeInterval:kOutputPollIntervalSeconds];
    }
    [outputThread_ release];
    outputThread_ = nil;
  }

  if (error) {
    // There appears to be a race condition where sometimes the simulator
    // framework will end with an error, but the error is that the simulated
    // app cleanly shut down; try to trap this error and don't fail the
    // simulator run.
    NSString* localizedDescription = [error localizedDescription];
    NSString* ignorableErrorStr =
        [self localizedSimulatorErrorString:kSimulatorAppQuitErrorKey];
    if ([ignorableErrorStr isEqual:localizedDescription]) {
      LogWarning(@"Ignoring that Simulator ended with: \"%@\" (%@:%ld)",
                 localizedDescription, [error domain],
                 static_cast<long int>([error code]));
    } else {
      LogError(@"Simulator ended with error: \"%@\" (%@:%ld)",
               localizedDescription, [error domain],
               static_cast<long int>([error code]));
      exit(EXIT_FAILURE);
    }
  }

  // Check if the simulated app exited abnormally by looking for system log
  // messages from launchd that refer to the simulated app's PID. Limit query
  // to messages in the last minute since PIDs are cyclical.
  aslmsg query = asl_new(ASL_TYPE_QUERY);
  asl_set_query(query, ASL_KEY_SENDER, "launchd",
                ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_SUBSTRING);
  asl_set_query(query, ASL_KEY_REF_PID,
                [[[session simulatedApplicationPID] stringValue] UTF8String],
                ASL_QUERY_OP_EQUAL);
  asl_set_query(query, ASL_KEY_TIME, "-1m", ASL_QUERY_OP_GREATER_EQUAL);

  // Log any messages found.
  aslresponse response = asl_search(NULL, query);
  BOOL entryFound = NO;
  aslmsg entry;
  while ((entry = aslresponse_next(response)) != NULL) {
    entryFound = YES;
    LogWarning(@"Console message: %s", asl_get(entry, ASL_KEY_MSG));
  }

  // launchd only sends messages if the process crashed or exits with a
  // non-zero status, so if the query returned any results iossim should exit
  // with non-zero status.
  if (entryFound) {
    LogError(@"Simulated app crashed or exited with non-zero status");
    exit(EXIT_FAILURE);
  }
  exit(EXIT_SUCCESS);
}
@end

namespace {

// Finds the developer dir via xcode-select or the DEVELOPER_DIR environment
// variable.
NSString* FindDeveloperDir() {
  // Check the env first.
  NSDictionary* env = [[NSProcessInfo processInfo] environment];
  NSString* developerDir = [env objectForKey:@"DEVELOPER_DIR"];
  if ([developerDir length] > 0)
    return developerDir;

  // Go look for it via xcode-select.
  NSTask* xcodeSelectTask = [[[NSTask alloc] init] autorelease];
  [xcodeSelectTask setLaunchPath:@"/usr/bin/xcode-select"];
  [xcodeSelectTask setArguments:[NSArray arrayWithObject:@"-print-path"]];

  NSPipe* outputPipe = [NSPipe pipe];
  [xcodeSelectTask setStandardOutput:outputPipe];
  NSFileHandle* outputFile = [outputPipe fileHandleForReading];

  [xcodeSelectTask launch];
  NSData* outputData = [outputFile readDataToEndOfFile];
  [xcodeSelectTask terminate];

  NSString* output =
      [[[NSString alloc] initWithData:outputData
                             encoding:NSUTF8StringEncoding] autorelease];
  output = [output stringByTrimmingCharactersInSet:
      [NSCharacterSet whitespaceAndNewlineCharacterSet]];
  if ([output length] == 0)
    output = nil;
  return output;
}

// Loads the Simulator framework from the given developer dir.
NSBundle* LoadSimulatorFramework(NSString* developerDir) {
  // The Simulator framework depends on some of the other Xcode private
  // frameworks; manually load them first so everything can be linked up.
  NSString* devToolsFoundationPath = [developerDir
      stringByAppendingPathComponent:kDevToolsFoundationRelativePath];
  NSBundle* devToolsFoundationBundle =
      [NSBundle bundleWithPath:devToolsFoundationPath];
  if (![devToolsFoundationBundle load])
    return nil;
  NSString* simBundlePath = [developerDir
      stringByAppendingPathComponent:kSimulatorFrameworkRelativePath];
  NSBundle* simBundle = [NSBundle bundleWithPath:simBundlePath];
  if (![simBundle load])
    return nil;
  return simBundle;
}

// Helper to find a class by name and die if it isn't found.
Class FindClassByName(NSString* nameOfClass) {
  Class theClass = NSClassFromString(nameOfClass);
  if (!theClass) {
    LogError(@"Failed to find class %@ at runtime.", nameOfClass);
    exit(EXIT_FAILURE);
  }
  return theClass;
}

// Converts the given app path to an application spec, which requires an
// absolute path.
DTiPhoneSimulatorApplicationSpecifier* BuildAppSpec(NSString* appPath) {
  Class applicationSpecifierClass =
      FindClassByName(@"DTiPhoneSimulatorApplicationSpecifier");
  if (![appPath isAbsolutePath]) {
    NSString* cwd = [[NSFileManager defaultManager] currentDirectoryPath];
    appPath = [cwd stringByAppendingPathComponent:appPath];
  }
  appPath = [appPath stringByStandardizingPath];
  return [applicationSpecifierClass specifierWithApplicationPath:appPath];
}

// Returns the system root for the given SDK version. If sdkVersion is nil, the
// default system root is returned.  Will return nil if the sdkVersion is not
// valid.
DTiPhoneSimulatorSystemRoot* BuildSystemRoot(NSString* sdkVersion) {
  Class systemRootClass = FindClassByName(@"DTiPhoneSimulatorSystemRoot");
  DTiPhoneSimulatorSystemRoot* systemRoot = [systemRootClass defaultRoot];
  if (sdkVersion)
    systemRoot = [systemRootClass rootWithSDKVersion:sdkVersion];

  return systemRoot;
}

// Builds a config object for starting the specified app.
DTiPhoneSimulatorSessionConfig* BuildSessionConfig(
    DTiPhoneSimulatorApplicationSpecifier* appSpec,
    DTiPhoneSimulatorSystemRoot* systemRoot,
    NSString* stdoutPath,
    NSString* stderrPath,
    NSArray* appArgs,
    NSDictionary* appEnv,
    NSNumber* deviceFamily) {
  Class sessionConfigClass = FindClassByName(@"DTiPhoneSimulatorSessionConfig");
  DTiPhoneSimulatorSessionConfig* sessionConfig =
      [[[sessionConfigClass alloc] init] autorelease];
  sessionConfig.applicationToSimulateOnStart = appSpec;
  sessionConfig.simulatedSystemRoot = systemRoot;
  sessionConfig.localizedClientName = @"chromium";
  sessionConfig.simulatedApplicationStdErrPath = stderrPath;
  sessionConfig.simulatedApplicationStdOutPath = stdoutPath;
  sessionConfig.simulatedApplicationLaunchArgs = appArgs;
  sessionConfig.simulatedApplicationLaunchEnvironment = appEnv;
  sessionConfig.simulatedDeviceFamily = deviceFamily;
  return sessionConfig;
}

// Builds a simulator session that will use the given delegate.
DTiPhoneSimulatorSession* BuildSession(SimulatorDelegate* delegate) {
  Class sessionClass = FindClassByName(@"DTiPhoneSimulatorSession");
  DTiPhoneSimulatorSession* session =
      [[[sessionClass alloc] init] autorelease];
  session.delegate = delegate;
  return session;
}

// Creates a temporary directory with a unique name based on the provided
// template. The template should not contain any path separators and be suffixed
// with X's, which will be substituted with a unique alphanumeric string (see
// 'man mkdtemp' for details). The directory will be created as a subdirectory
// of NSTemporaryDirectory(). For example, if dirNameTemplate is 'test-XXX',
// this method would return something like '/path/to/tempdir/test-3n2'.
//
// Returns the absolute path of the newly-created directory, or nill if unable
// to create a unique directory.
NSString* CreateTempDirectory(NSString* dirNameTemplate) {
  NSString* fullPathTemplate =
      [NSTemporaryDirectory() stringByAppendingPathComponent:dirNameTemplate];
  char* fullPath = mkdtemp(const_cast<char*>([fullPathTemplate UTF8String]));
  if (fullPath == NULL)
    return nil;

  return [NSString stringWithUTF8String:fullPath];
}

// Creates the necessary directory structure under the given user home directory
// path.
// Returns YES if successful, NO if unable to create the directories.
BOOL CreateHomeDirSubDirs(NSString* userHomePath) {
  NSFileManager* fileManager = [NSFileManager defaultManager];

  // Create user home and subdirectories.
  NSArray* subDirsToCreate = [NSArray arrayWithObjects:
                              @"Documents",
                              @"Library/Caches",
                              @"Library/Preferences",
                              nil];
  for (NSString* subDir in subDirsToCreate) {
    NSString* path = [userHomePath stringByAppendingPathComponent:subDir];
    NSError* error;
    if (![fileManager createDirectoryAtPath:path
                withIntermediateDirectories:YES
                                 attributes:nil
                                      error:&error]) {
      LogError(@"Unable to create directory: %@. Error: %@",
               path, [error localizedDescription]);
      return NO;
    }
  }

  return YES;
}

// Creates the necessary directory structure under the given user home directory
// path, then sets the path in the appropriate environment variable.
// Returns YES if successful, NO if unable to create or initialize the given
// directory.
BOOL InitializeSimulatorUserHome(NSString* userHomePath, NSString* deviceName) {
  if (!CreateHomeDirSubDirs(userHomePath))
    return NO;

  // Set the device to simulate. Note that the iOS Simulator must not be running
  // for this setting to take effect.
  NSMutableDictionary* plistDict =
      [NSMutableDictionary dictionaryWithObject:deviceName
                                         forKey:@"SimulateDevice"];
  NSString* plistPath = @"Library/Preferences/com.apple.iphonesimulator.plist";
  [plistDict writeToFile:[userHomePath stringByAppendingPathComponent:plistPath]
              atomically:YES];

  // Update the environment to use the specified directory as the user home
  // directory.
  // Note: the third param of setenv specifies whether or not to overwrite the
  // variable's value if it has already been set.
  if ((setenv(kUserHomeEnvVariable, [userHomePath UTF8String], YES) == -1) ||
      (setenv(kHomeEnvVariable, [userHomePath UTF8String], YES) == -1)) {
    LogError(@"Unable to set environment variables for home directory.");
    return NO;
  }

  return YES;
}

// Performs a case-insensitive search to see if |stringToSearch| begins with
// |prefixToFind|. Returns true if a match is found.
BOOL CaseInsensitivePrefixSearch(NSString* stringToSearch,
                                 NSString* prefixToFind) {
  NSStringCompareOptions options = (NSAnchoredSearch | NSCaseInsensitiveSearch);
  NSRange range = [stringToSearch rangeOfString:prefixToFind
                                        options:options];
  return range.location != NSNotFound;
}

// Prints the usage information to stderr.
void PrintUsage() {
  fprintf(stderr, "Usage: iossim [-d device] [-s sdkVersion] [-u homeDir] "
      "[-e envKey=value]* [-t startupTimeout] <appPath> [<appArgs>]\n"
      "  where <appPath> is the path to the .app directory and appArgs are any"
      " arguments to send the simulated app.\n"
      "\n"
      "Options:\n"
      "  -d  Specifies the device (must be one of the values from the iOS"
      " Simulator's Hardware -> Device menu. Defaults to 'iPhone'.\n"
      "  -s  Specifies the SDK version to use (e.g '4.3')."
      " Will use system default if not specified.\n"
      "  -u  Specifies a user home directory for the simulator."
      " Will create a new directory if not specified.\n"
      "  -e  Specifies an environment key=value pair that will be"
      " set in the simulated application's environment.\n"
      "  -t  Specifies the session startup timeout (in seconds)."
      " Defaults to %d.\n",
      static_cast<int>(kDefaultSessionStartTimeoutSeconds));
}

}  // namespace

int main(int argc, char* const argv[]) {
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

  // basename() may modify the passed in string and it returns a pointer to an
  // internal buffer. Give it a copy to modify, and copy what it returns.
  char* worker = strdup(argv[0]);
  char* toolName = basename(worker);
  if (toolName != NULL) {
    toolName = strdup(toolName);
    if (toolName != NULL)
      gToolName = toolName;
  }
  if (worker != NULL)
    free(worker);

  NSString* appPath = nil;
  NSString* appName = nil;
  NSString* sdkVersion = nil;
  NSString* deviceName = @"iPhone";
  NSString* simHomePath = nil;
  NSMutableArray* appArgs = [NSMutableArray array];
  NSMutableDictionary* appEnv = [NSMutableDictionary dictionary];
  NSTimeInterval sessionStartTimeout = kDefaultSessionStartTimeoutSeconds;

  // Parse the optional arguments
  int c;
  while ((c = getopt(argc, argv, "hs:d:u:e:t:")) != -1) {
    switch (c) {
      case 's':
        sdkVersion = [NSString stringWithUTF8String:optarg];
        break;
      case 'd':
        deviceName = [NSString stringWithUTF8String:optarg];
        break;
      case 'u':
        simHomePath = [[NSFileManager defaultManager]
            stringWithFileSystemRepresentation:optarg length:strlen(optarg)];
        break;
      case 'e': {
        NSString* envLine = [NSString stringWithUTF8String:optarg];
        NSRange range = [envLine rangeOfString:@"="];
        if (range.location == NSNotFound) {
          LogError(@"Invalid key=value argument for -e.");
          PrintUsage();
          exit(EXIT_FAILURE);
        }
        NSString* key = [envLine substringToIndex:range.location];
        NSString* value = [envLine substringFromIndex:(range.location + 1)];
        [appEnv setObject:value forKey:key];
      }
        break;
      case 't': {
        int timeout = atoi(optarg);
        if (timeout > 0) {
          sessionStartTimeout = static_cast<NSTimeInterval>(timeout);
        } else {
          LogError(@"Invalid startup timeout (%s).", optarg);
          PrintUsage();
          exit(EXIT_FAILURE);
        }
      }
        break;
      case 'h':
        PrintUsage();
        exit(EXIT_SUCCESS);
      default:
        PrintUsage();
        exit(EXIT_FAILURE);
    }
  }

  // There should be at least one arg left, specifying the app path. Any
  // additional args are passed as arguments to the app.
  if (optind < argc) {
    appPath = [[NSFileManager defaultManager]
        stringWithFileSystemRepresentation:argv[optind]
                                    length:strlen(argv[optind])];
    appName = [appPath lastPathComponent];
    while (++optind < argc) {
      [appArgs addObject:[NSString stringWithUTF8String:argv[optind]]];
    }
  } else {
    LogError(@"Unable to parse command line arguments.");
    PrintUsage();
    exit(EXIT_FAILURE);
  }

  NSString* developerDir = FindDeveloperDir();
  if (!developerDir) {
    LogError(@"Unable to find developer directory.");
    exit(EXIT_FAILURE);
  }

  NSBundle* simulatorFramework = LoadSimulatorFramework(developerDir);
  if (!simulatorFramework) {
    LogError(@"Failed to load the Simulator Framework.");
    exit(EXIT_FAILURE);
  }

  // Make sure the app path provided is legit.
  DTiPhoneSimulatorApplicationSpecifier* appSpec = BuildAppSpec(appPath);
  if (!appSpec) {
    LogError(@"Invalid app path: %@", appPath);
    exit(EXIT_FAILURE);
  }

  // Make sure the SDK path provided is legit (or nil).
  DTiPhoneSimulatorSystemRoot* systemRoot = BuildSystemRoot(sdkVersion);
  if (!systemRoot) {
    LogError(@"Invalid SDK version: %@", sdkVersion);
    exit(EXIT_FAILURE);
  }

  // Get the paths for stdout and stderr so the simulated app's output will show
  // up in the caller's stdout/stderr.
  NSString* outputDir = CreateTempDirectory(@"iossim-XXXXXX");
  NSString* stdioPath = [outputDir stringByAppendingPathComponent:@"stdio.txt"];

  // Determine the deviceFamily based on the deviceName
  NSNumber* deviceFamily = nil;
  if (!deviceName || CaseInsensitivePrefixSearch(deviceName, @"iPhone")) {
    deviceFamily = [NSNumber numberWithInt:kIPhoneFamily];
  } else if (CaseInsensitivePrefixSearch(deviceName, @"iPad")) {
    deviceFamily = [NSNumber numberWithInt:kIPadFamily];
  } else {
    LogError(@"Invalid device name: %@. Must begin with 'iPhone' or 'iPad'",
             deviceName);
    exit(EXIT_FAILURE);
  }

  // Set up the user home directory for the simulator
  if (!simHomePath) {
    NSString* dirNameTemplate =
        [NSString stringWithFormat:@"iossim-%@-%@-XXXXXX", appName, deviceName];
    simHomePath = CreateTempDirectory(dirNameTemplate);
    if (!simHomePath) {
      LogError(@"Unable to create unique directory for template %@",
               dirNameTemplate);
      exit(EXIT_FAILURE);
    }
  }
  if (!InitializeSimulatorUserHome(simHomePath, deviceName)) {
    LogError(@"Unable to initialize home directory for simulator: %@",
             simHomePath);
    exit(EXIT_FAILURE);
  }

  // Create the config and simulator session.
  DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec,
                                                              systemRoot,
                                                              stdioPath,
                                                              stdioPath,
                                                              appArgs,
                                                              appEnv,
                                                              deviceFamily);
  SimulatorDelegate* delegate =
      [[[SimulatorDelegate alloc] initWithStdioPath:stdioPath
                                       developerDir:developerDir] autorelease];
  DTiPhoneSimulatorSession* session = BuildSession(delegate);

  // Start the simulator session.
  NSError* error;
  BOOL started = [session requestStartWithConfig:config
                                         timeout:sessionStartTimeout
                                           error:&error];

  // Spin the runtime indefinitely. When the delegate gets the message that the
  // app has quit it will exit this program.
  if (started) {
    [[NSRunLoop mainRunLoop] run];
  } else {
    LogError(@"Simulator failed request to start:  \"%@\" (%@:%ld)",
             [error localizedDescription],
             [error domain], static_cast<long int>([error code]));
  }

  // Note that this code is only executed if the simulator fails to start
  // because once the main run loop is started, only the delegate calling
  // exit() will end the program.
  [pool drain];
  return EXIT_FAILURE;
}
