Use pythonified tester in CI
[ci.git] / vm-test.py
blob4532c35c90cfd27a7c30ba774e4a05953efac4da
1 #!/usr/bin/env python3
4 # Copyright (c) 2018 Vojtech Horky
5 # All rights reserved.
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
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.
32 import argparse
33 import yaml
34 import logging
35 import sys
37 from htest.vm.controller import VMManager
38 from htest.vm.qemu import QemuVMController
39 from htest.tasks import *
41 args = argparse.ArgumentParser(description='HelenOS VM tests')
42 args.add_argument('--headless',
43 dest='headless',
44 default=False,
45 action='store_true',
46 help='Do not show any VM windows.'
48 args.add_argument('--scenario',
49 metavar='FILENAME.yml',
50 dest='scenario',
51 default='scenarios/base/pcut.yml',
52 help='Scenario file'
54 args.add_argument('--arch',
55 metavar='ARCHITECTURE',
56 dest='architecture',
57 required=True,
58 help='Emulated architecture identification.'
60 args.add_argument('--memory',
61 metavar='MB',
62 dest='memory',
63 type=int,
64 required=False,
65 default=256,
66 help='Amount of memory for the virtual machine.'
68 args.add_argument('--image',
69 metavar='FILENAME',
70 dest='boot_image',
71 required=True,
72 help='HelenOS boot image (e.g. ISO file).'
74 args.add_argument('--pass',
75 metavar='OPTION',
76 dest='pass_thru_options',
77 default=[],
78 action='append',
79 help='Extra options to pass through to the emulator'
81 args.add_argument('--vterm-dump',
82 metavar='FILENAME.txt',
83 dest='vterm_dump',
84 default=None,
85 help='Where to store full vterm dump.'
87 args.add_argument('--last-screenshot',
88 metavar='FILENAME.png',
89 dest='last_screenshot',
90 default=None,
91 help='Where to store last screenshot.'
93 args.add_argument('--debug',
94 dest='debug',
95 default=False,
96 action='store_true',
97 help='Print debugging messages'
100 config = args.parse_args()
102 if config.debug:
103 config.logging_level = logging.DEBUG
104 else:
105 config.logging_level = logging.INFO
107 logging.basicConfig(
108 format='[%(asctime)s %(name)-16s %(levelname)7s] %(message)s',
109 level=config.logging_level
112 logger = logging.getLogger('main')
114 with open(config.scenario, 'r') as f:
115 try:
116 scenario = yaml.load(f)
117 except yaml.YAMLError as ex:
118 logger.error(ex)
119 sys.exit(1)
121 if config.memory < 8:
122 logger.error("Specify at least 8MB of memory.")
123 sys.exit(1)
125 controller = None
126 for ctl in [ QemuVMController ]:
127 if ctl.is_supported(config.architecture):
128 controller = ctl
130 if controller is None:
131 logger.error("Unsupported architecture {}.".format(config.architecture))
132 sys.exit(1)
134 vmm = VMManager(controller, config.architecture, config.boot_image, config.memory, config.headless, config.pass_thru_options)
136 scenario_tasks = []
137 for t in scenario['tasks']:
138 task_name = None
139 if type(t) is dict:
140 k = list(set(t.keys()) - set(['name', 'machine']))
141 if len(k) != 1:
142 raise Exception("Unknown task ({})!".format(k))
143 task_name = k[0]
144 elif type(t) is str:
145 task_name = t
146 t = {
147 task_name: {}
149 else:
150 raise Exception("Unknown task!")
151 task_classname = 'ScenarioTask' + task_name.title().replace('-', '_')
152 task_class = globals()[task_classname]
153 task_inst = task_class(t[task_name])
154 if not ('machine' in t):
155 t['machine'] = None
156 machine = vmm.get(t['machine'])
157 if machine is None:
158 if t['machine'] is None:
159 t['machine'] = 'default'
160 logger.debug("Creating new machine {}.".format(t['machine']))
161 machine = vmm.create(t['machine'])
162 task_inst.set_machine(machine)
163 scenario_tasks.append(task_inst)
165 exit_code = 0
166 try:
167 for t in scenario_tasks:
168 t.run()
169 except Exception as ex:
170 print(ex)
171 exit_code = 1
173 vmm.terminate(config.vterm_dump, config.last_screenshot)
174 sys.exit(exit_code)