@@ -102,6 +102,47 @@ protected function loadEnvironment() {
102102 }
103103 }
104104
105+ private function xcodeMajorVersion () {
106+ $ future = new ExecFuture ('%C -version ' , $ this ->xcodebuildBinary );
107+
108+ list ($ errcode , $ stdout , $ stderr ) = $ future ->resolve ();
109+
110+ if (!$ errcode && preg_match ("/Xcode (.+)/ " , $ stdout , $ matches )) {
111+ return intval ($ matches [1 ]);
112+ }
113+
114+ return null ;
115+ }
116+
117+ public function execFutureEndOnLine ($ future , $ line ) {
118+ $ wait = $ future ->getDefaultWait ();
119+ $ hasSeenLine = false ;
120+ do {
121+ if ($ future ->isReady ()) {
122+ break ;
123+ }
124+
125+ $ read = $ future ->getReadSockets ();
126+ $ write = $ future ->getWriteSockets ();
127+
128+ if ($ read || $ write ) {
129+ Future::waitForSockets ($ read , $ write , $ wait );
130+ }
131+
132+ $ pipes = $ future ->read ();
133+ if (!$ hasSeenLine && strpos ($ pipes [0 ], $ line ) !== false ) {
134+ $ hasSeenLine = true ;
135+
136+ } else if ($ hasSeenLine && empty ($ pipes [0 ])) {
137+ $ results = $ future ->resolveKill ();
138+ $ results [0 ] = 0 ; # Overwrite the 'kill' error code.
139+ return $ results ;
140+ }
141+ } while (true );
142+
143+ return $ future ->getResult ();
144+ }
145+
105146 public function run () {
106147 $ this ->loadEnvironment ();
107148
@@ -123,11 +164,26 @@ public function run() {
123164 $ future ->resolvex ();
124165 }
125166
126- // Build and run unit tests
127- $ future = new ExecFuture ('%C %C test ' ,
128- $ this ->xcodebuildBinary , implode (' ' , $ xcodeargs ));
167+ $ xcodeMajorVersion = $ this ->xcodeMajorVersion ();
168+ if ($ xcodeMajorVersion && $ xcodeMajorVersion >= 8 ) {
169+ // Build and run unit tests
170+ $ future = new ExecFuture ('%C build-for-testing %C ' ,
171+ $ this ->xcodebuildBinary , implode (' ' , $ xcodeargs ));
172+ list ($ builderror , $ xcbuild_stdout , $ xcbuild_stderr ) = $ future ->resolve ();
173+ if (!$ builderror ) {
174+ $ future = new ExecFuture ('%C test-without-building %C ' ,
175+ $ this ->xcodebuildBinary , implode (' ' , $ xcodeargs ));
129176
130- list ($ builderror , $ xcbuild_stdout , $ xcbuild_stderr ) = $ future ->resolve ();
177+ list ($ builderror , $ xcbuild_stdout , $ xcbuild_stderr ) =
178+ $ this ->execFutureEndOnLine ($ future , "** TEST EXECUTE SUCCEEDED ** " );
179+ }
180+
181+ } else {
182+ // Build and run unit tests
183+ $ future = new ExecFuture ('%C %C test ' ,
184+ $ this ->xcodebuildBinary , implode (' ' , $ xcodeargs ));
185+ list ($ builderror , $ xcbuild_stdout , $ xcbuild_stderr ) = $ future ->resolve ();
186+ }
131187
132188 // Error-code 65 is thrown for build/unit test failures.
133189 if ($ builderror !== 0 && $ builderror !== 65 ) {
@@ -170,7 +226,7 @@ public function run() {
170226 }
171227 }
172228 }
173-
229+
174230 // TODO(featherless): If we publicized the parseCoverageResults method on
175231 // XcodeTestResultParser we could parseTestResults, then call parseCoverageResults,
176232 // and the logic here would map the coverage results to the test results. This
0 commit comments