def test_package(self):
        """Test package function."""
        init_config(build_options={'silent': True})

        topdir = os.path.dirname(os.path.abspath(__file__))
        test_easyconfigs = os.path.join(topdir, 'easyconfigs', 'test_ecs')
        ec = EasyConfig(os.path.join(test_easyconfigs, 't', 'toy',
                                     'toy-0.0-gompi-1.3.12-test.eb'),
                        validate=False)

        mock_fpm(self.test_prefix)

        # import needs to be done here, since test easyblocks are only included later
        from easybuild.easyblocks.toy import EB_toy
        easyblock = EB_toy(ec)

        # build & install first
        easyblock.run_all_steps(False)

        # write a dummy log and report file to make sure they don't get packaged
        logfile = os.path.join(easyblock.installdir, log_path(), "logfile.log")
        write_file(logfile, "I'm a logfile")
        reportfile = os.path.join(easyblock.installdir, log_path(),
                                  "report.md")
        write_file(reportfile, "I'm a reportfile")

        # package using default packaging configuration (FPM to build RPM packages)
        pkgdir = package(easyblock)

        pkgfile = os.path.join(
            pkgdir,
            'toy-0.0-gompi-1.3.12-test-eb-%s.1.rpm' % EASYBUILD_VERSION)
        self.assertTrue(os.path.isfile(pkgfile), "Found %s" % pkgfile)

        pkgtxt = read_file(pkgfile)
        pkgtxt_regex = re.compile("STARTCONTENTS of installdir %s" %
                                  easyblock.installdir)
        self.assertTrue(
            pkgtxt_regex.search(pkgtxt),
            "Pattern '%s' found in: %s" % (pkgtxt_regex.pattern, pkgtxt))

        no_logfiles_regex = re.compile(
            r'STARTCONTENTS.*\.(log|md)$.*ENDCONTENTS',
            re.DOTALL | re.MULTILINE)
        self.assertFalse(
            no_logfiles_regex.search(pkgtxt), "Pattern not '%s' found in: %s" %
            (no_logfiles_regex.pattern, pkgtxt))

        if DEBUG:
            print "The FPM script debug output"
            print read_file(os.path.join(self.test_prefix, DEBUG_FPM_FILE))
            print "The Package File"
            print read_file(pkgfile)
Example #2
0
    def __init__(self, *args, **kwargs):
        """Constructor for Python easyblock."""
        super(EB_Python, self).__init__(*args, **kwargs)

        self.pyshortver = '.'.join(self.version.split('.')[:2])

        self.pythonpath = None
        if self.cfg['ebpythonprefixes']:
            easybuild_subdir = log_path()
            self.pythonpath = os.path.join(easybuild_subdir, 'python')

        ext_defaults = {
            # Use PYPI_SOURCE as the default for source_urls of extensions.
            'source_urls': [url for name, url, _ in TEMPLATE_CONSTANTS if name == 'PYPI_SOURCE'],
            # We should enable this (by default) for all extensions because the only installed packages at this point
            # (i.e. those in the site-packages folder) are the default installed ones, e.g. pip & setuptools.
            # And we must upgrade them cleanly, i.e. uninstall them first. This also applies to any other package
            # which is voluntarily or accidentally installed multiple times.
            # Example: Upgrading to a higher version after installing new dependencies.
            'pip_ignore_installed': False,
            # Python installations must be clean. Requires pip >= 9
            'sanity_pip_check': LooseVersion(self._get_pip_ext_version() or '0.0') >= LooseVersion('9.0'),
        }

        exts_default_options = self.cfg.get_ref('exts_default_options')
        for key in ext_defaults:
            if key not in exts_default_options:
                exts_default_options[key] = ext_defaults[key]
        self.log.debug("exts_default_options: %s", self.cfg['exts_default_options'])

        self.install_pip = self.cfg['install_pip']
        if self.install_pip:
            if not self._has_ensure_pip():
                raise EasyBuildError("The ensurepip module required to install pip (requested by install_pip=True) "
                                     "is not available in Python %s", self.version)
Example #3
0
    def test_log_path(self):
        """Test for log_path()."""
        # default
        self.assertEqual(log_path(), 'easybuild')

        # providing template values doesn't affect the default
        ec = {'name': 'foo', 'version': '1.2.3'}
        res = log_path(ec=ec)
        self.assertEqual(res, 'easybuild')

        # reconfigure with value for log directory that includes templates
        init_config(args=['--logfile-format=easybuild-%(name)s-%(version)s-%(date)s-%(time)s,log.txt'])
        regex = re.compile(r'^easybuild-foo-1\.2\.3-[0-9-]{8}-[0-9]{6}$')
        res = log_path(ec=ec)
        self.assertTrue(regex.match(res), "Pattern '%s' matches '%s'" % (regex.pattern, res))
        self.assertEqual(log_file_format(), 'log.txt')
Example #4
0
    def test_log_path(self):
        """Test for log_path()."""
        # default
        self.assertEqual(log_path(), 'easybuild')

        # providing template values doesn't affect the default
        ec = {'name': 'foo', 'version': '1.2.3'}
        res = log_path(ec=ec)
        self.assertEqual(res, 'easybuild')

        # reconfigure with value for log directory that includes templates
        init_config(args=['--logfile-format=easybuild-%(name)s-%(version)s-%(date)s-%(time)s,log.txt'])
        regex = re.compile(r'^easybuild-foo-1\.2\.3-[0-9-]{8}-[0-9]{6}$')
        res = log_path(ec=ec)
        self.assertTrue(regex.match(res), "Pattern '%s' matches '%s'" % (regex.pattern, res))
        self.assertEqual(log_file_format(), 'log.txt')
    def __init__(self, *args, **kwargs):
        """Constructor for Python easyblock."""
        super(EB_Python, self).__init__(*args, **kwargs)

        self.pyshortver = '.'.join(self.version.split('.')[:2])

        self.pythonpath = None
        if self.cfg['ebpythonprefixes']:
            easybuild_subdir = log_path()
            self.pythonpath = os.path.join(easybuild_subdir, 'python')
