// 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 iPhoneSimulatorRemoteClient and other frameworks 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.

// TODO(lliabraa): Once all builders are on Xcode 6 this ifdef can be removed
// (crbug.com/385030).
#if defined(IOSSIM_USE_XCODE_6)
@class DVTStackBacktrace;
#import "DVTFoundation.h"
#endif  // IOSSIM_USE_XCODE_6

@protocol OS_dispatch_queue
@end
@protocol OS_dispatch_source
@end
// TODO(lliabraa): Once all builders are on Xcode 6 this ifdef can be removed
// (crbug.com/385030).
#if defined(IOSSIM_USE_XCODE_6)
@protocol OS_xpc_object
@end
@protocol SimBridge;
@class SimDeviceSet;
@class SimDeviceType;
@class SimRuntime;
@class SimServiceConnectionManager;
#import "CoreSimulator.h"
#endif  // IOSSIM_USE_XCODE_6

@interface DVTPlatform : NSObject
+ (BOOL)loadAllPlatformsReturningError:(id*)arg1;
@end
@class DTiPhoneSimulatorApplicationSpecifier;
@class DTiPhoneSimulatorSession;
@class DTiPhoneSimulatorSessionConfig;
@class DTiPhoneSimulatorSystemRoot;
@class DVTConfinementServiceConnection;
@class DVTDispatchLock;
@class DVTiPhoneSimulatorMessenger;
@class DVTNotificationToken;
@class DVTTask;
// 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.
@protocol DTiPhoneSimulatorSessionDelegate
- (void)session:(DTiPhoneSimulatorSession*)session
    didEndWithError:(NSError*)error;
- (void)session:(DTiPhoneSimulatorSession*)session
       didStart:(BOOL)started
      withError:(NSError*)error;
@end
#import "DVTiPhoneSimulatorRemoteClient.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;

NSString* const kDVTFoundationRelativePath =
    @"../SharedFrameworks/DVTFoundation.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";

// Exit status codes.
const int kExitSuccess = EXIT_SUCCESS;
const int kExitFailure = EXIT_FAILURE;
const int kExitInvalidArguments = 2;
const int kExitInitializationFailure = 3;
const int kExitAppFailedToStart = 4;
const int kExitAppCrashed = 5;
const int kExitUnsupportedXcodeVersion = 6;

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);
}

// 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(kExitInitializationFailure);
  }
  return theClass;
}

// Returns the a NSString containing the stdout from running an NSTask that
// launches |toolPath| with th given command line |args|.
NSString* GetOutputFromTask(NSString* toolPath, NSArray* args) {
  NSTask* task = [[[NSTask alloc] init] autorelease];
  [task setLaunchPath:toolPath];
  [task setArguments:args];
  NSPipe* outputPipe = [NSPipe pipe];
  [task setStandardOutput:outputPipe];
  NSFileHandle* outputFile = [outputPipe fileHandleForReading];

  [task launch];
  NSData* outputData = [outputFile readDataToEndOfFile];
  [task waitUntilExit];
  if ([task isRunning]) {
    LogError(@"Task '%@ %@' is still running.",
        toolPath,
        [args componentsJoinedByString:@" "]);
    return nil;
  } else if ([task terminationStatus]) {
    LogError(@"Task '%@ %@' exited with return code %d.",
        toolPath,
        [args componentsJoinedByString:@" "],
        [task terminationStatus]);
    return nil;
  }
  return [[[NSString alloc] initWithData:outputData
                                encoding:NSUTF8StringEncoding] autorelease];
}

