예제 #1
0
def test_WBEMListener_incorrect_headers(desc, headers, exp_status,
                                        exp_headers):
    # pylint: disable=unused-argument
    """
    Verify that WBEMListener send fails when incorrect HTTP headers are used
    (along with the correct POST method).
    """

    host = 'localhost'
    http_port = 50000
    url = 'http://{}:{}'.format(host, http_port)
    # headers = copy(headers)

    listener = WBEMListener(host, http_port)
    listener.add_callback(process_indication)
    listener.start()

    try:

        # The code to be tested is running in listener thread
        response = post_bsl(url, headers=headers, data=None)

        assert response.status_code == exp_status
        for header_name in exp_headers:
            assert header_name in response.headers
            exp_header_pattern = exp_headers[header_name]
            assert re.match(exp_header_pattern, response.headers[header_name])

    finally:
        listener.stop()
예제 #2
0
def test_WBEMListener_incorrect_method(method, exp_status):
    """
    Verify that WBEMListener send fails when an incorrect HTTP method is used.
    """

    host = 'localhost'
    http_port = 50000
    url = 'http://{}:{}'.format(host, http_port)
    headers = {
        'Content-Type': 'application/xml; charset=utf-8',
        'CIMExport': 'MethodRequest',
        'CIMExportMethod': 'ExportIndication',
        'Accept-Encoding': 'Identity',
        'CIMProtocolVersion': '1.4',
    }

    listener = WBEMListener(host, http_port)
    listener.add_callback(process_indication)
    listener.start()

    try:

        # The code to be tested is running in listener thread
        response = requests.request(method, url, headers=headers, timeout=4)

        assert response.status_code == exp_status

    finally:
        listener.stop()
예제 #3
0
def test_WBEMListener_init(testcase, init_args, init_kwargs, exp_attrs):
    """
    Test function for WBEMListener.__init__()
    """

    # The code to be tested
    obj = WBEMListener(*init_args, **init_kwargs)

    # Ensure that exceptions raised in the remainder of this function
    # are not mistaken as expected exceptions
    assert testcase.exp_exc_types is None

    # Verify specified expected attributes
    for attr_name in exp_attrs:
        exp_attr = exp_attrs[attr_name]
        act_attr = getattr(obj, attr_name)
        assert act_attr == exp_attr
        assert isinstance(act_attr, type(exp_attr))

    # Verify attributes not set via init arguments

    assert isinstance(obj.logger, logging.Logger)
    assert re.match(r'pywbem\.listener\.', obj.logger.name)

    assert obj.http_started is False
    assert obj.https_started is False
    def test_context_mgr(self):
        # pylint: disable=no-self-use
        """
        Test starting the listener and automatic closing in a context manager.
        """

        host = 'localhost'

        # Don't use this port in other tests, to be on the safe side
        # as far as port reuse is concerned.
        http_port = '59998'

        # The code to be tested (is the context manager)
        with WBEMListener(host, http_port) as listener1:

            # Verify that CM enter returns the listener
            assert isinstance(listener1, WBEMListener)

            listener1.start()
            assert listener1.http_started is True

        # Verify that CM exit stops the listener
        assert listener1.http_started is False

        # Verify that the TCP/IP port can be used again
        listener2 = WBEMListener(host, http_port)
        listener2.start()
        assert listener2.http_started is True
        listener2.stop()
예제 #5
0
    def createlistener(host,
                       http_port=None,
                       https_port=None,
                       certfile=None,
                       keyfile=None):
        """
        Create and start a listener based on host, ports, etc.
        """
        global RCV_COUNT  # pylint: disable=global-statement
        global LISTENER  # pylint: disable=global-statement
        global RCV_FAIL  # pylint: disable=global-statement
        RCV_FAIL = False  # pylint: disable=global-statement

        _logging.basicConfig(stream=_sys.stderr,
                             level=_logging.WARNING,
                             format='%(levelname)s: %(message)s')

        RCV_COUNT = 0
        LISTENER = WBEMListener(host=host,
                                http_port=http_port,
                                https_port=https_port,
                                certfile=certfile,
                                keyfile=keyfile)
        LISTENER.add_callback(_process_indication)
        LISTENER.start()
예제 #6
0
    def test_attrs(self):
        """
        Test WBEMListener attributes.
        """

        host = 'localhost'
        http_port = '50000'  # as a string
        exp_http_port = 50000  # as an integer

        listener = WBEMListener(host, http_port)
        assert listener.host == host
        assert listener.http_port == exp_http_port
        assert listener.https_port is None
        assert listener.certfile is None
        assert listener.keyfile is None
        assert isinstance(listener.logger, _logging.Logger)
        assert listener.http_started is False
        assert listener.https_started is False