Example #6
0
    def __init__(self, *args, **kwargs):
        """Constructor for Python easyblock."""
        super(EB_Python, self).__init__(*args, **kwargs)

        self.pyshortver = '.'.join(self.version.split('.')[:2])

        self.pythonpath = None
        if self.cfg['ebpythonprefixes']:
            easybuild_subdir = log_path()
            self.pythonpath = os.path.join(easybuild_subdir, 'python')
    def test_package(self):
        """Test package function."""
        init_config(build_options={'silent': True})

        topdir = os.path.dirname(os.path.abspath(__file__))
        test_easyconfigs = os.path.join(topdir, 'easyconfigs', 'test_ecs')
        ec = EasyConfig(os.path.join(test_easyconfigs, 't', 'toy', 'toy-0.0-gompi-1.3.12-test.eb'), validate=False)

        mock_fpm(self.test_prefix)

        # import needs to be done here, since test easyblocks are only included later
        from easybuild.easyblocks.toy import EB_toy
        easyblock = EB_toy(ec)

        # build & install first
        easyblock.run_all_steps(False)

        # write a dummy log and report file to make sure they don't get packaged
        logfile = os.path.join(easyblock.installdir, log_path(), "logfile.log")
        write_file(logfile, "I'm a logfile")
        reportfile = os.path.join(easyblock.installdir, log_path(), "report.md")
        write_file(reportfile, "I'm a reportfile")

        # package using default packaging configuration (FPM to build RPM packages)
        pkgdir = package(easyblock)

        pkgfile = os.path.join(pkgdir, 'toy-0.0-gompi-1.3.12-test-eb-%s.1.rpm' % EASYBUILD_VERSION)
        self.assertTrue(os.path.isfile(pkgfile), "Found %s" % pkgfile)

        pkgtxt = read_file(pkgfile)
        pkgtxt_regex = re.compile("STARTCONTENTS of installdir %s" % easyblock.installdir)
        self.assertTrue(pkgtxt_regex.search(pkgtxt), "Pattern '%s' found in: %s" % (pkgtxt_regex.pattern, pkgtxt))

        no_logfiles_regex = re.compile(r'STARTCONTENTS.*\.(log|md)$.*ENDCONTENTS', re.DOTALL|re.MULTILINE)
        self.assertFalse(no_logfiles_regex.search(pkgtxt), "Pattern not '%s' found in: %s" % (no_logfiles_regex.pattern, pkgtxt))

        if DEBUG:
            print "The FPM script debug output"
            print read_file(os.path.join(self.test_prefix, DEBUG_FPM_FILE))
            print "The Package File"
            print read_file(pkgfile)
Example #8
0
    def test_cases_step(self):
        """Run provided list of test cases, or provided examples is no test cases were specified."""

        # run all examples if no test cases were specified
        # order and grouping is important for some of these tests (e.g., [o]h3tr*
        # Some of the examples are deleted
        # missing md parameter files: dna.nw, mache.nw, 18c6NaK.nw, membrane.nw, sdm.nw
        # method not implemented (unknown thory) or keyword not found: triplet.nw, C2H6.nw, pspw_MgO.nw
        #                                                              ccsdt_polar_small.nw, CG.nw
        # no convergence: diamond.nw
        # Too much memory required: ccsd_polar_big.nw
        if isinstance(self.cfg['tests'], bool):
            examples = [
                ('qmd', ['3carbo_dft.nw', '3carbo.nw', 'h2o_scf.nw']),
                ('pspw',
                 ['C2.nw', 'C6.nw', 'Carbene.nw', 'Na16.nw', 'NaCl.nw']),
                ('tcepolar', ['ccsd_polar_small.nw']),
                ('dirdyvtst/h3', ['h3tr1.nw', 'h3tr2.nw']),
                ('dirdyvtst/h3', ['h3tr3.nw']), ('dirdyvtst/h3', ['h3tr4.nw']),
                ('dirdyvtst/h3', ['h3tr5.nw']),
                ('dirdyvtst/oh3', ['oh3tr1.nw', 'oh3tr2.nw']),
                ('dirdyvtst/oh3', ['oh3tr3.nw']),
                ('dirdyvtst/oh3', ['oh3tr4.nw']),
                ('dirdyvtst/oh3', ['oh3tr5.nw']),
                ('pspw/session1', [
                    'band.nw', 'si4.linear.nw', 'si4.rhombus.nw',
                    'S2-drift.nw', 'silicon.nw', 'S2.nw', 'si4.rectangle.nw'
                ]), ('md/myo', ['myo.nw']), ('md/nak', ['NaK.nw']),
                ('md/crown', ['crown.nw']), ('md/hrc', ['hrc.nw']),
                ('md/benzene', ['benzene.nw'])
            ]

            self.cfg['tests'] = [(os.path.join(self.examples_dir, d), l)
                                 for (d, l) in examples]
            self.log.info("List of examples to be run as test cases: %s" %
                          self.cfg['tests'])

        try:
            # symlink $HOME/.nwchemrc to local copy of default nwchemrc
            default_nwchemrc = os.path.join(self.installdir, 'data',
                                            'default.nwchemrc')

            # make a local copy of the default .nwchemrc file at a fixed path, so we can symlink to it
            # this makes sure that multiple parallel builds can reuse the same symlink, even for different builds
            # there is apparently no way to point NWChem to a particular config file other that $HOME/.nwchemrc
            try:
                local_nwchemrc_dir = os.path.dirname(self.local_nwchemrc)
                if not os.path.exists(local_nwchemrc_dir):
                    os.makedirs(local_nwchemrc_dir)
                shutil.copy2(default_nwchemrc, self.local_nwchemrc)

                # only try to create symlink if it's not there yet
                # we've verified earlier that the symlink is what we expect it to be if it's there
                if not os.path.islink(self.home_nwchemrc):
                    symlink(self.local_nwchemrc, self.home_nwchemrc)
            except OSError as err:
                raise EasyBuildError("Failed to symlink %s to %s: %s",
                                     self.home_nwchemrc, self.local_nwchemrc,
                                     err)

            # run tests, keep track of fail ratio
            cwd = os.getcwd()

            fail = 0.0
            tot = 0.0

            success_regexp = re.compile(r"Total times\s*cpu:.*wall:.*")

            test_cases_logfn = os.path.join(self.installdir, config.log_path(),
                                            'test_cases.log')
            test_cases_log = open(test_cases_logfn, "w")

            for (testdir, tests) in self.cfg['tests']:

                # run test in a temporary dir
                tmpdir = tempfile.mkdtemp(prefix='nwchem_test_')
                change_dir(tmpdir)

                # copy all files in test case dir
                for item in os.listdir(testdir):
                    test_file = os.path.join(testdir, item)
                    if os.path.isfile(test_file):
                        self.log.debug("Copying %s to %s" %
                                       (test_file, tmpdir))
                        shutil.copy2(test_file, tmpdir)

                # run tests
                for testx in tests:
                    cmd = "nwchem %s" % testx
                    msg = "Running test '%s' (from %s) in %s..." % (
                        cmd, testdir, tmpdir)
                    self.log.info(msg)
                    test_cases_log.write("\n%s\n" % msg)
                    (out, ec) = run_cmd(cmd,
                                        simple=False,
                                        log_all=False,
                                        log_ok=False,
                                        log_output=True)

                    # check exit code and output
                    if ec:
                        msg = "Test %s failed (exit code: %s)!" % (testx, ec)
                        self.log.warning(msg)
                        test_cases_log.write('FAIL: %s' % msg)
                        fail += 1
                    else:
                        if success_regexp.search(out):
                            msg = "Test %s successful!" % testx
                            self.log.info(msg)
                            test_cases_log.write('SUCCESS: %s' % msg)
                        else:
                            msg = "No 'Total times' found for test %s (but exit code is %s)!" % (
                                testx, ec)
                            self.log.warning(msg)
                            test_cases_log.write('FAIL: %s' % msg)
                            fail += 1

                    test_cases_log.write("\nOUTPUT:\n\n%s\n\n" % out)

                    tot += 1

                # go back
                change_dir(cwd)
                shutil.rmtree(tmpdir)

            fail_ratio = fail / tot
            fail_pcnt = fail_ratio * 100

            msg = "%d of %d tests failed (%s%%)!" % (fail, tot, fail_pcnt)
            self.log.info(msg)
            test_cases_log.write('\n\nSUMMARY: %s' % msg)

            test_cases_log.close()
            self.log.info("Log for test cases saved at %s" % test_cases_logfn)

            if fail_ratio > self.cfg['max_fail_ratio']:
                max_fail_pcnt = self.cfg['max_fail_ratio'] * 100
                raise EasyBuildError(
                    "Over %s%% of test cases failed, assuming broken build.",
                    max_fail_pcnt)

            # cleanup
            try:
                shutil.rmtree(self.examples_dir)
                shutil.rmtree(local_nwchemrc_dir)
            except OSError as err:
                raise EasyBuildError("Cleanup failed: %s", err)

            # set post msg w.r.t. cleaning up $HOME/.nwchemrc symlink
            self.postmsg += "\nRemember to clean up %s after all NWChem builds are finished." % self.home_nwchemrc

        except OSError as err:
            raise EasyBuildError("Failed to run test cases: %s", err)
