// 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 <getopt.h>
#include <string>

namespace {

void PrintUsage() {
  fprintf(
      stderr,
      "Usage: iossim [-d device] [-s sdk_version] <app_path> <xctest_path>\n"
      "  where <app_path> is the path to the .app directory and <xctest_path> "
      "is the path to an optional xctest bundle.\n"
      "Options:\n"
      "  -u  Specifies the device udid to use. Will use -d, -s values to get "
      "devices if not specified.\n"
      "  -d  Specifies the device (must be one of the values from the iOS "
      "Simulator's Hardware -> Device menu. Defaults to 'iPhone 6s'.\n"
      "  -w  Wipe the device's contents and settings before running the "
      "test.\n"
      "  -e  Specifies an environment key=value pair that will be"
      " set in the simulated application's environment.\n"
      "  -t  Specifies a test or test suite that should be included in the "
      "test run. All other tests will be excluded from this run.\n"
      "  -c  Specifies command line flags to pass to application.\n"
      "  -p  Print the device's home directory, does not run a test.\n"
      "  -s  Specifies the SDK version to use (e.g '9.3'). Will use system "
      "default if not specified.\n");
}

// Exit status codes.
const int kExitSuccess = EXIT_SUCCESS;
const int kExitInvalidArguments = 2;

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

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

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

  va_end(list);
}

}

// Wrap boiler plate calls to xcrun NSTasks.
@interface XCRunTask : NSObject {
  NSTask* _task;
}
- (instancetype)initWithArguments:(NSArray*)arguments;
- (void)run;
- (void)setStandardOutput:(id)output;
- (void)setStandardError:(id)error;
- (int)getTerminationStatus;
@end

@implementation XCRunTask

- (instancetype)initWithArguments:(NSArray*)arguments {
  self = [super init];
  if (self) {
    _task = [[NSTask alloc] init];
    SEL selector = @selector(setStartsNewProcessGroup:);
    if ([_task respondsToSelector:selector])
      [_task performSelector:selector withObject:nil];
    [_task setLaunchPath:@"/usr/bin/xcrun"];
    [_task setArguments:arguments];
  }
  return self;
}

- (void)dealloc {
  [_task release];
  [super dealloc];
}

- (void)setStandardOutput:(id)output {
  [_task setStandardOutput:output];
}

- (void)setStandardError:(id)error {
  [_task setStandardError:error];
}

- (int)getTerminationStatus {
  return [_task terminationStatus];
}

- (void)run {
  [_task launch];
  [_task waitUntilExit];
}

- (void)launch {
  [_task launch];
}

- (void)waitUntilExit {
  [_task waitUntilExit];
}

@end

// Return array of available iOS runtime dictionaries.  Unavailable (old Xcode
// versions) or other runtimes (tvOS, watchOS) are removed.
NSArray* Runtimes(NSDictionary* simctl_list) {
  NSMutableArray* runtimes =
      [[simctl_list[@"runtimes"] mutableCopy] autorelease];
  for (NSDictionary* runtime in simctl_list[@"runtimes"]) {
    if (![runtime[@"identifier"]
            hasPrefix:@"com.apple.CoreSimulator.SimRuntime.iOS"] ||
        ![runtime[@"availability"] isEqualToString:@"(available)"]) {
      [runtimes removeObject:runtime];
    }
  }
  return runtimes;
}

// Return array of device dictionaries.
NSArray* Devices(NSDictionary* simctl_list) {
  NSMutableArray* devicetypes =
      [[simctl_list[@"devicetypes"] mutableCopy] autorelease];
  for (NSDictionary* devicetype in simctl_list[@"devicetypes"]) {
    if (![devicetype[@"identifier"]
            hasPrefix:@"com.apple.CoreSimulator.SimDeviceType.iPad"] &&
        ![devicetype[@"identifier"]
            hasPrefix:@"com.apple.CoreSimulator.SimDeviceType.iPhone"]) {
      [devicetypes removeObject:devicetype];
    }
  }
  return devicetypes;
}

