tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_SUMMARY_HELP_LINE = \
    '-s, --summary Show only a summary (count) of the objects.'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_NAMES_ONLY_HELP_LINE = \
    '--no, --names-only Retrieve only the object paths (names).'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_MULTIPLE_NAMESPACE_HELP_LINE = \
    '-n, --namespace NAMESPACE  Add a namespace to the search scope. May be'
tests/unit/pywbemcli/cli_test_extensions.py
PYWBEM_0 = not PYWBEM_1
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_INCLUDE_QUALIFIERS_GET_HELP_LINE = \
    '--iq, --include-qualifiers Include qualifiers in the returned'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_NAMESPACE_HELP_LINE = \
    '-n, --namespace NAMESPACE Namespace to use for this command'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_HELP_INSTANCENAME_HELP_LINE = \
    '--hi, --help-instancename Show help message for specifying INSTANCENAME'
tests/unit/pywbemcli/cli_test_extensions.py
class CLITestsBase(object):
    # pylint: disable=too-few-public-methods, useless-object-inheritance
    """
        Defines methods to execute tests on pywbemcli.

    """
    def command_test(self, desc, command_grp, inputs, exp_response, mock_files,
                     condition, verbose=False):
        # pylint: disable=line-too-long, no-self-use
        """
        Test method to execute test on pywbemcli by calling the executable
        pywbemcli for the command defined by command with arguments defined
        by args. This can execute pywbemcli either with a mock environment
        by using the mock_files variable or without mock if the mock_files
        parameter is None. The method tests the results of the execution
        of pywbemcli using the exp_response parameter.

        Parameters:
          desc (:term:`string`):
            Description of the test

          command_grp (:term:`string`):
            Pywbemcli command group for this test. This is the first level of
            the command, e.g. 'class' or 'instance'.

          inputs (:term:`string` or tuple/list of :term:`string` or :class:`py:dict`):

            * If inputs is a string or a tuple/list of strings, it contains the
              command line arguments, without the command name or command group.

              Each single argument must be its own item in the iterable;
              combining the arguments into a string does not work, and the
              string is not split into words (anymore).

              The arguments may be binary strings encoded in UTF-8, or unicode
              strings.

            * If inputs is a dict it can contain the following optional items:

              - 'connections_file_args': tuple(conn_file, conn_content) that can
                specify a connections file to be prepared for the test.
                The tuple items are passed as arguments to the
                'connections_file()' context manager. See there for details.

              - 'args': String or tuple/list of strings with local
                (command-level) options that will be added to the command
                line after the command name.

                Each single argument (e.g. option name and option arguments)
                must be its own item in the iterable.

              - 'general': String or tuple/list of strings with general
                options that will be added to the command line before the
                command name.

                Each single argument (e.g. option name and option arguments)
                must be its own item in the iterable.

              - 'env': Dictionary of environment variables where key is the
                variable name; dict value is the variable value (without any
                shell escaping needed).

                If omitted, None, or empty, no environment variables will be
                set for the test.

              - 'stdin': A string or a tuple/list of strings, that contains the
                standard input for the command.

                This can be used for commands in interactive mode, and for
                responding to prompts.

                If present, the command group specified in the `command_grp`
                parameter is not added to the command line, but the local and
                global options are added.

                If specified as a tuple/list of strings, these strings are
                joined into a single string separated by an EOL char. Each line
                is processed as a separate repl line or prompt input by
                pybemcli.

                If omitted or None, no standard input will be provided to the
                pywbemcli command.

          exp_response (:class:`py:dict`)

            Keyword arguments for expected response.

            Includes the following possible keys:

               'stdout' or 'stderr' - Defines which return is expected (the
               expected response). The value is a string or iterable defining
               the data expected in the response. The data definition in
               this dictionary entry must be compatible with the definition
               of expected data for the test selected.
               Only one of these keys may exist.

               'test' - If it exists defines the test used to compare the
               returned data with the expected returned data defined as the
               value of 'stdout'/'stderr'.

               The tests define are:

                 'startswith' - Expected Response must be a single string
                 The returned text defined starts with the defined string

                 'lines' -  Expected response may be either a list of strings or
                 single string

                 Compares for exact match between the expected response and the
                 returned data line by line. The number of lines and the data
                 in each line must match.  If the expected response is a single
                 string it is split into lines separated at each new line
                 before the match

                 'linesnows' - Expected response may be either list of strings
                 or single string. Compares as with lines except that all
                 whitespace is removed from the strings before the compare.

                 'patterns' - Expected response must be same as lines test
                 except that each line in the expected response is treated as
                 a regex expression and a regex match is executed for each line.

                 'regex' - Expected response is a single string or list of
                 strings. Each string is considered a regex expression. The
                 regex expression is tested against each line in the output
                 using regex search. All strings in the expected response must
                 be found in actual response to pass the test

                 'in' - Expected response is string or list of strings.
                 Tests the complete response line by line to determine if each
                 entry in expected response is in the response data as a single
                 test.

                 'innows' - Like 'in, except that differences in whitespace are
                 ignored.

                 Executes a single regex search of the entire
                 response data to match with each entry in the expected
                 response

               'rc' expected exit_code from pywbemcli.  If None, code 0
               is expected.

          mock_files (:term:`string` or list of string or None):
            If this is a string, this test will be executed using the
            --mock-server pywbemcl option with this file as the name of the
            objects to be compiled or executed. This should be just a file name
            and this method assumes the file is in the tests/unit directory.

            If it is a list, the same rules apply to each entry in the list.

            If None, test is executed without the --mock-server input parameter
            and defines an artificial server name  Used to test commands
            and options that do not communicate with a server.  It is faster
            than installing the mock repository

          condition (True, False, 'pdb', or 'verbose'):
            If True, the test is executed.
            If False, the test is skipped.
            If 'pdb', the test breaks in the debugger.
            If 'verbose', verbose mode is enabled for the test.

          verbose (:class:`py:bool`):
            If True, verbose mode is enabled for the test.

            In verbose mode, the assembled command line, the environment
            variables set by 'env', and other details will be displayed.
        """  # noqa: E501
        # pylint: enable=line-too-long

        if not condition:
            pytest.skip('Condition for test case {} not met'.format(desc))

        env = None
        stdin = None
        general_args = None
        connections_file_args = (None, None)
        if isinstance(inputs, dict):
            connections_file_args = inputs.get(
                "connections_file_args", (None, None))
            general_args = inputs.get("general", None)
            local_args = inputs.get("args", None)
            env = inputs.get("env", None)
            stdin = inputs.get('stdin', None)
            if stdin:
                if isinstance(stdin, (tuple, list)):
                    stdin = '\n'.join(stdin)
        elif isinstance(inputs, six.string_types):
            local_args = inputs
        elif isinstance(inputs, (list, tuple)):
            local_args = inputs
        else:
            assert False, 'Invalid inputs param to test {!r}. Allowed types ' \
                'are dict, string, list, tuple.'.format(inputs)

        if stdin and condition == 'pdb':
            assert False, "Condition 'pdb' cannot be used on testcases that " \
                "specify stdin"

        if isinstance(local_args, six.string_types):
            # Is not split into words anymore
            local_args = [local_args]

        if isinstance(general_args, six.string_types):
            # Is not split into words anymore
            general_args = [general_args]

        cmd_line = []

        if condition == 'pdb':
            capture = False
            cmd_line.append('--pdb')
        else:
            capture = True

        if general_args:
            cmd_line.extend(general_args)

        if mock_files:
            if isinstance(mock_files, (list, tuple)):
                for item in mock_files:
                    cmd_line.extend(['--mock-server',
                                     os.path.join(TEST_DIR, item)])
            elif isinstance(mock_files, six.string_types):
                cmd_line.extend(['--mock-server',
                                 os.path.join(TEST_DIR, mock_files)])
            else:
                assert False, \
                    'CLI_TEST_EXTENSIONS mock_file {} invalid' \
                    .format(mock_files)

        if not stdin:
            cmd_line.append(command_grp)

        if local_args:
            cmd_line.extend(local_args)

        if not verbose:
            verbose = condition == 'verbose'

        with connections_file(*connections_file_args):
            rc, stdout, stderr = execute_command(
                'pywbemcli', cmd_line, env=env, stdin=stdin, verbose=verbose,
                capture=capture)

        exp_rc = exp_response['rc'] if 'rc' in exp_response else 0
        assert_rc(exp_rc, rc, stdout, stderr, desc)

        if exp_response['test']:
            test_definition = exp_response['test']
        else:
            test_definition = None

        if 'stdout' in exp_response:
            test_value = exp_response['stdout']
            rtn_value = stdout
            rtn_type = 'stdout'
        elif 'stderr' in exp_response:
            test_value = exp_response['stderr']
            rtn_value = stderr
            rtn_type = 'stderr'
        else:
            assert False, 'Expected "stdout" or "stderr" key. One of these ' \
                          'keys required in exp_response.'

        if test_definition:
            if 'test' in exp_response:
                test_definition = exp_response['test']
                # test that rtn_value starts with test_value
                if test_definition == 'startswith':
                    assert isinstance(test_value, six.string_types)
                    assert rtn_value.startswith(test_value), \
                        "Unexpected start of line on {} in test:\n" \
                        "{}\n" \
                        "Expected start of line:\n" \
                        "------------\n" \
                        "{}\n" \
                        "------------\n" \
                        "Actual output line(s):\n" \
                        "------------\n" \
                        "{}\n" \
                        "------------\n". \
                        format(rtn_type, desc, test_value, rtn_value)
                # test that lines match between test_value and rtn_value
                # base on regex match
                elif test_definition == 'patterns':
                    if isinstance(test_value, six.string_types):
                        test_value = test_value.splitlines()
                    assert isinstance(test_value, (list, tuple))
                    assert_patterns(test_value, rtn_value.splitlines(),
                                    rtn_type, desc)
                # test that each line in the test value matches the
                # corresponding line in the rtn_value exactly
                elif test_definition == 'lines':
                    if isinstance(test_value, six.string_types):
                        test_value = test_value.splitlines()
                    if isinstance(test_value, (list, tuple)):
                        assert_lines(test_value, rtn_value.splitlines(),
                                     rtn_type, desc)
                    else:
                        assert(isinstance(test_value, six.string_types))
                        assert_lines(test_value.splitlines(),
                                     rtn_value.splitlines(),
                                     rtn_type, desc)
                # compress test_value and rtn_value into whitespace single
                # strings and assert_lines.
                elif test_definition == 'linesnows':
                    assert_lines(remove_ws(test_value),
                                 remove_ws(rtn_value),
                                 rtn_type, desc)

                # test with a regex search that all values in list exist in
                # the return. Build rtn_value into single string and do
                # re.search against it for each test_value
                elif test_definition == 'regex':
                    assert isinstance(rtn_value, six.string_types)
                    if isinstance(test_value, six.string_types):
                        test_value = [test_value]
                    for regex in test_value:
                        assert isinstance(regex, six.string_types)
                        match_result = re.search(regex, rtn_value, re.MULTILINE)
                        assert match_result, \
                            "Missing pattern on {} in test:\n" \
                            "{}\n" \
                            "Expected pattern in any line:\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n" \
                            "Actual output line(s):\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n". \
                            format(rtn_type, desc, regex, rtn_value)
                elif test_definition == 'in':
                    if isinstance(test_value, six.string_types):
                        test_value = [test_value]
                    for test_str in test_value:
                        assert test_str in rtn_value, \
                            "Missing in-string on {} in test:\n" \
                            "{}\n" \
                            "Expected in-string in any line:\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n" \
                            "Actual output line(s):\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n". \
                            format(rtn_type, desc, test_str, rtn_value)
                elif test_definition == 'innows':
                    if isinstance(test_value, six.string_types):
                        test_value = [test_value]
                    for test_str in test_value:
                        assert remove_ws(test_str, join=True) in \
                            remove_ws(rtn_value, join=True), \
                            "Missing ws-agnostic in-string on {} in test:\n" \
                            "{}\n" \
                            "Expected ws-agnostic in-string in any line:\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n" \
                            "Actual output line(s):\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n". \
                            format(rtn_type, desc, test_str, rtn_value)
                elif test_definition == 'not-innows':
                    if isinstance(test_value, six.string_types):
                        test_value = [test_value]
                    for test_str in test_value:
                        assert remove_ws(test_str, join=True) not in \
                            remove_ws(rtn_value, join=True), \
                            "Unexpected ws-agnostic in-string on {} in test:\n"\
                            "{}\n" \
                            "Unexpected ws-agnostic in-string in any line:\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n" \
                            "Actual output line(s):\n" \
                            "------------\n" \
                            "{}\n" \
                            "------------\n". \
                            format(rtn_type, desc, test_str, rtn_value)
                else:
                    raise AssertionError(
                        "Test validation {!r} is invalid in test:\n"
                        "{}\n".format(test_definition, desc))
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_LEAFCLASSES_FILTER_HELP_LINE = \
    "Filter the returned classes to return only"
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_FILTER_QUERY_LINE = \
    '--fq, --filter-query QUERY-STRING When pull operations are used, filter ' \
    'the instances in the result'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_HELP_HELP_LINE = \
    '-h, --help Show this help message.'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_INCLUDE_QUALIFIERS_LIST_HELP_LINE = \
    '--iq, --include-qualifiers When traditional operations are used, ' \
    'include qualifiers in the returned'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_ASSOCIATION_FILTER_HELP_LINE = \
    '--association / --no-association'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_EXPERIMENTAL_FILTER_HELP_LINE = \
    '--experimental / --no-experimental'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_INDICATION_FILTER_HELP_LINE = \
    '--indication / --no-indication'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_VERIFY_HELP_LINE = \
    '-V, --verify Prompt for confirmation before performing a change'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_PROPERTYLIST_HELP_LINE = \
    '--pl, --propertylist PROPERTYLIST Filter the properties included in'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_LOCAL_ONLY_INSTANCE_LIST_HELP_LINE = \
    '--lo, --local-only When traditional operations are used, do not include ' \
    'superclass properties'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_SHOW_NULL_HELP_LINE = \
    '--show-null In the TABLE output formats, show properties with no '
