 
   // Runs Xcode tests on the given Xcode project and scheme.
   func testXcodeProject(_ xcodeProjectURL: URL, scheme: String) {
-    let semaphore = DispatchSemaphore(value: 0)
-    let xcodeTest = TulsiProcessRunner.createProcess("/usr/bin/xcodebuild",
-                                                       arguments: ["test",
-                                                                   "-project",
-                                                                   xcodeProjectURL.path,
-                                                                   "-scheme",
-                                                                   scheme,
-                                                                   "-destination",
-                                                                   "platform=iOS Simulator,name=iPhone 8,OS=11.2"]) {
-      completionInfo in
-        if let stdoutput = String(data: completionInfo.stdout, encoding: .utf8),
-          let result = stdoutput.split(separator: "\n").last {
-          XCTAssertEqual(String(result), "** TEST SUCCEEDED **", "xcodebuild did not return test success.")
-        } else if let error = String(data: completionInfo.stderr, encoding: .utf8), !error.isEmpty {
-          XCTFail(error)
-        } else {
-          XCTFail("Xcode project tests did not return  success.")
-        }
-        semaphore.signal()
-    }
-    xcodeTest.launch()
-    _ = semaphore.wait(timeout: DispatchTime.distantFuture)
+    let destination = "platform=iOS Simulator,name=\(TulsiEndToEndTest.simulatorName)"
+    let completionInfo = ProcessRunner.launchProcessSync("/usr/bin/xcodebuild",
+                                                         arguments: ["test",
+                                                                     "-project",
+                                                                     xcodeProjectURL.path,
+                                                                     "-scheme",
+                                                                     scheme,
+                                                                     "-destination",
+                                                                     destination])
+
+    if let stdoutput = String(data: completionInfo.stdout, encoding: .utf8),
+      let result = stdoutput.split(separator: "\n").last {
+      if (String(result) != "** TEST SUCCEEDED **") {
+        print(stdoutput)
+        XCTFail("\(completionInfo.commandlineString) did not return test sucess. Exit code: \(completionInfo.terminationStatus)")
+      }
+    } else if let error = String(data: completionInfo.stderr, encoding: .utf8), !error.isEmpty {
+      XCTFail(error)
+    } else {
+      XCTFail("Xcode project tests did not return  success.")
+    }
+  }
+
+  // Runs 'simctl' in a subprocess with whatever command (i.e. boot, shutdown, delete, etc) and
+  // target simulator specified.
+  fileprivate func runSimctlCommand(_ command: String, onSimulator target: String) {
+    let completionInfo = ProcessRunner.launchProcessSync("/usr/bin/xcrun",
+                                              arguments: ["simctl",
+                                                          command,
+                                                          target])
+
+    if let error = String(data: completionInfo.stderr, encoding: .utf8), !error.isEmpty {
+      print("""
+            \(completionInfo.commandlineString) failed with exit code: \(completionInfo.terminationStatus)
+            Error: \(error)
+            """)
+    }
   }
 }
 

// Parent class for end to end tests that generate an xcodeproj with the Tulsi binary and verify the
// generated xcodeproj by running the projects unit tests.
class TulsiEndToEndTest: BazelIntegrationTestCase {
  let fileManager = FileManager.default
  var runfilesWorkspaceURL: URL! = nil

  override func setUp() {
    super.setUp()
    super.continueAfterFailure = false
    runfilesWorkspaceURL = fakeBazelWorkspace.runfilesWorkspaceURL
    XCTAssertNotNil(runfilesWorkspaceURL, "runfilesWorkspaceURL must be not be nil after setup.")

    // Unzip the Tulsi.app bundle to the temp space.
    let semaphore = DispatchSemaphore(value: 0)
    let tulsiZipPath = "tulsi.zip"
    let tulsiZipURL = runfilesWorkspaceURL.appendingPathComponent(tulsiZipPath, isDirectory: false)
    let process = TulsiProcessRunner.createProcess("/usr/bin/unzip",
                                                   arguments: [tulsiZipURL.path,
                                                               "-d",
                                                               workspaceRootURL.path]) {
      completionInfo in
        if let error = String(data: completionInfo.stderr, encoding: .utf8), !error.isEmpty {
          XCTFail(error)
        }
        semaphore.signal()
    }
    process.launch()
    _ = semaphore.wait(timeout: DispatchTime.distantFuture)
  }

  // Takes a short path to data files and adds them to the fake Bazel workspace.

    let configPath = projectURL.path + ":" + config

    // Generate Xcode project with Tulsi.
    let completionInfo = ProcessRunner.launchProcessSync(tulsiBinURL.path,
                                                         arguments: ["--",
                                                                     "--genconfig",
                                                                     configPath,
                                                                     "--outputfolder",
                                                                     workspaceRootURL.path,
                                                                     "--bazel",
                                                                     bazelURL.path,
                                                                     "--no-open-xcode"])

    if let stdoutput = String(data: completionInfo.stdout, encoding: .utf8) {
      print(stdoutput)
    }
    if let erroutput = String(data: completionInfo.stderr, encoding: .utf8) {
      print(erroutput)
    }

    let filename = TulsiGeneratorConfig.sanitizeFilename("\(config).xcodeproj")
    let xcodeProjectURL = workspaceRootURL.appendingPathComponent(filename, isDirectory: true)
