Skip to content

Commit 6d94d39

Browse files
committed
add test for installing extensions in parallel
1 parent 3e186fb commit 6d94d39

File tree

3 files changed

+127
-16
lines changed

3 files changed

+127
-16
lines changed

test/framework/sandbox/easybuild/easyblocks/generic/toy_extension.py

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030

3131
from easybuild.framework.easyconfig import CUSTOM
3232
from easybuild.framework.extensioneasyblock import ExtensionEasyBlock
33-
from easybuild.easyblocks.toy import EB_toy
33+
from easybuild.easyblocks.toy import EB_toy, compose_toy_build_cmd
34+
from easybuild.tools.build_log import EasyBuildError
3435
from easybuild.tools.run import run_cmd
3536

3637

@@ -45,20 +46,55 @@ def extra_options():
4546
}
4647
return ExtensionEasyBlock.extra_options(extra_vars=extra_vars)
4748

48-
def run(self):
49-
"""Build toy extension."""
49+
@property
50+
def required_deps(self):
51+
"""Return list of required dependencies for this extension."""
52+
deps = {
53+
'bar': [],
54+
'barbar': ['bar'],
55+
'ls': [],
56+
}
57+
if self.name in deps:
58+
return deps[self.name]
59+
else:
60+
raise EasyBuildError("Dependencies for %s are unknown!", self.name)
61+
62+
def run(self, *args, **kwargs):
63+
"""
64+
Install toy extension.
65+
"""
5066
if self.src:
51-
super(Toy_Extension, self).run(unpack_src=True)
52-
EB_toy.configure_step(self.master, name=self.name)
5367
EB_toy.build_step(self.master, name=self.name, buildopts=self.cfg['buildopts'])
5468

5569
if self.cfg['toy_ext_param']:
5670
run_cmd(self.cfg['toy_ext_param'])
5771

58-
EB_toy.install_step(self.master, name=self.name)
59-
6072
return self.module_generator.set_environment('TOY_EXT_%s' % self.name.upper(), self.name)
6173

74+
def prerun(self):
75+
"""
76+
Prepare installation of toy extension.
77+
"""
78+
if self.src:
79+
super(Toy_Extension, self).run(unpack_src=True)
80+
EB_toy.configure_step(self.master, name=self.name)
81+
82+
def run_async(self):
83+
"""
84+
Install toy extension asynchronously.
85+
"""
86+
if self.src:
87+
cmd = compose_toy_build_cmd(self.cfg, self.name, self.cfg['prebuildopts'], self.cfg['buildopts'])
88+
self.async_cmd_start(cmd)
89+
else:
90+
self.async_cmd_info = False
91+
92+
def postrun(self):
93+
"""
94+
Wrap up installation of toy extension.
95+
"""
96+
EB_toy.install_step(self.master, name=self.name)
97+
6298
def sanity_check_step(self, *args, **kwargs):
6399
"""Custom sanity check for toy extensions."""
64100
self.log.info("Loaded modules: %s", self.modules_tool.list())

test/framework/sandbox/easybuild/easyblocks/t/toy.py

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,19 @@
4141
from easybuild.tools.run import run_cmd
4242

4343

44+
def compose_toy_build_cmd(cfg, name, prebuildopts, buildopts):
45+
"""
46+
Compose command to build toy.
47+
"""
48+
49+
cmd = "%(prebuildopts)s gcc %(name)s.c -o %(name)s %(buildopts)s" % {
50+
'name': name,
51+
'prebuildopts': prebuildopts,
52+
'buildopts': buildopts,
53+
}
54+
return cmd
55+
56+
4457
class EB_toy(ExtensionEasyBlock):
4558
"""Support for building/installing toy."""
4659

@@ -92,17 +105,13 @@ def configure_step(self, name=None):
92105

93106
def build_step(self, name=None, buildopts=None):
94107
"""Build toy."""
95-
96108
if buildopts is None:
97109
buildopts = self.cfg['buildopts']
98-
99110
if name is None:
100111
name = self.name
101-
run_cmd('%(prebuildopts)s gcc %(name)s.c -o %(name)s %(buildopts)s' % {
102-
'name': name,
103-
'prebuildopts': self.cfg['prebuildopts'],
104-
'buildopts': buildopts,
105-
})
112+
113+
cmd = compose_toy_build_cmd(self.cfg, name, self.cfg['prebuildopts'], buildopts)
114+
run_cmd(cmd)
106115

