4 # Copyright (c) 2018 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.
37 from htest
.vm
.controller
import VMManager
38 from htest
.vm
.qemu
import QemuVMController
39 from htest
.vm
.msim
import MsimVMController
40 from htest
.tasks
import *
42 args
= argparse
.ArgumentParser(
43 description
='Testing of HelenOS in VM',
44 formatter_class
=argparse
.RawDescriptionHelpFormatter
,
46 Typical invocation will use the following arguments:
48 --scenario scenario.yml
49 --arch amd64 # ia32, ppc32 etc.
50 --vterm-dump dump.txt # all text from main vterm
51 --last-screenshot shot.png # last VM screen
54 args
.add_argument('--headless',
58 help='Do not show any VM windows.'
60 args
.add_argument('--scenario',
61 metavar
='FILENAME.yml',
66 args
.add_argument('--arch',
67 metavar
='ARCHITECTURE',
70 help='Emulated architecture identification.'
72 args
.add_argument('--memory',
78 help='Amount of memory for the virtual machine.'
80 args
.add_argument('--image',
84 help='HelenOS boot image (e.g. ISO file).'
86 args
.add_argument('--disk',
91 help='Disk image (e.g. hdisk.img).'
93 args
.add_argument('--vm-config',
98 help='VM emulator configuration (e.g. msim.conf)'
100 args
.add_argument('--pass',
102 dest
='pass_thru_options',
105 help='Extra options to pass through to the emulator'
107 args
.add_argument('--vterm-dump',
108 metavar
='FILENAME.txt',
111 help='Where to store full vterm dump.'
113 args
.add_argument('--last-screenshot',
114 metavar
='FILENAME.png',
115 dest
='last_screenshot',
117 help='Where to store last screenshot.'
119 args
.add_argument('--debug',
123 help='Print debugging messages'
126 config
= args
.parse_args()
129 config
.logging_level
= logging
.DEBUG
131 config
.logging_level
= logging
.INFO
134 format
='[%(asctime)s %(name)-16s %(levelname)7s] %(message)s',
135 level
=config
.logging_level
138 logger
= logging
.getLogger('main')
140 with
open(config
.scenario
, 'r') as f
:
142 scenario
= yaml
.load(f
)
143 except yaml
.YAMLError
as ex
:
147 if config
.memory
< 8:
148 logger
.error("Specify at least 8MB of memory.")
152 for ctl
in [ QemuVMController
, MsimVMController
]:
153 if ctl
.is_supported(config
.architecture
):
156 if controller
is None:
157 logger
.error("Unsupported architecture {}.".format(config
.architecture
))
160 vmm
= VMManager(controller
, config
.architecture
, config
.vm_config
, config
.boot_image
, config
.disk_image
, config
.memory
, config
.headless
, config
.pass_thru_options
)
163 for t
in scenario
['tasks']:
166 k
= list(set(t
.keys()) - set(['name', 'machine']))
168 raise Exception("Unknown task ({})!".format(k
))
176 raise Exception("Unknown task!")
177 task_classname
= 'ScenarioTask' + task_name
.title().replace('-', '_')
178 task_class
= globals()[task_classname
]
179 task_inst
= task_class(t
[task_name
])
180 if not ('machine' in t
):
182 machine
= vmm
.get(t
['machine'])
184 if t
['machine'] is None:
185 t
['machine'] = 'default'
186 logger
.debug("Creating new machine {}.".format(t
['machine']))
187 machine
= vmm
.create(t
['machine'])
188 task_inst
.set_machine(machine
)
189 scenario_tasks
.append(task_inst
)
193 for t
in scenario_tasks
:
195 print("Scenario passed.")
196 except Exception as ex
:
197 logger
.exception("Scenario aborted: {}".format(ex
))
198 print("Scenario aborted: {}".format(ex
))
201 vmm
.terminate(config
.vterm_dump
, config
.last_screenshot
)