// Finds the Xcode version via xcodebuild -version. Output from xcodebuild is
// expected to look like:
//   Xcode <version>
//   Build version 5B130a
// where <version> is the string returned by this function (e.g. 6.0).
NSString* FindXcodeVersion() {
  NSString* output = GetOutputFromTask(@"/usr/bin/xcodebuild",
                                       @[ @"-version" ]);
  // Scan past the "Xcode ", then scan the rest of the line into |version|.
  NSScanner* scanner = [NSScanner scannerWithString:output];
  BOOL valid = [scanner scanString:@"Xcode " intoString:NULL];
  NSString* version;
  valid =
      [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet]
                              intoString:&version];
  if (!valid) {
    LogError(@"Unable to find Xcode version. 'xcodebuild -version' "
             @"returned \n%@", output);
    return nil;
  }
  return version;
}

// Returns true if iossim is running with Xcode 6 or later installed on the
// host.
BOOL IsRunningWithXcode6OrLater() {
  static NSString* xcodeVersion = FindXcodeVersion();
  if (!xcodeVersion) {
    return false;
  }
  NSArray* components = [xcodeVersion componentsSeparatedByString:@"."];
  if ([components count] < 1) {
    return false;
  }
  NSInteger majorVersion = [[components objectAtIndex:0] integerValue];
  return majorVersion >= 6;
}