예제 #7
0
def test_WBEMListener_incorrect_payload2(desc, payload, exp_status,
                                         exp_headers, exp_payload):
    # pylint: disable=unused-argument
    """
    Verify that WBEMListener send fails with export response indicating error
    when incorrect HTTP payload is used that triggers that.
    """

    host = 'localhost'
    http_port = 50000
    url = 'http://{}:{}'.format(host, http_port)
    headers = {
        'Content-Type': 'application/xml; charset=utf-8',
        'CIMExport': 'MethodRequest',
        'CIMExportMethod': 'ExportIndication',
        'Accept-Encoding': 'Identity',
        'CIMProtocolVersion': '1.4',
    }

    listener = WBEMListener(host, http_port)
    listener.add_callback(process_indication)
    listener.start()

    try:

        # The code to be tested is running in listener thread
        response = post_bsl(url, headers=headers, data=payload)

        assert response.status_code == exp_status
        for header_name in exp_headers:
            assert header_name in response.headers
            exp_header_pattern = exp_headers[header_name]
            assert re.match(exp_header_pattern, response.headers[header_name])
        act_payload = response.content
        re.match(exp_payload, act_payload, re.MULTILINE)

    finally:
        listener.stop()
예제 #8
0
def test_WBEMListener_send_indications(send_count):
    """
    Test performance of sending indications to the pywbem.WBEMListener.
    """

    if send_count > 100 and sys.platform == 'win32':
        pytest.skip("Skipping test due to lengthy elapsed time")

    host = 'localhost'
    http_port = 50000

    listener = WBEMListener(host, http_port)
    listener.add_callback(process_indication)
    listener.start()

    # Warm up
    send_indications(host, http_port, 10)

    repetitions = 5
    try:
        times = []
        for _ in range(0, repetitions):
            time = send_indications(host, http_port, send_count)
            times.append(time)
        mean_time = statistics.mean(times)
        stdev_time = statistics.stdev(times)
        mean_rate = send_count / mean_time

        print("\nSent {} indications ({} repetitions): mean: {:.3f} s, "
              "stdev: {:.3f} s, mean rate: {:.0f} ind/s".
              format(send_count, repetitions, mean_time, stdev_time, mean_rate))
        sys.stdout.flush()

    finally:
        listener.stop()

        # Give some time to free up the port
        sleep(1.0)
예제 #9
0
def test_WBEMListener_start_stop():
    """
    Test starting and stopping of the listener.
    """

    host = 'localhost'
    http_port = '50000'

    listener = WBEMListener(host, http_port)
    assert listener.http_started is False
    assert listener.https_started is False

    listener.start()
    assert listener.http_started is True
    assert listener.https_started is False

    listener.stop()
    assert listener.http_started is False
    assert listener.https_started is False
예제 #10
0
    def createlistener(host, http_port=None, https_port=None,
                       certfile=None, keyfile=None):

        global RCV_COUNT
        global LISTENER
        global RCV_FAIL
        RCV_FAIL = False

        _logging.basicConfig(stream=_sys.stderr, level=_logging.WARNING,
                             format='%(levelname)s: %(message)s')

        RCV_COUNT = 0
        LISTENER = WBEMListener(host=host,
                                http_port=http_port,
                                https_port=https_port,
                                certfile=certfile,
                                keyfile=keyfile)
        LISTENER.add_callback(_process_indication)
        LISTENER.start()
예제 #11
0
    def test_start_stop(self):
        # pylint: disable=no-self-use
        """
        Test starting and stopping of the the listener.
        """

        host = 'localhost'
        http_port = '50000'

        listener = WBEMListener(host, http_port)
        assert listener.http_started is False
        assert listener.https_started is False

        listener.start()
        assert listener.http_started is True
        assert listener.https_started is False

        listener.stop()
        assert listener.http_started is False
        assert listener.https_started is False