107116
def install_step(self, name=None):
108117
"""Install toy."""
@@ -118,11 +127,38 @@ def install_step(self, name=None):
118127
mkdir(libdir, parents=True)
119128
write_file(os.path.join(libdir, 'lib%s.a' % name), name.upper())
120129

121-
def run(self):
122-
"""Install toy as extension."""
130+
@property
131+
def required_deps(self):
132+
"""Return list of required dependencies for this extension."""
133+
if self.name == 'toy':
134+
return ['bar', 'barbar']
135+
else:
136+
raise EasyBuildError("Dependencies for %s are unknown!", self.name)
137+
138+
def prerun(self):
139+
"""
140+
Prepare installation of toy as extension.
141+
"""
123142
super(EB_toy, self).run(unpack_src=True)
124143
self.configure_step()
144+
145+
def run(self):
146+
"""
147+
Install toy as extension.
148+
"""
125149
self.build_step()
150+
151+
def run_async(self):
152+
"""
153+
Asynchronous installation of toy as extension.
154+
"""
155+
cmd = compose_toy_build_cmd(self.cfg, self.name, self.cfg['prebuildopts'], self.cfg['buildopts'])
156+
self.async_cmd_start(cmd)
157+
158+
def postrun(self):
159+
"""
160+
Wrap up installation of toy as extension.
161+
"""
126162
self.install_step()
127163

128164
def make_module_step(self, fake=False):

test/framework/toy_build.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,6 +1777,45 @@ def test_module_only_extensions(self):
17771777
self.eb_main([test_ec, '--module-only', '--force'], do_build=True, raise_error=True)
17781778
self.assertTrue(os.path.exists(toy_mod))
17791779

1780+
def test_toy_exts_parallel(self):
1781+
"""
1782+
Test parallel installation of extensions (--parallel-extensions-install)
1783+
"""
1784+
topdir = os.path.abspath(os.path.dirname(__file__))
1785+
toy_ec = os.path.join(topdir, 'easyconfigs', 'test_ecs', 't', 'toy', 'toy-0.0.eb')
1786+
1787+
toy_mod = os.path.join(self.test_installpath, 'modules', 'all', 'toy', '0.0')
1788+
if get_module_syntax() == 'Lua':
1789+
toy_mod += '.lua'
1790+
1791+
test_ec = os.path.join(self.test_prefix, 'test.eb')
1792+
test_ec_txt = read_file(toy_ec)
1793+
test_ec_txt += '\n' + '\n'.join([
1794+
"exts_list = [",
1795+
" ('ls'),",
1796+
" ('bar', '0.0'),",
1797+
" ('barbar', '0.0', {",
1798+
" 'start_dir': 'src',",
1799+
" }),",
1800+
" ('toy', '0.0'),",
1801+
"]",
1802+
"sanity_check_commands = ['barbar', 'toy']",
1803+
"sanity_check_paths = {'files': ['bin/barbar', 'bin/toy'], 'dirs': ['bin']}",
1804+
])
1805+
write_file(test_ec, test_ec_txt)
1806+
1807+
args = ['--parallel-extensions-install', '--experimental', '--force']
1808+
stdout, stderr = self.run_test_toy_build_with_output(ec_file=test_ec, extra_args=args)
1809+
self.assertEqual(stderr, '')
1810+
expected_stdout = '\n'.join([
1811+
"== 0 out of 4 extensions installed (2 queued, 2 running: ls, bar)",
1812+
"== 2 out of 4 extensions installed (1 queued, 1 running: barbar)",
1813+
"== 3 out of 4 extensions installed (0 queued, 1 running: toy)",
1814+
"== 4 out of 4 extensions installed (0 queued, 0 running: )",
1815+
'',
1816+
])
1817+
self.assertEqual(stdout, expected_stdout)
1818+
17801819
def test_backup_modules(self):
17811820
"""Test use of backing up of modules with --module-only."""
17821821

0 commit comments

Comments
 (0)