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.
33 from htest
.utils
import retries
37 Base class for individual tasks that are executed in a scenario.
40 def __init__(self
, name
):
42 Set @name to the task name (call from subclass).
47 self
.fail_message
= ''
48 self
.logger
= logging
.getLogger(name
)
50 def check_required_argument(self
, args
, name
):
52 To be used by subclasses to check that arguments
56 raise Exception("Required argument {} missing.".format(name
))
58 def is_vm_launcher(self
):
60 Whether this task starts a new VM.
67 def set_machine(self
, machine
):
69 Set machine responsible for executing this task.
71 self
.machine
= machine
75 Actually execute this task.
79 class ScenarioTaskBoot(ScenarioTask
):
81 Brings the machine up.
83 def __init__(self
, args
):
84 ScenarioTask
.__init
__(self
, 'boot')
87 def is_vm_launcher(self
):
93 class ScenarioTaskCommand(ScenarioTask
):
95 Run a command in vterm.
98 def __init__(self
, args
):
99 ScenarioTask
.__init
__(self
, 'command')
100 if type(args
) is str:
101 args
= { 'args': args
}
102 self
.check_required_argument(args
, 'args')
103 self
.command
= args
['args']
106 def _grep(self
, text
, lines
):
108 if l
.find(text
) != -1:
113 self
.logger
.info("Typing '{}' into {}.".format(self
.command
, self
.machine
.name
))
115 self
.machine
.type(self
.command
)
116 self
.machine
.type('\n')
118 for xxx
in retries(timeout
=60, interval
=2, name
="vterm-run", message
="Failed to run command"):
119 lines
= self
.machine
.capture_vterm()
120 if 'negassert' in self
.args
:
121 if self
._grep
(self
.args
['negassert'], lines
):
122 raise Exception('Found forbidden text {} ...'.format(self
.args
['negassert']))
123 if 'assert' in self
.args
:
124 if self
._grep
(self
.args
['assert'], lines
):
126 if self
._grep
('Cannot spawn', lines
) or self
._grep
('Command failed', lines
):
127 raise Exception('Failed to run command')
128 if self
._grep
('# _', lines
):
129 if 'assert' in self
.args
:
130 raise Exception('Missing expected text {} ...'.format(self
.args
['assert']))
132 self
.logger
.info("Command '{}' done.".format(self
.command
))
134 class ScenarioTaskCls(ScenarioTask
):
139 def __init__(self
, args
):
140 ScenarioTask
.__init
__(self
, 'vterm-cls')
143 self
.logger
.info("Clearing the screen.")
146 self
.machine
.type('\n')