// Get list of devices, runtimes, etc from sim_ctl.
NSDictionary* GetSimulatorList() {
  XCRunTask* task = [[[XCRunTask alloc]
      initWithArguments:@[ @"simctl", @"list", @"-j" ]] autorelease];
  NSPipe* out = [NSPipe pipe];
  [task setStandardOutput:out];

  // In the rest of the this file we read from the pipe after -waitUntilExit
  // (We normally wrap -launch and -waitUntilExit in one -run method).  However,
  // on some swarming slaves this led to a hang on simctl's pipe.  Since the
  // output of simctl is so instant, reading it before exit seems to work, and
  // seems to avoid the hang.
  [task launch];
  NSData* data = [[out fileHandleForReading] readDataToEndOfFile];
  [task waitUntilExit];

  NSError* error = nil;
  return [NSJSONSerialization JSONObjectWithData:data
                                         options:kNilOptions
                                           error:&error];
}

// List supported runtimes and devices.
void PrintSupportedDevices(NSDictionary* simctl_list) {
  printf("\niOS devices:\n");
  for (NSDictionary* type in Devices(simctl_list)) {
    printf("%s\n", [type[@"name"] UTF8String]);
  }
  printf("\nruntimes:\n");
  for (NSDictionary* runtime in Runtimes(simctl_list)) {
    printf("%s\n", [runtime[@"version"] UTF8String]);
  }
}

// Expand path to absolute path.
NSString* ResolvePath(NSString* path) {
  path = [path stringByExpandingTildeInPath];
  path = [path stringByStandardizingPath];
  const char* cpath = [path cStringUsingEncoding:NSUTF8StringEncoding];
  char* resolved_name = NULL;
  char* abs_path = realpath(cpath, resolved_name);
  if (abs_path == NULL) {
    return nil;
  }
  return [NSString stringWithCString:abs_path encoding:NSUTF8StringEncoding];
}

// Search |simctl_list| for a udid matching |device_name| and |sdk_version|.
NSString* GetDeviceBySDKAndName(NSDictionary* simctl_list,
                                NSString* device_name,
                                NSString* sdk_version) {
  NSString* sdk = [@"iOS " stringByAppendingString:sdk_version];
  NSArray* devices = [simctl_list[@"devices"] objectForKey:sdk];
  for (NSDictionary* device in devices) {
    if ([device[@"name"] isEqualToString:device_name]) {
      return device[@"udid"];
    }
  }
  return nil;
}

bool FindDeviceByUDID(NSDictionary* simctl_list, NSString* udid) {
  NSDictionary* devices_table = simctl_list[@"devices"];
  for (id runtimes in devices_table) {
    NSArray* devices = devices_table[runtimes];
    for (NSDictionary* device in devices) {
      if ([device[@"udid"] isEqualToString:udid]) {
        return true;
      }
    }
  }
  return false;
}

// Prints the HOME environment variable for a device.  Used by the bots to
// package up all the test data.
void PrintDeviceHome(NSString* udid) {
  XCRunTask* task = [[[XCRunTask alloc]
      initWithArguments:@[ @"simctl", @"getenv", udid, @"HOME" ]] autorelease];
  [task run];
}

// Erase a device, used by the bots before a clean test run.
void WipeDevice(NSString* udid) {
  XCRunTask* shutdown = [[[XCRunTask alloc]
      initWithArguments:@[ @"simctl", @"shutdown", udid ]] autorelease];
  [shutdown setStandardOutput:nil];
  [shutdown setStandardError:nil];
  [shutdown run];

  XCRunTask* erase = [[[XCRunTask alloc]
      initWithArguments:@[ @"simctl", @"erase", udid ]] autorelease];
  [erase run];
}

void KillSimulator() {
  XCRunTask* task = [[[XCRunTask alloc]
      initWithArguments:@[ @"killall", @"Simulator" ]] autorelease];
  [task setStandardOutput:nil];
  [task setStandardError:nil];
  [task run];
}