Example #9
0
    def test_cases_step(self):
        """Run provided list of test cases, or provided examples is no test cases were specified."""

        # run all examples if no test cases were specified
        # order and grouping is important for some of these tests (e.g., [o]h3tr*
        # Some of the examples are deleted
        # missing md parameter files: dna.nw, mache.nw, 18c6NaK.nw, membrane.nw, sdm.nw
        # method not implemented (unknown thory) or keyword not found: triplet.nw, C2H6.nw, pspw_MgO.nw, ccsdt_polar_small.nw, CG.nw
        # no convergence: diamond.nw
        # Too much memory required: ccsd_polar_big.nw
        if type(self.cfg['tests']) is bool:
            examples = [('qmd', ['3carbo_dft.nw', '3carbo.nw', 'h2o_scf.nw']),
                        ('pspw', ['C2.nw', 'C6.nw', 'Carbene.nw', 'Na16.nw', 'NaCl.nw']),
                        ('tcepolar', ['ccsd_polar_small.nw']),
                        ('dirdyvtst/h3', ['h3tr1.nw', 'h3tr2.nw']),
                        ('dirdyvtst/h3', ['h3tr3.nw']), ('dirdyvtst/h3', ['h3tr4.nw']), ('dirdyvtst/h3', ['h3tr5.nw']),
                        ('dirdyvtst/oh3', ['oh3tr1.nw', 'oh3tr2.nw']),
                        ('dirdyvtst/oh3', ['oh3tr3.nw']), ('dirdyvtst/oh3', ['oh3tr4.nw']), ('dirdyvtst/oh3', ['oh3tr5.nw']),
                        ('pspw/session1', ['band.nw', 'si4.linear.nw', 'si4.rhombus.nw', 'S2-drift.nw', 
                                           'silicon.nw', 'S2.nw', 'si4.rectangle.nw']),
                        ('md/myo', ['myo.nw']), ('md/nak', ['NaK.nw']), ('md/crown', ['crown.nw']), ('md/hrc', ['hrc.nw']),
                        ('md/benzene', ['benzene.nw'])]

            self.cfg['tests'] = [(os.path.join(self.examples_dir, d), l) for (d, l) in examples]
            self.log.info("List of examples to be run as test cases: %s" % self.cfg['tests'])

        try:
            # symlink $HOME/.nwchemrc to local copy of default nwchemrc
            default_nwchemrc = os.path.join(self.installdir, 'data', 'default.nwchemrc')

            # make a local copy of the default .nwchemrc file at a fixed path, so we can symlink to it
            # this makes sure that multiple parallel builds can reuse the same symlink, even for different builds
            # there is apparently no way to point NWChem to a particular config file other that $HOME/.nwchemrc
            try:
                local_nwchemrc_dir = os.path.dirname(self.local_nwchemrc)
                if not os.path.exists(local_nwchemrc_dir):
                    os.makedirs(local_nwchemrc_dir)
                shutil.copy2(default_nwchemrc, self.local_nwchemrc)

                # only try to create symlink if it's not there yet
                # we've verified earlier that the symlink is what we expect it to be if it's there
                if not os.path.exists(self.home_nwchemrc):
                    os.symlink(self.local_nwchemrc, self.home_nwchemrc)
            except OSError, err:
                raise EasyBuildError("Failed to symlink %s to %s: %s", self.home_nwchemrc, self.local_nwchemrc, err)

            # run tests, keep track of fail ratio
            cwd = os.getcwd()

            fail = 0.0
            tot = 0.0

            success_regexp = re.compile("Total times\s*cpu:.*wall:.*")

            test_cases_logfn = os.path.join(self.installdir, config.log_path(), 'test_cases.log')
            test_cases_log = open(test_cases_logfn, "w")

            for (testdir, tests) in self.cfg['tests']:

                # run test in a temporary dir
                tmpdir = tempfile.mkdtemp(prefix='nwchem_test_')
                os.chdir(tmpdir)

                # copy all files in test case dir
                for item in os.listdir(testdir):
                    test_file = os.path.join(testdir, item)
                    if os.path.isfile(test_file):
                        self.log.debug("Copying %s to %s" % (test_file, tmpdir))
                        shutil.copy2(test_file, tmpdir)

                # run tests
                for testx in tests:
                    cmd = "nwchem %s" % testx
                    msg = "Running test '%s' (from %s) in %s..." % (cmd, testdir, tmpdir)
                    self.log.info(msg)
                    test_cases_log.write("\n%s\n" % msg)
                    (out, ec) = run_cmd(cmd, simple=False, log_all=False, log_ok=False, log_output=True)

                    # check exit code and output
                    if ec:
                        msg = "Test %s failed (exit code: %s)!" % (testx, ec)
                        self.log.warning(msg)
                        test_cases_log.write('FAIL: %s' % msg)
                        fail += 1
                    else:
                        if success_regexp.search(out):
                            msg = "Test %s successful!" % testx
                            self.log.info(msg)
                            test_cases_log.write('SUCCESS: %s' % msg)
                        else:
                            msg = "No 'Total times' found for test %s (but exit code is %s)!" % (testx, ec)
                            self.log.warning(msg)
                            test_cases_log.write('FAIL: %s' % msg)
                            fail += 1

                    test_cases_log.write("\nOUTPUT:\n\n%s\n\n" % out)

                    tot += 1

                # go back
                os.chdir(cwd)
                shutil.rmtree(tmpdir)

            fail_ratio = fail / tot
            fail_pcnt = fail_ratio * 100

            msg = "%d of %d tests failed (%s%%)!" % (fail, tot, fail_pcnt)
            self.log.info(msg)
            test_cases_log.write('\n\nSUMMARY: %s' % msg)

            test_cases_log.close()
            self.log.info("Log for test cases saved at %s" % test_cases_logfn)

            if fail_ratio > self.cfg['max_fail_ratio']:
                max_fail_pcnt = self.cfg['max_fail_ratio'] * 100
                raise EasyBuildError("Over %s%% of test cases failed, assuming broken build.", max_fail_pcnt)

            # cleanup
            try:
                shutil.rmtree(self.examples_dir)
                shutil.rmtree(local_nwchemrc_dir)
            except OSError, err:
                raise EasyBuildError("Cleanup failed: %s", err)