// Prints supported devices and SDKs.
void PrintSupportedDevices() {
  if (IsRunningWithXcode6OrLater()) {
#if defined(IOSSIM_USE_XCODE_6)
    printf("Supported device/SDK combinations:\n");
    Class simDeviceSetClass = FindClassByName(@"SimDeviceSet");
    id deviceSet =
        [simDeviceSetClass setForSetPath:[simDeviceSetClass defaultSetPath]];
    for (id simDevice in [deviceSet availableDevices]) {
      NSString* deviceInfo =
          [NSString stringWithFormat:@"  -d '%@' -s '%@'\n",
              [simDevice name], [[simDevice runtime] versionString]];
      printf("%s", [deviceInfo UTF8String]);
    }
#endif  // IOSSIM_USE_XCODE_6
  } else {
    printf("Supported SDK versions:\n");
    Class rootClass = FindClassByName(@"DTiPhoneSimulatorSystemRoot");
    for (id root in [rootClass knownRoots]) {
      printf("  '%s'\n", [[root sdkVersion] UTF8String]);
    }
    // This is the list of devices supported on Xcode 5.1.x.
    printf("Supported devices:\n");
    printf("  'iPhone'\n");
    printf("  'iPhone Retina (3.5-inch)'\n");
    printf("  'iPhone Retina (4-inch)'\n");
    printf("  'iPhone Retina (4-inch 64-bit)'\n");
    printf("  'iPad'\n");
    printf("  'iPad Retina'\n");
    printf("  'iPad Retina (64-bit)'\n");
  }
}
}  // 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_;
  NSString* simulatorHome_;
  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
                          simulatorHome:(NSString*)simulatorHome {
  self = [super init];
  if (self) {
    stdioPath_ = [stdioPath copy];
    developerDir_ = [developerDir copy];
    simulatorHome_ = [simulatorHome 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)tailOutputForSession:(DTiPhoneSimulatorSession*)session {
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

  NSFileHandle* simio = [NSFileHandle fileHandleForReadingAtPath:stdioPath_];
  if (IsRunningWithXcode6OrLater()) {
#if defined(IOSSIM_USE_XCODE_6)
    // With iOS 8 simulators on Xcode 6, the app output is relative to the
    // simulator's data directory.
    NSString* versionString =
        [[[session sessionConfig] simulatedSystemRoot] sdkVersion];
    NSInteger majorVersion = [[[versionString componentsSeparatedByString:@"."]
        objectAtIndex:0] intValue];
    if (majorVersion >= 8) {
      NSString* dataPath = session.sessionConfig.device.dataPath;
      NSString* appOutput =
          [dataPath stringByAppendingPathComponent:stdioPath_];
      simio = [NSFileHandle fileHandleForReadingAtPath:appOutput];
    }
#endif  // IOSSIM_USE_XCODE_6
  }
  NSFileHandle* standardOutput = [NSFileHandle fileHandleWithStandardOutput];
  // Copy data to stdout/stderr while the app is running.
  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 tailOutputForSession:session];
      // 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(kExitFailure);
    }

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

  // Start a thread to write contents of outputPath to stdout.
  appRunning_ = YES;
  outputThread_ =
      [[NSThread alloc] initWithTarget:self
                              selector:@selector(tailOutputForSession:)
                                object:session];
  [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(kExitFailure);
    }
  }

  // Try to determine if the simulated app crashed or quit with a non-zero
  // status code. iOS Simluator handles things a bit differently depending on
  // the version, so first determine the iOS version being used.
  BOOL badEntryFound = NO;
  NSString* versionString =
      [[[session sessionConfig] simulatedSystemRoot] sdkVersion];
  NSInteger majorVersion = [[[versionString componentsSeparatedByString:@"."]
      objectAtIndex:0] intValue];
  if (majorVersion <= 6) {
    // In iOS 6 and before, logging from the simulated apps went to the main
    // system logs, so use ASL to 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);
    char session_id[20];
    if (snprintf(session_id, 20, "%d", [session simulatedApplicationPID]) < 0) {
      LogError(@"Failed to get [session simulatedApplicationPID]");
      exit(kExitFailure);
    }
    asl_set_query(query, ASL_KEY_REF_PID, session_id, ASL_QUERY_OP_EQUAL);
    asl_set_query(query, ASL_KEY_TIME, "-1m", ASL_QUERY_OP_GREATER_EQUAL);

    // Log any messages found, and take note of any messages that may indicate
    // the app crashed or did not exit cleanly.
    aslresponse response = asl_search(NULL, query);
    aslmsg entry;
    while ((entry = aslresponse_next(response)) != NULL) {
      const char* message = asl_get(entry, ASL_KEY_MSG);
      LogWarning(@"Console message: %s", message);
      // Some messages are harmless, so don't trigger a failure for them.
      if (strstr(message, "The following job tried to hijack the service"))
        continue;
      badEntryFound = YES;
    }
  } else {
    // Otherwise, the iOS Simulator's system logging is sandboxed, so parse the
    // sandboxed system.log file for known errors.
    NSString* path;
    if (IsRunningWithXcode6OrLater()) {
#if defined(IOSSIM_USE_XCODE_6)
      NSString* dataPath = session.sessionConfig.device.dataPath;
      path =
          [dataPath stringByAppendingPathComponent:@"Library/Logs/system.log"];
#endif  // IOSSIM_USE_XCODE_6
    } else {
      NSString* relativePathToSystemLog =
          [NSString stringWithFormat:
              @"Library/Logs/iOS Simulator/%@/system.log", versionString];
      path = [simulatorHome_
          stringByAppendingPathComponent:relativePathToSystemLog];
    }
    NSFileManager* fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:path]) {
      NSString* content =
          [NSString stringWithContentsOfFile:path
                                    encoding:NSUTF8StringEncoding
                                       error:NULL];
      NSArray* lines = [content componentsSeparatedByCharactersInSet:
          [NSCharacterSet newlineCharacterSet]];
      NSString* simulatedAppPID =
          [NSString stringWithFormat:@"%d", session.simulatedApplicationPID];
      NSArray* kErrorStrings = @[
        @"Service exited with abnormal code:",
        @"Service exited due to signal:",
      ];
      for (NSString* line in lines) {
        if ([line rangeOfString:simulatedAppPID].location != NSNotFound) {
          for (NSString* errorString in kErrorStrings) {
            if ([line rangeOfString:errorString].location != NSNotFound) {
              LogWarning(@"Console message: %@", line);
              badEntryFound = YES;
              break;
            }
          }
          if (badEntryFound) {
            break;
          }
        }
      }
      // Remove the log file so subsequent invocations of iossim won't be
      // looking at stale logs.
      remove([path fileSystemRepresentation]);
    } else {
        LogWarning(@"Unable to find system log at '%@'.", path);
    }
  }

  // If the query returned any nasty-looking results, iossim should exit with
  // non-zero status.
  if (badEntryFound) {
    LogError(@"Simulated app crashed or exited with non-zero status");
    exit(kExitAppCrashed);
  }
  exit(kExitSuccess);
}
@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.
  NSString* output = GetOutputFromTask(@"/usr/bin/xcode-select",
                                       @[ @"-print-path" ]);
  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* dvtFoundationPath = [developerDir
      stringByAppendingPathComponent:kDVTFoundationRelativePath];
  NSBundle* dvtFoundationBundle =
      [NSBundle bundleWithPath:dvtFoundationPath];
  if (![dvtFoundationBundle load])
    return nil;

  NSString* devToolsFoundationPath = [developerDir
      stringByAppendingPathComponent:kDevToolsFoundationRelativePath];
  NSBundle* devToolsFoundationBundle =
      [NSBundle bundleWithPath:devToolsFoundationPath];
  if (![devToolsFoundationBundle load])
    return nil;

  // Prime DVTPlatform.
  NSError* error;
  Class DVTPlatformClass = FindClassByName(@"DVTPlatform");
  if (![DVTPlatformClass loadAllPlatformsReturningError:&error]) {
    LogError(@"Unable to loadAllPlatformsReturningError. Error: %@",
         [error localizedDescription]);
    return nil;
  }

  // The path within the developer dir of the private Simulator frameworks.
  NSString* simulatorFrameworkRelativePath;
  if (IsRunningWithXcode6OrLater()) {
    simulatorFrameworkRelativePath =
        @"../SharedFrameworks/DVTiPhoneSimulatorRemoteClient.framework";
    NSString* const kCoreSimulatorRelativePath =
       @"Library/PrivateFrameworks/CoreSimulator.framework";
    NSString* coreSimulatorPath = [developerDir
        stringByAppendingPathComponent:kCoreSimulatorRelativePath];
    NSBundle* coreSimulatorBundle =
        [NSBundle bundleWithPath:coreSimulatorPath];
    if (![coreSimulatorBundle load])
      return nil;
  } else {
    simulatorFrameworkRelativePath =
      @"Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/"
      @"DVTiPhoneSimulatorRemoteClient.framework";
  }
  NSString* simBundlePath = [developerDir
      stringByAppendingPathComponent:simulatorFrameworkRelativePath];
  NSBundle* simBundle = [NSBundle bundleWithPath:simBundlePath];
  if (![simBundle load])
    return nil;
  return simBundle;
}