int RunApplication(NSString* app_path,
                   NSString* xctest_path,
                   NSString* udid,
                   NSMutableDictionary* app_env,
                   NSMutableArray* cmd_args,
                   NSMutableArray* tests_filter) {
  NSString* tempFilePath = [NSTemporaryDirectory()
      stringByAppendingPathComponent:[[NSUUID UUID] UUIDString]];
  [[NSFileManager defaultManager] createFileAtPath:tempFilePath
                                          contents:nil
                                        attributes:nil];

  NSMutableDictionary* xctestrun = [NSMutableDictionary dictionary];
  NSMutableDictionary* testTargetName = [NSMutableDictionary dictionary];

  NSMutableDictionary* testingEnvironmentVariables =
      [NSMutableDictionary dictionary];
  [testingEnvironmentVariables setValue:[app_path lastPathComponent]
                                 forKey:@"IDEiPhoneInternalTestBundleName"];

  [testingEnvironmentVariables
      setValue:
          @"__TESTROOT__/Debug-iphonesimulator:__PLATFORMS__/"
          @"iPhoneSimulator.platform/Developer/Library/Frameworks"
        forKey:@"DYLD_FRAMEWORK_PATH"];
  [testingEnvironmentVariables
      setValue:
          @"__TESTROOT__/Debug-iphonesimulator:__PLATFORMS__/"
          @"iPhoneSimulator.platform/Developer/Library"
        forKey:@"DYLD_LIBRARY_PATH"];

  if (xctest_path) {
    [testTargetName setValue:xctest_path forKey:@"TestBundlePath"];
    NSString* inject =
        @"__PLATFORMS__/iPhoneSimulator.platform/Developer/Library/"
        @"PrivateFrameworks/IDEBundleInjection.framework/"
        @"IDEBundleInjection:__PLATFORMS__/iPhoneSimulator.platform/Developer/"
        @"usr/lib/libXCTestBundleInject.dylib";
    [testingEnvironmentVariables setValue:inject
                                   forKey:@"DYLD_INSERT_LIBRARIES"];
    [testingEnvironmentVariables
        setValue:[NSString stringWithFormat:@"__TESTHOST__/%@",
                                            [[app_path lastPathComponent]
                                                stringByDeletingPathExtension]]
          forKey:@"XCInjectBundleInto"];
  } else {
    [testTargetName setValue:app_path forKey:@"TestBundlePath"];
  }
  [testTargetName setValue:app_path forKey:@"TestHostPath"];

  if ([app_env count]) {
    [testTargetName setObject:app_env forKey:@"EnvironmentVariables"];
  }

  if ([cmd_args count] > 0) {
    [testTargetName setObject:cmd_args forKey:@"CommandLineArguments"];
  }

  if ([tests_filter count] > 0) {
    [testTargetName setObject:tests_filter forKey:@"OnlyTestIdentifiers"];
  }

  [testTargetName setObject:testingEnvironmentVariables
                     forKey:@"TestingEnvironmentVariables"];
  [xctestrun setObject:testTargetName forKey:@"TestTargetName"];

  NSString* error;
  NSData* data = [NSPropertyListSerialization
      dataFromPropertyList:xctestrun
                    format:NSPropertyListXMLFormat_v1_0
          errorDescription:&error];
  [data writeToFile:tempFilePath atomically:YES];
  XCRunTask* task = [[[XCRunTask alloc] initWithArguments:@[
    @"xcodebuild", @"-xctestrun", tempFilePath, @"-destination",
    [@"platform=iOS Simulator,id=" stringByAppendingString:udid],
    @"test-without-building"
  ]] autorelease];

  if (!xctest_path) {
    // The following stderr messages are meaningless on iossim when not running
    // xctests and can be safely stripped.
    NSArray* ignore_strings = @[
      @"IDETestOperationsObserverErrorDomain", @"** TEST EXECUTE FAILED **"
    ];
    NSPipe* stderr_pipe = [NSPipe pipe];
    stderr_pipe.fileHandleForReading.readabilityHandler =
        ^(NSFileHandle* handle) {
          NSString* log = [[[NSString alloc] initWithData:handle.availableData
                                                 encoding:NSUTF8StringEncoding]
              autorelease];
          for (NSString* ignore_string in ignore_strings) {
            if ([log rangeOfString:ignore_string].location != NSNotFound) {
              return;
            }
          }
          printf("%s", [log UTF8String]);
        };
    [task setStandardError:stderr_pipe];
  }
  [task run];
  return [task getTerminationStatus];
}