def package_with_fpm(easyblock):
    """
    This function will build a package using fpm and return the directory where the packages are
    """

    workdir = tempfile.mkdtemp(prefix='eb-pkgs-')
    pkgtype = build_option('package_type')
    _log.info("Will be creating %s package(s) in %s", pkgtype, workdir)

    origdir = change_dir(workdir)

    package_naming_scheme = ActivePNS()

    pkgname = package_naming_scheme.name(easyblock.cfg)
    pkgver = package_naming_scheme.version(easyblock.cfg)
    pkgrel = package_naming_scheme.release(easyblock.cfg)

    _log.debug("Got the PNS values name: %s version: %s release: %s", pkgname,
               pkgver, pkgrel)
    cmdlist = [
        PKG_TOOL_FPM,
        '--workdir',
        workdir,
        '--name',
        pkgname,
        '--provides',
        pkgname,
        '-t',
        pkgtype,  # target
        '-s',
        'dir',  # source
        '--version',
        pkgver,
        '--iteration',
        pkgrel,
        '--description',
        easyblock.cfg["description"],
        '--url',
        easyblock.cfg["homepage"],
    ]

    extra_pkg_options = build_option('package_tool_options')
    if extra_pkg_options:
        cmdlist.extend(extra_pkg_options.split(' '))

    if build_option('debug'):
        cmdlist.append('--debug')

    deps = []
    if not easyblock.toolchain.is_system_toolchain():
        toolchain_dict = easyblock.toolchain.as_dict()
        deps.extend([toolchain_dict])

    deps.extend(easyblock.cfg.dependencies())

    _log.debug(
        "The dependencies to be added to the package are: %s",
        pprint.pformat([easyblock.toolchain.as_dict()] +
                       easyblock.cfg.dependencies()))
    for dep in deps:
        if dep.get('external_module', False):
            _log.debug("Skipping dep marked as external module: %s",
                       dep['name'])
        else:
            _log.debug("The dep added looks like %s ", dep)
            dep_pkgname = package_naming_scheme.name(dep)
            cmdlist.extend(["--depends", dep_pkgname])

    # Excluding the EasyBuild logs and test reports that might be in the installdir
    exclude_files_globs = [
        os.path.join(log_path(ec=easyblock.cfg), "*.log"),
        os.path.join(log_path(ec=easyblock.cfg), "*.md"),
    ]
    # stripping off leading / to match expected glob in fpm
    for exclude_files_glob in exclude_files_globs:
        cmdlist.extend([
            '--exclude',
            os.path.join(easyblock.installdir.lstrip(os.sep),
                         exclude_files_glob)
        ])

    cmdlist.extend([
        easyblock.installdir,
        easyblock.module_generator.get_module_filepath(),
    ])
    cmd = ' '.join(cmdlist)
    _log.debug("The flattened cmdlist looks like: %s", cmd)
    run_cmd(cmdlist, log_all=True, simple=True, shell=False)

    _log.info("Created %s package(s) in %s", pkgtype, workdir)

    change_dir(origdir)

    return workdir
