4 # Copyright (c) 2017 Vojtech Horky
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
11 # - Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # - Redistributions in binary form must reproduce the above copyright
14 # notice, this list of conditions and the following disclaimer in the
15 # documentation and/or other materials provided with the distribution.
16 # - The name of the author may not be used to endorse or promote products
17 # derived from this software without specific prior written permission.
19 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 from hbuild
.scheduler
import Task
, RunCommandException
36 from hbuild
.builders
.helenos
import HelenOSBuildWithHarboursTask
38 class GetTestListTask(Task
):
39 def __init__(self
, root_path
, test_filter
):
40 Task
.__init
__(self
, None)
41 self
.root_path
= os
.path
.abspath(os
.path
.join(root_path
, 'scenarios'))
42 self
.test_filter
= test_filter
44 def get_scenario_list(self
, root
, base
):
49 for name
in os
.listdir(root
):
50 path
= os
.path
.join(root
, name
)
51 if os
.path
.isdir(path
):
52 tmp
= self
.get_scenario_list(path
, base
+ name
+ '/')
55 elif os
.path
.isfile(path
):
56 xxx
, ext
= os
.path
.splitext(path
)
58 tests
.append(base
+ name
)
63 files
= self
.get_scenario_list(self
.root_path
, '')
65 if 'ALL' in self
.test_filter
:
66 self
.test_filter
= files
70 for pat
in self
.test_filter
:
71 if fnmatch
.fnmatch(fn
, pat
):
72 files_filtered
.append(fn
)
75 self
.ctl
.dprint('scenarios files: %s', files_filtered
)
77 'scenarios' : files_filtered
,
78 'scenario_dir': self
.root_path
82 class ScheduleTestsTask(Task
):
83 NEEDED_HARBOUR_PATTERN
= re
.compile('^[ ]*#[ ]*@needs[ ]+(?P<HARBOURS>.*)$')
84 SPLIT_HARBOURS_PATTERN
= re
.compile('\w+')
86 def __init__(self
, scheduler
, extra_builds
, base_path
, extra_tester_options
):
87 self
.scheduler
= scheduler
88 self
.testable_profiles
= [ 'ia32', 'amd64', 'arm32/integratorcp', 'ppc32' ]
89 self
.extra_builds
= extra_builds
90 self
.base_path
= base_path
91 self
.extra_tester_options
= extra_tester_options
92 Task
.__init
__(self
, None)
95 helenos_build_tasks
= self
.ctl
.get_dependency_data('helenos_tasks')
96 scenarios
= self
.ctl
.get_dependency_data('scenarios')
97 scenario_base_path
= self
.ctl
.get_dependency_data('scenario_dir')
98 harbour_tasks
= self
.ctl
.get_dependency_data('harbour_tasks')
100 self
.extra_builds
.set_dependent_tasks(helenos_build_tasks
, harbour_tasks
)
102 profiles_all
= helenos_build_tasks
.keys()
104 for p
in self
.testable_profiles
:
105 if p
in profiles_all
:
109 for scenario
in scenarios
:
110 for profile
in profiles
:
111 scenario_filename
= os
.path
.join(scenario_base_path
, scenario
)
112 dep_harbours
= self
.get_needed_harbours(scenario_filename
)
113 if len(dep_harbours
) > 0:
114 helenos_task
= self
.extra_builds
.build(profile
, dep_harbours
)
115 if helenos_task
is None:
116 # TODO: properly handle the error
119 helenos_task
= helenos_build_tasks
[profile
]
120 scenario_flat
= scenario
.replace('/', '-').replace('.', '-')
121 self
.scheduler
.submit("Testing {} on {}".format(scenario
, profile
),
122 'test-{}-{}'.format(profile
.replace('/', '-'), scenario_flat
),
123 TestRunTask(profile
, scenario
, scenario_filename
,
124 os
.path
.abspath(os
.path
.join(self
.base_path
, 'test-in-vm.py')), self
.extra_tester_options
),
131 def get_needed_harbours(self
, scenario_filename
):
132 with
open(scenario_filename
) as f
:
135 scenario
= yaml
.load(f
)
136 if ('meta' in scenario
) and ('harbours' in scenario
['meta']):
137 res
= scenario
['meta']['harbours']
140 except Exception as ex
:
144 class TestRunTask(Task
):
145 def __init__(self
, profile
, scenario_name
, scenario_full_filename
, test_script_filename
, extra_test_script_options
):
146 self
.profile
= profile
147 self
.scenario_name
= scenario_name
148 self
.scenario
= scenario_full_filename
149 self
.tester
= os
.path
.abspath(test_script_filename
)
150 self
.tester_options
= extra_test_script_options
151 Task
.__init
__(self
, 'test',
153 scenario
=scenario_name
,
154 description
=self
.get_scenario_description(scenario_full_filename
)
157 def get_scenario_description(self
, filename
):
158 with
open(filename
) as f
:
161 scenario
= yaml
.load(f
)
162 if ('meta' in scenario
) and ('name' in scenario
['meta']):
163 return '{}'.format(scenario
['meta']['name'])
164 except Exception as ex
:
169 os_image
= self
.ctl
.get_dependency_data('image')
170 my_dir
= self
.ctl
.get_dependency_data('dir')
173 # FIXME: this is probably not the best location for the files
174 vterm_dump
= os
.path
.join(my_dir
, 'dump.txt')
175 screenshot
= os
.path
.join(my_dir
, 'screenshot.png')
180 '--arch={}'.format(self
.profile
),
181 '--image={}'.format(os_image
),
182 '--vterm-dump={}'.format(vterm_dump
),
183 '--last-screenshot={}'.format(screenshot
),
185 for i
in self
.tester_options
:
187 command
.append('--scenario')
188 command
.append(self
.scenario
)
193 command_res
= self
.ctl
.run_command(command
)
194 except RunCommandException
as ex
:
197 profile_flat
= self
.profile
.replace("/", "-")
198 scenario_flat
= self
.scenario_name
.replace('.yml', '').replace('/', '-').replace('.', '-')
200 self
.ctl
.add_downloadable_file("Last screen", '{}/test-{}-screen.png'.format(profile_flat
, scenario_flat
), screenshot
)
204 self
.ctl
.add_downloadable_file("Terminal dump", '{}/test-{}-vterm.txt'.format(profile_flat
, scenario_flat
), vterm_dump
)
208 if command_exc
is not None: