diff --git a/.gitignore b/.gitignore index 4de26c09e0ab6546337b881a5b572779624b1dd4..f3e467d16480a0ed37f4e242a10b0254a8a40537 100755 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,6 @@ pip-log.txt #Mr Developer .mr.developer.cfg + +#temp files +*~ diff --git a/lettuce/__init__.py b/lettuce/__init__.py deleted file mode 100644 index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000 --- a/lettuce/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/lettuce/feat2py.py b/lettuce/feat2py.py new file mode 100755 index 0000000000000000000000000000000000000000..de44f6ef9d4769b027616f88d364e04b1b19a237 --- /dev/null +++ b/lettuce/feat2py.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2019-2019 Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import sys +import os +import re + + +def load_steps(): + #@step('Client requests option (\d+).') + steps = [] + funcs = set() + for fname in os.listdir('features'): + if not fname.endswith('.py'): + continue + path = os.path.join('features', fname) + with open(path) as f: + regex = None + for l in f: + l = l.strip() + + if regex: + func = l.split(' ')[1].split('(')[0] + if func in funcs: + raise Exception("Func '%s' from '%s' already present" % (func, fname)) + else: + funcs.add(func) + steps.append((regex, fname, func)) + regex = None + + if not l.startswith('@step('): + continue + regex = l[7:-2] + + return steps + + +def _find_matching_func(steps, line): + if 'Server MUST NOT respond' in line: + print(' %r' % line) + for regex, fname, func in steps: + if 'Server MUST NOT respond' in line: + print(' %r' % regex) + m = re.search(regex, line) + if m: + print('match %s' % str(m.groups())) + print(' %r' % line) + print(' %r' % regex) + return fname, func, m.groups(), regex + raise Exception("no match for '%s'" % line) + + +def parse_feature_file(feature_file_path, steps): + scenarios_list = [] + used_modules = set() + + scenario = None + with open(feature_file_path) as f: + for lineno, line in enumerate(f): + try: + line = line.rstrip() + sline = line.strip() + + if line.startswith('Feature:'): + feature = line[9:] + continue + + if sline.startswith('@'): + sline = sline.replace('@', '') + tags = sline.split(' ') + scenario = None + continue + + if sline.startswith('Scenario:'): + scen_name = sline[10:] + scenario = dict(name=scen_name, tags=tags, commands=[]) + scenarios_list.append(scenario) + continue + + if scenario: + if sline.startswith('#'): + scenario['commands'].append(('comment', sline[1:].strip())) + continue + + if sline == '': + scenario['commands'].append(('empty-line', '')) + continue + + step = _find_matching_func(steps, sline) + used_modules.add(step[0]) + cmd = (step, sline) + scenario['commands'].append(cmd) + except: + print("problem in line %s: '%s'" % (lineno + 1, line)) + raise + + return feature, scenarios_list, used_modules + + +def generate_py_file(feature, scenarios_list, used_modules, py_file_path): + with open(py_file_path, 'w') as f: + f.write('"""%s"""\n' % feature) + f.write("\n\n") + + f.write("import sys\n") + f.write("if 'features' not in sys.path:\n") + f.write(" sys.path.append('features')\n") + f.write("\n") + f.write("import lettuce\n") + f.write("\n") + + for mod in used_modules: + mod = mod.replace('.py', '') + f.write("import %s\n" % mod) + f.write("\n\n") + + #f.write("FEATURE = '%s'\n" % feature) + #f.write("\n\n") + + for scen in scenarios_list: + + f.write("@lettuce.mark.py_test\n") + for tag in scen['tags']: + f.write("@lettuce.mark.%s\n" % tag) + + name = scen['name'] + name = name.replace('.', '_') + name = name.replace('-', '_') + name = 'test_' + name + f.write("def %s(step):\n" % name) + f.write(' """new-%s"""\n' % scen['name']) + + for step, line in scen['commands']: + if step == 'comment': + f.write(' # %s\n' % line) + continue + + if step == 'empty-line': + f.write('\n') + continue + + #f.write(' # %s\n' % line) # original line in comment + mod = step[0].replace('.py', '') + func = step[1] + args = step[2] + args = ['None' if a is None else "'%s'" % a.replace("'", "\\'") for a in args] + args2 = ", ".join(args) + if args2: + args2 = ', ' + args2 + + new_line = ' %s.%s(step%s)\n' % (mod, func, args2) + if len(new_line) < 100: + f.write(new_line) + continue + + new_line = ' %s.%s(step,\n' % (mod, func) + f.write(new_line) + + spaces_num = len(new_line) - 6 + args_txt = "" + for arg in args: + args_txt += " " * spaces_num + args_txt += "%s,\n" % arg + args_txt = args_txt[:-2] + ')\n' + f.write(args_txt) + + f.write("\n\n") + + +def main(feature_file_path): + print("Converting file %s." % feature_file_path) + + steps = load_steps() + print("Loaded %s step definitions." % len(steps)) + #for s in steps: + # print(s) + + feature, scenarios_list, used_modules = parse_feature_file(feature_file_path, steps) + + if feature_file_path.endswith('/logging.feature'): + feature_file_path = feature_file_path.replace('/logging.feature', '/kea_logging.feature') + + py_file_path = feature_file_path.replace('.feature', '').replace('.', '_') + '.py' + + generate_py_file(feature, scenarios_list, used_modules, py_file_path) + + print('Feature: %s' % feature) + for idx, scen in enumerate(scenarios_list): + print('%s. Scenario: %s' % (idx, scen['name'])) + print(' Tags: %s' % scen['tags']) + print(' Commands:') + for cmd in scen['commands']: + print(' %s' % str(cmd)) + print('') + + + +if __name__ == '__main__': + main(sys.argv[1]) diff --git a/lettuce/features/config.py b/lettuce/features/config.py index 5b4b1b31d8088b4a0a58a654229542d46e5873ad..431cc9d3ccc7be3d17e9fb77c5250a638a16ede4 100755 --- a/lettuce/features/config.py +++ b/lettuce/features/config.py @@ -34,7 +34,7 @@ def stop_a_named_process(step, process_name): world.processes.stop_process(process_name) @step('wait for (new )?(\w+) stderr message (\w+)(?: not (\w+))?') -def wait_for_message(step, new, process_name, message, not_message): +def wait_for_err_message(step, new, process_name, message, not_message): """ Block until the given message is printed to the given process's stderr output. @@ -54,7 +54,7 @@ def wait_for_message(step, new, process_name, message, not_message): assert found != not_message, line @step('wait for (new )?(\w+) stdout message (\w+)(?: not (\w+))?') -def wait_for_message(step, process_name, message, not_message): +def wait_for_out_message(step, process_name, message, not_message): """ Block until the given message is printed to the given process's stdout output. diff --git a/lettuce/features/logging_facility.py b/lettuce/features/logging_facility.py index 840214dbac05b0f575769e36c8ecad7defef9f4f..c4b2e9bd1768a58a204e8e137f410bae2f299da9 100644 --- a/lettuce/features/logging_facility.py +++ b/lettuce/features/logging_facility.py @@ -19,15 +19,17 @@ def logger_initialize(loglevel): """ Initialize logger instance common to the framework """ - # Get the instance of the common (named) logger - logger = get_common_logger() + # Get the instance of the root logger to set level for forge and 3rd party libs. + logger = logging.getLogger('') logger_handler = logging.StreamHandler() + # Parse the logging level specified as string (most likely from the config file) numeric_level = getattr(logging, loglevel.upper(), None) if not isinstance(numeric_level, int): raise ValueError('Invalid log level: %s' % loglevel) logger.setLevel(numeric_level) logger.addHandler(logger_handler) + # This is the only message that is logged using the 'print' function because we # always want to have this message printed. Further log messages should go through # the logger. @@ -39,4 +41,3 @@ def get_common_logger(): Returns instance of the common logger """ return logging.getLogger('forge-main-logger') - diff --git a/lettuce/features/protosupport/multi_protocol_functions.py b/lettuce/features/protosupport/multi_protocol_functions.py index 7ab16a4fb6fac02eb71c2cd246579a06148ceaf3..41c179cbfd4e63bbd4f1d758d3f185e0819f3f0a 100644 --- a/lettuce/features/protosupport/multi_protocol_functions.py +++ b/lettuce/features/protosupport/multi_protocol_functions.py @@ -36,7 +36,7 @@ def forge_sleep(time, time_units): def test_pause(): """ - Pause the test for any reason. Press any key to continue. + Pause the test for any reason. Press any key to continue. """ def getch(): import tty @@ -62,9 +62,9 @@ def copy_file_from_server(step, remote_path): def send_file_to_server(step, local_path, remote_path): """ Send file to remote server via ssh. Address/login/password from init_all - Two paths required. + Two paths required. Local - relative to lettuce directory - Remote - absolute + Remote - absolute """ fabric_send_file(local_path, remote_path) @@ -97,9 +97,9 @@ def compare_file(step, local_path): """ if not os.path.exists(local_path): assert False, 'No local file %s' % local_path - + outcome = open(world.cfg["dir_name"] + '/file_compare', 'w') - + # first remove all commented and blank lines of both files downloaded_stripped = strip_file(world.cfg["dir_name"] + '/downloaded_file') local_stripped = strip_file(local_path) @@ -114,10 +114,10 @@ def compare_file(step, local_path): line_number += 1 if error_flag: remove_local_file(world.cfg["dir_name"] + '/file_compare') - + assert error_flag, 'Downloaded file is NOT the same as local. Check %s/file_compare for details'\ % world.cfg["dir_name"] - + if len(downloaded_stripped) != len(local_stripped): assert len(downloaded_stripped) > len(local_stripped), 'Downloaded file is part of a local file.' assert len(downloaded_stripped) < len(local_stripped), 'Local file is a part of a downlaoded life.' @@ -138,16 +138,16 @@ def file_includes_line(step, condition, line): def add_variable(variable_name, variable_val, val_type): """ - Define variable and add it to temporary list or to init_all.py file. + Define variable and add it to temporary list or to init_all.py file. """ import re assert not bool(re.compile('[^A-Z^0-9^_] + ').search(variable_name)),\ "Variable name contain invalid characters (Allowed are only capital letters, numbers and sign '_')." - + if not val_type: # temporary if variable_name not in world.define: - tmp = variable_val if variable_val.isdigit() else variable_val + tmp = variable_val if variable_val.isdigit() else variable_val world.define.append([variable_name, tmp]) else: world.define[variable_name] = variable_val @@ -333,14 +333,16 @@ def send_through_socket_server_site(socket_path, command, destination_address=wo command_file.write(command) except: command_file.close() - command_file = open(world.cfg["dir_name"] + '/command_file', 'wb') + command_file = open(world.cfg["dir_name"] + '/command_file', 'wb') # TODO: why 'w' / 'wb' command_file.write(command) command_file.close() fabric_send_file(world.cfg["dir_name"] + '/command_file', 'command_file', destination_host=destination_address) world.control_channel = fabric_sudo_command('socat UNIX:' + socket_path + ' - 0: - options += [("param_req_list", str(world.prl))] + if conf.version == '2.2.0-dev': + options += [("param_req_list", str(world.prl))] + else: + options += [("param_req_list", [ord(o) for o in world.prl])] # else: # assert False, "No PRL defined" @@ -63,19 +67,19 @@ def client_send_msg(step, msgname, iface, addr): # msg code: 1 # world.cfg["values"]["broadcastBit"] = True msg = build_msg([("message-type", "discover")] + options) - + elif msgname == "REQUEST": # msg code: 3 msg = build_msg([("message-type", "request")] + options) - + elif msgname == "DECLINE": # msg code: 4 msg = build_msg([("message-type", "decline")] + options) - + elif msgname == "RELEASE": # msg code: 7 msg = build_msg([("message-type", "release")] + options) - + elif msgname == "INFORM": # msg code: 8 msg = build_msg([("message-type", "inform")] + options) @@ -160,7 +164,7 @@ def client_does_include(step, opt_type, value): def response_check_content(step, expect, data_type, expected): - + if data_type == 'yiaddr': received = world.srvmsg[0].yiaddr elif data_type == 'ciaddr': @@ -179,10 +183,10 @@ def response_check_content(step, expect, data_type, expected): received = world.srvmsg[0].sname.replace('\x00', '') elif data_type == 'file': received = world.srvmsg[0].file.replace('\x00', '') - + else: assert False, "Value %s is not supported" % data_type - + # because we are using function to parse full option not just value # I did little hack, added 'value:' as option code, and changed assertion message outcome, received = test_option(0, ['value:', received], expected) @@ -209,9 +213,9 @@ def client_save_option(step, opt_name, count=0): def client_copy_option(step, opt_name): opt_code = world.kea_options4.get(opt_name) - + assert opt_name in world.kea_options4, "Unsupported option name " + opt_name - + received = get_option(world.srvmsg[0], opt_code) world.cliopts.append(received) @@ -236,7 +240,7 @@ def build_msg(opts): hw = convert_MAC("0a:00:27:00:00:00") tmp_hw = None - # we need to choose if we want to use chaddr, or client id. + # we need to choose if we want to use chaddr, or client id. # also we can include both: client_id and chaddr if world.cfg["values"]["chaddr"] is None or world.cfg["values"]["chaddr"] == "default": tmp_hw = hw @@ -281,7 +285,7 @@ def build_msg(opts): def get_msg_type(msg): - + msg_types = {1: "DISCOVER", 2: "OFFER", 3: "REQUEST", @@ -294,15 +298,15 @@ def get_msg_type(msg): # option 53 it's message type opt = get_option(msg, 53) - # BOOTP_REPLYs have no message type + # BOOTP_REPLYs have no message type if opt is None: return "BOOTP_REPLY" - + # opt[1] it's value of message-type option for msg_code in msg_types.keys(): if opt[1] == msg_code: return msg_types[msg_code] - + return "UNKNOWN-TYPE" @@ -363,7 +367,7 @@ def get_option(msg, opt_code): # if there's one we're looking for world.opts = [] opt_name = DHCPOptions[int(opt_code)] - # dhcpv4 implementation in Scapy is a mess. The options array contains mix of + # dhcpv4 implementation in Scapy is a mess. The options array contains mix of # strings, IPField, ByteEnumField and who knows what else. In each case the # values are accessed differently if isinstance(opt_name, Field): @@ -417,7 +421,7 @@ def response_check_include_option(step, expected, opt_code): def response_check_option_content(opt_code, expect, data_type, expected): # expect == None when we want that content and NOT when we dont want! that's messy correct that! assert len(world.srvmsg) != 0, "No response received." - + opt_code = int(opt_code) received = get_option(world.srvmsg[0], opt_code) diff --git a/lettuce/features/protosupport/v6/srv_msg.py b/lettuce/features/protosupport/v6/srv_msg.py index b3ce9db8ee5c1640ee514964306699f7b2de2245..1d832ca35410577069c2dc6e83e7629f05749a80 100644 --- a/lettuce/features/protosupport/v6/srv_msg.py +++ b/lettuce/features/protosupport/v6/srv_msg.py @@ -19,6 +19,8 @@ # This file contains a number of common steps that are general and may be used # By a lot of feature files. # +import random + from cookielib import debug from features.logging_facility import get_common_logger from lettuce.registry import world diff --git a/lettuce/features/references.py b/lettuce/features/references.py index 507bbc133b81775c79d5d3c78e3eaa32c1721e4d..c647033e86ea4bc362efd1e5fa588dae9229532a 100755 --- a/lettuce/features/references.py +++ b/lettuce/features/references.py @@ -29,5 +29,5 @@ def references_check(step, references): @step('Tags: (\S+)') -def references_check(step, tags): +def tags_check(step, tags): assert len(tags), "Tags cannot be empty." diff --git a/lettuce/features/softwaresupport/kea6_server/mysql_reservation.py b/lettuce/features/softwaresupport/kea6_server/mysql_reservation.py index 4d6bf54707c73495e3322a1c4caa7a5ad548d1bd..de3026d6aa8066e7e0fd82be636b856533fba5a2 100644 --- a/lettuce/features/softwaresupport/kea6_server/mysql_reservation.py +++ b/lettuce/features/softwaresupport/kea6_server/mysql_reservation.py @@ -14,6 +14,8 @@ # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # Author: Wlodzimierz Wencel +import os + from lettuce.registry import world from softwaresupport.multi_server_functions import fabric_run_command, fabric_send_file,\ diff --git a/lettuce/features/softwaresupport/kea6_server/pgsql_reservation.py b/lettuce/features/softwaresupport/kea6_server/pgsql_reservation.py index b3ca26e563f17219b543ae4d822f948d526fdc7e..2f7380e0355fb6bcb8622f009bb3ad9b6d5780e5 100644 --- a/lettuce/features/softwaresupport/kea6_server/pgsql_reservation.py +++ b/lettuce/features/softwaresupport/kea6_server/pgsql_reservation.py @@ -14,6 +14,8 @@ # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # Author: Wlodzimierz Wencel +import os + from lettuce.registry import world from softwaresupport.multi_server_functions import fabric_run_command, fabric_send_file,\ diff --git a/lettuce/features/srv_control.py b/lettuce/features/srv_control.py index 14754a7dce13d8a1d553aa92334be49d3bab5e22..fb8d3f16f5442ce225bf1a8d95a767a0342d40a7 100644 --- a/lettuce/features/srv_control.py +++ b/lettuce/features/srv_control.py @@ -154,7 +154,7 @@ def config_srv_subnet(step, subnet, pool): @step('Server is configured on interface (\S+) and address (\S+) with (\S+) subnet with (\S+) pool.') -def config_srv_subnet(step, interface, address, subnet, pool): +def config_srv_subnet_with_iface(step, interface, address, subnet, pool): """ Adds server configuration with specified subnet and pool. subnet may define specific subnet or use the word "default" @@ -436,7 +436,7 @@ def add_parameter_to_hook(step, hook_no, parameter_name, parameter_value): @step('Add High-Availability hook library located (\S+).') -def add_parameter_to_hook(step, lib_location): +def add_ha_hook(step, lib_location): lib_location = test_define_value(lib_location)[0] dhcp.ha_add_parameter_to_hook("lib", lib_location) @@ -445,7 +445,7 @@ def add_parameter_to_hook(step, lib_location): @step('To HA hook configuration add (\S+) with value: (.+)') -def add_parameter_to_hook(step, parameter_name, parameter_value): +def add_parameter_to_ha_hook(step, parameter_name, parameter_value): parameter_name, parameter_value = test_define_value(parameter_name, parameter_value) dhcp.ha_add_parameter_to_hook(parameter_name, parameter_value) @@ -579,7 +579,7 @@ def option_db_record_reservation(step, reserved_option_code, reserved_option_val @step('Dump all the reservation entries from (\S+) database.') -def upload_db_reservation(step, db_type): +def dump_db_reservation(step, db_type): if db_type == 'MySQL': mysql_reservation.clear_all_reservations() elif db_type == 'PostgreSQL': @@ -667,7 +667,7 @@ def set_conf_parameter_shared_subnet(step, parameter_name, value, subnet_id): ##subnet options @step('Reserve (\S+) (\S+) in subnet (\d+) for host uniquely identified by (\S+) (\S+).') -def host_reservation(step, reservation_type, reserved_value, subnet, unique_host_value_type, unique_host_value): +def host_reservation_in_subnet(step, reservation_type, reserved_value, subnet, unique_host_value_type, unique_host_value): """ Ability to configure simple host reservations in subnet. """ @@ -686,7 +686,7 @@ def host_reservation(step, reservation_type, reserved_value, subnet, unique_host @step('For host reservation entry no. (\d+) in subnet (\d+) add (\S+) with value (\S+).') -def host_reservation(step, reservation_number, subnet, reservation_type, reserved_value): +def host_reservation_in_subnet_add_value(step, reservation_number, subnet, reservation_type, reserved_value): """ Ability to configure simple host reservations in subnet. """ @@ -698,7 +698,7 @@ def host_reservation(step, reservation_number, subnet, reservation_type, reserve @step('Time (\S+) in subnet (\d+) is configured with value (\d+).') -def set_time(step, which_time, subnet, value): +def set_time_in_subnet(step, which_time, subnet, value): """ Change values of T1, T2, preffered lifetime and valid lifetime. """ @@ -729,7 +729,7 @@ def config_srv(step, option_name, subnet, option_value): @step('Server is configured with (\S+) option in subnet (\d+) and pool (\d+) with value (\S+).') -def config_srv(step, option_name, subnet, pool, option_value): +def config_srv_pool(step, option_name, subnet, pool, option_value): """ """ # dhcp.prepare_cfg_add_option_subnet(step, option_name, subnet, option_value) @@ -739,7 +739,7 @@ def config_srv(step, option_name, subnet, pool, option_value): @step('On space (\S+) server is configured with (\S+) option in subnet (\d+) with value (\S+).') -def config_srv(step, space, option_name, subnet, option_value): +def config_srv_on_space(step, space, option_name, subnet, option_value): """ Prepare server configuration with the specified option. option_name name of the option, e.g. dns-servers (number may be used here) @@ -757,7 +757,7 @@ def config_client_classification(step, subnet, option_value): @step('Server is configured with require-client-classification option in subnet (\d+) with name (\S+).') -def config_client_classification(step, subnet, option_value): +def config_require_client_classification(step, subnet, option_value): """ """ dhcp.config_require_client_classification(step, subnet, option_value) @@ -844,7 +844,7 @@ def build_and_send_config_files(step, connection_type, configuration_type): @step('Send server configuration using (\S+) and (\S+) and destination address (\S+).') -def build_and_send_config_files(step, connection_type, configuration_type, destination_address): +def build_and_send_config_files_dest_addr(step, connection_type, configuration_type, destination_address): """ Step used to choosing configuration type and channel to send it. :param step: @@ -915,7 +915,7 @@ def check_remote_address(remote_address): @step('Remote (\S+) server is (started|stopped|restarted|reconfigured) on address (\S+).') -def start_srv(step, name, type_of_action, destination_address): +def remote_start_srv(step, name, type_of_action, destination_address): """ Decide which you want, start server of failed start (testing incorrect configuration) Also decide in which part should it failed. @@ -949,7 +949,7 @@ def start_srv(step, name, type_of_action, destination_address): @step('(\S+) server failed to start. During (\S+) process.') -def start_srv(step, name, process): +def start_srv_during_process(step, name, process): """ Decide which you want, start server of failed start (testing incorrect configuration) Also decide in which part should it failed. @@ -963,7 +963,7 @@ def start_srv(step, name, process): @step('(\S+) server failed to start. During (\S+) process on remote destination (\S+).') -def start_srv(step, name, process, destination_address): +def start_srv_during_remote_process(step, name, process, destination_address): """ Decide which you want, start server of failed start (testing incorrect configuration) Also decide in which part should it failed. @@ -1028,9 +1028,5 @@ def add_keys(step, name, algorithm, secret): @step('Use DNS set no. (\d+).') -def log_includes_count(step, number): - """ - Check if Log includes line. - Be aware that tested line is every thing after "line: " until end of the line. - """ +def use_dns_set_number(step, number): dns.use_config_set(int(number)) diff --git a/lettuce/features/srv_msg.py b/lettuce/features/srv_msg.py index 803a241c2186f7bdcfff909129dfa6584aaeff1a..538c628c2b5885f7c909ec6100991068574d7ff0 100644 --- a/lettuce/features/srv_msg.py +++ b/lettuce/features/srv_msg.py @@ -15,6 +15,8 @@ # Author: Wlodzimierz Wencel +import json + from lettuce import world, step import importlib from srv_control import test_define_value @@ -96,7 +98,7 @@ def client_does_include(step, sender_type, yes_or_not, opt_type): @step('Relay-agent does include (\S+).') -def client_does_include(step, opt_type): +def relay_agent_does_include(step, opt_type): # add " option." to the end of the step - change all tests! """ """ @@ -294,7 +296,7 @@ def client_save_option(step, option_name): @step('Client saves into set no. (\d+) (\S+) option from received message.') -def client_save_option(step, count, option_name): +def client_save_option_count(step, count, option_name): """ """ assert len(world.srvmsg), "No messages received, nothing to save." @@ -313,7 +315,7 @@ def client_add_saved_option(step, yes_or_no): @step('Client adds saved options in set no. (\d+). And (DONT )?Erase.') -def client_add_saved_option(step, count, yes_or_no): +def client_add_saved_option_count(step, count, yes_or_no): """ """ assert len(world.savedmsg), "No options to add." @@ -350,7 +352,7 @@ def network_variable(step, value_name, value): @step('(\S+) log MUST (NOT )?contain line: (.+)') -def log_includes_line(step, server_type, condition, line): +def log_contains_line(step, server_type, condition, line): """ Check if Log includes line. Be aware that tested line is every thing after "line: " until end of the line. @@ -360,7 +362,7 @@ def log_includes_line(step, server_type, condition, line): @step('File stored in (\S+) MUST (NOT )?contain line or phrase: (.+)') -def log_includes_line(step, file_path, condition, line): +def file_contains_line(step, file_path, condition, line): """ Check if Log includes line. Be aware that tested line is every thing after "line: " until end of the line. @@ -380,7 +382,7 @@ def remote_log_includes_line(step, destination, file_path, condition, line): @step('Table (\S+) in (\S+) database MUST (NOT )?contain line or phrase: (.+)') -def log_includes_line(step, table_name, db_type, condition, line): +def table_contains_line(step, table_name, db_type, condition, line): """ Check if in table X in database type Y include line. Be aware that tested line is every thing after "line: " until end of the line. @@ -430,7 +432,7 @@ def test_stop(step): @step('Fail test.') -def test_stop(step): +def test_fail(step): assert False, "Test failed on purpose." @@ -523,7 +525,7 @@ def test_victory(step): @step('Execute (\S+) script in path: (\S+) with arguments: (.+)') -def execute_shell(step, script_type, path, arg): +def execute_shell_with_args(step, script_type, path, arg): path, arg = test_define_value(path, arg) other.execute_shell_script(path, arg) @@ -551,7 +553,7 @@ def check_socket_server_site(step, socket_path): @step('Using UNIX socket on remote server (\S+) in path (\S+) send (.+)') -def send_through_socket_server_site(step, destination_address, socket_path, command): +def send_through_socket_given_server_site(step, destination_address, socket_path, command): destination_address, socket_path, command = test_define_value(destination_address, socket_path, command) other.send_through_socket_server_site(socket_path, command, destination_address=destination_address) diff --git a/lettuce/forge.py b/lettuce/forge.py index cd00df9f62750840696ad850e39ce91de86357b7..40a2c7edfebaa2f960588be0bbb6235d2249ae8e 100755 --- a/lettuce/forge.py +++ b/lettuce/forge.py @@ -398,7 +398,7 @@ def test_path_select(number, test_set, name, explicit_path): # Test search path will be /letttuce/features/