Example #11
0
def package_with_fpm(easyblock):
    """
    This function will build a package using fpm and return the directory where the packages are
    """

    workdir = tempfile.mkdtemp(prefix='eb-pkgs-')
    pkgtype = build_option('package_type')
    _log.info("Will be creating %s package(s) in %s", pkgtype, workdir)

    origdir = change_dir(workdir)

    package_naming_scheme = ActivePNS()

    pkgname = package_naming_scheme.name(easyblock.cfg)
    pkgver = package_naming_scheme.version(easyblock.cfg)
    pkgrel = package_naming_scheme.release(easyblock.cfg)

    _log.debug("Got the PNS values name: %s version: %s release: %s", pkgname, pkgver, pkgrel)
    cmdlist = [
        PKG_TOOL_FPM,
        '--workdir', workdir,
        '--name', pkgname,
        '--provides', pkgname,
        '-t', pkgtype,  # target
        '-s', 'dir',  # source
        '--version', pkgver,
        '--iteration', pkgrel,
        '--description', easyblock.cfg["description"],
        '--url', easyblock.cfg["homepage"],
    ]

    extra_pkg_options = build_option('package_tool_options')
    if extra_pkg_options:
        cmdlist.extend(extra_pkg_options.split(' '))

    if build_option('debug'):
        cmdlist.append('--debug')

    deps = []
    if easyblock.toolchain.name != DUMMY_TOOLCHAIN_NAME:
        toolchain_dict = easyblock.toolchain.as_dict()
        deps.extend([toolchain_dict])

    deps.extend(easyblock.cfg.dependencies())

    _log.debug("The dependencies to be added to the package are: %s",
               pprint.pformat([easyblock.toolchain.as_dict()] + easyblock.cfg.dependencies()))
    for dep in deps:
        if dep.get('external_module', False):
            _log.debug("Skipping dep marked as external module: %s", dep['name'])
        else:
            _log.debug("The dep added looks like %s ", dep)
            dep_pkgname = package_naming_scheme.name(dep)
            cmdlist.extend(["--depends", dep_pkgname])

    # Excluding the EasyBuild logs and test reports that might be in the installdir
    exclude_files_globs = [
        os.path.join(log_path(), "*.log"),
        os.path.join(log_path(), "*.md"),
    ]
    # stripping off leading / to match expected glob in fpm
    for exclude_files_glob in exclude_files_globs:
        cmdlist.extend(['--exclude', os.path.join(easyblock.installdir.lstrip(os.sep), exclude_files_glob)])

    cmdlist.extend([
        easyblock.installdir,
        easyblock.module_generator.get_module_filepath(),
    ])
    cmd = ' '.join(cmdlist)
    _log.debug("The flattened cmdlist looks like: %s", cmd)
    run_cmd(cmdlist, log_all=True, simple=True, shell=False)

    _log.info("Created %s package(s) in %s", pkgtype, workdir)

    change_dir(origdir)

    return workdir
    ended = "ended"

    # successful build
    if result:

        # collect build stats
        _log.info("Collecting build stats...")

        currentbuildstats = app.cfg['buildstats']
        buildstats = get_build_stats(app, starttime)
        _log.debug("Build stats: %s" % buildstats)

        if app.cfg['stop']:
            ended = "STOPPED"
            newLogDir = os.path.join(app.builddir, config.log_path())
        else:
            newLogDir = os.path.join(app.installdir, config.log_path())

            try:
                # upload spec to central repository
                repo = init_repository(get_repository(), get_repositorypath())
                if 'originalSpec' in module:
                    repo.add_easyconfig(module['originalSpec'], app.name, app.get_installversion() + ".block", buildstats, currentbuildstats)
                repo.add_easyconfig(spec, app.name, app.get_installversion(), buildstats, currentbuildstats)
                repo.commit("Built %s/%s" % (app.name, app.get_installversion()))
                del repo
            except EasyBuildError, err:
                _log.warn("Unable to commit easyconfig to repository: %s", err)

        exitCode = 0
Example #13
0
    def test_package(self):
        """Test package function."""
        build_options = {
            'package_tool_options': '--foo bar',
            'silent': True,
        }
        init_config(build_options=build_options)

        topdir = os.path.dirname(os.path.abspath(__file__))
        test_easyconfigs = os.path.join(topdir, 'easyconfigs', 'test_ecs')
        ec = EasyConfig(os.path.join(test_easyconfigs, 't', 'toy', 'toy-0.0-gompi-2018a-test.eb'), validate=False)

        mock_fpm(self.test_prefix)

        # import needs to be done here, since test easyblocks are only included later
        from easybuild.easyblocks.toy import EB_toy
        easyblock = EB_toy(ec)

        # build & install first
        easyblock.run_all_steps(False)

        # write a dummy log and report file to make sure they don't get packaged
        logfile = os.path.join(easyblock.installdir, log_path(), "logfile.log")
        write_file(logfile, "I'm a logfile")
        reportfile = os.path.join(easyblock.installdir, log_path(), "report.md")
        write_file(reportfile, "I'm a reportfile")

        # package using default packaging configuration (FPM to build RPM packages)
        pkgdir = package(easyblock)
        pkgfile = os.path.join(pkgdir, 'toy-0.0-gompi-2018a-test-eb-%s.1.rpm' % EASYBUILD_VERSION)

        fpm_output = read_file(os.path.join(self.test_prefix, FPM_OUTPUT_FILE))
        pkgtxt = read_file(pkgfile)

        self.assertTrue(os.path.isfile(pkgfile), "Found %s" % pkgfile)

        # check whether extra packaging options were passed down
        regex = re.compile("^got an unhandled option: --foo bar$", re.M)
        self.assertTrue(regex.search(fpm_output), "Pattern '%s' found in: %s" % (regex.pattern, fpm_output))

        pkgtxt = read_file(pkgfile)
        pkgtxt_regex = re.compile("STARTCONTENTS of installdir %s" % easyblock.installdir)
        self.assertTrue(pkgtxt_regex.search(pkgtxt), "Pattern '%s' found in: %s" % (pkgtxt_regex.pattern, pkgtxt))

        no_logfiles_regex = re.compile(r'STARTCONTENTS.*\.(log|md)$.*ENDCONTENTS', re.DOTALL | re.MULTILINE)
        res = no_logfiles_regex.search(pkgtxt)
        self.assertFalse(res, "Pattern not '%s' found in: %s" % (no_logfiles_regex.pattern, pkgtxt))

        toy_txt = read_file(os.path.join(test_easyconfigs, 't', 'toy', 'toy-0.0-gompi-2018a-test.eb'))
        replace_str = '''description = """Toy C program, 100% toy. Now with `backticks'\n'''
        replace_str += '''and newlines"""'''
        toy_txt = re.sub('description = .*', replace_str, toy_txt)
        toy_file = os.path.join(self.test_prefix, 'toy-test-description.eb')
        write_file(toy_file, toy_txt)

        regex = re.compile(r"""`backticks'""")
        self.assertTrue(regex.search(toy_txt), "Pattern '%s' found in: %s" % (regex.pattern, toy_txt))
        ec_desc = EasyConfig(toy_file, validate=False)
        easyblock_desc = EB_toy(ec_desc)
        easyblock_desc.run_all_steps(False)
        pkgdir = package(easyblock_desc)
        pkgfile = os.path.join(pkgdir, 'toy-0.0-gompi-2018a-test-eb-%s.1.rpm' % EASYBUILD_VERSION)
        self.assertTrue(os.path.isfile(pkgfile))
        pkgtxt = read_file(pkgfile)
        regex_pkg = re.compile(r"""DESCRIPTION:.*`backticks'.*""")
        self.assertTrue(regex_pkg.search(pkgtxt), "Pattern '%s' not found in: %s" % (regex_pkg.pattern, pkgtxt))
        regex_pkg = re.compile(r"""DESCRIPTION:.*\nand newlines""", re.MULTILINE)
        self.assertTrue(regex_pkg.search(pkgtxt), "Pattern '%s' not found in: %s" % (regex_pkg.pattern, pkgtxt))