예제 #12
0
    def test_port_in_use(self):
        # pylint: disable=no-self-use
        """
        Test starting the listener when port is in use by another listener.
        """

        host = 'localhost'

        # Don't use this port in other tests, to be on the safe side
        # as far as port reuse is concerned.
        http_port = '59999'

        exp_exc_type = OSError

        listener1 = WBEMListener(host, http_port)
        listener1.start()
        assert listener1.http_started is True

        listener2 = WBEMListener(host, http_port)

        try:

            # The code to be tested
            listener2.start()

        except Exception as exc:  # pylint: disable=broad-except
            # e.g. on Linux
            assert isinstance(exc, exp_exc_type)
            assert getattr(exc, 'errno', None) == errno.EADDRINUSE
            assert listener2.http_started is False
        else:
            # e.g. on Windows
            assert listener2.http_started is True

        # Verify that in any case, listener1 is still started
        assert listener1.http_started is True

        listener1.stop()  # cleanup
        listener2.stop()  # cleanup (for cases where it started)
예제 #13
0
def test_WBEMListener_send_indications(send_count):
    """
    Test WBEMListener with an indication generator.

    This test sends the number of indications defined by the send_count
    parameter using HTTP. It confirms that they are all received by the
    listener.

    This test validates the main paths of the listener and that the listener can
    receive large numbers of indications without duplicates or dropping
    indications.

    It does not validate all of the possible xml options on indications.

    Creates the listener, starts the listener, creates the indication XML and
    adds sequence number and time to the indication instance and sends that
    instance using requests.

    The indication instance is modified for each indication count so that each
    carries its own sequence number.
    """

    # Note: Global variables that are modified must be declared global
    global RCV_COUNT  # pylint: disable=global-statement
    global RCV_ERRORS  # pylint: disable=global-statement

    # Enable logging for this test function
    if LOGLEVEL > logging.NOTSET:
        logging.getLogger('').setLevel(LOGLEVEL)

    # Fixes issue #528 where on Windows, localhost adds multisecond delay
    # probably due to hosts table or DNS misconfiguration.
    if sys.platform == 'win32':
        host = '127.0.0.1'
    else:
        host = 'localhost'
    http_port = 50000

    listener = WBEMListener(host, http_port)
    listener.add_callback(process_indication)
    listener.start()

    try:

        start_time = time()
        url = 'http://{}:{}'.format(host, http_port)
        cim_protocol_version = '1.4'
        headers = {
            'Content-Type': 'application/xml; charset=utf-8',
            'CIMExport': 'MethodRequest',
            'CIMExportMethod': 'ExportIndication',
            'Accept-Encoding': 'Identity',
            'CIMProtocolVersion': cim_protocol_version,
        }
        # We include Accept-Encoding because of requests issue.
        # He supplies it if we don't.  TODO try None

        delta_time = time() - start_time
        random_base = randint(1, 10000)
        timer = ElapsedTimer()

        RCV_COUNT = 0
        RCV_ERRORS = False

        for i in range(send_count):

            msg_id = random_base + i
            payload = create_indication_data(msg_id, i, delta_time,
                                             cim_protocol_version)

            LOGGER.debug("Testcase sending indication #%s", i)

            try:
                response = post_bsl(url, headers=headers, data=payload)
            except requests.exceptions.RequestException as exc:
                msg = ("Testcase sending indication #{} raised {}: {}".format(
                    i, exc.__class__.__name__, exc))
                LOGGER.error(msg)
                new_exc = AssertionError(msg)
                new_exc.__cause__ = None  # Disable to see original traceback
                raise new_exc

            LOGGER.debug(
                "Testcase received response from sending "
                "indication #%s", i)

            if response.status_code != 200:
                msg = ("Testcase sending indication #{} failed with HTTP "
                       "status {}".format(i, response.status_code))
                LOGGER.error(msg)
                raise AssertionError(msg)

        endtime = timer.elapsed_sec()

        # Make sure the listener thread has processed all indications
        sleep(1)

        if VERBOSE_SUMMARY:
            print("\nSent {} indications in {} sec or {:.2f} ind/sec".format(
                send_count, endtime, (send_count / endtime)))
            sys.stdout.flush()

        assert not RCV_ERRORS, \
            "Errors occurred in process_indication(), as printed to stdout"

        assert send_count == RCV_COUNT, \
            "Mismatch between total send count {} and receive count {}". \
            format(send_count, RCV_COUNT)

    finally:
        listener.stop()

        # Disable logging for this test function
        if LOGLEVEL > logging.NOTSET:
            logging.getLogger('').setLevel(logging.NOTSET)
예제 #14
0
    assert isinstance(obj.logger, logging.Logger)
    assert re.match(r'pywbem\.listener\.', obj.logger.name)

    assert obj.http_started is False
    assert obj.https_started is False


TESTCASES_WBEMLISTENER_STR = [

    # Testcases for WBEMListener.__str__() / str()

    # Each list item is a testcase tuple with these items:
    # * obj: WBEMListener object to be tested.
    (WBEMListener(host='woot.com',
                  http_port=6997,
                  https_port=6998,
                  certfile='certfile.pem',
                  keyfile='keyfile.pem')),
]


