def test_get_start_update_stop_progress_bar(self): """ Test starting/updating/stopping of progress bars. """ # clear progress bar cache first, this test assumes we start with a clean slate easybuild.tools.output._progress_bar_cache.clear() # restore default configuration to show progress bars (disabled to avoid mangled test output) update_build_option('show_progress_bar', True) # stopping a progress bar that never was started results in an error error_pattern = "Failed to stop extensions progress bar, since it was never started" self.assertErrorRegex(EasyBuildError, error_pattern, stop_progress_bar, PROGRESS_BAR_EXTENSIONS) # updating a progress bar that never was started is silently ignored on purpose update_progress_bar(PROGRESS_BAR_EXTENSIONS) update_progress_bar(PROGRESS_BAR_EXTENSIONS, label="foo") update_progress_bar(PROGRESS_BAR_EXTENSIONS, progress_size=100) # also test normal cycle: start, update, stop start_progress_bar(PROGRESS_BAR_EXTENSIONS, 100) update_progress_bar(PROGRESS_BAR_EXTENSIONS) # single step progress update_progress_bar(PROGRESS_BAR_EXTENSIONS, total=50) update_progress_bar(PROGRESS_BAR_EXTENSIONS, label="test123", progress_size=5) stop_progress_bar(PROGRESS_BAR_EXTENSIONS)
def test_update_build_option(self): """Test updating of a build option.""" self.assertEqual(build_option('banned_linked_shared_libs'), None) update_build_option('banned_linked_shared_libs', '/usr/lib64/libssl.so.1.1') self.assertEqual(build_option('banned_linked_shared_libs'), '/usr/lib64/libssl.so.1.1')
def test_create_progress_bar(self): """Test create_progress_bar function.""" # restore default (was disabled in EnhancedTestCase.setUp to avoid messing up test output) update_build_option('show_progress_bar', True) if HAVE_RICH: expected_progress_bar_class = rich.progress.Progress else: expected_progress_bar_class = DummyProgress progress_bar = create_progress_bar() error_msg = "%s should be instance of class %s" % ( progress_bar, expected_progress_bar_class) self.assertTrue(isinstance(progress_bar, expected_progress_bar_class), error_msg) update_build_option('output_style', 'basic') progress_bar = create_progress_bar() self.assertTrue(isinstance(progress_bar, DummyProgress)) if HAVE_RICH: update_build_option('output_style', 'rich') progress_bar = create_progress_bar() error_msg = "%s should be instance of class %s" % ( progress_bar, expected_progress_bar_class) self.assertTrue( isinstance(progress_bar, expected_progress_bar_class), error_msg) update_build_option('show_progress_bar', False) progress_bar = create_progress_bar() self.assertTrue(isinstance(progress_bar, DummyProgress))
def test_get_progress_bar(self): """ Test get_progress_bar. """ # restore default configuration to show progress bars (disabled to avoid mangled test output), # to ensure we'll get actual Progress instances when Rich is available update_build_option('show_progress_bar', True) for pbar_type in PROGRESS_BAR_TYPES: pbar = get_progress_bar(pbar_type, ignore_cache=True) if HAVE_RICH: self.assertTrue(isinstance(pbar, rich.progress.Progress)) else: self.assertTrue(isinstance(pbar, DummyRich))
def test_submit_jobs(self): """Test submit_jobs""" test_easyconfigs_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'easyconfigs', 'test_ecs') toy_ec = os.path.join(test_easyconfigs_dir, 't', 'toy', 'toy-0.0.eb') args = [ '--debug', '--tmpdir', '/tmp', '--optarch="GCC:O3 -mtune=generic;Intel:O3 -xHost"', '--parallel=2', '--try-toolchain=intel,2016a', # should be excluded in job script '--robot', self.test_prefix, # should be excluded in job script '--job', # should be excluded in job script '--job-cores=3', ] eb_go = parse_options(args=args) cmd = submit_jobs([toy_ec], eb_go.generate_cmd_line(), testing=True) # these patterns must be found regexs = [ r' --debug ', # values got wrapped in single quotes (to avoid interpretation by shell) r" --tmpdir='/tmp' ", r" --parallel='2' ", # (unparsed) optarch value got wrapped in single quotes, double quotes got stripped r" --optarch='GCC:O3 -mtune=generic;Intel:O3 -xHost' ", # templates to be completed via build_easyconfigs_in_parallel -> create_job r' eb %\(spec\)s ', r' %\(add_opts\)s ', r' --testoutput=%\(output_dir\)s', r' --disable-job ', ] for regex in regexs: regex = re.compile(regex) self.assertTrue(regex.search(cmd), "Pattern '%s' found in: %s" % (regex.pattern, cmd)) # these patterns should NOT be found, these options get filtered out # (self.test_prefix was argument to --robot) for regex in ['--job', '--job-cores', '--try-toolchain', '--robot=[ =]', self.test_prefix + ' ']: regex = re.compile(regex) self.assertFalse(regex.search(cmd), "Pattern '%s' should *not* be found in: %s" % (regex.pattern, cmd)) # test again with custom EasyBuild command to use in jobs update_build_option('job_eb_cmd', "/just/testing/bin/eb --debug") cmd = submit_jobs([toy_ec], eb_go.generate_cmd_line(), testing=True) regex = re.compile(r" && /just/testing/bin/eb --debug %\(spec\)s ") self.assertTrue(regex.search(cmd), "Pattern '%s' found in: %s" % (regex.pattern, cmd))
def test_update_build_option(self): """Test updating of a build option.""" self.assertEqual(build_option('banned_linked_shared_libs'), None) orig_banned_linked_shared_libs = update_build_option( 'banned_linked_shared_libs', '/usr/lib64/libssl.so.1.1') self.assertEqual(build_option('banned_linked_shared_libs'), '/usr/lib64/libssl.so.1.1') self.assertEqual(orig_banned_linked_shared_libs, None) self.assertTrue(build_option('cleanup_builddir')) orig_cleanup_builddir = update_build_option('cleanup_builddir', False) self.assertFalse(build_option('cleanup_builddir')) self.assertTrue(orig_cleanup_builddir) self.assertEqual(build_option('pr_target_account'), 'easybuilders') orig_pr_target_account = update_build_option('pr_target_account', 'test_pr_target_account') self.assertEqual(build_option('pr_target_account'), 'test_pr_target_account') self.assertEqual(orig_pr_target_account, 'easybuilders')
def test_get_output_style(self): """Test get_output_style function.""" self.assertEqual(build_option('output_style'), 'auto') for style in (None, 'auto'): if style: update_build_option('output_style', style) if HAVE_RICH: self.assertEqual(get_output_style(), 'rich') else: self.assertEqual(get_output_style(), 'basic') test_styles = ['basic', 'no_color'] if HAVE_RICH: test_styles.append('rich') for style in test_styles: update_build_option('output_style', style) self.assertEqual(get_output_style(), style) if not HAVE_RICH: update_build_option('output_style', 'rich') error_pattern = "Can't use 'rich' output style, Rich Python package is not available!" self.assertErrorRegex(EasyBuildError, error_pattern, get_output_style)
def test_use_rich_show_progress_bars(self): """Test use_rich and show_progress_bar functions.""" # restore default configuration to show progress bars (disabled to avoid mangled test output) update_build_option('show_progress_bar', True) self.assertEqual(build_option('output_style'), 'auto') if HAVE_RICH: self.assertTrue(use_rich()) self.assertTrue(show_progress_bars()) update_build_option('output_style', 'rich') self.assertTrue(use_rich()) self.assertTrue(show_progress_bars()) else: self.assertFalse(use_rich()) self.assertFalse(show_progress_bars()) update_build_option('output_style', 'basic') self.assertFalse(use_rich()) self.assertFalse(show_progress_bars())
def setUp(self): """Set up testcase.""" super(EnhancedTestCase, self).setUp() # make sure option parser doesn't pick up any cmdline arguments/options while len(sys.argv) > 1: sys.argv.pop() # keep track of log handlers log = fancylogger.getLogger(fname=False) self.orig_log_handlers = log.handlers[:] log.info("setting up test %s" % self.id()) self.orig_tmpdir = tempfile.gettempdir() # use a subdirectory for this test (which we can clean up easily after the test completes) self.test_prefix = set_tmpdir() self.log = fancylogger.getLogger(self.__class__.__name__, fname=False) fd, self.logfile = tempfile.mkstemp(suffix='.log', prefix='eb-test-') os.close(fd) self.cwd = os.getcwd() # keep track of original environment to restore self.orig_environ = copy.deepcopy(os.environ) # keep track of original environment/Python search path to restore self.orig_sys_path = sys.path[:] testdir = os.path.dirname(os.path.abspath(__file__)) self.test_sourcepath = os.path.join(testdir, 'sandbox', 'sources') os.environ['EASYBUILD_SOURCEPATH'] = self.test_sourcepath os.environ['EASYBUILD_PREFIX'] = self.test_prefix self.test_buildpath = tempfile.mkdtemp() os.environ['EASYBUILD_BUILDPATH'] = self.test_buildpath self.test_installpath = tempfile.mkdtemp() os.environ['EASYBUILD_INSTALLPATH'] = self.test_installpath # make sure that the tests only pick up easyconfigs provided with the tests os.environ['EASYBUILD_ROBOT_PATHS'] = os.path.join(testdir, 'easyconfigs', 'test_ecs') # make sure that the EasyBuild installation is still known even if we purge an EB module if os.getenv('EB_SCRIPT_PATH') is None: eb_path = which('eb') if eb_path is not None: os.environ['EB_SCRIPT_PATH'] = eb_path # make sure no deprecated behaviour is being triggered (unless intended by the test) self.orig_current_version = eb_build_log.CURRENT_VERSION self.disallow_deprecated_behaviour() init_config() # disable progress bars when running the tests, # since it messes with test suite progress output when test installations are performed os.environ['EASYBUILD_DISABLE_SHOW_PROGRESS_BAR'] = '1' update_build_option('show_progress_bar', False) import easybuild # try to import easybuild.easyblocks(.generic) packages # it's OK if it fails here, but important to import first before fiddling with sys.path try: import easybuild.easyblocks import easybuild.easyblocks.generic except ImportError: pass # add sandbox to Python search path, update namespace packages testdir_sandbox = os.path.join(testdir, 'sandbox') sys.path.append(testdir_sandbox) # required to make sure the 'easybuild' dir in the sandbox is picked up; # this relates to the other 'reload' statements below reload(easybuild) # required to 'reset' easybuild.tools.module_naming_scheme namespace reload(easybuild.tools) reload(easybuild.tools.module_naming_scheme) # remove any entries in Python search path that seem to provide easyblocks (except the sandbox) for path in sys.path[:]: if os.path.exists(os.path.join(path, 'easybuild', 'easyblocks', '__init__.py')): if not os.path.samefile(path, testdir_sandbox): sys.path.remove(path) # hard inject location to (generic) test easyblocks into Python search path # only prepending to sys.path is not enough due to 'pkgutil.extend_path' in easybuild/easyblocks/__init__.py easybuild.__path__.insert(0, os.path.join(testdir_sandbox, 'easybuild')) import easybuild.easyblocks test_easyblocks_path = os.path.join(testdir_sandbox, 'easybuild', 'easyblocks') easybuild.easyblocks.__path__.insert(0, test_easyblocks_path) reload(easybuild.easyblocks) import easybuild.easyblocks.generic test_easyblocks_path = os.path.join(test_easyblocks_path, 'generic') easybuild.easyblocks.generic.__path__.insert(0, test_easyblocks_path) reload(easybuild.easyblocks.generic) # kick out any paths that shouldn't be there for easybuild.easyblocks and easybuild.easyblocks.generic # to avoid that easyblocks picked up from other places cause trouble for pkg in ('easybuild.easyblocks', 'easybuild.easyblocks.generic'): for path in sys.modules[pkg].__path__[:]: if testdir_sandbox not in path: sys.modules[pkg].__path__.remove(path) # save values of $PATH & $PYTHONPATH, so they can be restored later # this is important in case EasyBuild was installed as a module, since that module may be unloaded, # for example due to changes to $MODULEPATH in case EasyBuild was installed in a module hierarchy # cfr. https://github.com/easybuilders/easybuild-framework/issues/1685 self.env_path = os.environ.get('PATH') self.env_pythonpath = os.environ.get('PYTHONPATH') self.modtool = modules_tool() self.reset_modulepath([os.path.join(testdir, 'modules')]) reset_module_caches()