// 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];
  NSFileManager* fileManager = [NSFileManager defaultManager];
  if (![fileManager fileExistsAtPath:appPath]) {
    LogError(@"File not found: %@", appPath);
    exit(kExitInvalidArguments);
  }
  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,
    NSString* deviceName) {
  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.simulatedDeviceInfoName = deviceName;
  sessionConfig.simulatedDeviceFamily = deviceFamily;

  if (IsRunningWithXcode6OrLater()) {
#if defined(IOSSIM_USE_XCODE_6)
    Class simDeviceTypeClass = FindClassByName(@"SimDeviceType");
    id simDeviceType =
        [simDeviceTypeClass supportedDeviceTypesByName][deviceName];
    Class simRuntimeClass = FindClassByName(@"SimRuntime");
    NSString* identifier = systemRoot.runtime.identifier;
    id simRuntime = [simRuntimeClass supportedRuntimesByIdentifier][identifier];

    // Attempt to use an existing device, but create one if a suitable match
    // can't be found. For example, if the simulator is running with a
    // non-default home directory (e.g. via iossim's -u command line arg) then
    // there won't be any devices so one will have to be created.
    Class simDeviceSetClass = FindClassByName(@"SimDeviceSet");
    id deviceSet =
        [simDeviceSetClass setForSetPath:[simDeviceSetClass defaultSetPath]];
    id simDevice = nil;
    for (id device in [deviceSet availableDevices]) {
      if ([device runtime] == simRuntime &&
          [device deviceType] == simDeviceType) {
        simDevice = device;
        break;
      }
    }
    if (!simDevice) {
      NSError* error = nil;
      // n.b. only the device name is necessary because the iOS Simulator menu
      // already splits devices by runtime version.
      NSString* name = [NSString stringWithFormat:@"iossim - %@ ", deviceName];
      simDevice = [deviceSet createDeviceWithType:simDeviceType
                                          runtime:simRuntime
                                             name:name
                                            error:&error];
      if (error) {
        LogError(@"Failed to create device: %@", error);
        exit(kExitInitializationFailure);
      }
    }
    sessionConfig.device = simDevice;
#endif  // IOSSIM_USE_XCODE_6
  }
  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) {
  if (!CreateHomeDirSubDirs(userHomePath))
    return NO;

  // 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"
      "  -l  List supported devices and iOS versions.\n",
      static_cast<int>(kDefaultSessionStartTimeoutSeconds));
}
}  // namespace