Example #14
0
    def test_cases_step(self):
        """Run provided list of test cases, or provided examples is no test cases were specified."""

        # run all examples if no test cases were specified
        # order and grouping is important for some of these tests (e.g., [o]h3tr*
        if type(self.cfg['tests']) is bool:
            examples = [('qmd', ['3carbo_dft.nw', '3carbo.nw', 'h2o_scf.nw']),
                        ('pspw', ['C2.nw', 'C6.nw', 'CG.nw', 'Carbene.nw', 'Na16.nw', 'NaCl.nw']),
                        ('tcepolar', ['ccsdt_polar_small.nw', 'ccsd_polar_big.nw', 'ccsd_polar_small.nw']),
                        ('dirdyvtst/h3', ['h3tr1.nw', 'h3tr2.nw', 'h3tr3.nw', 'h3tr4.nw', 'h3tr5.nw']),
                        ('dirdyvtst/oh3', ['oh3tr1.nw', 'oh3tr2.nw', 'oh3tr3.nw', 'oh3tr4.nw', 'oh3tr5.nw']),
                        ('pspw/session1', ['band.nw', 'si4.linear.nw', 'si4.rhombus.nw', 'S2-drift.nw', 'diamond.nw',
                                           'silicon.nw', 'S2.nw', 'si4.rectangle.nw']),
                        ('pspw/MgO+Cu', ['pspw_MgO.nw']), ('pspw/C2H6', ['C2H6.nw']), ('pspw/Carbene', ['triplet.nw']),
                        ('md/dna', ['dna.nw']), ('md/ache', ['mache.nw']), ('md/myo', ['myo.nw']),
                        ('md/nak', ['NaK.nw']), ('md/nak', ['18c6NaK.nw']), ('md/membrane', ['membrane.nw']),
                        ('md/sdm', ['sdm.nw']), ('md/crown', ['crown.nw']), ('md/hrc', ['hrc.nw']),
                        ('md/benzene', ['benzene.nw'])]
            self.cfg['tests'] = [(os.path.join(self.examples_dir, d), l) for (d, l) in examples]
            self.log.info("List of examples to be run as test cases: %s" % self.cfg['tests'])

        try:
            # symlink $HOME/.nwchemrc to local copy of default nwchemrc
            default_nwchemrc = os.path.join(self.installdir, 'data', 'default.nwchemrc')
            home_nwchemrc = os.path.join(os.getenv('HOME'), '.nwchemrc')
            local_nwchemrc = os.path.join(tempfile.gettempdir(), os.getenv('USER'), 'easybuild_nwchem', '.nwchemrc')

            local_nwchemrc_dir = os.path.dirname(local_nwchemrc)
            if not os.path.exists(local_nwchemrc_dir):
                os.makedirs(local_nwchemrc_dir)

            shutil.copy2(default_nwchemrc, local_nwchemrc)
            symlink_ok = False
            if os.path.exists(home_nwchemrc):
                if not os.path.islink(home_nwchemrc) or not os.path.samefile(home_nwchemrc, local_nwchemrc):
                    self.log.error("File %s is present, but is not a symlink to %s" % (home_nwchemrc, local_nwchemrc))
                else:
                    symlink_ok = True

            if not symlink_ok:
                os.symlink(local_nwchemrc, home_nwchemrc)

            # run tests, keep track of fail ratio
            cwd = os.getcwd()

            fail = 0.0
            tot = 0.0

            success_regexp = re.compile("Total times\s*cpu:.*wall:.*")

            test_cases_logfn = os.path.join(self.installdir, config.log_path(), 'test_cases.log')
            test_cases_log = open(test_cases_logfn, "w")

            for (testdir, tests) in self.cfg['tests']:

                # run test in a temporary dir
                tmpdir = tempfile.mkdtemp(prefix='nwchem_test_')
                os.chdir(tmpdir)

                # copy all files in test case dir
                for item in os.listdir(testdir):
                    test_file = os.path.join(testdir, item)
                    if os.path.isfile(test_file):
                        self.log.debug("Copying %s to %s" % (test_file, tmpdir))
                        shutil.copy2(test_file, tmpdir)

                # run tests
                for testx in tests:
                    cmd = "nwchem %s" % testx
                    msg = "Running test '%s' (from %s) in %s..." % (cmd, testdir, tmpdir)
                    self.log.info(msg)
                    test_cases_log.write("\n%s\n" % msg)
                    (out, ec) = run_cmd(cmd, simple=False, log_all=False, log_ok=False, log_output=True)

                    # check exit code and output
                    if ec:
                        msg = "Test %s failed (exit code: %s)!" % (testx, ec)
                        self.log.warning(msg)
                        test_cases_log.write('FAIL: %s' % msg)
                        fail += 1
                    else:
                        if success_regexp.search(out):
                            msg = "Test %s successful!" % testx
                            self.log.info(msg)
                            test_cases_log.write('SUCCESS: %s' % msg)
                        else:
                            msg = "No 'Total times' found for test %s (but exit code is %s)!" % (testx, ec)
                            self.log.warning(msg)
                            test_cases_log.write('FAIL: %s' % msg)
                            fail += 1

                    test_cases_log.write("\nOUTPUT:\n\n%s\n\n" % out)

                    tot += 1

                # go back
                os.chdir(cwd)
                shutil.rmtree(tmpdir)

            fail_ratio = fail / tot
            fail_pcnt = fail_ratio * 100

            msg = "%d of %d tests failed (%s%%)!" % (fail, tot, fail_pcnt)
            self.log.info(msg)
            test_cases_log.write('\n\nSUMMARY: %s' % msg)

            test_cases_log.close()
            self.log.info("Log for test cases saved at %s" % test_cases_logfn)

            if fail_ratio > self.cfg['max_fail_ratio']:
                max_fail_pcnt = self.cfg['max_fail_ratio'] * 100
                self.log.error("Over %s%% of test cases failed, assuming broken build." % max_fail_pcnt)

            shutil.rmtree(self.examples_dir)
            shutil.rmtree(local_nwchemrc_dir)

        except OSError, err:
            self.log.error("Failed to run test cases: %s" % err)
