def test_single_application_context_is_wrapped_in_tuple(self): self.assertEqual( CommandId('command', 'desc', None, [], application_contexts=ApplicationContext.EXTENDABLE). application_contexts, (ApplicationContext.EXTENDABLE, ))
def test_extension_extending_commandid_matches(self): command = CommandId('name', 'doc', lambda x: x, ()) extension = self.mock_extension(extends=[command]) self.em._all_extensions.append(extension) self.em.enable_all_extensions() self.assertEqual(self.em.command_extensions(command), [extension])
def test_applicable_for_application_context_when_context_is_specified( self): command = CommandId('command', 'desc', None, [], application_contexts=ApplicationContext.STANDALONE) self.assertTrue( command.is_applicable_for_application( ApplicationContext.STANDALONE))
def test_not_applicable_for_application_context_that_is_not_specified( self): command = CommandId('command', 'desc', None, [], application_contexts=ApplicationContext.EXTENDABLE) self.assertFalse( command.is_applicable_for_application( ApplicationContext.STANDALONE))
def test_extension_extending_command_capability_matches_command_name(self): extension = self.mock_extension(extends=['name']) command = CommandId('name', 'doc', lambda x: x, ()) self.em._all_extensions.append(extension) self.em.enable_all_extensions() self.assertEqual(self.em.command_extensions(command), [extension])
def test_multiple_application_contexts_is_converted_to_tuple(self): self.assertEqual( CommandId('command', 'desc', None, [], application_contexts=[ ApplicationContext.INTERNAL, ApplicationContext.EXTENDABLE ]).application_contexts, (ApplicationContext.INTERNAL, ApplicationContext.EXTENDABLE))
def test_mixed_extends(self): command = CommandId('name', 'doc', lambda x: x, (), uses=['a']) extension_1 = self.mock_extension(extends=[command]) self.em._all_extensions.append(extension_1) extension_2 = self.mock_extension(extends=['a', 'name']) self.em._all_extensions.append(extension_2) self.em.enable_all_extensions() self.assertEqual(self.em.command_extensions(command), [extension_1, extension_2])
def test_call_get_endpoints_and_messages_with_uninitialized_command_extension( self): extension = Mock() extension.endpoints_and_messages = {Mock(): [Mock(), Mock()]} extension.extension_type = ExtensionType.COMMAND extension.load_order = 5 command = CommandId('name', 'doc', lambda x: x, ()) extension.extends = [command] self.em._all_extensions.append(extension) self.em.enable_all_extensions() self.assertEqual(self.em.get_endpoints_and_messages(command), extension.endpoints_and_messages)
multiple=True, namespace='httpfileserver') FILE_SERVER_REDIRECT = ConfigOptionId('redirect', 'Redirect path to another. from:to', multiple=True, namespace='httpfileserver') FILE_SERVER = CommandId('httpfileserver', httpfileserver_command.__doc__, httpfileserver_command, config_options=[ ConfigOption(FILE_SERVER_IP, required=True), ConfigOption(FILE_SERVER_PORT, required=True), ConfigOption(FILE_SERVER_SERVE_DATA, required=False), ConfigOption(FILE_SERVER_SERVE_FILE, required=False), ConfigOption(FILE_SERVER_ACCEPT_UPLOAD, required=False), ConfigOption(FILE_SERVER_DENY, required=False), ConfigOption(FILE_SERVER_REDIRECT, required=False), ]) @FrameworkExtension(name='httpfileserver', config_options=[], commands=[FILE_SERVER], endpoints_and_messages={}) class HttpFileServerAddon(AbstractExtension): def __init__(self, config, instances):
from zaf.commands.command import CommandId from zaf.extensions.extension import AbstractExtension, CommandExtension def action(): pass TESTCOMMANDADDON_COMMAND = CommandId('testcommand', 'A command only used for testing', action, []) @CommandExtension('testcommandaddon', extends=[TESTCOMMANDADDON_COMMAND]) class TestCommandAddon(AbstractExtension): def __init__(self, config, instances): pass
try: futures[0].result() print('Created output file: {file}'.format(file=output_html)) return 0 except Exception as e: print("Failed to create file '{file}': {msg}".format(file=output_html, msg=str(e))) return 1 OUTPUT_HTML = ConfigOptionId('output.html', 'The output HTML file. Default <input name>.html.') HTML_CSS_STYLESHEET = ConfigOptionId( 'css.stylesheet', 'The CSS stylesheet', default=data_file('styles/zenterio-html-theme.css'), option_type=Path(exists=True)) HTML_COMMAND = CommandId( 'html', 'Generate HTML', html, [ ConfigOption(OUTPUT_HTML, required=False), ConfigOption(HTML_CSS_STYLESHEET, required=True), ]) @FrameworkExtension( name='htmlcommand', commands=[HTML_COMMAND], ) class HtmlCommand(AbstractExtension): pass
'include.custom.logging.docs', 'Include application-specific logging documentation items', option_type=Path(), multiple=True, namespace='docgen', short_alias=True) DOCGEN_COMMAND = CommandId( 'docgen', docgen.__doc__, docgen, config_options=[ ConfigOption(DOC_DIR, required=True), ConfigOption(LIMIT_EXTENSION_NAMESPACES, required=False), ConfigOption(ADDITIONAL_EXTENSIONS, required=False), ConfigOption(INCLUDE_COMPONENTS, required=True), ConfigOption(INCLUDE_ENDPOINTS_AND_MESSAGES, required=True), ConfigOption(INCLUDE_CLASSES, required=True), ConfigOption(INCLUDE_HIDDEN_COMMANDS, required=True), ConfigOption(INCLUDE_HIDDEN_OPTIONS, required=True), ConfigOption(INCLUDE_CUSTOM_LOGGING_DOCS, required=False), ], hidden=True, uses=['changelog'], ) @FrameworkExtension(name='docgencommand', commands=[DOCGEN_COMMAND]) class DocGenCommand(object): """Provides the docgen command.""" def __init__(self, config, instances): pass
'A specific test case can be identified by appending :<test>. ' 'This can be given multiple times and it overrides the extension name argument' ), multiple=True, namespace='unittest', short_alias=True) UNITTEST_COMMAND = CommandId( 'unittest', unittest.__doc__, unittest, config_options=[ ConfigOption(EXTENSION_NAMES, required=False), ConfigOption(REPORT_ENABLED, required=False), ConfigOption(REPORT_FILE, required=False), ConfigOption(COVERAGE_ENABLED, required=False), ConfigOption(COVERAGE_FILE, required=False), ConfigOption(COVERAGE_XML_ENABLED, required=False), ConfigOption(COVERAGE_XML_FILE, required=False), ConfigOption(DETAILS, required=False), ConfigOption(EXCLUDE_SYSTESTS, required=False), ConfigOption(TESTS, required=False) ], hidden=True, ) @FrameworkExtension(name='unittestcommand', commands=[UNITTEST_COMMAND]) class UnittestCommand(): """Provides the unittest command.""" def __init__(self, config, instances): pass
self): check_for_ambiguous_duplicates( 'zaf', [], { COMMAND: [option('name')], COMMAND2: [option('name', namespace='namespace')] }) def test_commands_options_on_different_commands_with_same_short_name_does_not_raise_exception( self): check_for_ambiguous_duplicates( 'zaf', [], { COMMAND: [option('name1', short_name='n')], COMMAND2: [option('name2', short_name='n')] }) def option(name, namespace=None, short_name=None): global unique_id_counter unique_id_counter += 1 return ConfigOption( ConfigOptionId( name, str(unique_id_counter), namespace=namespace, short_alias=bool(namespace), short_name=short_name), required=True) COMMAND2 = CommandId('command2', '', callable=None, config_options=[])
def test_application_contexts_not_given_gives_empty_tuple(self): self.assertEqual( CommandId('command', 'desc', None, []).application_contexts, ())
filename=os.path.splitext(adoc_file)[0]) output_yaml = os.path.abspath(output_yaml) futures = zpider.messagebus.send_request( GENERATE_DOC, data=YamlAsciidoctorCommand(output_yaml)) futures.wait() try: futures[0].result() print('Created output file: {file}'.format(file=output_yaml)) return 0 except Exception as e: print("Failed to create file '{file}': {msg}".format(file=output_yaml, msg=str(e))) return 1 OUTPUT_YAML = ConfigOptionId( 'output.yaml', 'The output YAML file. Default <input name>.yaml.') YAML_COMMAND = CommandId('yaml', 'Generate YAML', yaml, [ ConfigOption(OUTPUT_YAML, required=False), ]) @FrameworkExtension( name='yamlcommand', commands=[YAML_COMMAND], ) class YamlCommand(AbstractExtension): pass
text += 'The power state of sut {sut} was already {state}\n'.format( sut=sut, state=sut_result['state']) return text POWER_SUBCOMMAND = ConfigOptionId( 'powerswitch.subcommand', 'The subcommand to powerswitch', option_type=Choice(['state', 'on', 'off']), argument=True) POWER_COMMAND = CommandId( 'powerswitch', power.__doc__, power, config_options=[ ConfigOption(POWER_SUBCOMMAND, required=True), ConfigOption(JSON_OUTPUT, required=False), ConfigOption(SUT, required=True) ]) @FrameworkExtension( 'powerswitch', commands=[POWER_COMMAND], groups=['powerswitch'], ) class PowerSwitchExtension(object): """Provides the power command.""" def __init__(self, config, instances):
def test_count_clamped_to_max_value(self): count_option = ConfigOption(ConfigOptionId('count', '', option_type=Count(0, 1)), required=False) self.config.set(count_option.option_id, 0) with patch('sys.argv', ['zaf', '--count', '--count', 'command']): extension_config = self.plugin.get_config(self.config, [count_option], {COMMAND: []}) self.assertIn('count', extension_config.config) self.assertEqual(extension_config.config['count'], 1) COMMAND = CommandId('command', '', callable=None, config_options=[]) COMMAND_ALLOW_UNKNOWN = CommandId('command-unknown', '', callable=None, config_options=[], allow_unknown_options=True) REQUIRED = ConfigOption(ConfigOptionId('required', ''), required=True) ENTITY_IDS = ConfigOptionId('ids', '', entity=True, multiple=True, namespace='entities') DEPENDENT = ConfigOption(ConfigOptionId('dependent', '', at=ENTITY_IDS), required=True) REQUIRED_ARGUMENT = ConfigOptionId('required.arg', '', argument=True) SINGLE_ENTITY_ID = ConfigOptionId('id',
"""Provides the *noop* (no operation) command.""" import logging from zaf.application import ApplicationContext from zaf.commands.command import CommandId from zaf.extensions.extension import AbstractExtension, FrameworkExtension, get_logger_name logger = logging.getLogger(get_logger_name('zaf', 'noop')) logger.addHandler(logging.NullHandler()) def noop(core): """Noop (no operation) command. Does nothing. Takes no arguments.""" return 0 NOOP_COMMAND = CommandId('noop', noop.__doc__, noop, [], hidden=True, application_contexts=ApplicationContext.EXTENDABLE) @FrameworkExtension(name='noop', commands=[NOOP_COMMAND]) class NoopExtension(AbstractExtension): """Provides the noop (no operation) command.""" def __init__(self, config, instances): pass
cfg = application.config print('command', cfg.get(COMMAND_OPTION)) def subcommand(application): cfg = application.config print('subcommand', cfg.get(COMMAND_OPTION), cfg.get(SUBCOMMAND_OPTION)) def subsubcommand(application): cfg = application.config print('subsubcommand', cfg.get(COMMAND_OPTION), cfg.get(SUBCOMMAND_OPTION), cfg.get(SUBSUBCOMMAND_OPTION)) COMMAND = CommandId('command', 'description', command, [ConfigOption(COMMAND_OPTION, required=True)]) SUBCOMMAND = CommandId('subcommand', 'description', subcommand, [ConfigOption(SUBCOMMAND_OPTION, required=True)], parent=COMMAND) SUBSUBCOMMAND = CommandId('subsubcommand', 'description', subsubcommand, [ConfigOption(SUBSUBCOMMAND_OPTION, required=True)], parent=SUBCOMMAND) @FrameworkExtension('subcommands', commands=[COMMAND, SUBCOMMAND, SUBSUBCOMMAND]) class Commands(AbstractExtension):
# Send CONTINUE before stopping blocking so that it exists in the testcase queue # on next get. This verifies that the block actually blocked the test case client.send_request(CONTINUE, ENDPOINT).wait(timeout=1) blocker.stop_blocking() assert blocker.wait_for_finished() # Send a final continue to test case. This is needed because otherwise the remote server # will be stopped before the BLOCKING_COMPLETED message has been received client.send_request(CONTINUE, ENDPOINT, is_async=True) print('Reached end of command') REMOTE_AND_BLOCKER_COMMAND = CommandId('remoteandblockercommand', '', remote_and_blocker_command, config_options=[]) REMOTE_AND_BLOCKER_USING_BLOCKER_COMPONENT_COMMAND = CommandId( 'remoteandblockerusingblockercomponentcommand', '', remote_and_blocker_using_blocker_component_command, config_options=[]) @FrameworkExtension( 'usestheblockerandremotefacilitiesextension', commands=[ REMOTE_AND_BLOCKER_COMMAND, REMOTE_AND_BLOCKER_USING_BLOCKER_COMPONENT_COMMAND ],
with self.assertRaisesRegex(TypeError, regex): self.validator.get_config(config, [], {CMD: all_options}) def create_config(options, entity=None, additional_options={}): config = ConfigManager() for option_id, value in options.items(): key = config._option_key(option_id, entity) config._config[key].add(value, 1, '') for option, value in additional_options.items(): key = config._option_key(option.option_id) config._config[key].add(value, 1, '') return config CMD = CommandId('cmd', '', None, []) MULTIPLE_STR_OPTION = ConfigOption(ConfigOptionId('multiple.str.option', '', multiple=True), required=False) STR_OPTION = ConfigOption(ConfigOptionId('str.option', ''), required=False) INT_OPTION = ConfigOption(ConfigOptionId('int.option', '', option_type=int), required=False) FLOAT_OPTION = ConfigOption(ConfigOptionId('float.option', '', option_type=float), required=False) BOOL_OPTION = ConfigOption(ConfigOptionId('bool.option', '', option_type=bool), required=False) FLAG_OPTION = ConfigOption(ConfigOptionId('flag.option', '',
help_output = StringIO() with patch('sys.argv', ['zaf', '--full-help']), \ self.assertRaises(SystemExit),\ redirect_stdout(help_output): self.plugin.get_config(self.config, self.options, self.commands_with_options) if not_in: self.assertNotIn(string, help_output.getvalue(), msg=help_output.getvalue()) else: self.assertIn(string, help_output.getvalue(), msg=help_output.getvalue()) COMMAND_INTERNAL = CommandId( 'internalcommand', '', callable=None, config_options=[], application_contexts=ApplicationContext.INTERNAL) COMMAND_EXTENDABLE = CommandId( 'extendablecommand', '', callable=None, config_options=[], application_contexts=ApplicationContext.EXTENDABLE) COMMAND_NONE = CommandId('nonecommand', '', callable=None, config_options=[]) OPTION_INTERNAL = ConfigOption( ConfigOptionId('internaloption', '', application_contexts=ApplicationContext.INTERNAL), required=False) OPTION_EXTENDABLE = ConfigOption( ConfigOptionId('extendableoption', '', application_contexts=ApplicationContext.EXTENDABLE), required=False)
with patch('sys.argv', argv), \ self.assertRaises(SystemExit),\ redirect_stdout(help_output): self.plugin.get_config(self.config, options, commands_with_options) if not_in: self.assertNotIn(string, help_output.getvalue(), msg=help_output.getvalue()) else: self.assertIn(string, help_output.getvalue(), msg=help_output.getvalue()) COMMAND = CommandId('mycommand', '', callable=None, config_options=[]) COMMAND_HIDDEN = CommandId('myhiddencommand', '', callable=None, config_options=[], hidden=True) OPTION_REQUIRED = ConfigOption(ConfigOptionId( 'requiredoption', '', ), required=True) OPTION_REQUIRED_WITH_DEFAULT = ConfigOption(ConfigOptionId( 'defaultrequiredoption', '', default='mydefault'), required=True) OPTION_OPTIONAL = ConfigOption(ConfigOptionId( 'optionaloption',
{{message.name}} {%- for line in message.description.strip().splitlines() %} {{line}} {%- endfor %} {%- if endpoints %} endpoints {%- for endpoint in endpoints %} {{endpoint.name}} {%- endfor %} {%- endif %} {% endfor %} """) return render_template(template_string, messages_with_endpoints=messages_with_endpoints) MESSAGES_COMMAND = CommandId( 'messages', messages.__doc__, messages, config_options=[ConfigOption(TARGET_COMMAND, required=True)], application_contexts=ApplicationContext.EXTENDABLE) @FrameworkExtension(name='messagescommand', commands=[MESSAGES_COMMAND]) class MessagesCommand(): """Provides the messages command.""" def __init__(self, config, instances): pass
:param name: the message_id defining the sequence poitn :param message_bus: the messagebus to send the message to :param data: message data """ logger.debug('Executing sequence point {sequence_point}'.format( sequence_point=message_id.name)) messagebus.trigger_event(message_id, RUN_COMMAND_ENDPOINT, entity=entity, data=data) RUN_COMMAND = CommandId( 'run', run.__doc__, run, [ ConfigOption(EXIT_CODE_FROM_VERDICT, required=True), ], uses=['sut']) @FrameworkExtension(name='runcommand', commands=[RUN_COMMAND], endpoints_and_messages={ RUN_COMMAND_ENDPOINT: [ PRE_INITIALIZE_SUT, INITIALIZE_SUT, POST_INITIALIZE_SUT, UNINITIALIZE_SUT, PRE_TEST_RUN, TEST_RUN, POST_TEST_RUN, GET_RUN_VERDICT ] })
def _init_commands(self): """ Initialize the command metadata objects. Commands are only included if the belong to an extension class that is included in the metadata and they are not filtered out by the MetadataFilter. The commands will only contain config option ids that are not filtered out by the metadata filter. """ framework_config_option_ids = { config_option.option_id for ext_class in self._extension_manager.framework_extensions( only_enabled=False) if ext_class in self._extension_classes for config_option in ext_class.config_options if self._metadata_filter.include_config_option_id( config_option.option_id) } root_command = CommandId( self._application_name, 'The {application} root command.'.format( application=self._application_name), None, []) commands = OrderedDict([ (root_command, CommandMetadata(self, root_command, None, root_command, [], [], framework_config_option_ids)) ]) for command, defining_ext_class in sorted( ((command, ext_class) for ext_class in self._extension_classes.keys() for command in ext_class.commands if self._metadata_filter.include_command(command)), key=lambda t: t[0].name): config_option_ids = [ config_option.option_id for config_option in command.config_options if self._metadata_filter.include_config_option_id( config_option.option_id) ] ext_classes = [ ext_class for ext_class in self._extension_manager.command_extensions( command, only_enabled=False) if ext_class in self._extension_classes ] extension_config_option_ids = set() for ext_class in ext_classes: extension_config_option_ids.update([ config_option.option_id for config_option in ext_class.config_options if self._metadata_filter.include_config_option_id( config_option.option_id) ]) commands[command] = CommandMetadata( self, command, defining_ext_class, root_command, ext_classes, config_option_ids, sorted(extension_config_option_ids, key=lambda c: c.key)) self._commands = commands
{{cmd.name}} {%- for line in cmd.description.splitlines() %} {{line}} {%- endfor %} {% endfor %} """) return render_template(template_string, commands=commands) COMMANDS_SHORT = ConfigOptionId( name='short', description='Short format (less information)', option_type=Flag(), default=False, namespace='commands', short_alias=True) COMMANDS_COMMAND = CommandId( 'commands', command_list.__doc__, command_list, [ConfigOption(COMMANDS_SHORT, required=False)], application_contexts=ApplicationContext.EXTENDABLE) @FrameworkExtension(name='commandscommand', commands=[COMMANDS_COMMAND]) class CommandsCommand(): """Provides the commands command.""" def __init__(self, config, instances): pass
return docker_run.run_in_docker(command_with_arguments, forward_signals=False) EXEC_COMMAND_WITH_ARGUMENTS = ConfigOptionId( 'command.with.arguments', 'The command to run.', multiple=True, namespace='exec', argument=True, ) EXEC_COMMAND = CommandId( 'exec', exec.__doc__, exec, config_options=[ ConfigOption(EXEC_COMMAND_WITH_ARGUMENTS, required=True), ], allow_unknown_options=True, ) @FrameworkExtension( 'execcommand', commands=[EXEC_COMMAND], ) class ExecExtension(AbstractExtension): pass
{{endpoint.name}} {%- for line in endpoint.description.strip().splitlines() %} {{line}} {%- endfor %} {%- if messages %} messages {%- for message in messages %} {{message.name}} {%- endfor %} {%- endif %} {% endfor %} """) return render_template(template_string, endpoints_and_messages=endpoints_and_messages) ENDPOINTS_COMMAND = CommandId( 'endpoints', endpoints.__doc__, endpoints, config_options=[ConfigOption(TARGET_COMMAND, required=True)], application_contexts=ApplicationContext.EXTENDABLE) @FrameworkExtension('endpointscommand', commands=[ENDPOINTS_COMMAND]) class EndpointsCommand(): """Provides the endpoints command.""" def __init__(self, config, instances): pass