void EnsureSupportForCurrentXcodeVersion() {
  if (IsRunningWithXcode6OrLater()) {
#if !IOSSIM_USE_XCODE_6
    LogError(@"Running on Xcode 6, but Xcode 6 support was not compiled in.");
    exit(kExitUnsupportedXcodeVersion);
#endif  // IOSSIM_USE_XCODE_6
  }
}

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

  EnsureSupportForCurrentXcodeVersion();

  // 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 = IsRunningWithXcode6OrLater() ? @"iPhone 5" : @"iPhone";
  NSString* simHomePath = nil;
  NSMutableArray* appArgs = [NSMutableArray array];
  NSMutableDictionary* appEnv = [NSMutableDictionary dictionary];
  NSTimeInterval sessionStartTimeout = kDefaultSessionStartTimeoutSeconds;

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

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

  // Parse the optional arguments
  int c;
  while ((c = getopt(argc, argv, "hs:d:u:e:t:l")) != -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(kExitInvalidArguments);
        }
        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(kExitInvalidArguments);
        }
      }
        break;
      case 'l':
        PrintSupportedDevices();
        exit(kExitSuccess);
        break;
      case 'h':
        PrintUsage();
        exit(kExitSuccess);
      default:
        PrintUsage();
        exit(kExitInvalidArguments);
    }
  }

  // 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(kExitInvalidArguments);
  }

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

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

  // 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 (IsRunningWithXcode6OrLater()) {
#if defined(IOSSIM_USE_XCODE_6)
    Class simDeviceTypeClass = FindClassByName(@"SimDeviceType");
    if ([simDeviceTypeClass supportedDeviceTypesByName][deviceName] == nil) {
      LogError(@"Invalid device name: %@.", deviceName);
      PrintSupportedDevices();
      exit(kExitInvalidArguments);
    }
#endif  // IOSSIM_USE_XCODE_6
  } else {
    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(kExitInvalidArguments);
    }
  }

  // Set up the user home directory for the simulator only if a non-default
  // value was specified.
  if (simHomePath) {
    if (!InitializeSimulatorUserHome(simHomePath)) {
      LogError(@"Unable to initialize home directory for simulator: %@",
               simHomePath);
      exit(kExitInitializationFailure);
    }
  } else {
    simHomePath = NSHomeDirectory();
  }

  // Create the config and simulator session.
  DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec,
                                                              systemRoot,
                                                              stdioPath,
                                                              stdioPath,
                                                              appArgs,
                                                              appEnv,
                                                              deviceFamily,
                                                              deviceName);
  SimulatorDelegate* delegate =
      [[[SimulatorDelegate alloc] initWithStdioPath:stdioPath
                                       developerDir:developerDir
                                      simulatorHome:simHomePath] 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 kExitFailure;
}