Example #15
0
    ended = "ended"

    # successful build
    if result:

        # collect build stats
        _log.info("Collecting build stats...")

        currentbuildstats = app.cfg["buildstats"]
        buildstats = get_build_stats(app, starttime)
        _log.debug("Build stats: %s" % buildstats)

        if app.cfg["stop"]:
            ended = "STOPPED"
            newLogDir = os.path.join(app.builddir, config.log_path())
        else:
            newLogDir = os.path.join(app.installdir, config.log_path())

            try:
                # upload spec to central repository
                repo = init_repository(get_repository(), get_repositorypath())
                if "originalSpec" in module:
                    repo.add_easyconfig(
                        module["originalSpec"],
                        app.name,
                        app.get_installversion() + ".block",
                        buildstats,
                        currentbuildstats,
                    )
                repo.add_easyconfig(spec, app.name, app.get_installversion(), buildstats, currentbuildstats)
    deps.extend(easyblock.cfg.dependencies())

    _log.debug("The dependencies to be added to the package are: %s",
               pprint.pformat([easyblock.toolchain.as_dict()] + easyblock.cfg.dependencies()))
    depstring = ''
    for dep in deps:
        if dep.get('external_module', False):
            _log.debug("Skipping dep marked as external module: %s", dep['name'])
        else:
            _log.debug("The dep added looks like %s ", dep)
            dep_pkgname = package_naming_scheme.name(dep)
            depstring += " --depends %s" % quote_str(dep_pkgname)

    # Excluding the EasyBuild logs and test reports that might be in the installdir
    exclude_files_glob = [
        os.path.join(log_path(), "*.log"),
        os.path.join(log_path(), "*.md"),
    ]
    # stripping off leading / to match expected glob in fpm
    exclude_files_glob = [
        '--exclude %s' % quote_str(os.path.join(easyblock.installdir.lstrip(os.sep), x))
        for x in exclude_files_glob
    ]
    _log.debug("The list of excluded files passed to fpm: %s", exclude_files_glob)
    cmdlist = [
        PKG_TOOL_FPM,
        '--workdir', workdir,
        '--name', quote_str(pkgname),
        '--provides', quote_str(pkgname),
        '-t', pkgtype,  # target
        '-s', 'dir',  # source
Example #17
0
    def test_cases_step(self):
        """Run provided list of test cases, or provided examples is no test cases were specified."""

        # run all examples if no test cases were specified
        # order and grouping is important for some of these tests (e.g., [o]h3tr*
        if type(self.cfg['tests']) is bool:
            examples = [
                ('qmd', ['3carbo_dft.nw', '3carbo.nw', 'h2o_scf.nw']),
                ('pspw', [
                    'C2.nw', 'C6.nw', 'CG.nw', 'Carbene.nw', 'Na16.nw',
                    'NaCl.nw'
                ]),
                ('tcepolar', [
                    'ccsdt_polar_small.nw', 'ccsd_polar_big.nw',
                    'ccsd_polar_small.nw'
                ]),
                ('dirdyvtst/h3',
                 ['h3tr1.nw', 'h3tr2.nw', 'h3tr3.nw', 'h3tr4.nw', 'h3tr5.nw']),
                ('dirdyvtst/oh3', [
                    'oh3tr1.nw', 'oh3tr2.nw', 'oh3tr3.nw', 'oh3tr4.nw',
                    'oh3tr5.nw'
                ]),
                ('pspw/session1', [
                    'band.nw', 'si4.linear.nw', 'si4.rhombus.nw',
                    'S2-drift.nw', 'diamond.nw', 'silicon.nw', 'S2.nw',
                    'si4.rectangle.nw'
                ]), ('pspw/MgO+Cu', ['pspw_MgO.nw']),
                ('pspw/C2H6', ['C2H6.nw']), ('pspw/Carbene', ['triplet.nw']),
                ('md/dna', ['dna.nw']), ('md/ache', ['mache.nw']),
                ('md/myo', ['myo.nw']), ('md/nak', ['NaK.nw']),
                ('md/nak', ['18c6NaK.nw']), ('md/membrane', ['membrane.nw']),
                ('md/sdm', ['sdm.nw']), ('md/crown', ['crown.nw']),
                ('md/hrc', ['hrc.nw']), ('md/benzene', ['benzene.nw'])
            ]
            self.cfg['tests'] = [(os.path.join(self.examples_dir, d), l)
                                 for (d, l) in examples]
            self.log.info("List of examples to be run as test cases: %s" %
                          self.cfg['tests'])

        try:
            # symlink $HOME/.nwchemrc to local copy of default nwchemrc
            default_nwchemrc = os.path.join(self.installdir, 'data',
                                            'default.nwchemrc')
            home_nwchemrc = os.path.join(os.getenv('HOME'), '.nwchemrc')
            local_nwchemrc = os.path.join(tempfile.gettempdir(),
                                          os.getenv('USER'),
                                          'easybuild_nwchem', '.nwchemrc')

            local_nwchemrc_dir = os.path.dirname(local_nwchemrc)
            if not os.path.exists(local_nwchemrc_dir):
                os.makedirs(local_nwchemrc_dir)

            shutil.copy2(default_nwchemrc, local_nwchemrc)
            symlink_ok = False
            if os.path.exists(home_nwchemrc):
                if not os.path.islink(home_nwchemrc) or not os.path.samefile(
                        home_nwchemrc, local_nwchemrc):
                    self.log.error(
                        "File %s is present, but is not a symlink to %s" %
                        (home_nwchemrc, local_nwchemrc))
                else:
                    symlink_ok = True

            if not symlink_ok:
                os.symlink(local_nwchemrc, home_nwchemrc)

            # run tests, keep track of fail ratio
            cwd = os.getcwd()

            fail = 0.0
            tot = 0.0

            success_regexp = re.compile("Total times\s*cpu:.*wall:.*")

            test_cases_logfn = os.path.join(self.installdir, config.log_path(),
                                            'test_cases.log')
            test_cases_log = open(test_cases_logfn, "w")

            for (testdir, tests) in self.cfg['tests']:

                # run test in a temporary dir
                tmpdir = tempfile.mkdtemp(prefix='nwchem_test_')
                os.chdir(tmpdir)

                # copy all files in test case dir
                for item in os.listdir(testdir):
                    test_file = os.path.join(testdir, item)
                    if os.path.isfile(test_file):
                        self.log.debug("Copying %s to %s" %
                                       (test_file, tmpdir))
                        shutil.copy2(test_file, tmpdir)

                # run tests
                for testx in tests:
                    cmd = "nwchem %s" % testx
                    msg = "Running test '%s' (from %s) in %s..." % (
                        cmd, testdir, tmpdir)
                    self.log.info(msg)
                    test_cases_log.write("\n%s\n" % msg)
                    (out, ec) = run_cmd(cmd,
                                        simple=False,
                                        log_all=False,
                                        log_ok=False,
                                        log_output=True)

                    # check exit code and output
                    if ec:
                        msg = "Test %s failed (exit code: %s)!" % (testx, ec)
                        self.log.warning(msg)
                        test_cases_log.write('FAIL: %s' % msg)
                        fail += 1
                    else:
                        if success_regexp.search(out):
                            msg = "Test %s successful!" % testx
                            self.log.info(msg)
                            test_cases_log.write('SUCCESS: %s' % msg)
                        else:
                            msg = "No 'Total times' found for test %s (but exit code is %s)!" % (
                                testx, ec)
                            self.log.warning(msg)
                            test_cases_log.write('FAIL: %s' % msg)
                            fail += 1

                    test_cases_log.write("\nOUTPUT:\n\n%s\n\n" % out)

                    tot += 1

                # go back
                os.chdir(cwd)
                shutil.rmtree(tmpdir)

            fail_ratio = fail / tot
            fail_pcnt = fail_ratio * 100

            msg = "%d of %d tests failed (%s%%)!" % (fail, tot, fail_pcnt)
            self.log.info(msg)
            test_cases_log.write('\n\nSUMMARY: %s' % msg)

            test_cases_log.close()
            self.log.info("Log for test cases saved at %s" % test_cases_logfn)

            if fail_ratio > self.cfg['max_fail_ratio']:
                max_fail_pcnt = self.cfg['max_fail_ratio'] * 100
                self.log.error(
                    "Over %s%% of test cases failed, assuming broken build." %
                    max_fail_pcnt)

            shutil.rmtree(self.examples_dir)
            shutil.rmtree(local_nwchemrc_dir)

        except OSError, err:
            self.log.error("Failed to run test cases: %s" % err)
Example #18
0
        "The dependencies to be added to the package are: %s",
        pprint.pformat([easyblock.toolchain.as_dict()] +
                       easyblock.cfg.dependencies()))
    depstring = ''
    for dep in deps:
        if dep.get('external_module', False):
            _log.debug("Skipping dep marked as external module: %s",
                       dep['name'])
        else:
            _log.debug("The dep added looks like %s ", dep)
            dep_pkgname = package_naming_scheme.name(dep)
            depstring += " --depends %s" % quote_str(dep_pkgname)

    # Excluding the EasyBuild logs and test reports that might be in the installdir
    exclude_files_glob = [
        os.path.join(log_path(), "*.log"),
        os.path.join(log_path(), "*.md"),
    ]
    # stripping off leading / to match expected glob in fpm
    exclude_files_glob = [
        '--exclude %s' %
        quote_str(os.path.join(easyblock.installdir.lstrip(os.sep), x))
        for x in exclude_files_glob
    ]
    _log.debug("The list of excluded files passed to fpm: %s",
               exclude_files_glob)
    cmdlist = [
        PKG_TOOL_FPM,
        '--workdir',
        workdir,
        '--name',
Example #19
0
    def test_package(self):
        """Test package function."""
        build_options = {
            'package_tool_options': '--foo bar',
            'silent': True,
        }
        init_config(build_options=build_options)

        topdir = os.path.dirname(os.path.abspath(__file__))
        test_easyconfigs = os.path.join(topdir, 'easyconfigs', 'test_ecs')
        ec = EasyConfig(os.path.join(test_easyconfigs, 't', 'toy', 'toy-0.0-gompi-2018a-test.eb'), validate=False)

        mock_fpm(self.test_prefix)

        # import needs to be done here, since test easyblocks are only included later
        from easybuild.easyblocks.toy import EB_toy
        easyblock = EB_toy(ec)

        # build & install first
        easyblock.run_all_steps(False)

        # write a dummy log and report file to make sure they don't get packaged
        logfile = os.path.join(easyblock.installdir, log_path(), "logfile.log")
        write_file(logfile, "I'm a logfile")
        reportfile = os.path.join(easyblock.installdir, log_path(), "report.md")
        write_file(reportfile, "I'm a reportfile")

        # package using default packaging configuration (FPM to build RPM packages)
        pkgdir = package(easyblock)
        pkgfile = os.path.join(pkgdir, 'toy-0.0-gompi-2018a-test-eb-%s.1.rpm' % EASYBUILD_VERSION)

        fpm_output = read_file(os.path.join(self.test_prefix, FPM_OUTPUT_FILE))
        pkgtxt = read_file(pkgfile)

        self.assertTrue(os.path.isfile(pkgfile), "Found %s" % pkgfile)

        # check whether extra packaging options were passed down
        regex = re.compile("^got an unhandled option: --foo bar$", re.M)
        self.assertTrue(regex.search(fpm_output), "Pattern '%s' found in: %s" % (regex.pattern, fpm_output))

        pkgtxt = read_file(pkgfile)
        pkgtxt_regex = re.compile("STARTCONTENTS of installdir %s" % easyblock.installdir)
        self.assertTrue(pkgtxt_regex.search(pkgtxt), "Pattern '%s' found in: %s" % (pkgtxt_regex.pattern, pkgtxt))

        no_logfiles_regex = re.compile(r'STARTCONTENTS.*\.(log|md)$.*ENDCONTENTS', re.DOTALL | re.MULTILINE)
        res = no_logfiles_regex.search(pkgtxt)
        self.assertFalse(res, "Pattern not '%s' found in: %s" % (no_logfiles_regex.pattern, pkgtxt))

        toy_txt = read_file(os.path.join(test_easyconfigs, 't', 'toy', 'toy-0.0-gompi-2018a-test.eb'))
        replace_str = '''description = """Toy C program, 100% toy. Now with `backticks'\n'''
        replace_str += '''and newlines"""'''
        toy_txt = re.sub('description = .*', replace_str, toy_txt)
        toy_file = os.path.join(self.test_prefix, 'toy-test-description.eb')
        write_file(toy_file, toy_txt)

        regex = re.compile(r"""`backticks'""")
        self.assertTrue(regex.search(toy_txt), "Pattern '%s' found in: %s" % (regex.pattern, toy_txt))
        ec_desc = EasyConfig(toy_file, validate=False)
        easyblock_desc = EB_toy(ec_desc)
        easyblock_desc.run_all_steps(False)
        pkgdir = package(easyblock_desc)
        pkgfile = os.path.join(pkgdir, 'toy-0.0-gompi-2018a-test-eb-%s.1.rpm' % EASYBUILD_VERSION)
        self.assertTrue(os.path.isfile(pkgfile))
        pkgtxt = read_file(pkgfile)
        regex_pkg = re.compile(r"""DESCRIPTION:.*`backticks'.*""")
        self.assertTrue(regex_pkg.search(pkgtxt), "Pattern '%s' not found in: %s" % (regex_pkg.pattern, pkgtxt))
        regex_pkg = re.compile(r"""DESCRIPTION:.*\nand newlines""", re.MULTILINE)
        self.assertTrue(regex_pkg.search(pkgtxt), "Pattern '%s' not found in: %s" % (regex_pkg.pattern, pkgtxt))