@pytest.mark.parametrize("obj", TESTCASES_WBEMLISTENER_STR)
def test_WBEMListener_str(obj):
    """
    Test function for WBEMListener.__str__() / str()
    """

    # The code to be tested
    result = str(obj)

    assert re.match(r'^WBEMListener\(', result)
예제 #15
0
def run_test(svr_url, listener_host, user, password, http_listener_port, \
             https_listener_port, requested_indications, repeat_loop):
    """
        Runs a test that:
        1. Creates a server
        2. Creates a dynamic listener and starts ti
        3. Creates a filter and subscription
        4. Calls the server to execute a method that creates an indication
        5. waits for indications to be received.
        6. Removes the filter and subscription and stops the listener
    """
    if os.path.exists(LOGFILE):
        os.remove(LOGFILE)
    try:
        conn = WBEMConnection(svr_url, (user, password), no_verification=True)
        server = WBEMServer(conn)

        # Create subscription_manager here to be sure we can communicate with
        # server before Creating listener, etc.
        sub_mgr = WBEMSubscriptionManager(
            subscription_manager_id='pegasusIndicationTest')

        # Add server to subscription manager
        server_id = sub_mgr.add_server(server)
        old_filters = sub_mgr.get_all_filters(server_id)
        old_subs = sub_mgr.get_all_subscriptions(server_id)
        # TODO filter for our sub mgr
        if len(old_subs) != 0 or len(old_filters) != 0:
            sub_mgr.remove_subscriptions(server_id,
                                         [inst.path for inst in old_subs])
            for filter_ in old_filters:
                sub_mgr.remove_filter(server_id, filter_.path)

    except ConnectionError as ce:
        print('Connection Error %s with %s' % (ce, svr_url))
        sys.exit(2)

    except Error as er:
        print('Error communicationg with WBEMServer %s' % er)
        sys.exit(1)

    # Create the listener and listener call back and start the listener
    #pylint: disable=global-statement
    global LISTENER
    ####stream=sys.stderr,
    logging.basicConfig(filename='pegasusindicationtest.log',
                        level=logging.INFO,
                        format='%(asctime)s %(levelname)s: %(message)s')
    # Create and start local listener
    LISTENER = WBEMListener(listener_host,
                            http_port=http_listener_port,
                            https_port=https_listener_port)

    # Start connect and start listener.
    LISTENER.add_callback(consume_indication)
    LISTENER.start()

    listener_url = '%s://%s:%s' % ('http', 'localhost', http_listener_port)
    sub_mgr.add_listener_destinations(server_id, listener_url)

    # Create a dynamic alert indication filter and subscribe for it
    filter_ = sub_mgr.add_filter(server_id,
                                 TEST_CLASS_NAMESPACE,
                                 TEST_QUERY,
                                 query_language="DMTF:CQL")
    subscriptions = sub_mgr.add_subscriptions(server_id, filter_.path)

    # Request server to create indications by invoking method
    # This is pegasus specific
    class_name = CIMClassName(TEST_CLASS, namespace=TEST_CLASS_NAMESPACE)

    while repeat_loop > 0:
        repeat_loop += -1
        global RECEIVED_INDICATION_COUNT, INDICATION_START_TIME
        RECEIVED_INDICATION_COUNT = 0
        INDICATION_START_TIME = None
        if send_request_for_indications(conn, class_name,
                                        requested_indications):
            # Wait for indications to be received.
            success = wait_for_indications(requested_indications)
            if not success:
                insts = conn.EnumerateInstances('PG_ListenerDestinationQueue',
                                                namespace='root/PG_Internal')
                for inst in insts:
                    print('%s queueFullDropped %s, maxretry %s, InQueue %s' % \
                          (inst['ListenerDestinationName'],
                           inst['QueueFullDroppedIndications'],
                           inst['RetryAttemptsExceededIndications'],
                           inst['CurrentIndications']))
        if repeat_loop > 0:
            time.sleep(requested_indications / 150)

    sub_mgr.remove_subscriptions(server_id,
                                 [inst.path for inst in subscriptions])
    sub_mgr.remove_filter(server_id, filter_.path)
    sub_mgr.remove_server(server_id)
    LISTENER.stop()

    # Test for all expected indications received.
    if RECEIVED_INDICATION_COUNT != requested_indications:
        print('Incorrect count of indications received expected=%s, received'
              '=%s' % (requested_indications, RECEIVED_INDICATION_COUNT))
        sys.exit(1)
    else:
        print('Success, %s indications' % requested_indications)
    print('Max time between indications %s' % MAX_TIME_BETWEEN_INDICATIONS)