int main(int argc, char* const argv[]) {
  // When the last running simulator is from Xcode 7, an Xcode 8 run will yeild
  // a failure to "unload a stale CoreSimulatorService job" message.  Sending a
  // hidden simctl to do something simple (list devices) helpfully works around
  // this issue.
  XCRunTask* workaround_task = [[[XCRunTask alloc]
      initWithArguments:@[ @"simctl", @"list", @"-j" ]] autorelease];
  [workaround_task setStandardOutput:nil];
  [workaround_task setStandardError:nil];
  [workaround_task run];

  NSString* app_path = nil;
  NSString* xctest_path = nil;
  NSString* udid = nil;
  NSString* device_name = @"iPhone 6s";
  bool wants_wipe = false;
  bool wants_print_home = false;
  NSDictionary* simctl_list = GetSimulatorList();
  float sdk = 0;
  for (NSDictionary* runtime in Runtimes(simctl_list)) {
    sdk = fmax(sdk, [runtime[@"version"] floatValue]);
  }
  NSString* sdk_version = [NSString stringWithFormat:@"%0.1f", sdk];
  NSMutableDictionary* app_env = [NSMutableDictionary dictionary];
  NSMutableArray* cmd_args = [NSMutableArray array];
  NSMutableArray* tests_filter = [NSMutableArray array];

  int c;
  while ((c = getopt(argc, argv, "hs:d:u:t:e:c:pwl")) != -1) {
    switch (c) {
      case 's':
        sdk_version = [NSString stringWithUTF8String:optarg];
        break;
      case 'd':
        device_name = [NSString stringWithUTF8String:optarg];
        break;
      case 'u':
        udid = [NSString stringWithUTF8String:optarg];
        break;
      case 'w':
        wants_wipe = true;
        break;
      case 'c': {
        NSString* cmd_arg = [NSString stringWithUTF8String:optarg];
        [cmd_args addObject:cmd_arg];
      } break;
      case 't': {
        NSString* test = [NSString stringWithUTF8String:optarg];
        [tests_filter addObject:test];
      } 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)];
        [app_env setObject:value forKey:key];
      } break;
      case 'p':
        wants_print_home = true;
        break;
      case 'l':
        PrintSupportedDevices(simctl_list);
        exit(kExitSuccess);
        break;
      case 'h':
        PrintUsage();
        exit(kExitSuccess);
        break;
      default:
        PrintUsage();
        exit(kExitInvalidArguments);
    }
  }

  if (udid == nil) {
    udid = GetDeviceBySDKAndName(simctl_list, device_name, sdk_version);
    if (udid == nil) {
      LogError(@"Unable to find a device %@ with SDK %@.", device_name,
               sdk_version);
      PrintSupportedDevices(simctl_list);
      exit(kExitInvalidArguments);
    }
  } else {
    if (!FindDeviceByUDID(simctl_list, udid)) {
      LogError(
          @"Unable to find a device with udid %@. Use 'xcrun simctl list' to "
          @"see valid device udids.",
          udid);
      exit(kExitInvalidArguments);
    }
  }

  if (wants_print_home) {
    PrintDeviceHome(udid);
    exit(kExitSuccess);
  }

  KillSimulator();
  if (wants_wipe) {
    WipeDevice(udid);
    printf("Device wiped.\n");
    exit(kExitSuccess);
  }

  // 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) {
    NSString* unresolved_path = [[NSFileManager defaultManager]
        stringWithFileSystemRepresentation:argv[optind]
                                    length:strlen(argv[optind])];
    app_path = ResolvePath(unresolved_path);
    if (!app_path) {
      LogError(@"Unable to resolve app_path %@", unresolved_path);
      exit(kExitInvalidArguments);
    }

    if (++optind < argc) {
      NSString* unresolved_path = [[NSFileManager defaultManager]
          stringWithFileSystemRepresentation:argv[optind]
                                      length:strlen(argv[optind])];
      xctest_path = ResolvePath(unresolved_path);
      if (!xctest_path) {
        LogError(@"Unable to resolve xctest_path %@", unresolved_path);
        exit(kExitInvalidArguments);
      }
    }
  } else {
    LogError(@"Unable to parse command line arguments.");
    PrintUsage();
    exit(kExitInvalidArguments);
  }

  int return_code = RunApplication(app_path, xctest_path, udid, app_env,
                                   cmd_args, tests_filter);
  KillSimulator();
  return return_code;
}
