@@ -3121,9 +3121,22 @@ def test_toy_cuda_sanity_check(self):
31213121 topdir = os .path .dirname (os .path .abspath (__file__ ))
31223122 toy_ec = os .path .join (topdir , 'easyconfigs' , 'test_ecs' , 't' , 'toy' , 'toy-0.0.eb' )
31233123
3124+ toy_bin = '%(installdir)s/bin/toy'
3125+ py_site_pkgs = '%(installdir)s/lib/python3.9/site-packages'
3126+ shlib_ext = get_shared_lib_ext ()
3127+
31243128 toy_ec_cuda = os .path .join (self .test_prefix , 'toy-0.0-cuda.eb' )
3125- write_file (toy_ec_cuda , read_file (toy_ec ) + "\n dependencies = [('CUDA', '5.5.22', '', SYSTEM)]" )
3126- toy_ec = toy_ec_cuda
3129+ toy_ec_txt = read_file (toy_ec )
3130+ toy_ec_txt += '\n ' + '\n ' .join ([
3131+ "dependencies = [('CUDA', '5.5.22', '', SYSTEM)]" ,
3132+ "postinstallcmds += [" ,
3133+ " 'mkdir -p %(installdir)s/lib/python3.9/site-packages/plugins'," ,
3134+ # copy 'toy' binary, must be something that passes 'file' check in get_cuda_object_dump_raw
3135+ " 'cp %s %s/pytoy-cuda.cpython-39-x86_64-linux-gnu.%s'," % (toy_bin , py_site_pkgs , shlib_ext ),
3136+ " 'cp %s %s/plugins/libpytoy_cuda.%s'," % (toy_bin , py_site_pkgs , shlib_ext ),
3137+ "]" ,
3138+ ])
3139+ write_file (toy_ec_cuda , toy_ec_txt )
31273140
31283141 # Create mock cuobjdump
31293142 # First, lets define sections of echo's for cuobjdump for various scenarios
@@ -3243,10 +3256,10 @@ def test_toy_cuda_sanity_check(self):
32433256 # If either of these fail their assert, print an informative, standardized message
32443257 def assert_regex (pattern , log , stdout = None ):
32453258 regex = re .compile (pattern , re .M )
3246- msg = "Pattern %s not found in full build log: %s" % (pattern , log )
3259+ msg = "Pattern '%s' not found in full build log: %s" % (pattern , log )
32473260 self .assertTrue (regex .search (log ), msg )
32483261 if stdout is not None :
3249- msg2 = "Pattern %s not found in standard output: %s" % (pattern , stdout )
3262+ msg2 = "Pattern '%s' not found in standard output: %s" % (pattern , stdout )
32503263 self .assertTrue (regex .search (stdout ), msg2 )
32513264
32523265 def assert_cuda_report (missing_cc , additional_cc , missing_ptx , log , stdout = None , missing_cc_but_ptx = None ,
@@ -3278,9 +3291,9 @@ def assert_cuda_report(missing_cc, additional_cc, missing_ptx, log, stdout=None,
32783291 args = ['--cuda-compute-capabilities=8.0' ]
32793292 # We expect this to pass, so no need to check errors
32803293 with self .mocked_stdout_stderr ():
3281- outtxt = self ._test_toy_build (ec_file = toy_ec , extra_args = args , raise_error = True )
3294+ outtxt = self ._test_toy_build (ec_file = toy_ec_cuda , extra_args = args , raise_error = True )
32823295 stdout = self .get_stdout ()
3283- assert_cuda_report (missing_cc = 0 , additional_cc = 0 , missing_ptx = 1 , log = outtxt , stdout = stdout )
3296+ assert_cuda_report (missing_cc = 0 , additional_cc = 0 , missing_ptx = 3 , log = outtxt , stdout = stdout )
32843297
32853298 # Test case 1b: test with default options, --cuda-compute-capabilities=8.0 and a binary that contains
32863299 # 7.0 and 9.0 device code and 8.0 PTX code.
@@ -3297,29 +3310,29 @@ def assert_cuda_report(missing_cc, additional_cc, missing_ptx, log, stdout=None,
32973310 args = ['--cuda-compute-capabilities=8.0' ]
32983311 # We expect this to pass, so no need to check errors
32993312 with self .mocked_stdout_stderr ():
3300- outtxt = self ._test_toy_build (ec_file = toy_ec , extra_args = args , raise_error = True )
3313+ outtxt = self ._test_toy_build (ec_file = toy_ec_cuda , extra_args = args , raise_error = True )
33013314 stdout = self .get_stdout ()
3302- msg = "Pattern %s not found in full build log: %s" % (device_additional_70_90_code_regex .pattern , outtxt )
3315+ msg = "Pattern '%s' not found in full build log: %s" % (device_additional_70_90_code_regex .pattern , outtxt )
33033316 self .assertTrue (device_additional_70_90_code_regex .search (outtxt ), msg )
3304- msg = "Pattern %s not found in full build log: %s" % (device_missing_80_code_regex .pattern , outtxt )
3317+ msg = "Pattern '%s' not found in full build log: %s" % (device_missing_80_code_regex .pattern , outtxt )
33053318 self .assertTrue (device_missing_80_code_regex .search (outtxt ), msg )
3306- assert_cuda_report (missing_cc = 1 , additional_cc = 1 , missing_ptx = 0 , log = outtxt , stdout = stdout )
3319+ assert_cuda_report (missing_cc = 3 , additional_cc = 3 , missing_ptx = 0 , log = outtxt , stdout = stdout )
33073320
33083321 # Test case 2: same as Test case 1, but add --cuda-sanity-check-error-on-failed-checks
33093322 # This is expected to fail since there is missing device code for CC80
33103323 args = ['--cuda-compute-capabilities=8.0' , '--cuda-sanity-check-error-on-failed-checks' ]
33113324 # We expect this to fail, so first check error, then run again to check output
3312- error_pattern = r"Files missing CUDA device code: 1 ."
3325+ error_pattern = r"Files missing CUDA device code: 3 ."
33133326 with self .mocked_stdout_stderr ():
3314- self .assertErrorRegex (EasyBuildError , error_pattern , self ._test_toy_build , ec_file = toy_ec ,
3327+ self .assertErrorRegex (EasyBuildError , error_pattern , self ._test_toy_build , ec_file = toy_ec_cuda ,
33153328 extra_args = args , raise_error = True )
3316- outtxt = self ._test_toy_build (ec_file = toy_ec , extra_args = args , raise_error = False , verify = False )
3329+ outtxt = self ._test_toy_build (ec_file = toy_ec_cuda , extra_args = args , raise_error = False , verify = False )
33173330 stdout = self .get_stdout ()
3318- msg = "Pattern %s not found in full build log: %s" % (device_additional_70_90_code_regex .pattern , outtxt )
3331+ msg = "Pattern '%s' not found in full build log: %s" % (device_additional_70_90_code_regex .pattern , outtxt )
33193332 self .assertTrue (device_additional_70_90_code_regex .search (outtxt ), msg )
3320- msg = "Pattern %s not found in full build log: %s" % (device_missing_80_code_regex .pattern , outtxt )
3333+ msg = "Pattern '%s' not found in full build log: %s" % (device_missing_80_code_regex .pattern , outtxt )
33213334 self .assertTrue (device_missing_80_code_regex .search (outtxt ), msg )
3322- assert_cuda_report (missing_cc = 1 , additional_cc = 1 , missing_ptx = 0 , log = outtxt , stdout = stdout )
3335+ assert_cuda_report (missing_cc = 3 , additional_cc = 3 , missing_ptx = 0 , log = outtxt , stdout = stdout )
33233336
33243337 # Test case 3: same as Test case 2, but add --cuda-sanity-check-accept-ptx-as-devcode
33253338 # This is expected to succeed, since now the PTX code for CC80 will be accepted as
@@ -3329,28 +3342,28 @@ def assert_cuda_report(missing_cc, additional_cc, missing_ptx, log, stdout=None,
33293342 '--cuda-sanity-check-accept-ptx-as-devcode' ]
33303343 # We expect this to pass, so no need to check errors
33313344 with self .mocked_stdout_stderr ():
3332- outtxt = self ._test_toy_build (ec_file = toy_ec , extra_args = args , raise_error = True )
3345+ outtxt = self ._test_toy_build (ec_file = toy_ec_cuda , extra_args = args , raise_error = True )
33333346 stdout = self .get_stdout ()
3334- msg = "Pattern %s not found in full build log: %s" % (device_additional_70_90_code_regex .pattern , outtxt )
3347+ msg = "Pattern '%s' not found in full build log: %s" % (device_additional_70_90_code_regex .pattern , outtxt )
33353348 self .assertTrue (device_additional_70_90_code_regex .search (outtxt ), msg )
3336- msg = "Pattern %s not found in full build log: %s" % (device_missing_80_code_regex .pattern , outtxt )
3349+ msg = "Pattern '%s' not found in full build log: %s" % (device_missing_80_code_regex .pattern , outtxt )
33373350 self .assertTrue (device_missing_80_code_regex .search (outtxt ), msg )
3338- assert_cuda_report (missing_cc = 0 , additional_cc = 1 , missing_ptx = 0 , log = outtxt , stdout = stdout ,
3339- missing_cc_but_ptx = 1 )
3351+ assert_cuda_report (missing_cc = 0 , additional_cc = 3 , missing_ptx = 0 , log = outtxt , stdout = stdout ,
3352+ missing_cc_but_ptx = 3 )
33403353
33413354 # Test case 4: same as Test case 2, but run with --cuda-compute-capabilities=9.0
33423355 # This is expected to fail: device code is present, but PTX code for the highest CC (9.0) is missing
33433356 args = ['--cuda-compute-capabilities=9.0' , '--cuda-sanity-check-error-on-failed-checks' ]
33443357 # We expect this to fail, so first check error, then run again to check output
3345- error_pattern = r"Files missing CUDA PTX code: 1 "
3358+ error_pattern = r"Files missing CUDA PTX code: 3 "
33463359 with self .mocked_stdout_stderr ():
3347- self .assertErrorRegex (EasyBuildError , error_pattern , self ._test_toy_build , ec_file = toy_ec ,
3360+ self .assertErrorRegex (EasyBuildError , error_pattern , self ._test_toy_build , ec_file = toy_ec_cuda ,
33483361 extra_args = args , raise_error = True )
3349- outtxt = self ._test_toy_build (ec_file = toy_ec , extra_args = args , raise_error = False , verify = False )
3362+ outtxt = self ._test_toy_build (ec_file = toy_ec_cuda , extra_args = args , raise_error = False , verify = False )
33503363 stdout = self .get_stdout ()
3351- msg = "Pattern %s not found in full build log: %s" % (device_additional_70_code_regex .pattern , outtxt )
3364+ msg = "Pattern '%s' not found in full build log: %s" % (device_additional_70_code_regex .pattern , outtxt )
33523365 self .assertTrue (device_additional_70_code_regex .search (outtxt ), msg )
3353- assert_cuda_report (missing_cc = 0 , additional_cc = 1 , missing_ptx = 1 , log = outtxt , stdout = stdout )
3366+ assert_cuda_report (missing_cc = 0 , additional_cc = 3 , missing_ptx = 3 , log = outtxt , stdout = stdout )
33543367
33553368 # Test case 5: same as Test case 4, but add --cuda-sanity-check-accept-missing-ptx
33563369 # This is expected to succeed: device code is present, PTX code is missing, but that's accepted
@@ -3362,43 +3375,49 @@ def assert_cuda_report(missing_cc, additional_cc, missing_ptx, log, stdout=None,
33623375 warning_pattern += r"\(PTX architectures supported in that file: \['8\.0'\]\)"
33633376 warning_pattern_regex = re .compile (warning_pattern , re .M )
33643377 with self .mocked_stdout_stderr ():
3365- outtxt = self ._test_toy_build (ec_file = toy_ec , extra_args = args , raise_error = True )
3378+ outtxt = self ._test_toy_build (ec_file = toy_ec_cuda , extra_args = args , raise_error = True )
33663379 stdout = self .get_stdout ()
3367- msg = "Pattern %s not found in full build log: %s" % (device_additional_70_code_regex .pattern , outtxt )
3380+ msg = "Pattern '%s' not found in full build log: %s" % (device_additional_70_code_regex .pattern , outtxt )
33683381 self .assertTrue (device_additional_70_code_regex .search (outtxt ), msg )
3369- msg = "Pattern %s not found in full build log: %s" % (warning_pattern , outtxt )
3382+ msg = "Pattern '%s' not found in full build log: %s" % (warning_pattern , outtxt )
33703383 self .assertTrue (warning_pattern_regex .search (outtxt ), msg )
3371- assert_cuda_report (missing_cc = 0 , additional_cc = 1 , missing_ptx = 1 , log = outtxt , stdout = stdout )
3384+ assert_cuda_report (missing_cc = 0 , additional_cc = 3 , missing_ptx = 3 , log = outtxt , stdout = stdout )
33723385
33733386 # Test case 6: same as Test case 5, but add --cuda-sanity-check-strict
33743387 # This is expected to fail: device code is present, PTX code is missing (but accepted due to option)
33753388 # but additional device code is present, which is not allowed by --cuda-sanity-check-strict
33763389 args = ['--cuda-compute-capabilities=9.0' , '--cuda-sanity-check-error-on-failed-checks' ,
33773390 '--cuda-sanity-check-accept-missing-ptx' , '--cuda-sanity-check-strict' ]
33783391 # We expect this to fail, so first check error, then run again to check output
3379- error_pattern = r"Files with additional CUDA device code: 1 "
3392+ error_pattern = r"Files with additional CUDA device code: 3 "
33803393 with self .mocked_stdout_stderr ():
3381- self .assertErrorRegex (EasyBuildError , error_pattern , self ._test_toy_build , ec_file = toy_ec ,
3394+ self .assertErrorRegex (EasyBuildError , error_pattern , self ._test_toy_build , ec_file = toy_ec_cuda ,
33823395 extra_args = args , raise_error = True )
3383- outtxt = self ._test_toy_build (ec_file = toy_ec , extra_args = args , raise_error = False , verify = False )
3396+ outtxt = self ._test_toy_build (ec_file = toy_ec_cuda , extra_args = args , raise_error = False , verify = False )
33843397 stdout = self .get_stdout ()
3385- msg = "Pattern %s not found in full build log: %s" % (device_additional_70_code_regex .pattern , outtxt )
3398+ msg = "Pattern '%s' not found in full build log: %s" % (device_additional_70_code_regex .pattern , outtxt )
33863399 self .assertTrue (device_additional_70_code_regex .search (outtxt ), msg )
3387- assert_cuda_report (missing_cc = 0 , additional_cc = 1 , missing_ptx = 1 , log = outtxt , stdout = stdout )
3400+ assert_cuda_report (missing_cc = 0 , additional_cc = 3 , missing_ptx = 3 , log = outtxt , stdout = stdout )
33883401
33893402 # Test case 7: same as Test case 6, but add the failing file to the cuda_sanity_ignore_files
33903403 # This is expected to succeed: the individual file which _would_ cause the sanity check to fail is
33913404 # now on the ignore list
33923405 toy_whitelist_ec = os .path .join (self .test_prefix , 'toy-0.0-cuda-whitelist.eb' )
3393- write_file (toy_whitelist_ec , read_file (toy_ec ) + '\n cuda_sanity_ignore_files = ["bin/toy"]' )
3406+ toy_ec_txt = read_file (toy_ec )
3407+ toy_ec_txt += '\n ' + '\n ' .join ([
3408+ "dependencies = [('CUDA', '5.5.22', '', SYSTEM)]" ,
3409+ "cuda_sanity_ignore_files = ['bin/toy']" ,
3410+ ])
3411+ write_file (toy_ec_cuda , toy_ec_txt )
3412+ write_file (toy_whitelist_ec , toy_ec_txt )
33943413
33953414 args = ['--cuda-compute-capabilities=9.0' , '--cuda-sanity-check-error-on-failed-checks' ,
33963415 '--cuda-sanity-check-accept-missing-ptx' , '--cuda-sanity-check-strict' ]
33973416 # We expect this to succeed, so check output for expected patterns
33983417 with self .mocked_stdout_stderr ():
33993418 outtxt = self ._test_toy_build (ec_file = toy_whitelist_ec , extra_args = args , raise_error = True , verify = False )
34003419 stdout = self .get_stdout ()
3401- msg = "Pattern %s not found in full build log: %s" % (device_additional_70_code_regex .pattern , outtxt )
3420+ msg = "Pattern '%s' not found in full build log: %s" % (device_additional_70_code_regex .pattern , outtxt )
34023421 self .assertTrue (device_additional_70_code_regex .search (outtxt ), msg )
34033422 assert_cuda_report (missing_cc = 0 , additional_cc = 1 , missing_ptx = 1 , log = outtxt , stdout = stdout )
34043423
@@ -3417,15 +3436,15 @@ def assert_cuda_report(missing_cc, additional_cc, missing_ptx, log, stdout=None,
34173436 '--cuda-sanity-check-strict' ]
34183437 # We expect this to pass, so no need to check errors
34193438 with self .mocked_stdout_stderr ():
3420- outtxt = self ._test_toy_build (ec_file = toy_ec , extra_args = args , raise_error = True )
3439+ outtxt = self ._test_toy_build (ec_file = toy_ec_cuda , extra_args = args , raise_error = True )
34213440 stdout = self .get_stdout ()
3422- msg = "Pattern %s not found in full build log: %s" % (device_code_regex_success .pattern , outtxt )
3441+ msg = "Pattern '%s' not found in full build log: %s" % (device_code_regex_success .pattern , outtxt )
34233442 self .assertTrue (device_code_regex_success .search (outtxt ), msg )
3424- msg = "Pattern %s not found in full build log: %s" % (ptx_code_regex_success .pattern , outtxt )
3443+ msg = "Pattern '%s' not found in full build log: %s" % (ptx_code_regex_success .pattern , outtxt )
34253444 self .assertTrue (ptx_code_regex_success .search (outtxt ), msg )
34263445 expected_result_pattern = "INFO Sanity check for toy successful"
34273446 expected_result = re .compile (expected_result_pattern , re .M )
3428- msg = "Pattern %s not found in full build log: %s" % (expected_result , outtxt )
3447+ msg = "Pattern '%s' not found in full build log: %s" % (expected_result , outtxt )
34293448 self .assertTrue (expected_result .search (outtxt ), msg )
34303449 assert_cuda_report (missing_cc = 0 , additional_cc = 0 , missing_ptx = 0 , log = outtxt , stdout = stdout )
34313450
@@ -3434,15 +3453,15 @@ def assert_cuda_report(missing_cc, additional_cc, missing_ptx, log, stdout=None,
34343453 args = ['--cuda-sanity-check-error-on-failed-checks' , '--cuda-sanity-check-strict' ]
34353454 # We expect this to pass, so no need to check errors
34363455 with self .mocked_stdout_stderr ():
3437- outtxt = self ._test_toy_build (ec_file = toy_ec , extra_args = args , raise_error = True )
3456+ outtxt = self ._test_toy_build (ec_file = toy_ec_cuda , extra_args = args , raise_error = True )
34383457 stdout = self .get_stdout ()
34393458 cuda_sanity_skipped = r"INFO Skipping CUDA sanity check, as no CUDA compute capabilities were configured"
34403459 cuda_sanity_skipped_regex = re .compile (cuda_sanity_skipped , re .M )
3441- msg = "Pattern %s not found in full build log: %s" % (cuda_sanity_skipped , outtxt )
3460+ msg = "Pattern '%s' not found in full build log: %s" % (cuda_sanity_skipped , outtxt )
34423461 self .assertTrue (cuda_sanity_skipped_regex .search (outtxt ), msg )
34433462 expected_result_pattern = "INFO Sanity check for toy successful"
34443463 expected_result = re .compile (expected_result_pattern , re .M )
3445- msg = "Pattern %s not found in full build log: %s" % (expected_result , outtxt )
3464+ msg = "Pattern '%s' not found in full build log: %s" % (expected_result , outtxt )
34463465 self .assertTrue (expected_result .search (outtxt ), msg )
34473466
34483467 # Test case 10: running with default options and a binary that does not contain ANY CUDA device code
@@ -3453,16 +3472,16 @@ def assert_cuda_report(missing_cc, additional_cc, missing_ptx, log, stdout=None,
34533472 args = ['--cuda-compute-capabilities=9.0' ]
34543473 # We expect this to pass, so no need to check errors
34553474 with self .mocked_stdout_stderr ():
3456- outtxt = self ._test_toy_build (ec_file = toy_ec , extra_args = args , raise_error = True )
3475+ outtxt = self ._test_toy_build (ec_file = toy_ec_cuda , extra_args = args , raise_error = True )
34573476 stdout = self .get_stdout ()
34583477 no_cuda_pattern = r".*/bin/toy does not appear to be a CUDA executable \(no CUDA device code found\), "
34593478 no_cuda_pattern += r"so skipping CUDA sanity check"
34603479 no_cuda_regex = re .compile (no_cuda_pattern , re .M )
3461- msg = "Pattern %s not found in full build log: %s" % (no_cuda_pattern , outtxt )
3480+ msg = "Pattern '%s' not found in full build log: %s" % (no_cuda_pattern , outtxt )
34623481 self .assertTrue (no_cuda_regex .search (outtxt ), msg )
34633482 expected_result_pattern = "INFO Sanity check for toy successful"
34643483 expected_result = re .compile (expected_result_pattern , re .M )
3465- msg = "Pattern %s not found in full build log: %s" % (expected_result , outtxt )
3484+ msg = "Pattern '%s' not found in full build log: %s" % (expected_result , outtxt )
34663485 self .assertTrue (expected_result .search (outtxt ), msg )
34673486 assert_cuda_report (missing_cc = 0 , additional_cc = 0 , missing_ptx = 0 , log = outtxt , stdout = stdout , num_checked = 0 )
34683487
@@ -3471,16 +3490,16 @@ def assert_cuda_report(missing_cc, additional_cc, missing_ptx, log, stdout=None,
34713490 args = ['--cuda-compute-capabilities=9.0' , '--cuda-sanity-check-error-on-failed-checks' ]
34723491 # We expect this to pass, so no need to check errors
34733492 with self .mocked_stdout_stderr ():
3474- outtxt = self ._test_toy_build (ec_file = toy_ec , extra_args = args , raise_error = True )
3493+ outtxt = self ._test_toy_build (ec_file = toy_ec_cuda , extra_args = args , raise_error = True )
34753494 stdout = self .get_stdout ()
34763495 no_cuda_pattern = r".*/bin/toy does not appear to be a CUDA executable \(no CUDA device code found\), "
34773496 no_cuda_pattern += r"so skipping CUDA sanity check"
34783497 no_cuda_regex = re .compile (no_cuda_pattern , re .M )
3479- msg = "Pattern %s not found in full build log: %s" % (no_cuda_pattern , outtxt )
3498+ msg = "Pattern '%s' not found in full build log: %s" % (no_cuda_pattern , outtxt )
34803499 self .assertTrue (no_cuda_regex .search (outtxt ), msg )
34813500 expected_result_pattern = "INFO Sanity check for toy successful"
34823501 expected_result = re .compile (expected_result_pattern , re .M )
3483- msg = "Pattern %s not found in full build log: %s" % (expected_result , outtxt )
3502+ msg = "Pattern '%s' not found in full build log: %s" % (expected_result , outtxt )
34843503 self .assertTrue (expected_result .search (outtxt ), msg )
34853504 assert_cuda_report (missing_cc = 0 , additional_cc = 0 , missing_ptx = 0 , log = outtxt , stdout = stdout , num_checked = 0 )
34863505
0 commit comments