예제 #16
0
def run_test(
    svr_url, listener_host, user, password, http_listener_port, https_listener_port, requested_indications, repeat_loop
):
    """
        Runs a test that:
        1. Creates a server
        2. Creates a dynamic listener and starts ti
        3. Creates a filter and subscription
        4. Calls the server to execute a method that creates an indication
        5. waits for indications to be received.
        6. Removes the filter and subscription and stops the listener
    """
    if os.path.exists(LOGFILE):
        os.remove(LOGFILE)
    try:
        conn = WBEMConnection(svr_url, (user, password), no_verification=True)
        server = WBEMServer(conn)

        # Create subscription_manager here to be sure we can communicate with
        # server before Creating listener, etc.
        sub_mgr = WBEMSubscriptionManager(subscription_manager_id="pegasusIndicationTest")

        # Add server to subscription manager
        server_id = sub_mgr.add_server(server)
        old_filters = sub_mgr.get_all_filters(server_id)
        old_subs = sub_mgr.get_all_subscriptions(server_id)
        # TODO filter for our sub mgr
        if len(old_subs) != 0 or len(old_filters) != 0:
            sub_mgr.remove_subscriptions(server_id, [inst.path for inst in old_subs])
            for filter_ in old_filters:
                sub_mgr.remove_filter(server_id, filter_.path)

    except ConnectionError as ce:
        print("Connection Error %s with %s" % (ce, svr_url))
        sys.exit(2)

    except Error as er:
        print("Error communicationg with WBEMServer %s" % er)
        sys.exit(1)

    # Create the listener and listener call back and start the listener
    # pylint: disable=global-statement
    global LISTENER
    ####stream=sys.stderr,
    logging.basicConfig(
        filename="pegasusindicationtest.log", level=logging.INFO, format="%(asctime)s %(levelname)s: %(message)s"
    )
    # Create and start local listener
    LISTENER = WBEMListener(listener_host, http_port=http_listener_port, https_port=https_listener_port)

    # Start connect and start listener.
    LISTENER.add_callback(consume_indication)
    LISTENER.start()

    listener_url = "%s://%s:%s" % ("http", "localhost", http_listener_port)
    sub_mgr.add_listener_destinations(server_id, listener_url)

    # Create a dynamic alert indication filter and subscribe for it
    filter_ = sub_mgr.add_filter(server_id, TEST_CLASS_NAMESPACE, TEST_QUERY, query_language="DMTF:CQL")
    subscriptions = sub_mgr.add_subscriptions(server_id, filter_.path)

    # Request server to create indications by invoking method
    # This is pegasus specific
    class_name = CIMClassName(TEST_CLASS, namespace=TEST_CLASS_NAMESPACE)

    while repeat_loop > 0:
        repeat_loop += -1
        global RECEIVED_INDICATION_COUNT, INDICATION_START_TIME
        RECEIVED_INDICATION_COUNT = 0
        INDICATION_START_TIME = None
        if send_request_for_indications(conn, class_name, requested_indications):
            # Wait for indications to be received.
            success = wait_for_indications(requested_indications)
            if not success:
                insts = conn.EnumerateInstances("PG_ListenerDestinationQueue", namespace="root/PG_Internal")
                for inst in insts:
                    print(
                        "%s queueFullDropped %s, maxretry %s, InQueue %s"
                        % (
                            inst["ListenerDestinationName"],
                            inst["QueueFullDroppedIndications"],
                            inst["RetryAttemptsExceededIndications"],
                            inst["CurrentIndications"],
                        )
                    )
        if repeat_loop > 0:
            time.sleep(requested_indications / 150)

    sub_mgr.remove_subscriptions(server_id, [inst.path for inst in subscriptions])
    sub_mgr.remove_filter(server_id, filter_.path)
    sub_mgr.remove_server(server_id)
    LISTENER.stop()

    # Test for all expected indications received.
    if RECEIVED_INDICATION_COUNT != requested_indications:
        print(
            "Incorrect count of indications received expected=%s, received"
            "=%s" % (requested_indications, RECEIVED_INDICATION_COUNT)
        )
        sys.exit(1)
    else:
        print("Success, %s indications" % requested_indications)
    print("Max time between indications %s" % MAX_TIME_BETWEEN_INDICATIONS)