2015-08-24 12:18:54 -04:00

264 lines
8.2 KiB
Python

#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
#
import gc
import time
try:
from proton import VERSION_MAJOR, VERSION_MINOR
except ImportError:
# older proton did not export version info
VERSION_MAJOR = 0
VERSION_MINOR = 0
import pyngus
class Test(object):
PROTON_VERSION = (int(VERSION_MAJOR), int(VERSION_MINOR))
def __init__(self, name):
self.name = name
def configure(self, config):
self.config = config
def default(self, name, value, **profiles):
default = value
profile = self.config.defines.get("profile")
if profile:
default = profiles.get(profile, default)
return self.config.defines.get(name, default)
def setup(self):
gc.enable()
gc.collect()
assert not gc.garbage, "Object leak: %s" % str(gc.garbage)
def teardown(self):
gc.collect()
assert not gc.garbage, "Object leak: %s" % str(gc.garbage)
@property
def delay(self):
return float(self.default("delay", "1", fast="0.1"))
@property
def timeout(self):
return float(self.default("timeout", "60", fast="10"))
@property
def verbose(self):
return int(self.default("verbose", 0))
class Skipped(Exception):
"""Throw to skip a test without generating a test failure."""
skipped = True
def do_connection_io(c1, c2):
"""Transfer data between two Connection objects, return True if I/O
occured."""
def _do_io(src, dst):
count = min(src.has_output, dst.needs_input)
if count > 0:
count = dst.process_input(src.output_data())
if count > 0:
src.output_written(count)
return count
o1 = _do_io(c1, c2)
o2 = _do_io(c2, c1)
return o1 > 0 or o2 > 0
def process_connections(c1, c2, timestamp=None):
"""Do I/O and protocol processing on two connected Connections until no
further data is transferred."""
if timestamp is None:
timestamp = time.time()
c1.process(timestamp)
c2.process(timestamp)
while do_connection_io(c1, c2):
c1.process(timestamp)
c2.process(timestamp)
def _validate_conn_callback(connection):
"""Callbacks must only occur when holding the Connection callback lock"""
assert connection._callback_lock.in_callback, \
connection._callback_lock.in_callback
def _validate_link_callback(link):
"""Callbacks must only occur when holding the Link callback lock."""
assert link._callback_lock.in_callback, link._callback_lock.in_callback
class ConnCallback(pyngus.ConnectionEventHandler):
"""Caches the callback parameters for processing by a test."""
class RequestArgs(object):
def __init__(self, handle, name, source, target, props):
self.link_handle = handle
self.name = name
self.requested_source = source
self.requested_target = target
self.properties = props
def __init__(self):
self.active_ct = 0
self.failed_ct = 0
self.failed_error = None
self.remote_closed_ct = 0
self.remote_closed_error = None
self.closed_ct = 0
self.sender_requested_ct = 0
self.sender_requested_args = []
self.receiver_requested_ct = 0
self.receiver_requested_args = []
self.sasl_step_ct = 0
self.sasl_done_ct = 0
self.sasl_done_outcome = None
def connection_active(self, connection):
_validate_conn_callback(connection)
self.active_ct += 1
def connection_failed(self, connection, error):
_validate_conn_callback(connection)
self.failed_ct += 1
self.failed_error = error
def connection_remote_closed(self, connection, error=None):
_validate_conn_callback(connection)
self.remote_closed_ct += 1
self.remote_closed_error = error
def connection_closed(self, connection):
_validate_conn_callback(connection)
self.closed_ct += 1
def sender_requested(self, connection, link_handle,
name, requested_source,
properties):
_validate_conn_callback(connection)
self.sender_requested_ct += 1
args = ConnCallback.RequestArgs(link_handle, name,
requested_source, None,
properties)
self.sender_requested_args.append(args)
def receiver_requested(self, connection, link_handle,
name, requested_target,
properties):
_validate_conn_callback(connection)
self.receiver_requested_ct += 1
args = ConnCallback.RequestArgs(link_handle, name,
None, requested_target,
properties)
self.receiver_requested_args.append(args)
def sasl_step(self, connection, pn_sasl):
_validate_conn_callback(connection)
self.sasl_step_ct += 1
def sasl_done(self, connection, pn_sasl, result):
_validate_conn_callback(connection)
self.sasl_done_ct += 1
self.sasl_done_outcome = result
class SenderCallback(pyngus.SenderEventHandler):
def __init__(self):
self.active_ct = 0
self.remote_closed_ct = 0
self.remote_closed_error = None
self.closed_ct = 0
self.credit_granted_ct = 0
def sender_active(self, sender_link):
_validate_link_callback(sender_link)
self.active_ct += 1
def sender_remote_closed(self, sender_link, error=None):
_validate_link_callback(sender_link)
self.remote_closed_ct += 1
self.remote_closed_error = error
def sender_closed(self, sender_link):
_validate_link_callback(sender_link)
self.closed_ct += 1
def credit_granted(self, sender_link):
_validate_link_callback(sender_link)
self.credit_granted_ct += 1
class DeliveryCallback(object):
"""Capture the message delivery callback for a sent message."""
def __init__(self):
self.link = None
self.handle = None
self.status = None
self.info = None
self.count = 0
def __call__(self, link, handle, status, info):
_validate_link_callback(link)
self.link = link
self.handle = handle
self.status = status
self.info = info
self.count += 1
class ReceiverCallback(pyngus.ReceiverEventHandler):
def __init__(self):
self.active_ct = 0
self.remote_closed_ct = 0
self.remote_closed_error = None
self.closed_ct = 0
self.message_received_ct = 0
self.received_messages = []
def receiver_active(self, receiver_link):
_validate_link_callback(receiver_link)
_validate_conn_callback(receiver_link.connection)
self.active_ct += 1
def receiver_remote_closed(self, receiver_link, error=None):
_validate_link_callback(receiver_link)
_validate_conn_callback(receiver_link.connection)
self.remote_closed_ct += 1
self.remote_closed_error = error
def receiver_closed(self, receiver_link):
_validate_link_callback(receiver_link)
_validate_conn_callback(receiver_link.connection)
self.closed_ct += 1
def message_received(self, receiver_link, message, handle):
_validate_link_callback(receiver_link)
_validate_conn_callback(receiver_link.connection)
self.message_received_ct += 1
self.received_messages.append((message, handle))