pywbemtools/_version.py

tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_KEYS_HELP_LINE = \
    '-k, --key KEYNAME=VALUE         Value for a key in keybinding of'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_LOCAL_ONLY_INSTANCE_GET_HELP_LINE = \
    '--lo, --local-only Do not include superclass properties in the returned'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_FILTER_QUERY_LANGUAGE_LINE = \
    '--filter-query-language QUERY-LANGUAGE The filter query language to be ' \
    'used'
tests/unit/pywbemcli/cli_test_extensions.py
FAKEURL_STR = '//FakedUrl:5988' if PYWBEM_1 else '//FakedUrl'
tests/unit/pywbemcli/common_options_help_lines.py
CMD_OPTION_INCLUDE_CLASSORIGIN_HELP_LINE = \
    '--ico, --include-classorigin Include class origin information in the ' \
    'returned'


Question: import os
import pytest
from packaging.version import parse as parse_version
from pywbem import __version__ as pywbem_version
from .cli_test_extensions import CLITestsBase, FAKEURL_STR, PYWBEM_0
from .common_options_help_lines import CMD_OPTION_NAMES_ONLY_HELP_LINE, \
    CMD_OPTION_HELP_HELP_LINE, CMD_OPTION_SUMMARY_HELP_LINE, \
    CMD_OPTION_NAMESPACE_HELP_LINE, CMD_OPTION_PROPERTYLIST_HELP_LINE, \
    CMD_OPTION_INCLUDE_CLASSORIGIN_HELP_LINE, CMD_OPTION_VERIFY_HELP_LINE, \
    CMD_OPTION_INCLUDE_QUALIFIERS_LIST_HELP_LINE, \
    CMD_OPTION_INCLUDE_QUALIFIERS_GET_HELP_LINE, \
    CMD_OPTION_FILTER_QUERY_LINE, \
    CMD_OPTION_FILTER_QUERY_LANGUAGE_LINE, \
    CMD_OPTION_LOCAL_ONLY_INSTANCE_LIST_HELP_LINE, \
    CMD_OPTION_LOCAL_ONLY_INSTANCE_GET_HELP_LINE, \
    CMD_OPTION_MULTIPLE_NAMESPACE_HELP_LINE, \
    CMD_OPTION_KEYS_HELP_LINE, \
    CMD_OPTION_ASSOCIATION_FILTER_HELP_LINE, \
    CMD_OPTION_INDICATION_FILTER_HELP_LINE, \
    CMD_OPTION_EXPERIMENTAL_FILTER_HELP_LINE, \
    CMD_OPTION_HELP_INSTANCENAME_HELP_LINE, \
    CMD_OPTION_LEAFCLASSES_FILTER_HELP_LINE, \
    CMD_OPTION_SHOW_NULL_HELP_LINE
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Tests the commands in the server command group.
"""

from __future__ import absolute_import, print_function





_PYWBEM_VERSION = parse_version(pywbem_version)
# pywbem 1.0.0 or later
PYWBEM_1_0_0 = _PYWBEM_VERSION.release >= (1, 0, 0)

TEST_DIR = os.path.dirname(__file__)
TEST_DIR_REL = os.path.relpath(TEST_DIR)

SIMPLE_MOCK_FILE = 'simple_mock_model.mof'
ASSOC_MOCK_FILE = 'simple_assoc_mock_model.mof'
ALLTYPES_MOCK_FILE = 'all_types.mof'
QUALIFIER_FILTER_MODEL = 'qualifier_filter_model.mof'

INVOKE_METHOD_MOCK_FILE_0 = 'simple_mock_invokemethod_v0.py'
INVOKE_METHOD_MOCK_FILE_1 = 'simple_mock_invokemethod_v1old.py'
INVOKE_METHOD_MOCK_FILE = INVOKE_METHOD_MOCK_FILE_0 if PYWBEM_0 else \
    INVOKE_METHOD_MOCK_FILE_1

COMPLEX_ASSOC_MODEL = "complex_assoc_model.mof"

MOCK_SERVER_MODEL = os.path.join(TEST_DIR, 'testmock',
                                 'wbemserver_mock_script.py')

INSTANCE_TABLE_MODEL_FILE = 'simple_instance_tablefmt_test.mof'


#
# Definition of files that mock selected pywbemcli calls for tests
# These are installed in pywbemcli through a special env variable set
# before the test that is NOT one of the externally defined environment
# variables
#
def GET_TEST_PATH_STR(filename):  # pylint: disable=invalid-name
    """
    Return the string representing the relative path of the file name provided.
    """
    return (str(os.path.join(TEST_DIR_REL, filename)))


MOCK_DEFINITION_ENVVAR = 'PYWBEMCLI_STARTUP_SCRIPT'
MOCK_PROMPT_0_FILE = "mock_prompt_0.py"
MOCK_PROMPT_PICK_RESPONSE_3_FILE = 'mock_prompt_pick_response_3.py'
MOCK_PROMPT_PICK_RESPONSE_5_FILE = 'mock_prompt_pick_response_5.py'
MOCK_PROMPT_PICK_RESPONSE_11_FILE = 'mock_prompt_pick_response_11.py'
MOCK_CONFIRM_Y_FILE = "mock_confirm_y.py"
MOCK_CONFIRM_N_FILE = "mock_confirm_n.py"

ALLTYPES_INVOKEMETHOD_MOCK_FILE = 'all_types_method_mock_v0.py' if PYWBEM_0 \
    else 'all_types_method_mock_v1old.py'


#
# The following list define the help for each command in terms of particular
# parts of lines that are to be tested.
# For each test, try to include:
# 1. The usage line and in particular the argument component
# 2. The single
# 2. The last line CMD_OPTION_HELP_HELP_LINE
# Defined in alphabetical order

INSTANCE_HELP_LINES = [
    'Usage: pywbemcli [GENERAL-OPTIONS] instance COMMAND [ARGS] '
    '[COMMAND-OPTIONS]',
    'Command group for CIM instances.',
    CMD_OPTION_HELP_HELP_LINE,
    'associators   List the instances associated with an instance.',
    'count         Count the instances of each class with matching class '
    'name.',
    'create        Create an instance of a class in a namespace.',
    'delete        Delete an instance of a class.',
    'enumerate     List the instances of a class.',
    'get           Get an instance of a class.',
    'invokemethod  Invoke a method on an instance.',
    'modify        Modify properties of an instance.',
    'query         Execute a query on instances in a namespace.',
    'references    List the instances referencing an instance.',
]

INSTANCE_HELP_INSTANCENAME_LINES = [
    'An instance path is specified using the INSTANCENAME argument',
    '1. By specifying the instance path as an untyped WBEM URI',
    '2. By specifying the class path of the creation class of the instance',
    '3. By specifying the class path of the creation class of the instance',
]

INSTANCE_ASSOCIATORS_HELP_LINES = [
    # pylint: disable=line-too-long
    'Usage: pywbemcli [GENERAL-OPTIONS] instance associators INSTANCENAME [COMMAND-OPTIONS]',  # noqa: E501
    'List the instances associated with an instance.',
    '--ac, --assoc-class CLASSNAME Filter the result set by association clas',
    '--rc, --result-class CLASSNAME Filter the result set by result class',
    '-r, --role PROPERTYNAME Filter the result set by source end role',
    '--rr, --result-role PROPERTYNAME Filter the result set by far end role',
    CMD_OPTION_INCLUDE_QUALIFIERS_LIST_HELP_LINE,
    CMD_OPTION_INCLUDE_CLASSORIGIN_HELP_LINE,
    CMD_OPTION_PROPERTYLIST_HELP_LINE,
    CMD_OPTION_NAMES_ONLY_HELP_LINE,
    CMD_OPTION_NAMESPACE_HELP_LINE,

Answer:     CMD_OPTION_SUMMARY_HELP_LINE,