94
94
import glob
95
95
import os
96
96
import platform
97
+ import stat
97
98
import shutil
98
99
import subprocess
99
100
import time
145
146
_IOS : "iOS" ,
146
147
_WINDOWS : "Win64" ,
147
148
_MACOS : "OSXUniversal" ,
148
- _LINUX : "Linux64"
149
+ _LINUX : "Linux64" ,
150
+ _PLAYMODE : "Playmode"
149
151
}
150
152
151
153
_SUPPORTED_PLATFORMS = (
264
266
" c can be a combination of digits and letters." )
265
267
266
268
269
+ @attr .s (frozen = False , eq = False )
270
+ class Test (object ):
271
+ """Holds data related to the testing of one testapp."""
272
+ testapp_path = attr .ib ()
273
+ logs = attr .ib ()
274
+
275
+
267
276
def main (argv ):
268
277
del argv # Unused.
269
278
@@ -286,6 +295,7 @@ def main(argv):
286
295
platforms = validate_platforms (FLAGS .platforms )
287
296
288
297
output_root = os .path .join (root_output_dir , "testapps" )
298
+ playmode_tests = []
289
299
failures = []
290
300
for version in unity_versions :
291
301
runtime = get_runtime (version , FLAGS .force_latest_runtime )
@@ -329,14 +339,17 @@ def main(argv):
329
339
if p == _DESKTOP : # e.g. 'Desktop' -> 'OSXUniversal'
330
340
p = get_desktop_platform ()
331
341
if p == _PLAYMODE :
332
- perform_in_editor_tests (dir_helper )
342
+ logs = perform_in_editor_tests (dir_helper )
343
+ playmode_tests .append (Test (testapp_path = dir_helper .unity_project_dir , logs = logs ))
333
344
else :
334
345
build_testapp (
335
346
dir_helper = dir_helper ,
336
347
api_config = api_config ,
337
348
ios_config = ios_config ,
338
349
target = _BUILD_TARGET [p ])
339
350
except (subprocess .SubprocessError , RuntimeError ) as e :
351
+ if p == _PLAYMODE :
352
+ playmode_tests .append (Test (testapp_path = dir_helper .unity_project_dir , logs = str (e )))
340
353
failures .append (
341
354
Failure (
342
355
testapp = testapp ,
@@ -350,20 +363,32 @@ def main(argv):
350
363
logging .info (f .read ())
351
364
# Free up space by removing unneeded Unity directory.
352
365
if FLAGS .ci :
353
- shutil . rmtree (dir_helper .unity_project_dir )
366
+ _rm_dir_safe (dir_helper .unity_project_dir )
354
367
else :
355
- shutil . rmtree (os .path .join (dir_helper .unity_project_dir , "Library" ))
368
+ _rm_dir_safe (os .path .join (dir_helper .unity_project_dir , "Library" ))
356
369
logging .info ("END %s" , build_desc )
357
370
358
- _collect_integration_tests (config , testapps , root_output_dir , output_dir , FLAGS .artifact_name )
359
-
360
- return _summarize_results (
361
- testapps = testapps ,
362
- platforms = platforms ,
363
- versions = unity_versions ,
364
- failures = failures ,
365
- output_dir = root_output_dir ,
366
- artifact_name = FLAGS .artifact_name )
371
+ playmode_passes = True
372
+ build_passes = True
373
+ if _PLAYMODE in platforms :
374
+ platforms .remove (_PLAYMODE )
375
+ playmode_passes = test_validation .summarize_test_results (
376
+ playmode_tests ,
377
+ test_validation .UNITY ,
378
+ root_output_dir ,
379
+ file_name = "test-results-" + FLAGS .artifact_name + ".log" )
380
+
381
+ if platforms :
382
+ _collect_integration_tests (config , testapps , root_output_dir , output_dir , FLAGS .artifact_name )
383
+ build_passes = _summarize_build_results (
384
+ testapps = testapps ,
385
+ platforms = platforms ,
386
+ versions = unity_versions ,
387
+ failures = failures ,
388
+ output_dir = root_output_dir ,
389
+ artifact_name = FLAGS .artifact_name )
390
+
391
+ return (playmode_passes and build_passes )
367
392
368
393
369
394
def setup_unity_project (dir_helper , setup_options ):
@@ -531,7 +556,7 @@ def perform_in_editor_tests(dir_helper, retry_on_license_check=True):
531
556
dir_helper .unity_path ,
532
557
dir_helper .unity_project_dir ,
533
558
shared_args = ["-batchmode" , "-nographics" , "-accept-apiupdate" ])
534
- log = dir_helper .make_log_path ("editor_tests " )
559
+ log = dir_helper .make_log_path ("build_Playmode " )
535
560
arg_builder .set_log_file (log )
536
561
run_args = arg_builder .get_args_for_method ("InEditorRunner.EditorRun" )
537
562
dir_helper .copy_editor_script ("InEditorRunner.cs" )
@@ -554,7 +579,7 @@ def perform_in_editor_tests(dir_helper, retry_on_license_check=True):
554
579
open_process .kill ()
555
580
logging .info ("Finished running playmode tests" )
556
581
557
- results = test_validation .validate_results_unity (text )
582
+ results = test_validation .validate_results (text , test_validation . UNITY )
558
583
if results .complete :
559
584
if results .passes and not results .fails : # Success
560
585
logging .info (results .summary )
@@ -564,6 +589,8 @@ def perform_in_editor_tests(dir_helper, retry_on_license_check=True):
564
589
raise RuntimeError (
565
590
"Tests did not finish running. Log tail:\n " + results .summary )
566
591
592
+ return text
593
+
567
594
568
595
def run_xcodebuild (dir_helper , ios_config , device_type ):
569
596
"""Uses xcode project generated by Unity to build an iOS binary."""
@@ -619,7 +646,7 @@ def _collect_integration_tests(config, testapps, root_output_dir, output_dir, ar
619
646
artifact_path = os .path .join (root_output_dir , testapps_artifact_dir )
620
647
logging .info ("Collecting artifacts to: %s" , artifact_path )
621
648
try :
622
- shutil . rmtree (artifact_path )
649
+ _rm_dir_safe (artifact_path )
623
650
except OSError as e :
624
651
logging .warning ("Failed to remove directory:\n %s" , e .strerror )
625
652
@@ -647,7 +674,7 @@ def _collect_integration_tests_platform(config, testapps, artifact_path, testapp
647
674
break
648
675
649
676
650
- def _summarize_results (testapps , platforms , versions , failures , output_dir , artifact_name ):
677
+ def _summarize_build_results (testapps , platforms , versions , failures , output_dir , artifact_name ):
651
678
"""Logs a readable summary of the results of the build."""
652
679
file_name = "build-results-" + artifact_name + ".log"
653
680
summary = []
@@ -956,6 +983,24 @@ def update_unity_versions(version_path_map, log=logging.error):
956
983
return valid_versions
957
984
958
985
986
+ def _handle_readonly_file (func , path , excinfo ):
987
+ """Function passed into shutil.rmtree to handle Access Denied error"""
988
+ os .chmod (path , stat .S_IWRITE )
989
+ func (path ) # will re-throw if a different error occurrs
990
+
991
+
992
+ def _rm_dir_safe (directory_path ):
993
+ """Removes directory at given path. No error if dir doesn't exist."""
994
+ logging .info ("Deleting %s..." , directory_path )
995
+ try :
996
+ shutil .rmtree (directory_path , onerror = _handle_readonly_file )
997
+ except OSError as e :
998
+ # There are two known cases where this can happen:
999
+ # The directory doesn't exist (FileNotFoundError)
1000
+ # A file in the directory is open in another process (PermissionError)
1001
+ logging .warning ("Failed to remove directory:\n %s" , e .strerror )
1002
+
1003
+
959
1004
def _fix_path (path ):
960
1005
"""Expands ~, normalizes slashes, and converts relative paths to absolute."""
961
1006
if not path :
0 commit comments