     let configPath = projectURL.path + ":" + config
 
     // Generate Xcode project with Tulsi.
-    let semaphore = DispatchSemaphore(value: 0)
-    let process = TulsiProcessRunner.createProcess(tulsiBinURL.path,
-                                                   arguments: ["--",
-                                                               "--genconfig",
-                                                               configPath,
-                                                               "--outputfolder",
-                                                               workspaceRootURL.path,
-                                                               "--bazel",
-                                                               bazelURL.path,
-                                                               "--no-open-xcode"]) {
-      completionInfo in
-        if let stdoutput = String(data: completionInfo.stdout, encoding: .utf8) {
-          print(stdoutput)
-        }
-        if let erroutput = String(data: completionInfo.stderr, encoding: .utf8) {
-          print(erroutput)
-        }
-        semaphore.signal()
-    }
-    process.launch()
-    _ = semaphore.wait(timeout: DispatchTime.distantFuture)
+    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)

// 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.


  // Runs Xcode tests on the given Xcode project and scheme.
  func testXcodeProject(_ xcodeProjectURL: URL, scheme: String) {
    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)
            """)
    }
  }
}

