summaryrefslogtreecommitdiff
path: root/qpid/python
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/python')
-rw-r--r--qpid/python/.gitignore3
-rw-r--r--qpid/python/LICENSE.txt203
-rw-r--r--qpid/python/MANIFEST.in4
-rw-r--r--qpid/python/NOTICE.txt5
-rw-r--r--qpid/python/README.md91
-rw-r--r--qpid/python/examples/README.txt42
-rwxr-xr-xqpid/python/examples/api/drain97
-rwxr-xr-xqpid/python/examples/api/hello52
-rwxr-xr-xqpid/python/examples/api/hello_xml77
-rwxr-xr-xqpid/python/examples/api/server95
-rwxr-xr-xqpid/python/examples/api/spout133
-rw-r--r--qpid/python/examples/api/statistics.py139
-rw-r--r--qpid/python/examples/reservations/common.py80
-rwxr-xr-xqpid/python/examples/reservations/inventory94
-rwxr-xr-xqpid/python/examples/reservations/machine-agent103
-rwxr-xr-xqpid/python/examples/reservations/reserve197
-rw-r--r--qpid/python/mllib/__init__.py86
-rw-r--r--qpid/python/mllib/dom.py310
-rw-r--r--qpid/python/mllib/parsers.py139
-rw-r--r--qpid/python/mllib/transforms.py164
-rwxr-xr-xqpid/python/qpid-python-test639
-rw-r--r--qpid/python/qpid-python-test-ant.xml192
-rwxr-xr-xqpid/python/qpid-python-test.bat2
-rw-r--r--qpid/python/qpid/__init__.py84
-rw-r--r--qpid/python/qpid/client.py286
-rw-r--r--qpid/python/qpid/codec.py701
-rw-r--r--qpid/python/qpid/codec010.py404
-rw-r--r--qpid/python/qpid/compat.py222
-rw-r--r--qpid/python/qpid/concurrency.py106
-rw-r--r--qpid/python/qpid/connection.py250
-rw-r--r--qpid/python/qpid/connection08.py600
-rw-r--r--qpid/python/qpid/content.py58
-rw-r--r--qpid/python/qpid/datatypes.py385
-rw-r--r--qpid/python/qpid/debug.py55
-rw-r--r--qpid/python/qpid/delegate.py53
-rw-r--r--qpid/python/qpid/delegates.py215
-rw-r--r--qpid/python/qpid/disp.py236
-rw-r--r--qpid/python/qpid/exceptions.py22
-rw-r--r--qpid/python/qpid/framer.py128
-rw-r--r--qpid/python/qpid/framing.py313
-rw-r--r--qpid/python/qpid/generator.py56
-rw-r--r--qpid/python/qpid/harness.py20
-rw-r--r--qpid/python/qpid/lexer.py118
-rw-r--r--qpid/python/qpid/log.py28
-rw-r--r--qpid/python/qpid/management.py922
-rw-r--r--qpid/python/qpid/managementdata.py773
-rw-r--r--qpid/python/qpid/message.py73
-rw-r--r--qpid/python/qpid/messaging/__init__.py35
-rw-r--r--qpid/python/qpid/messaging/address.py172
-rw-r--r--qpid/python/qpid/messaging/constants.py40
-rw-r--r--qpid/python/qpid/messaging/driver.py1451
-rw-r--r--qpid/python/qpid/messaging/endpoints.py1195
-rw-r--r--qpid/python/qpid/messaging/exceptions.py179
-rw-r--r--qpid/python/qpid/messaging/message.py173
-rw-r--r--qpid/python/qpid/messaging/transports.py236
-rw-r--r--qpid/python/qpid/messaging/util.py64
-rw-r--r--qpid/python/qpid/mimetype.py106
-rw-r--r--qpid/python/qpid/ops.py294
-rw-r--r--qpid/python/qpid/packer.py36
-rw-r--r--qpid/python/qpid/parser.py68
-rw-r--r--qpid/python/qpid/peer.py533
-rw-r--r--qpid/python/qpid/queue.py88
-rw-r--r--qpid/python/qpid/reference.py117
-rw-r--r--qpid/python/qpid/sasl.py119
-rw-r--r--qpid/python/qpid/saslmech/__init__.py22
-rw-r--r--qpid/python/qpid/saslmech/amqplain.py28
-rw-r--r--qpid/python/qpid/saslmech/anonymous.py27
-rw-r--r--qpid/python/qpid/saslmech/cram_md5.py27
-rw-r--r--qpid/python/qpid/saslmech/cram_md5_hex.py30
-rw-r--r--qpid/python/qpid/saslmech/external.py27
-rw-r--r--qpid/python/qpid/saslmech/finder.py66
-rw-r--r--qpid/python/qpid/saslmech/plain.py28
-rw-r--r--qpid/python/qpid/saslmech/sasl.py44
-rw-r--r--qpid/python/qpid/saslmech/scram.py91
-rw-r--r--qpid/python/qpid/saslmech/scram_sha_1.py27
-rw-r--r--qpid/python/qpid/saslmech/scram_sha_256.py25
-rw-r--r--qpid/python/qpid/selector.py167
-rw-r--r--qpid/python/qpid/session.py308
-rw-r--r--qpid/python/qpid/spec08.py504
-rw-r--r--qpid/python/qpid/specs/amqp-0-10-qpid-errata-stripped.xml1203
-rw-r--r--qpid/python/qpid/specs/amqp-0-10-stripped.xml1200
-rw-r--r--qpid/python/qpid/specs/amqp-0-10.dtd246
-rw-r--r--qpid/python/qpid/specs/amqp-0-8-qpid-stripped.xml784
-rw-r--r--qpid/python/qpid/specs/amqp-0-9-1-stripped.xml477
-rw-r--r--qpid/python/qpid/specs/amqp-0-9-qpid-stripped.xml876
-rw-r--r--qpid/python/qpid/specs_config.py26
-rw-r--r--qpid/python/qpid/testlib.py241
-rw-r--r--qpid/python/qpid/tests/__init__.py62
-rw-r--r--qpid/python/qpid/tests/codec.py729
-rw-r--r--qpid/python/qpid/tests/codec010.py133
-rw-r--r--qpid/python/qpid/tests/connection.py227
-rw-r--r--qpid/python/qpid/tests/datatypes.py296
-rw-r--r--qpid/python/qpid/tests/framing.py289
-rw-r--r--qpid/python/qpid/tests/messaging/__init__.py236
-rw-r--r--qpid/python/qpid/tests/messaging/address.py321
-rw-r--r--qpid/python/qpid/tests/messaging/endpoints.py1476
-rw-r--r--qpid/python/qpid/tests/messaging/implementation.py28
-rw-r--r--qpid/python/qpid/tests/messaging/message.py187
-rw-r--r--qpid/python/qpid/tests/mimetype.py56
-rw-r--r--qpid/python/qpid/tests/parser.py37
-rw-r--r--qpid/python/qpid/tests/queue.py71
-rw-r--r--qpid/python/qpid/tests/saslmech/__init__.py19
-rw-r--r--qpid/python/qpid/tests/saslmech/finder.py71
-rw-r--r--qpid/python/qpid/tests/saslmech/my_sasl.py22
-rw-r--r--qpid/python/qpid/tests/saslmech/my_sasl2.py28
-rw-r--r--qpid/python/qpid/tests/spec010.py74
-rw-r--r--qpid/python/qpid/tests/util.py52
-rw-r--r--qpid/python/qpid/util.py208
-rw-r--r--qpid/python/qpid/validator.py107
-rw-r--r--qpid/python/qpid_tests/__init__.py22
-rw-r--r--qpid/python/qpid_tests/broker_0_10/__init__.py39
-rw-r--r--qpid/python/qpid_tests/broker_0_10/alternate_exchange.py351
-rw-r--r--qpid/python/qpid_tests/broker_0_10/broker.py93
-rw-r--r--qpid/python/qpid_tests/broker_0_10/dtx.py790
-rw-r--r--qpid/python/qpid_tests/broker_0_10/example.py95
-rw-r--r--qpid/python/qpid_tests/broker_0_10/exchange.py558
-rw-r--r--qpid/python/qpid_tests/broker_0_10/extensions.py87
-rw-r--r--qpid/python/qpid_tests/broker_0_10/lvq.py122
-rw-r--r--qpid/python/qpid_tests/broker_0_10/management.py726
-rw-r--r--qpid/python/qpid_tests/broker_0_10/message.py1117
-rw-r--r--qpid/python/qpid_tests/broker_0_10/msg_groups.py1195
-rw-r--r--qpid/python/qpid_tests/broker_0_10/new_api.py358
-rw-r--r--qpid/python/qpid_tests/broker_0_10/persistence.py68
-rw-r--r--qpid/python/qpid_tests/broker_0_10/priority.py252
-rw-r--r--qpid/python/qpid_tests/broker_0_10/qmf_events.py83
-rw-r--r--qpid/python/qpid_tests/broker_0_10/query.py247
-rw-r--r--qpid/python/qpid_tests/broker_0_10/queue.py436
-rw-r--r--qpid/python/qpid_tests/broker_0_10/stats.py519
-rw-r--r--qpid/python/qpid_tests/broker_0_10/threshold.py212
-rw-r--r--qpid/python/qpid_tests/broker_0_10/tx.py265
-rw-r--r--qpid/python/qpid_tests/broker_0_8/__init__.py22
-rw-r--r--qpid/python/qpid_tests/broker_0_8/basic.py441
-rw-r--r--qpid/python/qpid_tests/broker_0_8/broker.py120
-rw-r--r--qpid/python/qpid_tests/broker_0_8/example.py94
-rw-r--r--qpid/python/qpid_tests/broker_0_8/exchange.py349
-rw-r--r--qpid/python/qpid_tests/broker_0_8/queue.py255
-rw-r--r--qpid/python/qpid_tests/broker_0_8/testlib.py66
-rw-r--r--qpid/python/qpid_tests/broker_0_8/tx.py209
-rw-r--r--qpid/python/qpid_tests/broker_0_9/__init__.py22
-rw-r--r--qpid/python/qpid_tests/broker_0_9/echo.py159
-rw-r--r--qpid/python/qpid_tests/broker_0_9/messageheader.py61
-rw-r--r--qpid/python/qpid_tests/broker_0_9/query.py224
-rw-r--r--qpid/python/qpid_tests/broker_0_9/queue.py148
-rw-r--r--qpid/python/qpid_tests/broker_1_0/__init__.py26
-rw-r--r--qpid/python/qpid_tests/broker_1_0/general.py81
-rw-r--r--qpid/python/qpid_tests/broker_1_0/legacy_exchanges.py96
-rw-r--r--qpid/python/qpid_tests/broker_1_0/selector.py95
-rw-r--r--qpid/python/qpid_tests/broker_1_0/translation.py87
-rw-r--r--qpid/python/qpid_tests/broker_1_0/tx.py264
-rwxr-xr-xqpid/python/qpid_tests/client/client-api-example-tests.py338
-rw-r--r--qpid/python/qpid_tests/client/log4j.conf25
-rwxr-xr-xqpid/python/setup.py323
152 files changed, 0 insertions, 36304 deletions
diff --git a/qpid/python/.gitignore b/qpid/python/.gitignore
deleted file mode 100644
index 4fca027dea..0000000000
--- a/qpid/python/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-MANIFEST
-build
-dist
diff --git a/qpid/python/LICENSE.txt b/qpid/python/LICENSE.txt
deleted file mode 100644
index 6b0b1270ff..0000000000
--- a/qpid/python/LICENSE.txt
+++ /dev/null
@@ -1,203 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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.
-
diff --git a/qpid/python/MANIFEST.in b/qpid/python/MANIFEST.in
deleted file mode 100644
index a8a4f1d063..0000000000
--- a/qpid/python/MANIFEST.in
+++ /dev/null
@@ -1,4 +0,0 @@
-recursive-include examples *
-recursive-exclude examples verify verify.in
-include *.txt
-include *.md
diff --git a/qpid/python/NOTICE.txt b/qpid/python/NOTICE.txt
deleted file mode 100644
index b0a6e0a0fe..0000000000
--- a/qpid/python/NOTICE.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Apache Qpid Python Client
-Copyright 2006-2016 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
diff --git a/qpid/python/README.md b/qpid/python/README.md
deleted file mode 100644
index 25807a7990..0000000000
--- a/qpid/python/README.md
+++ /dev/null
@@ -1,91 +0,0 @@
-# Qpid Python
-
-This distribution contains a Python client implementation and AMQP
-conformance tests for Apache Qpid.
-
-Apache Qpid is a high speed, language independent, platform
-independent enterprise messaging system. It currently provides two
-messaging brokers (one implemented in C++, one implemented in Java),
-and messaging client libraries for Java JMS, C++, C# .NET, Python,
-Ruby, and WCF. The messaging protocol for Apache Qpid is AMQP
-(Advanced Message Queuing Protocol). You can read more about Qpid
-here:
-
- http://qpid.apache.org/
-
-Documentation can be found here:
-
- http://qpid.apache.org/documentation.html
-
-## Getting started
-
-1. Make sure the Qpid Python client libraries are on your PYTHONPATH.
- Extract the archive and add the local directory to your PYTHONPATH:
-
- $ tar -xf qpid-python-VERSION.tar.gz
- $ cd qpid-python-VERSION
- $ export PYTHONPATH=$PWD:$PYTHONPATH
-
-2. Make sure a broker is running.
-
-3. Run the 'hello' example from qpid-0.8/python/examples/api:
-
- $ cd examples/api
- $ ./hello
- Hello world!
-
-## Examples
-
-The examples/api directory contains several examples.
-
-Read examples/README.txt for further details on these examples.
-
-## Running the tests
-
-The "tests" directory contains a collection of unit tests for the
-python client. The "tests\_0-10", "tests\_0-9", and "tests\_0-8"
-directories contain protocol level conformance tests for AMQP brokers
-of the specified version.
-
-The qpid-python-test script may be used to run these tests. It will by
-default run the python unit tests and the 0-10 conformance tests:
-
-1. Run a broker on the default port.
-
-2. Run the tests:
-
- $ ./qpid-python-test
-
-If you wish to run the 0-8 or 0-9 conformence tests, they may be
-selected as follows:
-
-1. Run a broker on the default port.
-
-2. Run the tests:
-
- $ ./qpid-python-test tests_0-8.*
-
- [or]
-
- $ ./qpid-python-test tests_0-9.*
-
-See the qpid-python-test usage for for additional options:
-
- $ ./qpid-python-test -h
-
-## Installation
-
-Other Qpid components depend on Qpid Python for testing. You can use
-setup.py to install Qpid Python to a standard location:
-
- # User-local install
-
- $ python setup.py install --user
- $ export PYTHONPATH=$HOME/.local/lib/python2.7/site-packages
- $ export PATH=$HOME/.local/bin:$PATH
-
- [or]
-
- # System-wide install
-
- $ sudo python setup.py install
diff --git a/qpid/python/examples/README.txt b/qpid/python/examples/README.txt
deleted file mode 100644
index 4395160fec..0000000000
--- a/qpid/python/examples/README.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-The Python Examples
-===================
-
-README.txt -- This file.
-
-api -- Directory containing drain, spout,
- sever, hello, and hello_xml examples.
-
-api/drain -- A simple messaging client that prints
- messages from the source specified on
- the command line.
-
-api/spout -- A simple messaging client that sends
- messages to the target specified on the
- command line.
-
-api/server -- An example server that process incoming
- messages and sends replies.
-
-api/hello -- An example client that sends a message
- and then receives it.
-
-api/hello_xml -- An example client that sends a message
- to the xml exchange and then receives
- it.
-
-
-reservations -- Directory containing an example machine
- reservation system.
-
-reservations/common.py -- Utility code used by reserve,
- machine-agent, and inventory scripts.
-
-reservations/reserve -- Messaging client for listing, reserving,
- and releasing machines.
-
-reservations/machine-agent -- Messaging server that tracks and reports
- on the status of its host machine and
- listens for reservation requests.
-
-reservations/inventory -- Messaging server that tracks the last
- known status of machines.
diff --git a/qpid/python/examples/api/drain b/qpid/python/examples/api/drain
deleted file mode 100755
index 5e30153bc2..0000000000
--- a/qpid/python/examples/api/drain
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/usr/bin/env 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 optparse
-from qpid.messaging import *
-from qpid.util import URL
-from qpid.log import enable, DEBUG, WARN
-
-parser = optparse.OptionParser(usage="usage: %prog [options] ADDRESS ...",
- description="Drain messages from the supplied address.")
-parser.add_option("-b", "--broker", default="localhost",
- help="connect to specified BROKER (default %default)")
-parser.add_option("-c", "--count", type="int",
- help="number of messages to drain")
-parser.add_option("-f", "--forever", action="store_true",
- help="ignore timeout and wait forever")
-parser.add_option("-r", "--reconnect", action="store_true",
- help="enable auto reconnect")
-parser.add_option("-i", "--reconnect-interval", type="float", default=3,
- help="interval between reconnect attempts")
-parser.add_option("-l", "--reconnect-limit", type="int",
- help="maximum number of reconnect attempts")
-parser.add_option("-t", "--timeout", type="float", default=0,
- help="timeout in seconds to wait before exiting (default %default)")
-parser.add_option("-p", "--print", dest="format", default="%(M)s",
- help="format string for printing messages (default %default)")
-parser.add_option("-v", dest="verbose", action="store_true",
- help="enable logging")
-
-opts, args = parser.parse_args()
-
-if opts.verbose:
- enable("qpid", DEBUG)
-else:
- enable("qpid", WARN)
-
-if args:
- addr = args.pop(0)
-else:
- parser.error("address is required")
-if opts.forever:
- timeout = None
-else:
- timeout = opts.timeout
-
-class Formatter:
-
- def __init__(self, message):
- self.message = message
- self.environ = {"M": self.message,
- "P": self.message.properties,
- "C": self.message.content}
-
- def __getitem__(self, st):
- return eval(st, self.environ)
-
-conn = Connection(opts.broker,
- reconnect=opts.reconnect,
- reconnect_interval=opts.reconnect_interval,
- reconnect_limit=opts.reconnect_limit)
-try:
- conn.open()
- ssn = conn.session()
- rcv = ssn.receiver(addr)
-
- count = 0
- while not opts.count or count < opts.count:
- try:
- msg = rcv.fetch(timeout=timeout)
- print opts.format % Formatter(msg)
- count += 1
- ssn.acknowledge()
- except Empty:
- break
-except ReceiverError, e:
- print e
-except KeyboardInterrupt:
- pass
-
-conn.close()
diff --git a/qpid/python/examples/api/hello b/qpid/python/examples/api/hello
deleted file mode 100755
index ad314da19e..0000000000
--- a/qpid/python/examples/api/hello
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env 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 sys
-from qpid.messaging import *
-
-if len(sys.argv)<2:
- broker = "localhost:5672"
-else:
- broker = sys.argv[1]
-
-if len(sys.argv)<3:
- address = "amq.topic"
-else:
- address = sys.argv[2]
-
-connection = Connection(broker)
-
-try:
- connection.open()
- session = connection.session()
-
- sender = session.sender(address)
- receiver = session.receiver(address)
-
- sender.send(Message("Hello world!"));
-
- message = receiver.fetch()
- print message.content
- session.acknowledge()
-
-except MessagingError,m:
- print m
-
-connection.close()
diff --git a/qpid/python/examples/api/hello_xml b/qpid/python/examples/api/hello_xml
deleted file mode 100755
index ab567ec5dd..0000000000
--- a/qpid/python/examples/api/hello_xml
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/env 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 sys
-from qpid.messaging import *
-
-broker = "localhost:5672"
-connection = Connection(broker)
-
-try:
- connection.open()
- session = connection.session()
-
-# Set up the receiver
- query = """
- let $w := ./weather
- return $w/station = 'Raleigh-Durham International Airport (KRDU)'
- and $w/temperature_f > 50
- and $w/temperature_f - $w/dewpoint > 5
- and $w/wind_speed_mph > 7
- and $w/wind_speed_mph < 20 """
-
-# query="./weather"
-
- address = """
- xml; {
- create: always,
- node:{ type: queue },
- link: {
- x-bindings: [{ exchange: xml, key: weather, arguments: { xquery: %r} }]
- }
- }
- """ % query
-
- receiver = session.receiver(address)
-
-# Send an observation
-
- observations = """
- <weather>
- <station>Raleigh-Durham International Airport (KRDU)</station>
- <wind_speed_mph>16</wind_speed_mph>
- <temperature_f>70</temperature_f>
- <dewpoint>35</dewpoint>
- </weather> """
-
- message = Message(subject="weather", content=observations)
- sender = session.sender("xml")
- sender.send(message)
-
-# Retrieve matching message from the receiver and print it
-
- message = receiver.fetch(timeout=1)
- print message.content
- session.acknowledge()
-
-except MessagingError,m:
- print m
-
-connection.close()
diff --git a/qpid/python/examples/api/server b/qpid/python/examples/api/server
deleted file mode 100755
index 78d812bfd2..0000000000
--- a/qpid/python/examples/api/server
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/usr/bin/env 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 optparse, sys, traceback
-from qpid.messaging import *
-from qpid.util import URL
-from subprocess import Popen, STDOUT, PIPE
-from qpid.log import enable, DEBUG, WARN
-
-parser = optparse.OptionParser(usage="usage: %prog [options] ADDRESS ...",
- description="handle requests from the supplied address.")
-parser.add_option("-b", "--broker", default="localhost",
- help="connect to specified BROKER (default %default)")
-parser.add_option("-r", "--reconnect", action="store_true",
- help="enable auto reconnect")
-parser.add_option("-i", "--reconnect-interval", type="float", default=3,
- help="interval between reconnect attempts")
-parser.add_option("-l", "--reconnect-limit", type="int",
- help="maximum number of reconnect attempts")
-parser.add_option("-v", dest="verbose", action="store_true",
- help="enable logging")
-
-opts, args = parser.parse_args()
-
-if opts.verbose:
- enable("qpid", DEBUG)
-else:
- enable("qpid", WARN)
-
-if args:
- addr = args.pop(0)
-else:
- parser.error("address is required")
-
-conn = Connection(opts.broker,
- reconnect=opts.reconnect,
- reconnect_interval=opts.reconnect_interval,
- reconnect_limit=opts.reconnect_limit)
-def dispatch(msg):
- msg_type = msg.properties.get("type")
- if msg_type == "shell":
- proc = Popen(msg.content, shell=True, stderr=STDOUT, stdin=PIPE, stdout=PIPE)
- output, _ = proc.communicate()
- result = Message(output)
- result.properties["exit"] = proc.returncode
- elif msg_type == "eval":
- try:
- content = eval(msg.content)
- except:
- content = traceback.format_exc()
- result = Message(content)
- else:
- result = Message("unrecognized message type: %s" % msg_type)
- return result
-
-try:
- conn.open()
- ssn = conn.session()
- rcv = ssn.receiver(addr)
-
- while True:
- msg = rcv.fetch()
- response = dispatch(msg)
- snd = None
- try:
- snd = ssn.sender(msg.reply_to)
- snd.send(response)
- except SendError, e:
- print e
- if snd is not None:
- snd.close()
- ssn.acknowledge()
-except ReceiverError, e:
- print e
-except KeyboardInterrupt:
- pass
-
-conn.close()
diff --git a/qpid/python/examples/api/spout b/qpid/python/examples/api/spout
deleted file mode 100755
index 6584b853fc..0000000000
--- a/qpid/python/examples/api/spout
+++ /dev/null
@@ -1,133 +0,0 @@
-#!/usr/bin/env 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 optparse, time
-from qpid.messaging import *
-from qpid.util import URL
-from qpid.log import enable, DEBUG, WARN
-
-def nameval(st):
- idx = st.find("=")
- if idx >= 0:
- name = st[0:idx]
- value = st[idx+1:]
- else:
- name = st
- value = None
- return name, value
-
-parser = optparse.OptionParser(usage="usage: %prog [options] ADDRESS [ CONTENT ... ]",
- description="Send messages to the supplied address.")
-parser.add_option("-b", "--broker", default="localhost",
- help="connect to specified BROKER (default %default)")
-parser.add_option("-r", "--reconnect", action="store_true",
- help="enable auto reconnect")
-parser.add_option("-i", "--reconnect-interval", type="float", default=3,
- help="interval between reconnect attempts")
-parser.add_option("-l", "--reconnect-limit", type="int",
- help="maximum number of reconnect attempts")
-parser.add_option("-c", "--count", type="int", default=1,
- help="stop after count messages have been sent, zero disables (default %default)")
-parser.add_option("-d", "--durable", action="store_true",
- help="make the message persistent")
-parser.add_option("-t", "--timeout", type="float", default=None,
- help="exit after the specified time")
-parser.add_option("-I", "--id", help="use the supplied id instead of generating one")
-parser.add_option("-S", "--subject", help="specify a subject")
-parser.add_option("-R", "--reply-to", help="specify reply-to address")
-parser.add_option("-P", "--property", dest="properties", action="append", default=[],
- metavar="NAME=VALUE", help="specify message property")
-parser.add_option("-M", "--map", dest="entries", action="append", default=[],
- metavar="KEY=VALUE",
- help="specify map entry for message body")
-parser.add_option("-v", dest="verbose", action="store_true",
- help="enable logging")
-
-opts, args = parser.parse_args()
-
-if opts.verbose:
- enable("qpid", DEBUG)
-else:
- enable("qpid", WARN)
-
-if opts.id is None:
- spout_id = str(uuid4())
-else:
- spout_id = opts.id
-if args:
- addr = args.pop(0)
-else:
- parser.error("address is required")
-
-content = None
-content_type = None
-
-if args:
- text = " ".join(args)
-else:
- text = None
-
-if opts.entries:
- content = {}
- if text:
- content["text"] = text
- for e in opts.entries:
- name, val = nameval(e)
- content[name] = val
-else:
- content = text
- # no entries were supplied, so assume text/plain for
- # compatibility with java (and other) clients
- content_type = "text/plain"
-
-conn = Connection(opts.broker,
- reconnect=opts.reconnect,
- reconnect_interval=opts.reconnect_interval,
- reconnect_limit=opts.reconnect_limit)
-try:
- conn.open()
- ssn = conn.session()
- snd = ssn.sender(addr)
-
- count = 0
- start = time.time()
- while (opts.count == 0 or count < opts.count) and \
- (opts.timeout is None or time.time() - start < opts.timeout):
- msg = Message(subject=opts.subject,
- reply_to=opts.reply_to,
- content=content)
- if opts.durable:
- msg.durable = True
- if content_type is not None:
- msg.content_type = content_type
- msg.properties["spout-id"] = "%s:%s" % (spout_id, count)
- for p in opts.properties:
- name, val = nameval(p)
- msg.properties[name] = val
-
- snd.send(msg)
- count += 1
- print msg
-except SendError, e:
- print e
-except KeyboardInterrupt:
- pass
-
-conn.close()
diff --git a/qpid/python/examples/api/statistics.py b/qpid/python/examples/api/statistics.py
deleted file mode 100644
index e095920e90..0000000000
--- a/qpid/python/examples/api/statistics.py
+++ /dev/null
@@ -1,139 +0,0 @@
-#!/usr/bin/env 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 time
-
-TS = "ts"
-TIME_SEC = 1000000000
-MILLISECOND = 1000
-
-class Statistic:
- def message(self, msg):
- return
- def report(self):
- return ""
- def header(self):
- return ""
-
-
-class Throughput(Statistic):
- def __init__(self):
- self.messages = 0
- self.started = False
-
- def message(self, m):
- self.messages += 1
- if not self.started:
- self.start = time.time()
- self.started = True
-
- def header(self):
- return "tp(m/s)"
-
- def report(self):
- if self.started:
- elapsed = time.time() - self.start
- return str(int(self.messages/elapsed))
- else:
- return "0"
-
-
-class ThroughputAndLatency(Throughput):
- def __init__(self):
- Throughput.__init__(self)
- self.total = 0.0
- self.min = float('inf')
- self.max = -float('inf')
- self.samples = 0
-
- def message(self, m):
- Throughput.message(self, m)
- if TS in m.properties:
- self.samples+=1
- latency = MILLISECOND * (time.time() - float(m.properties[TS])/TIME_SEC)
- if latency > 0:
- self.total += latency
- if latency < self.min:
- self.min = latency
- if latency > self.max:
- self.max = latency
-
- def header(self):
-# Throughput.header(self)
- return "%s\tl-min\tl-max\tl-avg" % Throughput.header(self)
-
- def report(self):
- output = Throughput.report(self)
- if (self.samples > 0):
- output += "\t%.2f\t%.2f\t%.2f" %(self.min, self.max, self.total/self.samples)
- return output
-
-
-# Report batch and overall statistics
-class ReporterBase:
- def __init__(self, batch, wantHeader):
- self.batchSize = batch
- self.batchCount = 0
- self.headerPrinted = not wantHeader
- self.overall = None
- self.batch = None
-
- def create(self):
- return
-
- # Count message in the statistics
- def message(self, m):
- if self.overall == None:
- self.overall = self.create()
- self.overall.message(m)
- if self.batchSize:
- if self.batch == None:
- self.batch = self.create()
- self.batch.message(m)
- self.batchCount+=1
- if self.batchCount == self.batchSize:
- self.header()
- print self.batch.report()
- self.create()
- self.batchCount = 0
-
- # Print overall report.
- def report(self):
- if self.overall == None:
- self.overall = self.create()
- self.header()
- print self.overall.report()
-
- def header(self):
- if not self.headerPrinted:
- if self.overall == None:
- self.overall = self.create()
- print self.overall.header()
- self.headerPrinted = True
-
-
-class Reporter(ReporterBase):
- def __init__(self, batchSize, wantHeader, Stats):
- ReporterBase.__init__(self, batchSize, wantHeader)
- self.__stats = Stats
-
- def create(self):
- ClassName = self.__stats.__class__
- return ClassName()
diff --git a/qpid/python/examples/reservations/common.py b/qpid/python/examples/reservations/common.py
deleted file mode 100644
index 12f07e1c92..0000000000
--- a/qpid/python/examples/reservations/common.py
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/env 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 traceback
-from fnmatch import fnmatch
-from qpid.messaging import *
-
-class Dispatcher:
-
- def unhandled(self, msg):
- print "UNHANDLED MESSAGE: %s" % msg
-
- def ignored(self, msg):
- return False
-
- def dispatch(self, msg):
- try:
- if self.ignored(msg):
- return ()
- else:
- type = msg.properties.get("type")
- replies = getattr(self, "do_%s" % type, self.unhandled)(msg)
- if replies is None:
- return ()
- else:
- return replies
- except:
- traceback.print_exc()
- return ()
-
- def run(self, session):
- while self.running():
- msg = session.next_receiver().fetch()
- replies = self.dispatch(msg)
-
- count = len(replies)
- sequence = 1
- for to, r in replies:
- r.correlation_id = msg.correlation_id
- r.properties["count"] = count
- r.properties["sequence"] = sequence
- sequence += 1
- try:
- snd = session.sender(to)
- snd.send(r)
- except SendError, e:
- print e
- finally:
- snd.close()
-
- session.acknowledge(msg)
-
-def get_status(msg):
- return msg.content["identity"], msg.content["status"], msg.content["owner"]
-
-FREE = "free"
-BUSY = "busy"
-
-def match(value, patterns):
- for p in patterns:
- if fnmatch(value, p):
- return True
- return False
diff --git a/qpid/python/examples/reservations/inventory b/qpid/python/examples/reservations/inventory
deleted file mode 100755
index 0a49643e5f..0000000000
--- a/qpid/python/examples/reservations/inventory
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/env 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 optparse, traceback
-from qpid.messaging import *
-from qpid.log import enable, DEBUG, WARN
-from common import *
-
-parser = optparse.OptionParser(usage="usage: %prog [options]",
- description="machine inventory agent")
-parser.add_option("-b", "--broker", default="localhost",
- help="connect to specified BROKER (default %default)")
-parser.add_option("-d", "--database",
- help="database file for persistent machine status")
-parser.add_option("-a", "--address", default="reservations",
- help="address for reservation requests")
-parser.add_option("-v", dest="verbose", action="store_true",
- help="enable verbose logging")
-
-opts, args = parser.parse_args()
-
-if opts.verbose:
- enable("qpid", DEBUG)
-else:
- enable("qpid", WARN)
-
-conn = Connection.establish(opts.broker, reconnect=True, reconnect_interval=1)
-
-class Inventory(Dispatcher):
-
- def __init__(self):
- self.agents = {}
-
- def running(self):
- return True
-
- def do_status(self, msg):
- id, status, owner = get_status(msg)
- self.agents[id] = (status, owner)
-
- def do_query(self, msg):
- patterns = msg.content["identity"]
- result = []
- for id, (status, owner) in self.agents.items():
- if match(id, patterns):
- r = Message(properties = {
- "type": "status"
- },
- content = {
- "identity": id,
- "status": status,
- "owner": owner
- })
- result.append((msg.reply_to, r))
- continue
- if not result:
- result.append((msg.reply_to,
- Message(properties = {"type": "empty"})))
- return result
-
- def ignored(self, msg):
- type = msg.properties.get("type")
- return type not in ("status", "query")
-
-try:
- ssn = conn.session()
- rcv = ssn.receiver(opts.address, capacity = 10)
- snd = ssn.sender(opts.address)
- snd.send(Message(reply_to = opts.address,
- properties = {"type": "discover", "identity": ["*"]}))
-
- inv = Inventory()
- inv.run(ssn)
-except KeyboardInterrupt:
- pass
-finally:
- conn.close()
diff --git a/qpid/python/examples/reservations/machine-agent b/qpid/python/examples/reservations/machine-agent
deleted file mode 100755
index a221a8b6de..0000000000
--- a/qpid/python/examples/reservations/machine-agent
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env 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 optparse, socket
-from qpid.messaging import *
-from qpid.log import enable, DEBUG, WARN
-from common import *
-
-host = socket.gethostname()
-
-parser = optparse.OptionParser(usage="usage: %prog [options]",
- description="machine reservation agent")
-parser.add_option("-b", "--broker", default="localhost",
- help="connect to specified BROKER (default %default)")
-parser.add_option("-d", "--database",
- help="database file for persistent machine status")
-parser.add_option("-a", "--address", default="reservations",
- help="address for reservation requests")
-parser.add_option("-i", "--identity", default=host,
- help="resource id (default %default)")
-parser.add_option("-v", dest="verbose", action="store_true",
- help="enable verbose logging")
-
-opts, args = parser.parse_args()
-
-if opts.verbose:
- enable("qpid", DEBUG)
-else:
- enable("qpid", WARN)
-
-conn = Connection.establish(opts.broker, reconnect=True, reconnect_interval=1)
-
-
-class Agent(Dispatcher):
-
- def __init__(self, identity):
- self.identity = identity
- self.status = FREE
- self.owner = None
-
- def running(self):
- return True
-
- def get_status(self):
- msg = Message(properties = {"type": "status"},
- content = {"identity": self.identity,
- "status": self.status,
- "owner": self.owner})
- return msg
-
- def do_discover(self, msg):
- r = self.get_status()
- return [(msg.reply_to, r)]
-
- def do_reserve(self, msg):
- if self.status == FREE:
- self.owner = msg.content["owner"]
- self.status = BUSY
- return self.do_discover(msg)
-
- def do_release(self, msg):
- if self.owner == msg.content["owner"]:
- self.status = FREE
- self.owner = None
- return self.do_discover(msg)
-
- def ignored(self, msg):
- patterns = msg.properties.get("identity")
- type = msg.properties.get("type")
- if patterns and match(self.identity, patterns):
- return type == "status"
- else:
- return True
-
-try:
- ssn = conn.session()
- rcv = ssn.receiver(opts.address)
- rcv.capacity = 10
- snd = ssn.sender(opts.address)
- agent = Agent(opts.identity)
- snd.send(agent.get_status())
- agent.run(ssn)
-except KeyboardInterrupt:
- pass
-finally:
- conn.close()
diff --git a/qpid/python/examples/reservations/reserve b/qpid/python/examples/reservations/reserve
deleted file mode 100755
index 68e7fee912..0000000000
--- a/qpid/python/examples/reservations/reserve
+++ /dev/null
@@ -1,197 +0,0 @@
-#!/usr/bin/env 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 optparse, os, sys, time
-from uuid import uuid4
-from qpid.messaging import *
-from qpid.log import enable, DEBUG, WARN
-from common import *
-
-parser = optparse.OptionParser(usage="usage: %prog [options] PATTERN ...",
- description="reserve a machine")
-parser.add_option("-b", "--broker", default="localhost",
- help="connect to specified BROKER (default %default)")
-parser.add_option("-a", "--address", default="reservations",
- help="address for reservation requests")
-parser.add_option("-r", "--release", action="store_true",
- help="release any machines matching the pattern")
-parser.add_option("-s", "--status", action="store_true",
- help="list machine status")
-parser.add_option("-d", "--discover", action="store_true",
- help="use discovery instead of inventory")
-parser.add_option("-o", "--owner", default=os.environ["USER"],
- help="the holder of the reservation")
-parser.add_option("-n", "--number", type=int, default=1,
- help="the number of machines to reserve")
-parser.add_option("-t", "--timeout", type=float, default=10,
- help="timeout in seconds to wait for resources")
-parser.add_option("-v", dest="verbose", action="store_true",
- help="enable verbose logging")
-
-opts, args = parser.parse_args()
-
-if opts.verbose:
- enable("qpid", DEBUG)
-else:
- enable("qpid", WARN)
-
-if args:
- patterns = args
-else:
- patterns = ["*"]
-
-conn = Connection.establish(opts.broker)
-
-if opts.release:
- request_type = "release"
- candidate_status = BUSY
- candidate_owner = opts.owner
-else:
- request_type = "reserve"
- candidate_status = FREE
- candidate_owner = None
-
-class Requester(Dispatcher):
-
- def __init__(self):
- self.agents = {}
- self.requests = set()
- self.outstanding = set()
-
- def agent_status(self, id):
- status, owner = self.agents[id]
- if owner:
- return "%s %s(%s)" % (id, status, owner)
- else:
- return "%s %s" % (id, status)
-
- def correlation(self, cid):
- self.requests.add(cid)
- self.outstanding.add(cid)
-
- def ignored(self, msg):
- return msg.properties.get("type") not in ("status", "empty") or \
- msg.correlation_id not in self.requests
-
- def do_status(self, msg):
- id, status, owner = get_status(msg)
- self.agents[id] = (status, owner)
-
- if opts.status:
- print self.agent_status(id)
-
- def do_empty(self, msg):
- print "no matching resources"
-
- def candidates(self, candidate_status, candidate_owner):
- for id, (status, owner) in self.agents.items():
- if status == candidate_status and owner == candidate_owner:
- yield id
-
- def dispatch(self, msg):
- result = Dispatcher.dispatch(self, msg)
- count = msg.properties.get("count")
- sequence = msg.properties.get("sequence")
- if count and sequence == count:
- self.outstanding.discard(msg.correlation_id)
- return result
-
-try:
- ssn = conn.session()
- rcv = ssn.receiver(opts.address, capacity=10)
- snd = ssn.sender(opts.address)
-
- correlation_id = str(uuid4())
-
- if opts.discover:
- properties = {"type": "discover", "identity": patterns}
- content = None
- else:
- properties = {"type": "query"}
- content = {"identity": patterns}
-
- snd.send(Message(reply_to = opts.address,
- correlation_id = correlation_id,
- properties = properties,
- content = content))
-
- req = Requester()
- req.correlation(correlation_id)
-
- start = time.time()
- ellapsed = 0
- requested = set()
- discovering = opts.discover
-
- while ellapsed <= opts.timeout and (discovering or req.outstanding):
- try:
- msg = rcv.fetch(opts.timeout - ellapsed)
- ssn.acknowledge(msg)
- except Empty:
- continue
- finally:
- ellapsed = time.time() - start
-
- req.dispatch(msg)
- if not opts.status:
- if len(requested) < opts.number:
- for cid in req.candidates(candidate_status, candidate_owner):
- if cid in requested: continue
- req_msg = Message(reply_to = opts.address,
- correlation_id = str(uuid4()),
- properties = {"type": request_type,
- "identity": [cid]},
- content = {"owner": opts.owner})
- if not requested:
- print "requesting %s:" % request_type,
- print cid,
- sys.stdout.flush()
- req.correlation(req_msg.correlation_id)
- snd.send(req_msg)
- requested.add(cid)
- else:
- discovering = False
-
- if requested:
- print
- owners = {}
- for id in requested:
- st, ow = req.agents[id]
- if not owners.has_key(ow):
- owners[ow] = []
- owners[ow].append(id)
- keys = list(owners.keys())
- keys.sort()
- for k in keys:
- owners[k].sort()
- v = ", ".join(owners[k])
- if k is None:
- print "free: %s" % v
- else:
- print "owner %s: %s" % (k, v)
- elif req.agents and not opts.status:
- print "no available resources"
-
- if req.outstanding:
- print "request timed out"
-except KeyboardInterrupt:
- pass
-finally:
- conn.close()
diff --git a/qpid/python/mllib/__init__.py b/qpid/python/mllib/__init__.py
deleted file mode 100644
index af192df1d1..0000000000
--- a/qpid/python/mllib/__init__.py
+++ /dev/null
@@ -1,86 +0,0 @@
-#
-# 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.
-#
-
-"""
-This module provides document parsing and transformation utilities for
-both SGML and XML.
-"""
-
-import os, dom, transforms, parsers, sys
-import xml.sax, types
-from xml.sax.handler import ErrorHandler
-from xml.sax.xmlreader import InputSource
-from cStringIO import StringIO
-
-def transform(node, *args):
- result = node
- for t in args:
- if isinstance(t, types.ClassType):
- t = t()
- result = result.dispatch(t)
- return result
-
-def sgml_parse(source):
- if isinstance(source, basestring):
- source = StringIO(source)
- fname = "<string>"
- elif hasattr(source, "name"):
- fname = source.name
- p = parsers.SGMLParser()
- num = 1
- for line in source:
- p.feed(line)
- p.parser.line(fname, num, None)
- num += 1
- p.close()
- return p.parser.tree
-
-class Resolver:
-
- def __init__(self, path):
- self.path = path
-
- def resolveEntity(self, publicId, systemId):
- for p in self.path:
- fname = os.path.join(p, systemId)
- if os.path.exists(fname):
- source = InputSource(systemId)
- source.setByteStream(open(fname))
- return source
- return InputSource(systemId)
-
-def xml_parse(filename, path=()):
- if sys.version_info[0:2] == (2,3):
- # XXX: this is for older versions of python
- from urllib import pathname2url
- source = "file:%s" % pathname2url( os.path.abspath( filename ) )
- else:
- source = filename
- h = parsers.XMLParser()
- p = xml.sax.make_parser()
- p.setContentHandler(h)
- p.setErrorHandler(ErrorHandler())
- p.setEntityResolver(Resolver(path))
- p.parse(source)
- return h.parser.tree
-
-def sexp(node):
- s = transforms.Sexp()
- node.dispatch(s)
- return s.out
diff --git a/qpid/python/mllib/dom.py b/qpid/python/mllib/dom.py
deleted file mode 100644
index 486f7082e1..0000000000
--- a/qpid/python/mllib/dom.py
+++ /dev/null
@@ -1,310 +0,0 @@
-#
-# 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.
-#
-
-"""
-Simple DOM for both SGML and XML documents.
-"""
-
-from __future__ import division
-from __future__ import generators
-from __future__ import nested_scopes
-
-import transforms
-
-class Container:
-
- def __init__(self):
- self.children = []
-
- def add(self, child):
- child.parent = self
- self.children.append(child)
-
- def extend(self, children):
- for child in children:
- child.parent = self
- self.children.append(child)
-
-class Component:
-
- def __init__(self):
- self.parent = None
-
- def index(self):
- if self.parent:
- return self.parent.children.index(self)
- else:
- return 0
-
- def _line(self, file, line, column):
- self.file = file
- self.line = line
- self.column = column
-
-class DispatchError(Exception):
-
- def __init__(self, scope, f):
- msg = "no such attribtue"
-
-class Dispatcher:
-
- def is_type(self, type):
- cls = self
- while cls != None:
- if cls.type == type:
- return True
- cls = cls.base
- return False
-
- def dispatch(self, f, attrs = ""):
- cls = self
- while cls != None:
- if hasattr(f, cls.type):
- return getattr(f, cls.type)(self)
- else:
- cls = cls.base
-
- cls = self
- while cls != None:
- if attrs:
- sep = ", "
- if cls.base == None:
- sep += "or "
- else:
- sep = ""
- attrs += "%s'%s'" % (sep, cls.type)
- cls = cls.base
-
- raise AttributeError("'%s' object has no attribute %s" %
- (f.__class__.__name__, attrs))
-
-class Node(Container, Component, Dispatcher):
-
- type = "node"
- base = None
-
- def __init__(self):
- Container.__init__(self)
- Component.__init__(self)
- self.query = Query([self])
-
- def __getitem__(self, name):
- for nd in self.query[name]:
- return nd
-
- def text(self):
- return self.dispatch(transforms.Text())
-
- def tag(self, name, *attrs, **kwargs):
- t = Tag(name, *attrs, **kwargs)
- self.add(t)
- return t
-
- def data(self, s):
- d = Data(s)
- self.add(d)
- return d
-
- def entity(self, s):
- e = Entity(s)
- self.add(e)
- return e
-
-class Tree(Node):
-
- type = "tree"
- base = Node
-
-class Tag(Node):
-
- type = "tag"
- base = Node
-
- def __init__(self, _name, *attrs, **kwargs):
- Node.__init__(self)
- self.name = _name
- self.attrs = list(attrs)
- self.attrs.extend(kwargs.items())
- self.singleton = False
-
- def get_attr(self, name):
- for k, v in self.attrs:
- if name == k:
- return v
-
- def _idx(self, attr):
- idx = 0
- for k, v in self.attrs:
- if k == attr:
- return idx
- idx += 1
- return None
-
- def set_attr(self, name, value):
- idx = self._idx(name)
- if idx is None:
- self.attrs.append((name, value))
- else:
- self.attrs[idx] = (name, value)
-
- def dispatch(self, f):
- try:
- attr = "do_" + self.name
- method = getattr(f, attr)
- except AttributeError:
- return Dispatcher.dispatch(self, f, "'%s'" % attr)
- return method(self)
-
-class Leaf(Component, Dispatcher):
-
- type = "leaf"
- base = None
-
- def __init__(self, data):
- assert isinstance(data, basestring)
- self.data = data
-
-class Data(Leaf):
- type = "data"
- base = Leaf
-
-class Entity(Leaf):
- type = "entity"
- base = Leaf
-
-class Character(Leaf):
- type = "character"
- base = Leaf
-
-class Comment(Leaf):
- type = "comment"
- base = Leaf
-
-###################
-## Query Classes ##
-###########################################################################
-
-class Adder:
-
- def __add__(self, other):
- return Sum(self, other)
-
-class Sum(Adder):
-
- def __init__(self, left, right):
- self.left = left
- self.right = right
-
- def __iter__(self):
- for x in self.left:
- yield x
- for x in self.right:
- yield x
-
-class View(Adder):
-
- def __init__(self, source):
- self.source = source
-
-class Filter(View):
-
- def __init__(self, predicate, source):
- View.__init__(self, source)
- self.predicate = predicate
-
- def __iter__(self):
- for nd in self.source:
- if self.predicate(nd): yield nd
-
-class Flatten(View):
-
- def __iter__(self):
- sources = [iter(self.source)]
- while sources:
- try:
- nd = sources[-1].next()
- if isinstance(nd, Tree):
- sources.append(iter(nd.children))
- else:
- yield nd
- except StopIteration:
- sources.pop()
-
-class Children(View):
-
- def __iter__(self):
- for nd in self.source:
- for child in nd.children:
- yield child
-
-class Attributes(View):
-
- def __iter__(self):
- for nd in self.source:
- for a in nd.attrs:
- yield a
-
-class Values(View):
-
- def __iter__(self):
- for name, value in self.source:
- yield value
-
-def flatten_path(path):
- if isinstance(path, basestring):
- for part in path.split("/"):
- yield part
- elif callable(path):
- yield path
- else:
- for p in path:
- for fp in flatten_path(p):
- yield fp
-
-class Query(View):
-
- def __iter__(self):
- for nd in self.source:
- yield nd
-
- def __getitem__(self, path):
- query = self.source
- for p in flatten_path(path):
- if callable(p):
- select = Query
- pred = p
- source = query
- elif isinstance(p, basestring):
- if p[0] == "@":
- select = Values
- pred = lambda x, n=p[1:]: x[0] == n
- source = Attributes(query)
- elif p[0] == "#":
- select = Query
- pred = lambda x, t=p[1:]: x.is_type(t)
- source = Children(query)
- else:
- select = Query
- pred = lambda x, n=p: isinstance(x, Tag) and x.name == n
- source = Flatten(Children(query))
- else:
- raise ValueError(p)
- query = select(Filter(pred, source))
-
- return query
diff --git a/qpid/python/mllib/parsers.py b/qpid/python/mllib/parsers.py
deleted file mode 100644
index 3e7cc10dc2..0000000000
--- a/qpid/python/mllib/parsers.py
+++ /dev/null
@@ -1,139 +0,0 @@
-#
-# 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.
-#
-
-"""
-Parsers for SGML and XML to dom.
-"""
-
-import sgmllib, xml.sax.handler
-from dom import *
-
-class Parser:
-
- def __init__(self):
- self.tree = Tree()
- self.node = self.tree
- self.nodes = []
-
- def line(self, id, lineno, colno):
- while self.nodes:
- n = self.nodes.pop()
- n._line(id, lineno, colno)
-
- def add(self, node):
- self.node.add(node)
- self.nodes.append(node)
-
- def start(self, name, attrs):
- tag = Tag(name, *attrs)
- self.add(tag)
- self.node = tag
-
- def end(self, name):
- self.balance(name)
- self.node = self.node.parent
-
- def data(self, data):
- children = self.node.children
- if children and isinstance(children[-1], Data):
- children[-1].data += data
- else:
- self.add(Data(data))
-
- def comment(self, comment):
- self.add(Comment(comment))
-
- def entity(self, ref):
- self.add(Entity(ref))
-
- def character(self, ref):
- self.add(Character(ref))
-
- def balance(self, name = None):
- while self.node != self.tree and name != self.node.name:
- self.node.parent.extend(self.node.children)
- del self.node.children[:]
- self.node.singleton = True
- self.node = self.node.parent
-
-
-class SGMLParser(sgmllib.SGMLParser):
-
- def __init__(self, entitydefs = None):
- sgmllib.SGMLParser.__init__(self)
- if entitydefs == None:
- self.entitydefs = {}
- else:
- self.entitydefs = entitydefs
- self.parser = Parser()
-
- def unknown_starttag(self, name, attrs):
- self.parser.start(name, attrs)
-
- def handle_data(self, data):
- self.parser.data(data)
-
- def handle_comment(self, comment):
- self.parser.comment(comment)
-
- def unknown_entityref(self, ref):
- self.parser.entity(ref)
-
- def unknown_charref(self, ref):
- self.parser.character(ref)
-
- def unknown_endtag(self, name):
- self.parser.end(name)
-
- def close(self):
- sgmllib.SGMLParser.close(self)
- self.parser.balance()
- assert self.parser.node == self.parser.tree
-
-class XMLParser(xml.sax.handler.ContentHandler):
-
- def __init__(self):
- self.parser = Parser()
- self.locator = None
-
- def line(self):
- if self.locator != None:
- self.parser.line(self.locator.getSystemId(),
- self.locator.getLineNumber(),
- self.locator.getColumnNumber())
-
- def setDocumentLocator(self, locator):
- self.locator = locator
-
- def startElement(self, name, attrs):
- self.parser.start(name, attrs.items())
- self.line()
-
- def endElement(self, name):
- self.parser.end(name)
- self.line()
-
- def characters(self, content):
- self.parser.data(content)
- self.line()
-
- def skippedEntity(self, name):
- self.parser.entity(name)
- self.line()
-
diff --git a/qpid/python/mllib/transforms.py b/qpid/python/mllib/transforms.py
deleted file mode 100644
index 69d99125e3..0000000000
--- a/qpid/python/mllib/transforms.py
+++ /dev/null
@@ -1,164 +0,0 @@
-#
-# 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.
-#
-
-"""
-Useful transforms for dom objects.
-"""
-
-import dom
-from cStringIO import StringIO
-
-class Visitor:
-
- def descend(self, node):
- for child in node.children:
- child.dispatch(self)
-
- def node(self, node):
- self.descend(node)
-
- def leaf(self, leaf):
- pass
-
-class Identity:
-
- def descend(self, node):
- result = []
- for child in node.children:
- result.append(child.dispatch(self))
- return result
-
- def default(self, tag):
- result = dom.Tag(tag.name, *tag.attrs)
- result.extend(self.descend(tag))
- return result
-
- def tree(self, tree):
- result = dom.Tree()
- result.extend(self.descend(tree))
- return result
-
- def tag(self, tag):
- return self.default(tag)
-
- def leaf(self, leaf):
- return leaf.__class__(leaf.data)
-
-class Sexp(Identity):
-
- def __init__(self):
- self.stack = []
- self.level = 0
- self.out = ""
-
- def open(self, s):
- self.out += "(%s" % s
- self.level += len(s) + 1
- self.stack.append(s)
-
- def line(self, s = ""):
- self.out = self.out.rstrip()
- self.out += "\n" + " "*self.level + s
-
- def close(self):
- s = self.stack.pop()
- self.level -= len(s) + 1
- self.out = self.out.rstrip()
- self.out += ")"
-
- def tree(self, tree):
- self.open("+ ")
- for child in tree.children:
- self.line(); child.dispatch(self)
- self.close()
-
- def tag(self, tag):
- self.open("Node(%s) " % tag.name)
- for child in tag.children:
- self.line(); child.dispatch(self)
- self.close()
-
- def leaf(self, leaf):
- self.line("%s(%s)" % (leaf.__class__.__name__, leaf.data))
-
-class Output:
-
- def descend(self, node):
- out = StringIO()
- for child in node.children:
- out.write(child.dispatch(self))
- return out.getvalue()
-
- def default(self, tag):
- out = StringIO()
- out.write("<%s" % tag.name)
- for k, v in tag.attrs:
- out.write(' %s="%s"' % (k, v))
- out.write(">")
- out.write(self.descend(tag))
- if not tag.singleton:
- out.write("</%s>" % tag.name)
- return out.getvalue()
-
- def tree(self, tree):
- return self.descend(tree)
-
- def tag(self, tag):
- return self.default(tag)
-
- def data(self, leaf):
- return leaf.data
-
- def entity(self, leaf):
- return "&%s;" % leaf.data
-
- def character(self, leaf):
- raise Exception("TODO")
-
- def comment(self, leaf):
- return "<!-- %s -->" % leaf.data
-
-class Empty(Output):
-
- def tag(self, tag):
- return self.descend(tag)
-
- def data(self, leaf):
- return ""
-
- def entity(self, leaf):
- return ""
-
- def character(self, leaf):
- return ""
-
- def comment(self, leaf):
- return ""
-
-class Text(Empty):
-
- def data(self, leaf):
- return leaf.data
-
- def entity(self, leaf):
- return "&%s;" % leaf.data
-
- def character(self, leaf):
- # XXX: is this right?
- return "&#%s;" % leaf.data
diff --git a/qpid/python/qpid-python-test b/qpid/python/qpid-python-test
deleted file mode 100755
index dfe6a6fc7a..0000000000
--- a/qpid/python/qpid-python-test
+++ /dev/null
@@ -1,639 +0,0 @@
-#!/usr/bin/env 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.
-#
-
-# TODO: summarize, test harness preconditions (e.g. broker is alive)
-
-import logging, optparse, os, struct, sys, time, traceback, types
-from fnmatch import fnmatchcase as match
-from getopt import GetoptError
-from logging import getLogger, StreamHandler, Formatter, Filter, \
- WARN, DEBUG, ERROR
-from qpid.harness import Skipped
-from qpid.util import URL
-
-levels = {
- "DEBUG": DEBUG,
- "WARN": WARN,
- "ERROR": ERROR
- }
-
-sorted_levels = [(v, k) for k, v in levels.items()]
-sorted_levels.sort()
-sorted_levels = [v for k, v in sorted_levels]
-
-parser = optparse.OptionParser(usage="usage: %prog [options] PATTERN ...",
- description="Run tests matching the specified PATTERNs.")
-parser.add_option("-l", "--list", action="store_true", default=False,
- help="list tests instead of executing them")
-parser.add_option("-b", "--broker", default="localhost",
- help="run tests against BROKER (default %default)")
-parser.add_option("-f", "--log-file", metavar="FILE", help="log output to FILE")
-parser.add_option("-v", "--log-level", metavar="LEVEL", default="WARN",
- help="only display log messages of LEVEL or higher severity: "
- "%s (default %%default)" % ", ".join(sorted_levels))
-parser.add_option("-c", "--log-category", metavar="CATEGORY", action="append",
- dest="log_categories", default=[],
- help="log only categories matching CATEGORY pattern")
-parser.add_option("-m", "--module", action="append", default=[],
- dest="modules", help="add module to test search path")
-parser.add_option("-i", "--ignore", action="append", default=[],
- help="ignore tests matching IGNORE pattern")
-parser.add_option("-I", "--ignore-file", metavar="IFILE", action="append",
- default=[],
- help="ignore tests matching patterns in IFILE")
-parser.add_option("-H", "--halt-on-error", action="store_true", default=False,
- dest="hoe", help="halt if an error is encountered")
-parser.add_option("-t", "--time", action="store_true", default=False,
- help="report timing information on test run")
-parser.add_option("-D", "--define", metavar="DEFINE", dest="defines",
- action="append", default=[], help="define test parameters")
-parser.add_option("-x", "--xml", metavar="XML", dest="xml",
- help="write test results in Junit style xml suitable for use by CI tools etc")
-
-class Config:
-
- def __init__(self):
- self.broker = URL("localhost")
- self.defines = {}
- self.log_file = None
- self.log_level = WARN
- self.log_categories = []
-
-opts, args = parser.parse_args()
-
-includes = []
-excludes = ["*__*__"]
-config = Config()
-list_only = opts.list
-config.broker = URL(opts.broker)
-for d in opts.defines:
- try:
- idx = d.index("=")
- name = d[:idx]
- value = d[idx+1:]
- config.defines[name] = value
- except ValueError:
- config.defines[d] = None
-config.log_file = opts.log_file
-config.log_level = levels[opts.log_level.upper()]
-config.log_categories = opts.log_categories
-excludes.extend([v.strip() for v in opts.ignore])
-for v in opts.ignore_file:
- f = open(v)
- for line in f:
- line = line.strip()
- if line.startswith("#"):
- continue
- excludes.append(line)
- f.close()
-
-for a in args:
- includes.append(a.strip())
-
-if not includes:
- if opts.modules:
- includes.append("*")
- else:
- includes.extend(["qpid.tests.*"])
-
-def is_ignored(path):
- for p in excludes:
- if match(path, p):
- return True
- return False
-
-def is_included(path):
- if is_ignored(path):
- return False
- for p in includes:
- if match(path, p):
- return True
- return False
-
-def is_smart():
- return sys.stdout.isatty() and os.environ.get("TERM", "dumb") != "dumb"
-
-try:
- import fcntl, termios
-
- def width():
- if is_smart():
- s = struct.pack("HHHH", 0, 0, 0, 0)
- fd_stdout = sys.stdout.fileno()
- x = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, s)
- rows, cols, xpx, ypx = struct.unpack("HHHH", x)
- return cols
- else:
- try:
- return int(os.environ.get("COLUMNS", "80"))
- except ValueError:
- return 80
-
- WIDTH = width()
-
- def resize(sig, frm):
- global WIDTH
- WIDTH = width()
-
- import signal
- signal.signal(signal.SIGWINCH, resize)
-
-except ImportError:
- WIDTH = 80
-
-def vt100_attrs(*attrs):
- return "\x1B[%sm" % ";".join(map(str, attrs))
-
-vt100_reset = vt100_attrs(0)
-
-KEYWORDS = {"pass": (32,),
- "skip": (33,),
- "fail": (31,),
- "start": (34,),
- "total": (34,),
- "ignored": (33,),
- "selected": (34,),
- "elapsed": (34,),
- "average": (34,)}
-
-COLORIZE = is_smart()
-
-def colorize_word(word, text=None):
- if text is None:
- text = word
- return colorize(text, *KEYWORDS.get(word, ()))
-
-def colorize(text, *attrs):
- if attrs and COLORIZE:
- return "%s%s%s" % (vt100_attrs(*attrs), text, vt100_reset)
- else:
- return text
-
-def indent(text):
- lines = text.split("\n")
- return " %s" % "\n ".join(lines)
-
-# Write a 'minimal' Junit xml style report file suitable for use by CI tools such as Jenkins.
-class JunitXmlStyleReporter:
-
- def __init__(self, file):
- self.f = open(file, "w");
-
- def begin(self):
- self.f.write('<?xml version="1.0" encoding="UTF-8" ?>\n')
- self.f.write('<testsuite>\n')
-
- def report(self, name, result):
- parts = name.split(".")
- method = parts[-1]
- module = '.'.join(parts[0:-1])
- self.f.write('<testcase classname="%s" name="%s" time="%f">\n' % (module, method, result.time))
- if result.failed:
- self.f.write('<failure>\n')
- self.f.write('<![CDATA[\n')
- self.f.write(result.exceptions)
- self.f.write(']]>\n')
- self.f.write('</failure>\n')
- self.f.write('</testcase>\n')
-
- def end(self):
- self.f.write('</testsuite>\n')
- self.f.close()
-
-class Interceptor:
-
- def __init__(self):
- self.newline = False
- self.indent = False
- self.passthrough = True
- self.dirty = False
- self.last = None
-
- def begin(self):
- self.newline = True
- self.indent = True
- self.passthrough = False
- self.dirty = False
- self.last = None
-
- def reset(self):
- self.newline = False
- self.indent = False
- self.passthrough = True
-
-class StreamWrapper:
-
- def __init__(self, interceptor, stream, prefix=" "):
- self.interceptor = interceptor
- self.stream = stream
- self.prefix = prefix
-
- def fileno(self):
- return self.stream.fileno()
-
- def isatty(self):
- return self.stream.isatty()
-
- def write(self, s):
- if self.interceptor.passthrough:
- self.stream.write(s)
- return
-
- if s:
- self.interceptor.dirty = True
-
- if self.interceptor.newline:
- self.interceptor.newline = False
- self.stream.write(" %s\n" % colorize_word("start"))
- self.interceptor.indent = True
- if self.interceptor.indent:
- self.stream.write(self.prefix)
- if s.endswith("\n"):
- s = s.replace("\n", "\n%s" % self.prefix)[:-2]
- self.interceptor.indent = True
- else:
- s = s.replace("\n", "\n%s" % self.prefix)
- self.interceptor.indent = False
- self.stream.write(s)
-
- if s:
- self.interceptor.last = s[-1]
-
- def flush(self):
- self.stream.flush()
-
-interceptor = Interceptor()
-
-out_wrp = StreamWrapper(interceptor, sys.stdout)
-err_wrp = StreamWrapper(interceptor, sys.stderr)
-
-out = sys.stdout
-err = sys.stderr
-sys.stdout = out_wrp
-sys.stderr = err_wrp
-
-class PatternFilter(Filter):
-
- def __init__(self, *patterns):
- Filter.__init__(self, patterns)
- self.patterns = patterns
-
- def filter(self, record):
- if not self.patterns:
- return True
- for p in self.patterns:
- if match(record.name, p):
- return True
- return False
-
-root = getLogger()
-handler = StreamHandler(sys.stdout)
-filter = PatternFilter(*config.log_categories)
-handler.addFilter(filter)
-handler.setFormatter(Formatter("%(asctime)s %(levelname)s %(message)s"))
-root.addHandler(handler)
-root.setLevel(WARN)
-
-log = getLogger("qpid.test")
-
-PASS = "pass"
-SKIP = "skip"
-FAIL = "fail"
-
-class Runner:
-
- def __init__(self):
- self.exceptions = []
- self.skip = False
-
- def passed(self):
- return not self.exceptions
-
- def skipped(self):
- return self.skip
-
- def failed(self):
- return self.exceptions and not self.skip
-
- def halt(self):
- return self.exceptions or self.skip
-
- def run(self, name, phase):
- try:
- phase()
- except KeyboardInterrupt:
- raise
- except:
- exi = sys.exc_info()
- if issubclass(exi[0], Skipped):
- self.skip = True
- self.exceptions.append((name, exi))
-
- def status(self):
- if self.passed():
- return PASS
- elif self.skipped():
- return SKIP
- elif self.failed():
- return FAIL
- else:
- return None
-
- def get_formatted_exceptions(self):
- for name, info in self.exceptions:
- if issubclass(info[0], Skipped):
- output = indent("".join(traceback.format_exception_only(*info[:2]))).rstrip()
- else:
- output = "Error during %s:" % name
- output += indent("".join(traceback.format_exception(*info))).rstrip()
- return output
-
-ST_WIDTH = 8
-
-def run_test(name, test, config):
- patterns = filter.patterns
- level = root.level
- filter.patterns = config.log_categories
- root.setLevel(config.log_level)
-
- parts = name.split(".")
- line = None
- output = ""
- for part in parts:
- if line:
- if len(line) + len(part) >= (WIDTH - ST_WIDTH - 1):
- output += "%s. \\\n" % line
- line = " %s" % part
- else:
- line = "%s.%s" % (line, part)
- else:
- line = part
-
- if line:
- output += "%s %s" % (line, (((WIDTH - ST_WIDTH) - len(line))*"."))
- sys.stdout.write(output)
- sys.stdout.flush()
- interceptor.begin()
- start = time.time()
- try:
- runner = test()
- finally:
- interceptor.reset()
- end = time.time()
- if interceptor.dirty:
- if interceptor.last != "\n":
- sys.stdout.write("\n")
- sys.stdout.write(output)
- print " %s" % colorize_word(runner.status())
- if runner.failed() or runner.skipped():
- print runner.get_formatted_exceptions()
- root.setLevel(level)
- filter.patterns = patterns
- return TestResult(end - start, runner.passed(), runner.skipped(), runner.failed(), runner.get_formatted_exceptions())
-
-class TestResult:
-
- def __init__(self, time, passed, skipped, failed, exceptions):
- self.time = time
- self.passed = passed
- self.skipped = skipped
- self.failed = failed
- self.exceptions = exceptions
-
-class FunctionTest:
-
- def __init__(self, test):
- self.test = test
-
- def name(self):
- return "%s.%s" % (self.test.__module__, self.test.__name__)
-
- def run(self):
- return run_test(self.name(), self._run, config)
-
- def _run(self):
- runner = Runner()
- runner.run("test", lambda: self.test(config))
- return runner
-
- def __repr__(self):
- return "FunctionTest(%r)" % self.test
-
-class MethodTest:
-
- def __init__(self, cls, method):
- self.cls = cls
- self.method = method
-
- def name(self):
- return "%s.%s.%s" % (self.cls.__module__, self.cls.__name__, self.method)
-
- def run(self):
- return run_test(self.name(), self._run, config)
-
- def _run(self):
- runner = Runner()
- inst = self.cls(self.method)
- test = getattr(inst, self.method)
-
- if hasattr(inst, "configure"):
- runner.run("configure", lambda: inst.configure(config))
- if runner.halt(): return runner
- if hasattr(inst, "setUp"):
- runner.run("setup", inst.setUp)
- if runner.halt(): return runner
- elif hasattr(inst, "setup"):
- runner.run("setup", inst.setup)
- if runner.halt(): return runner
-
- runner.run("test", test)
-
- if hasattr(inst, "tearDown"):
- runner.run("teardown", inst.tearDown)
- elif hasattr(inst, "teardown"):
- runner.run("teardown", inst.teardown)
-
- return runner
-
- def __repr__(self):
- return "MethodTest(%r, %r)" % (self.cls, self.method)
-
-class PatternMatcher:
-
- def __init__(self, *patterns):
- self.patterns = patterns
-
- def matches(self, name):
- for p in self.patterns:
- if match(name, p):
- return True
- return False
-
-class FunctionScanner(PatternMatcher):
-
- def inspect(self, obj):
- return type(obj) == types.FunctionType and self.matches(name)
-
- def descend(self, func):
- # the None is required for older versions of python
- return; yield None
-
- def extract(self, func):
- yield FunctionTest(func)
-
-class ClassScanner(PatternMatcher):
-
- def inspect(self, obj):
- return type(obj) in (types.ClassType, types.TypeType) and self.matches(obj.__name__)
-
- def descend(self, cls):
- # the None is required for older versions of python
- return; yield None
-
- def extract(self, cls):
- names = dir(cls)
- names.sort()
- for name in names:
- obj = getattr(cls, name)
- t = type(obj)
- if t == types.MethodType and name.startswith("test"):
- yield MethodTest(cls, name)
-
-class ModuleScanner:
-
- def inspect(self, obj):
- return type(obj) == types.ModuleType
-
- def descend(self, obj):
- names = dir(obj)
- names.sort()
- for name in names:
- yield getattr(obj, name)
-
- def extract(self, obj):
- # the None is required for older versions of python
- return; yield None
-
-class Harness:
-
- def __init__(self):
- self.scanners = [
- ModuleScanner(),
- ClassScanner("*Test", "*Tests", "*TestCase"),
- FunctionScanner("test_*")
- ]
- self.tests = []
- self.scanned = []
-
- def scan(self, *roots):
- objects = list(roots)
-
- while objects:
- obj = objects.pop(0)
- for s in self.scanners:
- if s.inspect(obj):
- self.tests.extend(s.extract(obj))
- for child in s.descend(obj):
- if not (child in self.scanned or child in objects):
- objects.append(child)
- self.scanned.append(obj)
-
-modules = opts.modules
-if not modules:
- modules.extend(["qpid.tests"])
-h = Harness()
-for name in modules:
- m = __import__(name, None, None, ["dummy"])
- h.scan(m)
-
-filtered = [t for t in h.tests if is_included(t.name())]
-ignored = [t for t in h.tests if is_ignored(t.name())]
-total = len(filtered) + len(ignored)
-
-if opts.xml and not list_only:
- xmlr = JunitXmlStyleReporter(opts.xml);
- xmlr.begin();
-else:
- xmlr = None
-
-passed = 0
-failed = 0
-skipped = 0
-start = time.time()
-for t in filtered:
- if list_only:
- print t.name()
- else:
- st = t.run()
- if xmlr:
- xmlr.report(t.name(), st)
- if st.passed:
- passed += 1
- elif st.skipped:
- skipped += 1
- elif st.failed:
- failed += 1
- if opts.hoe:
- break
-end = time.time()
-
-run = passed + failed
-
-if not list_only:
- if passed:
- _pass = "pass"
- else:
- _pass = "fail"
- if failed:
- outcome = "fail"
- else:
- outcome = "pass"
- if ignored:
- ign = "ignored"
- else:
- ign = "pass"
- if skipped:
- skip = "skip"
- else:
- skip = "pass"
- print colorize("Totals:", 1),
- totals = [colorize_word("total", "%s tests" % total),
- colorize_word(_pass, "%s passed" % passed),
- colorize_word(skip, "%s skipped" % skipped),
- colorize_word(ign, "%s ignored" % len(ignored)),
- colorize_word(outcome, "%s failed" % failed)]
- print ", ".join(totals),
- if opts.hoe and failed > 0:
- print " -- (halted after %s)" % run
- else:
- print
- if opts.time and run > 0:
- print colorize("Timing:", 1),
- timing = [colorize_word("elapsed", "%.2fs elapsed" % (end - start)),
- colorize_word("average", "%.2fs average" % ((end - start)/run))]
- print ", ".join(timing)
-
-if xmlr:
- xmlr.end()
-
-if failed:
- sys.exit(1)
-else:
- sys.exit(0)
diff --git a/qpid/python/qpid-python-test-ant.xml b/qpid/python/qpid-python-test-ant.xml
deleted file mode 100644
index f70e8923ed..0000000000
--- a/qpid/python/qpid-python-test-ant.xml
+++ /dev/null
@@ -1,192 +0,0 @@
-<!--
- -
- - 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.
- -
- -->
-
-<project name="qpid-python-test-ant" default="test" >
-
- <!-- Ant wrapper around qpid-python-test. Starts Qpid broker; runs
- qpid-python-test, and formats the test output. -->
-
- <!-- Directories etc -->
- <property name="python.dir" value="${basedir}"/>
- <property name="qpid.root.dir" value="${basedir}/.."/>
- <property name="java.dir" value="${basedir}/../java"/>
- <property name="cpp.dir" value="${basedir}/../cpp"/>
- <property name="build.dir" value="${python.dir}/build"/>
- <property name="test.results.dir" value="${build.dir}/results"/>
- <property name="test.work.dir" value="${build.dir}/work"/>
-
- <!-- Qpid Broker Executable/Url/Port -->
- <property name="qpid.port" value="15672"/>
- <property name="qpid.python.broker.url" value="amqp://guest/guest@localhost:${qpid.port}"/>
- <property name="qpid.executable" value="${java.dir}/build/bin/qpid-server"/>
- <property name="qpid.executable.args" value="-p ${qpid.port}"/>
-
- <!-- Additional modules to be added to command. Property must include -M -->
- <property name="python.test.modules" value=""/>
- <!-- Ignore file. Property must include -I -->
- <property name="python.test.ignore" value=""/>
-
- <!-- Time to wait for socket to be bound -->
- <property name="ensurefree.maxwait" value="1000"/>
- <property name="start.maxwait" value="20000"/>
- <property name="stop.maxwait" value="10000"/>
- <property name="socket.checkevery" value="1000"/>
-
- <!-- Success message -->
- <property name="passed.message" value=" 0 failed"/>
-
-
- <target name="test" depends="clean, init, ensure-port-free, start-broker, run-tests, stop-broker, kill-broker, report"/>
-
- <target name="init">
- <mkdir dir="${test.results.dir}"/>
- <mkdir dir="${test.work.dir}"/>
- </target>
-
- <target name="clean">
- <delete dir="${test.results.dir}"/>
- <delete dir="${test.work.dir}"/>
- </target>
-
- <target name="ensure-port-free" depends="init" unless="skip.ensure-port-free">
- <await-port-free port="${qpid.port}" maxwait="${ensurefree.maxwait}" checkevery="${socket.checkevery}" timeoutproperty="ensurefree.timeout"/>
- <fail message="Broker port ${qpid.port} is not free" if="ensurefree.timeout"/>
- </target>
-
- <target name="start-broker" depends="init">
- <echo>Starting Qpid with ${qpid.executable} ${qpid.executable.args}</echo>
- <exec executable="${qpid.executable}" spawn="true">
- <env key="QPID_WORK" value="${test.work.dir}"/>
- <arg line="${qpid.executable.args}"/>
- </exec>
-
- <await-port-bound port="${qpid.port}" maxwait="${start.maxwait}" checkevery="${socket.checkevery}" timeoutproperty="start.timeout"/>
- <antcall target="wait-for-broker-ready"/>
- </target>
-
- <target name="wait-for-broker-ready" if="java.broker">
- <await-broker-log path="${test.work.dir}/log/qpid.log" entry="BRK-1004" maxwait="${start.maxwait}" checkevery="${socket.checkevery}" timeoutproperty="start.timeout"/>
- </target>
-
- <target name="stop-broker" depends="init">
- <get-pid port="${qpid.port}" targetProperty="pid" resultproperty="stopresultproperty"/>
- <echo>Stopping Qpid with pid '${pid}'</echo>
- <kill-pid pid="${pid}" signo="-15"/>
-
- <await-port-free port="${qpid.port}" maxwait="${stop.maxwait}" checkevery="${socket.checkevery}" timeoutproperty="stop.timeout"/>
- </target>
-
- <target name="kill-broker" depends="init" if="stop.timeout">
- <get-pid port="${qpid.port}" targetProperty="pid" resultproperty="killresultproperty"/>
- <echo>Killing Qpid with pid '${pid}'</echo>
- <kill-pid pid="${pid}" signo="-9"/>
- </target>
-
- <target name="run-tests" depends="init" unless="start.timeout">
- <echo>Running test-suite</echo>
- <exec executable="${python.dir}/qpid-python-test" output="${test.results.dir}/results.out" error="${test.results.dir}/results.err">
- <env key="PYTHONPATH" value="${qpid.root.dir}/tests/src/py:${qpid.root.dir}/extras/qmf/src/py:${qpid.root.dir}/tools/src/py"/>
- <arg line="-b ${qpid.python.broker.url} -x ${test.results.dir}/TEST-python.xml ${python.test.modules} ${python.test.ignore}"/>
- </exec>
-
- <condition property="tests.passed">
- <isfileselected file="${test.results.dir}/results.out">
- <contains text="${passed.message}"/>
- </isfileselected>
- </condition>
- </target>
-
- <target name="report" depends="init" unless="tests.passed">
- <fail message="Test(s) failed" unless="tests.passed"/>
- <echo message="Test(s) passed" if="tests.passed"/>
- </target>
-
- <macrodef name="get-pid">
- <attribute name="targetProperty"/>
- <attribute name="port"/>
- <attribute name="resultproperty"/>
- <sequential>
- <exec executable="lsof" outputproperty="@{targetProperty}" resultproperty="@{resultproperty}">
- <arg value="-t"/> <!-- Terse output -->
- <arg value="-i"/> <arg value=":@{port}"/>
- </exec>
- <fail message="lsof failed to determine the pid using port @{port}, exit status ${@{resultproperty}}">
- <condition>
- <not>
- <equals arg1="${@{resultproperty}}" arg2="0"/>
- </not>
- </condition>
- </fail>
- </sequential>
- </macrodef>
-
- <macrodef name="kill-pid">
- <attribute name="pid"/>
- <attribute name="signo"/>
- <sequential>
- <exec executable="kill">
- <arg value="@{signo}"/>
- <arg value="@{pid}"/>
- </exec>
- </sequential>
- </macrodef>
-
- <macrodef name="await-port-free">
- <attribute name="maxwait"/>
- <attribute name="checkevery"/>
- <attribute name="timeoutproperty"/>
- <attribute name="port"/>
- <sequential>
- <waitfor maxwait="@{maxwait}" maxwaitunit="millisecond" checkevery="@{checkevery}" checkeveryunit="millisecond" timeoutproperty="@{timeoutproperty}">
- <not>
- <socket server="localhost" port="@{port}"/>
- </not>
- </waitfor>
- </sequential>
- </macrodef>
-
- <macrodef name="await-port-bound">
- <attribute name="maxwait"/>
- <attribute name="checkevery"/>
- <attribute name="timeoutproperty"/>
- <attribute name="port"/>
- <sequential>
- <waitfor maxwait="@{maxwait}" maxwaitunit="millisecond" checkevery="@{checkevery}" checkeveryunit="millisecond" timeoutproperty="@{timeoutproperty}">
- <socket server="localhost" port="@{port}"/>
- </waitfor>
- </sequential>
- </macrodef>
-
- <macrodef name="await-broker-log">
- <attribute name="maxwait"/>
- <attribute name="checkevery"/>
- <attribute name="timeoutproperty"/>
- <attribute name="entry"/>
- <attribute name="path"/>
- <sequential>
- <echo message="Waiting for entry '@{entry}' in '@{path}' "/>
- <waitfor maxwait="@{maxwait}" maxwaitunit="millisecond" checkevery="@{checkevery}" checkeveryunit="millisecond" timeoutproperty="@{timeoutproperty}">
- <resourcecontains resource="@{path}" substring="@{entry}"/>
- </waitfor>
- <echo message="Timeout @{timeoutproperty}"/>
- </sequential>
- </macrodef>
-</project>
diff --git a/qpid/python/qpid-python-test.bat b/qpid/python/qpid-python-test.bat
deleted file mode 100755
index 3fd6f9693b..0000000000
--- a/qpid/python/qpid-python-test.bat
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-python %~dp0\qpid-python-test %*
diff --git a/qpid/python/qpid/__init__.py b/qpid/python/qpid/__init__.py
deleted file mode 100644
index 780cab46a0..0000000000
--- a/qpid/python/qpid/__init__.py
+++ /dev/null
@@ -1,84 +0,0 @@
-#
-# 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 connection
-
-class Struct:
-
- def __init__(self, type, *args, **kwargs):
- self.__dict__["type"] = type
- self.__dict__["_values"] = {}
-
- if len(args) > len(self.type.fields):
- raise TypeError("too many args")
-
- for a, f in zip(args, self.type.fields):
- self.set(f.name, a)
-
- for k, a in kwargs.items():
- self.set(k, a)
-
- def _check(self, attr):
- field = self.type.fields.byname.get(attr)
- if field == None:
- raise AttributeError(attr)
- return field
-
- def exists(self, attr):
- return self.type.fields.byname.has_key(attr)
-
- def has(self, attr):
- self._check(attr)
- return self._values.has_key(attr)
-
- def set(self, attr, value):
- self._check(attr)
- self._values[attr] = value
-
- def get(self, attr):
- field = self._check(attr)
- return self._values.get(attr, field.default())
-
- def clear(self, attr):
- self._check(attr)
- del self._values[attr]
-
- def __setattr__(self, attr, value):
- self.set(attr, value)
-
- def __getattr__(self, attr):
- return self.get(attr)
-
- def __delattr__(self, attr):
- self.clear(attr)
-
- def __setitem__(self, attr, value):
- self.set(attr, value)
-
- def __getitem__(self, attr):
- return self.get(attr)
-
- def __delitem__(self, attr):
- self.clear(attr)
-
- def __str__(self):
- return "%s %s" % (self.type, self._values)
-
- def __repr__(self):
- return str(self)
diff --git a/qpid/python/qpid/client.py b/qpid/python/qpid/client.py
deleted file mode 100644
index 5c687898dc..0000000000
--- a/qpid/python/qpid/client.py
+++ /dev/null
@@ -1,286 +0,0 @@
-#
-# 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.
-#
-
-"""
-An AMQP client implementation that uses a custom delegate for
-interacting with the server.
-"""
-
-import os, threading
-from peer import Peer, Channel, Closed
-from delegate import Delegate
-from util import get_client_properties_with_defaults
-from connection08 import Connection, Frame, connect
-from spec08 import load
-from queue import Queue
-from reference import ReferenceId, References
-from saslmech.finder import get_sasl_mechanism
-from saslmech.sasl import SaslException
-
-
-class Client:
-
- def __init__(self, host, port, spec = None, vhost = None):
- self.host = host
- self.port = port
- if spec:
- self.spec = spec
- else:
- from specs_config import amqp_spec_0_9
- self.spec = load(amqp_spec_0_9)
- self.structs = StructFactory(self.spec)
- self.sessions = {}
-
- self.mechanism = None
- self.response = None
- self.locale = None
- self.sasl = None
-
- self.vhost = vhost
- if self.vhost == None:
- self.vhost = "/"
-
- self.queues = {}
- self.lock = threading.Lock()
-
- self.closed = False
- self.reason = None
- self.started = threading.Event()
- self.peer = None
-
- def wait(self):
- self.started.wait()
- if self.closed:
- raise Closed(self.reason)
-
- def queue(self, key):
- self.lock.acquire()
- try:
- try:
- q = self.queues[key]
- except KeyError:
- q = Queue(0)
- self.queues[key] = q
- finally:
- self.lock.release()
- return q
-
- def start(self, response=None, mechanism=None, locale="en_US", tune_params=None,
- username=None, password=None,
- client_properties=None, connection_options=None, sasl_options = None,
- channel_options=None):
- if response is not None and (username is not None or password is not None):
- raise RuntimeError("client must not specify both response and (username, password).")
- if response is not None:
- self.response = response
- authzid, self.username, self.password = response.split("\0")
- else:
- self.username = username
- self.password = password
- self.mechanism = mechanism
- self.locale = locale
- self.tune_params = tune_params
- self.client_properties=get_client_properties_with_defaults(provided_client_properties=client_properties, version_property_key="version")
- self.sasl_options = sasl_options
- self.socket = connect(self.host, self.port, connection_options)
- self.conn = Connection(self.socket, self.spec)
- self.peer = Peer(self.conn, ClientDelegate(self), Session, channel_options)
-
- self.conn.init()
- self.peer.start()
- self.wait()
- self.channel(0).connection_open(self.vhost)
-
- def channel(self, id):
- self.lock.acquire()
- try:
- ssn = self.peer.channel(id)
- ssn.client = self
- self.sessions[id] = ssn
- finally:
- self.lock.release()
- return ssn
-
- def session(self):
- self.lock.acquire()
- try:
- id = None
- for i in xrange(1, 64*1024):
- if not self.sessions.has_key(i):
- id = i
- break
- finally:
- self.lock.release()
- if id == None:
- raise RuntimeError("out of channels")
- else:
- return self.channel(id)
-
- def close(self):
- if self.peer:
- try:
- if not self.closed:
- channel = self.channel(0);
- if channel and not channel._closed:
- try:
- channel.connection_close(reply_code=200)
- except:
- pass
- self.closed = True
- finally:
- self.peer.stop()
-
-class ClientDelegate(Delegate):
-
- def __init__(self, client):
- Delegate.__init__(self)
- self.client = client
-
- def connection_start(self, ch, msg):
- if self.client.mechanism is None and self.client.response is not None:
- # Supports users passing the response argument
- self.client.mechanism = "PLAIN"
-
- serverSupportedMechs = msg.frame.args[3].split()
- if self.client.mechanism is None:
- self.client.sasl = get_sasl_mechanism(serverSupportedMechs, self.client.username, self.client.password,
- sasl_options=self.client.sasl_options)
- else:
- if self.client.mechanism not in serverSupportedMechs:
- raise SaslException("sasl negotiation failed: no mechanism agreed. Client requested: '%s' Server supports: %s"
- % (self.client.mechanism, serverSupportedMechs))
- self.client.sasl = get_sasl_mechanism([self.client.mechanism], self.client.username, self.client.password,
- sasl_options=self.client.sasl_options)
- if self.client.sasl is None:
- raise SaslException("sasl negotiation failed: no mechanism agreed. Client requested: '%s' Server supports: %s"
- % (self.client.mechanism, serverSupportedMechs))
- self.client.mechanism = self.client.sasl.mechanismName()
-
- if self.client.response is None:
- self.client.response = self.client.sasl.initialResponse()
-
- msg.start_ok(mechanism=self.client.mechanism,
- response=self.client.response or "",
- locale=self.client.locale,
- client_properties=self.client.client_properties)
-
- def connection_secure(self, ch, msg):
- msg.secure_ok(response=self.client.sasl.response(msg.challenge))
-
- def connection_tune(self, ch, msg):
- if self.client.tune_params:
- #todo: just override the params, i.e. don't require them
- # all to be included in tune_params
- msg.tune_ok(**self.client.tune_params)
- else:
- msg.tune_ok(*msg.frame.args)
- self.client.started.set()
-
- def message_transfer(self, ch, msg):
- self.client.queue(msg.destination).put(msg)
-
- def message_open(self, ch, msg):
- ch.references.open(msg.reference)
-
- def message_close(self, ch, msg):
- ch.references.close(msg.reference)
-
- def message_append(self, ch, msg):
- ch.references.get(msg.reference).append(msg.bytes)
-
- def message_acquired(self, ch, msg):
- ch.control_queue.put(msg)
-
- def basic_deliver(self, ch, msg):
- self.client.queue(msg.consumer_tag).put(msg)
-
- def channel_pong(self, ch, msg):
- msg.ok()
-
- def channel_close(self, ch, msg):
- ch.closed(msg)
-
- def channel_flow(self, ch, msg):
- # On resuming we don't want to send a message before flow-ok has been sent.
- # Therefore, we send flow-ok before we set the flow_control flag.
- if msg.active:
- msg.flow_ok()
- ch.set_flow_control(not msg.active)
- # On suspending we don't want to send a message after flow-ok has been sent.
- # Therefore, we send flow-ok after we set the flow_control flag.
- if not msg.active:
- msg.flow_ok()
-
- def session_ack(self, ch, msg):
- pass
-
- def session_closed(self, ch, msg):
- ch.closed(msg)
-
- def connection_close(self, ch, msg):
- self.client.peer.closed(msg)
-
- def execution_complete(self, ch, msg):
- ch.completion.complete(msg.cumulative_execution_mark)
-
- def execution_result(self, ch, msg):
- future = ch.futures[msg.command_id]
- future.put_response(ch, msg.data)
-
- def closed(self, reason):
- self.client.closed = True
- self.client.reason = reason
- self.client.started.set()
-
-class StructFactory:
-
- def __init__(self, spec):
- self.spec = spec
- self.factories = {}
-
- def __getattr__(self, name):
- if self.factories.has_key(name):
- return self.factories[name]
- elif self.spec.domains.byname.has_key(name):
- f = lambda *args, **kwargs: self.struct(name, *args, **kwargs)
- self.factories[name] = f
- return f
- else:
- raise AttributeError(name)
-
- def struct(self, name, *args, **kwargs):
- return self.spec.struct(name, *args, **kwargs)
-
-class Session(Channel):
-
- def __init__(self, *args):
- Channel.__init__(self, *args)
- self.references = References()
- self.client = None
-
- def open(self):
- self.session_open()
-
- def close(self):
- self.session_close()
- self.client.lock.acquire()
- try:
- del self.client.sessions[self.id]
- finally:
- self.client.lock.release()
diff --git a/qpid/python/qpid/codec.py b/qpid/python/qpid/codec.py
deleted file mode 100644
index a4c542415c..0000000000
--- a/qpid/python/qpid/codec.py
+++ /dev/null
@@ -1,701 +0,0 @@
-#!/usr/bin/env 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.
-#
-
-"""
-Utility code to translate between python objects and AMQP encoded data
-fields.
-
-The unit test for this module is located in tests/codec.py
-"""
-
-import re, qpid, spec08, os
-from cStringIO import StringIO
-from struct import *
-from reference import ReferenceId
-from logging import getLogger
-
-log = getLogger("qpid.codec")
-
-class EOF(Exception):
- pass
-
-# This code appears to be dead
-TYPE_ALIASES = {
- "long_string": "longstr",
- "unsigned_int": "long"
- }
-
-class Codec:
-
- """
- class that handles encoding/decoding of AMQP primitives
- """
-
- def __init__(self, stream, spec):
- """
- initializing the stream/fields used
- """
- self.stream = stream
- self.spec = spec
- self.nwrote = 0
- self.nread = 0
- self.incoming_bits = []
- self.outgoing_bits = []
-
- # Before 0-91, the AMQP's set of types did not include the boolean type. However,
- # the 0-8 and 0-9 Java client uses this type so we encode/decode it too. However, this
- # can be turned off by setting the followng environment value.
- if "QPID_CODEC_DISABLE_0_91_BOOLEAN" in os.environ:
- self.understand_boolean = False
- else:
- self.understand_boolean = True
-
- log.debug("AMQP 0-91 boolean supported : %r", self.understand_boolean)
-
- self.types = {}
- self.codes = {}
- self.integertypes = [int, long]
- self.encodings = {
- float: "double", # python uses 64bit floats, send them as doubles
- basestring: "longstr",
- None.__class__:"void",
- list: "sequence",
- tuple: "sequence",
- dict: "table"
- }
-
- if self.understand_boolean:
- self.encodings[bool] = "boolean"
-
- for constant in self.spec.constants:
- # This code appears to be dead
- if constant.klass == "field-table-type":
- type = constant.name.replace("field_table_", "")
- self.typecode(constant.id, TYPE_ALIASES.get(type, type))
-
- if not self.types:
- # long-string 'S'
- self.typecode(ord('S'), "longstr")
- # void 'V'
- self.typecode(ord('V'), "void")
- # long-int 'I' (32bit signed)
- self.typecode(ord('I'), "signed_int")
- # long-long-int 'l' (64bit signed)
- # This is a long standing pre-0-91-spec type used by the Java
- # client, 0-9-1 says it should be unsigned or use 'L')
- self.typecode(ord('l'), "signed_long")
- # double 'd'
- self.typecode(ord('d'), "double")
- # float 'f'
- self.typecode(ord('f'), "float")
-
- if self.understand_boolean:
- self.typecode(ord('t'), "boolean")
-
- ## The following are supported for decoding only ##
-
- # short-short-uint 'b' (8bit signed)
- self.types[ord('b')] = "signed_octet"
- # short-int 's' (16bit signed)
- # This is a long standing pre-0-91-spec type code used by the Java
- # client to send shorts, it should really be a short-string, or for 0-9-1 use 'U'
- self.types[ord('s')] = "signed_short"
-
- def typecode(self, code, type):
- self.types[code] = type
- self.codes[type] = code
-
- def resolve(self, klass, value):
- if(klass in self.integertypes):
- if (value >= -2147483648 and value <= 2147483647):
- return "signed_int"
- elif (value >= -9223372036854775808 and value <= 9223372036854775807):
- return "signed_long"
- else:
- raise ValueError('Integer value is outwith the supported 64bit signed range')
- if self.encodings.has_key(klass):
- return self.encodings[klass]
- for base in klass.__bases__:
- result = self.resolve(base, value)
- if result != None:
- return result
-
- def read(self, n):
- """
- reads in 'n' bytes from the stream. Can raise EOF exception
- """
- self.clearbits()
- data = self.stream.read(n)
- if n > 0 and len(data) == 0:
- raise EOF()
- self.nread += len(data)
- return data
-
- def write(self, s):
- """
- writes data 's' to the stream
- """
- self.flushbits()
- self.stream.write(s)
- self.nwrote += len(s)
-
- def flush(self):
- """
- flushes the bits and data present in the stream
- """
- self.flushbits()
- self.stream.flush()
-
- def flushbits(self):
- """
- flushes the bits(compressed into octets) onto the stream
- """
- if len(self.outgoing_bits) > 0:
- bytes = []
- index = 0
- for b in self.outgoing_bits:
- if index == 0: bytes.append(0)
- if b: bytes[-1] |= 1 << index
- index = (index + 1) % 8
- del self.outgoing_bits[:]
- for byte in bytes:
- self.encode_octet(byte)
-
- def clearbits(self):
- if self.incoming_bits:
- self.incoming_bits = []
-
- def pack(self, fmt, *args):
- """
- packs the data 'args' as per the format 'fmt' and writes it to the stream
- """
- self.write(pack(fmt, *args))
-
- def unpack(self, fmt):
- """
- reads data from the stream and unpacks it as per the format 'fmt'
- """
- size = calcsize(fmt)
- data = self.read(size)
- values = unpack(fmt, data)
- if len(values) == 1:
- return values[0]
- else:
- return values
-
- def encode(self, type, value):
- """
- calls the appropriate encode function e.g. encode_octet, encode_short etc.
- """
- if isinstance(type, spec08.Struct):
- self.encode_struct(type, value)
- else:
- getattr(self, "encode_" + type)(value)
-
- def decode(self, type):
- """
- calls the appropriate decode function e.g. decode_octet, decode_short etc.
- """
- if isinstance(type, spec08.Struct):
- return self.decode_struct(type)
- else:
- log.debug("Decoding using method: decode_" + type)
- return getattr(self, "decode_" + type)()
-
- def encode_bit(self, o):
- """
- encodes a bit
- """
- if o:
- self.outgoing_bits.append(True)
- else:
- self.outgoing_bits.append(False)
-
- def decode_bit(self):
- """
- decodes a bit
- """
- if len(self.incoming_bits) == 0:
- bits = self.decode_octet()
- for i in range(8):
- self.incoming_bits.append(bits >> i & 1 != 0)
- return self.incoming_bits.pop(0)
-
- def encode_octet(self, o):
- """
- encodes an UNSIGNED octet (8 bits) data 'o' in network byte order
- """
-
- # octet's valid range is [0,255]
- if (o < 0 or o > 255):
- raise ValueError('Valid range of octet is [0,255]')
-
- self.pack("!B", int(o))
-
- def decode_octet(self):
- """
- decodes an UNSIGNED octet (8 bits) encoded in network byte order
- """
- return self.unpack("!B")
-
- def decode_signed_octet(self):
- """
- decodes a signed octet (8 bits) encoded in network byte order
- """
- return self.unpack("!b")
-
- def encode_short(self, o):
- """
- encodes an UNSIGNED short (16 bits) data 'o' in network byte order
- AMQP 0-9-1 type: short-uint
- """
-
- # short int's valid range is [0,65535]
- if (o < 0 or o > 65535):
- raise ValueError('Valid range of short int is [0,65535]: %s' % o)
-
- self.pack("!H", int(o))
-
- def decode_short(self):
- """
- decodes an UNSIGNED short (16 bits) in network byte order
- AMQP 0-9-1 type: short-uint
- """
- return self.unpack("!H")
-
- def decode_signed_short(self):
- """
- decodes a signed short (16 bits) in network byte order
- AMQP 0-9-1 type: short-int
- """
- return self.unpack("!h")
-
- def encode_long(self, o):
- """
- encodes an UNSIGNED long (32 bits) data 'o' in network byte order
- AMQP 0-9-1 type: long-uint
- """
-
- # we need to check both bounds because on 64 bit platforms
- # struct.pack won't raise an error if o is too large
- if (o < 0 or o > 4294967295):
- raise ValueError('Valid range of long int is [0,4294967295]')
-
- self.pack("!L", int(o))
-
- def decode_long(self):
- """
- decodes an UNSIGNED long (32 bits) in network byte order
- AMQP 0-9-1 type: long-uint
- """
- return self.unpack("!L")
-
- def encode_signed_long(self, o):
- """
- encodes a signed long (64 bits) in network byte order
- AMQP 0-9-1 type: long-long-int
- """
- self.pack("!q", o)
-
- def decode_signed_long(self):
- """
- decodes a signed long (64 bits) in network byte order
- AMQP 0-9-1 type: long-long-int
- """
- return self.unpack("!q")
-
- def encode_signed_int(self, o):
- """
- encodes a signed int (32 bits) in network byte order
- AMQP 0-9-1 type: long-int
- """
- self.pack("!l", o)
-
- def decode_signed_int(self):
- """
- decodes a signed int (32 bits) in network byte order
- AMQP 0-9-1 type: long-int
- """
- return self.unpack("!l")
-
- def encode_longlong(self, o):
- """
- encodes an UNSIGNED long long (64 bits) data 'o' in network byte order
- AMQP 0-9-1 type: long-long-uint
- """
- self.pack("!Q", o)
-
- def decode_longlong(self):
- """
- decodes an UNSIGNED long long (64 bits) in network byte order
- AMQP 0-9-1 type: long-long-uint
- """
- return self.unpack("!Q")
-
- def encode_float(self, o):
- self.pack("!f", o)
-
- def decode_float(self):
- return self.unpack("!f")
-
- def encode_double(self, o):
- self.pack("!d", o)
-
- def decode_double(self):
- return self.unpack("!d")
-
- def encode_bin128(self, b):
- for idx in range (0,16):
- self.pack("!B", ord (b[idx]))
-
- def decode_bin128(self):
- result = ""
- for idx in range (0,16):
- result = result + chr (self.unpack("!B"))
- return result
-
- def encode_raw(self, len, b):
- for idx in range (0,len):
- self.pack("!B", b[idx])
-
- def decode_raw(self, len):
- result = ""
- for idx in range (0,len):
- result = result + chr (self.unpack("!B"))
- return result
-
- def enc_str(self, fmt, s):
- """
- encodes a string 's' in network byte order as per format 'fmt'
- """
- size = len(s)
- self.pack(fmt, size)
- self.write(s)
-
- def dec_str(self, fmt):
- """
- decodes a string in network byte order as per format 'fmt'
- """
- size = self.unpack(fmt)
- return self.read(size)
-
- def encode_shortstr(self, s):
- """
- encodes a short string 's' in network byte order
- """
-
- # short strings are limited to 255 octets
- if len(s) > 255:
- raise ValueError('Short strings are limited to 255 octets')
-
- self.enc_str("!B", s)
-
- def decode_shortstr(self):
- """
- decodes a short string in network byte order
- """
- return self.dec_str("!B")
-
- def encode_longstr(self, s):
- """
- encodes a long string 's' in network byte order
- """
- if isinstance(s, dict):
- self.encode_table(s)
- else:
- self.enc_str("!L", s)
-
- def decode_longstr(self):
- """
- decodes a long string 's' in network byte order
- """
- return self.dec_str("!L")
-
- def encode_table(self, tbl):
- """
- encodes a table data structure in network byte order
- """
- enc = StringIO()
- codec = Codec(enc, self.spec)
- if tbl:
- for key, value in tbl.items():
- if self.spec.major == 8 and self.spec.minor == 0 and len(key) > 128:
- raise ValueError("field table key too long: '%s'" % key)
- type = self.resolve(value.__class__, value)
- if type == None:
- raise ValueError("no encoding for: " + str(value.__class__))
- codec.encode_shortstr(key)
- codec.encode_octet(self.codes[type])
- codec.encode(type, value)
- s = enc.getvalue()
- self.encode_long(len(s))
- self.write(s)
-
- def decode_table(self):
- """
- decodes a table data structure in network byte order
- """
- size = self.decode_long()
- start = self.nread
- result = {}
- while self.nread - start < size:
- key = self.decode_shortstr()
- log.debug("Field table entry key: %r", key)
- code = self.decode_octet()
- log.debug("Field table entry type code: %r", code)
- if self.types.has_key(code):
- value = self.decode(self.types[code])
- else:
- w = width(code)
- if fixed(code):
- value = self.read(w)
- else:
- value = self.read(self.dec_num(w))
- result[key] = value
- log.debug("Field table entry value: %r", value)
- return result
-
- def encode_timestamp(self, t):
- """
- encodes a timestamp data structure in network byte order
- """
- self.encode_longlong(t)
-
- def decode_timestamp(self):
- """
- decodes a timestamp data structure in network byte order
- """
- return self.decode_longlong()
-
- def encode_content(self, s):
- """
- encodes a content data structure in network byte order
-
- content can be passed as a string in which case it is assumed to
- be inline data, or as an instance of ReferenceId indicating it is
- a reference id
- """
- if isinstance(s, ReferenceId):
- self.encode_octet(1)
- self.encode_longstr(s.id)
- else:
- self.encode_octet(0)
- self.encode_longstr(s)
-
- def decode_content(self):
- """
- decodes a content data structure in network byte order
-
- return a string for inline data and a ReferenceId instance for
- references
- """
- type = self.decode_octet()
- if type == 0:
- return self.decode_longstr()
- else:
- return ReferenceId(self.decode_longstr())
-
- # new domains for 0-10:
-
- def encode_rfc1982_long(self, s):
- self.encode_long(s)
-
- def decode_rfc1982_long(self):
- return self.decode_long()
-
- def encode_rfc1982_long_set(self, s):
- self.encode_short(len(s) * 4)
- for i in s:
- self.encode_long(i)
-
- def decode_rfc1982_long_set(self):
- count = self.decode_short() / 4
- set = []
- for i in range(0, count):
- set.append(self.decode_long())
- return set;
-
- def encode_uuid(self, s):
- self.pack("16s", s)
-
- def decode_uuid(self):
- return self.unpack("16s")
-
- def encode_void(self,o):
- #NO-OP, value is implicit in the type.
- return
-
- def decode_void(self):
- return None
-
- def enc_num(self, width, n):
- if width == 1:
- self.encode_octet(n)
- elif width == 2:
- self.encode_short(n)
- elif width == 3:
- self.encode_long(n)
- else:
- raise ValueError("invalid width: %s" % width)
-
- def dec_num(self, width):
- if width == 1:
- return self.decode_octet()
- elif width == 2:
- return self.decode_short()
- elif width == 4:
- return self.decode_long()
- else:
- raise ValueError("invalid width: %s" % width)
-
- def encode_struct(self, type, s):
- if type.size:
- enc = StringIO()
- codec = Codec(enc, self.spec)
- codec.encode_struct_body(type, s)
- codec.flush()
- body = enc.getvalue()
- self.enc_num(type.size, len(body))
- self.write(body)
- else:
- self.encode_struct_body(type, s)
-
- def decode_struct(self, type):
- if type.size:
- size = self.dec_num(type.size)
- if size == 0:
- return None
- return self.decode_struct_body(type)
-
- def encode_struct_body(self, type, s):
- reserved = 8*type.pack - len(type.fields)
- assert reserved >= 0
-
- for f in type.fields:
- if s == None:
- self.encode_bit(False)
- elif f.type == "bit":
- self.encode_bit(s.get(f.name))
- else:
- self.encode_bit(s.has(f.name))
-
- for i in range(reserved):
- self.encode_bit(False)
-
- for f in type.fields:
- if f.type != "bit" and s != None and s.has(f.name):
- self.encode(f.type, s.get(f.name))
-
- self.flush()
-
- def decode_struct_body(self, type):
- reserved = 8*type.pack - len(type.fields)
- assert reserved >= 0
-
- s = qpid.Struct(type)
-
- for f in type.fields:
- if f.type == "bit":
- s.set(f.name, self.decode_bit())
- elif self.decode_bit():
- s.set(f.name, None)
-
- for i in range(reserved):
- if self.decode_bit():
- raise ValueError("expecting reserved flag")
-
- for f in type.fields:
- if f.type != "bit" and s.has(f.name):
- s.set(f.name, self.decode(f.type))
-
- self.clearbits()
-
- return s
-
- def encode_long_struct(self, s):
- enc = StringIO()
- codec = Codec(enc, self.spec)
- type = s.type
- codec.encode_short(type.type)
- codec.encode_struct_body(type, s)
- self.encode_longstr(enc.getvalue())
-
- def decode_long_struct(self):
- codec = Codec(StringIO(self.decode_longstr()), self.spec)
- type = self.spec.structs[codec.decode_short()]
- return codec.decode_struct_body(type)
-
- def decode_array(self):
- size = self.decode_long()
- code = self.decode_octet()
- count = self.decode_long()
- result = []
- for i in range(0, count):
- if self.types.has_key(code):
- value = self.decode(self.types[code])
- else:
- w = width(code)
- if fixed(code):
- value = self.read(w)
- else:
- value = self.read(self.dec_num(w))
- result.append(value)
- return result
-
- def encode_boolean(self, s):
- if (s):
- self.pack("!c", "\x01")
- else:
- self.pack("!c", "\x00")
-
- def decode_boolean(self):
- b = self.unpack("!c")
- if b == "\x00":
- return False
- else:
- # AMQP spec says anything else is True
- return True
-
-
-
-def fixed(code):
- return (code >> 6) != 2
-
-def width(code):
- # decimal
- if code >= 192:
- decsel = (code >> 4) & 3
- if decsel == 0:
- return 5
- elif decsel == 1:
- return 9
- elif decsel == 3:
- return 0
- else:
- raise ValueError(code)
- # variable width
- elif code < 192 and code >= 128:
- lenlen = (code >> 4) & 3
- if lenlen == 3: raise ValueError(code)
- return 2 ** lenlen
- # fixed width
- else:
- return (code >> 4) & 7
diff --git a/qpid/python/qpid/codec010.py b/qpid/python/qpid/codec010.py
deleted file mode 100644
index f4dc60fcc4..0000000000
--- a/qpid/python/qpid/codec010.py
+++ /dev/null
@@ -1,404 +0,0 @@
-#
-# 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 datetime, string
-from packer import Packer
-from datatypes import serial, timestamp, RangedSet, Struct, UUID
-from ops import Compound, PRIMITIVE, COMPOUND
-
-class CodecException(Exception): pass
-
-def direct(t):
- return lambda x: t
-
-def map_str(s):
- for c in s:
- if ord(c) >= 0x80:
- return "vbin16"
- return "str16"
-
-class Codec(Packer):
-
- ENCODINGS = {
- bool: direct("boolean"),
- unicode: direct("str16"),
- str: map_str,
- buffer: direct("vbin32"),
- int: direct("int64"),
- long: direct("int64"),
- float: direct("double"),
- None.__class__: direct("void"),
- list: direct("list"),
- tuple: direct("list"),
- dict: direct("map"),
- timestamp: direct("datetime"),
- datetime.datetime: direct("datetime"),
- UUID: direct("uuid"),
- Compound: direct("struct32")
- }
-
- def encoding(self, obj):
- enc = self._encoding(obj.__class__, obj)
- if enc is None:
- raise CodecException("no encoding for %r" % obj)
- return PRIMITIVE[enc]
-
- def _encoding(self, klass, obj):
- if self.ENCODINGS.has_key(klass):
- return self.ENCODINGS[klass](obj)
- for base in klass.__bases__:
- result = self._encoding(base, obj)
- if result != None:
- return result
-
- def read_primitive(self, type):
- return getattr(self, "read_%s" % type.NAME)()
- def write_primitive(self, type, v):
- getattr(self, "write_%s" % type.NAME)(v)
-
- def read_void(self):
- return None
- def write_void(self, v):
- assert v == None
-
- def read_bit(self):
- return True
- def write_bit(self, b):
- if not b: raise ValueError(b)
-
- def read_uint8(self):
- return self.unpack("!B")
- def write_uint8(self, n):
- if n < 0 or n > 255:
- raise CodecException("Cannot encode %d as uint8" % n)
- return self.pack("!B", n)
-
- def read_int8(self):
- return self.unpack("!b")
- def write_int8(self, n):
- if n < -128 or n > 127:
- raise CodecException("Cannot encode %d as int8" % n)
- self.pack("!b", n)
-
- def read_char(self):
- return self.unpack("!c")
- def write_char(self, c):
- self.pack("!c", c)
-
- def read_boolean(self):
- return self.read_uint8() != 0
- def write_boolean(self, b):
- if b: n = 1
- else: n = 0
- self.write_uint8(n)
-
-
- def read_uint16(self):
- return self.unpack("!H")
- def write_uint16(self, n):
- if n < 0 or n > 65535:
- raise CodecException("Cannot encode %d as uint16" % n)
- self.pack("!H", n)
-
- def read_int16(self):
- return self.unpack("!h")
- def write_int16(self, n):
- if n < -32768 or n > 32767:
- raise CodecException("Cannot encode %d as int16" % n)
- self.pack("!h", n)
-
-
- def read_uint32(self):
- return self.unpack("!L")
- def write_uint32(self, n):
- if n < 0 or n > 4294967295:
- raise CodecException("Cannot encode %d as uint32" % n)
- self.pack("!L", n)
-
- def read_int32(self):
- return self.unpack("!l")
- def write_int32(self, n):
- if n < -2147483648 or n > 2147483647:
- raise CodecException("Cannot encode %d as int32" % n)
- self.pack("!l", n)
-
- def read_float(self):
- return self.unpack("!f")
- def write_float(self, f):
- self.pack("!f", f)
-
- def read_sequence_no(self):
- return serial(self.read_uint32())
- def write_sequence_no(self, n):
- self.write_uint32(n.value)
-
-
- def read_uint64(self):
- return self.unpack("!Q")
- def write_uint64(self, n):
- self.pack("!Q", n)
-
- def read_int64(self):
- return self.unpack("!q")
- def write_int64(self, n):
- self.pack("!q", n)
-
- def read_datetime(self):
- return timestamp(self.read_uint64())
- def write_datetime(self, t):
- if isinstance(t, datetime.datetime):
- t = timestamp(t)
- self.write_uint64(t)
-
- def read_double(self):
- return self.unpack("!d")
- def write_double(self, d):
- self.pack("!d", d)
-
- def read_vbin8(self):
- return self.read(self.read_uint8())
- def write_vbin8(self, b):
- if isinstance(b, buffer):
- b = str(b)
- self.write_uint8(len(b))
- self.write(b)
-
- def read_str8(self):
- return self.read_vbin8().decode("utf8")
- def write_str8(self, s):
- self.write_vbin8(s.encode("utf8"))
-
- def read_str16(self):
- return self.read_vbin16().decode("utf8")
- def write_str16(self, s):
- self.write_vbin16(s.encode("utf8"))
-
- def read_str16_latin(self):
- return self.read_vbin16().decode("iso-8859-15")
- def write_str16_latin(self, s):
- self.write_vbin16(s.encode("iso-8859-15"))
-
-
- def read_vbin16(self):
- return self.read(self.read_uint16())
- def write_vbin16(self, b):
- if isinstance(b, buffer):
- b = str(b)
- self.write_uint16(len(b))
- self.write(b)
-
- def read_sequence_set(self):
- result = RangedSet()
- size = self.read_uint16()
- nranges = size/8
- while nranges > 0:
- lower = self.read_sequence_no()
- upper = self.read_sequence_no()
- result.add(lower, upper)
- nranges -= 1
- return result
- def write_sequence_set(self, ss):
- size = 8*len(ss.ranges)
- self.write_uint16(size)
- for range in ss.ranges:
- self.write_sequence_no(range.lower)
- self.write_sequence_no(range.upper)
-
- def read_vbin32(self):
- return self.read(self.read_uint32())
- def write_vbin32(self, b):
- if isinstance(b, buffer):
- b = str(b)
- # Allow unicode values in connection 'response' field
- if isinstance(b, unicode):
- b = b.encode('utf8')
- self.write_uint32(len(b))
- self.write(b)
-
- def read_map(self):
- sc = StringCodec(self.read_vbin32())
- if not sc.encoded:
- return None
- count = sc.read_uint32()
- result = {}
- while sc.encoded:
- k = sc.read_str8()
- code = sc.read_uint8()
- type = PRIMITIVE[code]
- v = sc.read_primitive(type)
- result[k] = v
- return result
-
- def _write_map_elem(self, k, v):
- type = self.encoding(v)
- sc = StringCodec()
- sc.write_str8(k)
- sc.write_uint8(type.CODE)
- sc.write_primitive(type, v)
- return sc.encoded
-
- def write_map(self, m):
- sc = StringCodec()
- if m is not None:
- sc.write_uint32(len(m))
- sc.write(string.joinfields(map(self._write_map_elem, m.keys(), m.values()), ""))
- self.write_vbin32(sc.encoded)
-
- def read_array(self):
- sc = StringCodec(self.read_vbin32())
- if not sc.encoded:
- return None
- type = PRIMITIVE[sc.read_uint8()]
- count = sc.read_uint32()
- result = []
- while count > 0:
- result.append(sc.read_primitive(type))
- count -= 1
- return result
- def write_array(self, a):
- sc = StringCodec()
- if a is not None:
- if len(a) > 0:
- type = self.encoding(a[0])
- else:
- type = self.encoding(None)
- sc.write_uint8(type.CODE)
- sc.write_uint32(len(a))
- for o in a:
- sc.write_primitive(type, o)
- self.write_vbin32(sc.encoded)
-
- def read_list(self):
- sc = StringCodec(self.read_vbin32())
- if not sc.encoded:
- return None
- count = sc.read_uint32()
- result = []
- while count > 0:
- type = PRIMITIVE[sc.read_uint8()]
- result.append(sc.read_primitive(type))
- count -= 1
- return result
- def write_list(self, l):
- sc = StringCodec()
- if l is not None:
- sc.write_uint32(len(l))
- for o in l:
- type = self.encoding(o)
- sc.write_uint8(type.CODE)
- sc.write_primitive(type, o)
- self.write_vbin32(sc.encoded)
-
- def read_struct32(self):
- size = self.read_uint32()
- code = self.read_uint16()
- cls = COMPOUND[code]
- op = cls()
- self.read_fields(op)
- return op
- def write_struct32(self, value):
- self.write_compound(value)
-
- def read_compound(self, cls):
- size = self.read_size(cls.SIZE)
- if cls.CODE is not None:
- code = self.read_uint16()
- assert code == cls.CODE
- op = cls()
- self.read_fields(op)
- return op
- def write_compound(self, op):
- sc = StringCodec()
- if op.CODE is not None:
- sc.write_uint16(op.CODE)
- sc.write_fields(op)
- self.write_size(op.SIZE, len(sc.encoded))
- self.write(sc.encoded)
-
- def read_fields(self, op):
- flags = 0
- for i in range(op.PACK):
- flags |= (self.read_uint8() << 8*i)
-
- for i in range(len(op.FIELDS)):
- f = op.FIELDS[i]
- if flags & (0x1 << i):
- if COMPOUND.has_key(f.type):
- value = self.read_compound(COMPOUND[f.type])
- else:
- value = getattr(self, "read_%s" % f.type)()
- setattr(op, f.name, value)
- def write_fields(self, op):
- flags = 0
- for i in range(len(op.FIELDS)):
- f = op.FIELDS[i]
- value = getattr(op, f.name)
- if f.type == "bit":
- present = value
- else:
- present = value != None
- if present:
- flags |= (0x1 << i)
- for i in range(op.PACK):
- self.write_uint8((flags >> 8*i) & 0xFF)
- for i in range(len(op.FIELDS)):
- f = op.FIELDS[i]
- if flags & (0x1 << i):
- if COMPOUND.has_key(f.type):
- enc = self.write_compound
- else:
- enc = getattr(self, "write_%s" % f.type)
- value = getattr(op, f.name)
- enc(value)
-
- def read_size(self, width):
- if width > 0:
- attr = "read_uint%d" % (width*8)
- return getattr(self, attr)()
- def write_size(self, width, n):
- if width > 0:
- attr = "write_uint%d" % (width*8)
- getattr(self, attr)(n)
-
- def read_uuid(self):
- return UUID(bytes=self.unpack("16s"))
- def write_uuid(self, s):
- if isinstance(s, UUID):
- s = s.bytes
- self.pack("16s", s)
-
- def read_bin128(self):
- return self.unpack("16s")
- def write_bin128(self, b):
- self.pack("16s", b)
-
-
-
-class StringCodec(Codec):
-
- def __init__(self, encoded = ""):
- self.encoded = encoded
-
- def read(self, n):
- result = self.encoded[:n]
- self.encoded = self.encoded[n:]
- return result
-
- def write(self, s):
- self.encoded += s
diff --git a/qpid/python/qpid/compat.py b/qpid/python/qpid/compat.py
deleted file mode 100644
index 89e378791e..0000000000
--- a/qpid/python/qpid/compat.py
+++ /dev/null
@@ -1,222 +0,0 @@
-#
-# 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 sys
-import errno
-import time
-from logging import getLogger
-log = getLogger("qpid.messaging")
-
-try:
- set = set
-except NameError:
- from sets import Set as set
-
-try:
- from socket import SHUT_RDWR
-except ImportError:
- SHUT_RDWR = 2
-
-try:
- from traceback import format_exc
-except ImportError:
- import traceback
- def format_exc():
- return "".join(traceback.format_exception(*sys.exc_info()))
-
-# QPID-5588: prefer poll() to select(), as it allows file descriptors with
-# values > FD_SETSIZE
-import select as _select_mod
-try:
- # QPID-5790: unless eventlet/greenthreads have monkey-patched the select
- # module, as to date poll() is not properly supported by eventlet
- import eventlet
- _is_patched = eventlet.patcher.is_monkey_patched("select")
-except ImportError:
- _is_patched = False
-
-if hasattr(_select_mod, "poll") and not _is_patched:
- from select import error as SelectError
- def select(rlist, wlist, xlist, timeout=None):
- fd_count = 0
- rset = set(rlist)
- wset = set(wlist)
- xset = set(xlist)
- if timeout:
- # select expects seconds, poll milliseconds
- timeout = float(timeout) * 1000
- poller = _select_mod.poll()
-
- rwset = rset.intersection(wset)
- for rw in rwset:
- poller.register(rw, (_select_mod.POLLIN | _select_mod.POLLOUT))
- fd_count += 1
- for ro in rset.difference(rwset):
- poller.register(ro, _select_mod.POLLIN)
- fd_count += 1
- for wo in wset.difference(rwset):
- poller.register(wo, _select_mod.POLLOUT)
- fd_count += 1
- for x in xset:
- poller.register(x, _select_mod.POLLPRI)
- fd_count += 1
-
- # select returns the objects passed in, but poll gives us back only the
- # integer fds. Maintain a map to get back:
- fd_map = {}
- for o in rset | wset | xset:
- if hasattr(o, "fileno"):
- fd_map[o.fileno()] = o
-
- log.debug("poll(%d fds, timeout=%s)", fd_count, timeout)
- active = poller.poll(timeout)
- log.debug("poll() returned %s fds", len(active))
-
- rfds = []
- wfds = []
- xfds = []
- # set the error conditions so we do a read(), which will report the error
- rflags = (_select_mod.POLLIN | _select_mod.POLLERR | _select_mod.POLLHUP)
- for fds, flags in active:
- if fds in fd_map:
- fds = fd_map[fds]
- if (flags & rflags):
- rfds.append(fds)
- if (flags & _select_mod.POLLOUT):
- wfds.append(fds)
- if (flags & _select_mod.POLLPRI):
- xfds.append(fds)
- return (rfds, wfds, xfds)
-else:
- if tuple(sys.version_info[0:2]) < (2, 4):
- from select import error as SelectError
- from select import select as old_select
- def select(rlist, wlist, xlist, timeout=None):
- return old_select(list(rlist), list(wlist), list(xlist), timeout)
- else:
- from select import select
- from select import error as SelectError
-
-class BaseWaiter:
-
- def wakeup(self):
- self._do_write()
-
- def wait(self, timeout=None):
- start = time.time()
- if timeout is not None:
- ready = False
- while timeout > 0:
- try:
- ready, _, _ = select([self], [], [], timeout)
- break
- except SelectError, e:
- if e[0] == errno.EINTR:
- elapsed = time.time() - start
- timeout = timeout - elapsed
- else:
- raise e
- else:
- ready = True
-
- if ready:
- self._do_read()
- return True
- else:
- return False
-
- def reading(self):
- return True
-
- def readable(self):
- self._do_read()
-
-if sys.platform in ('win32', 'cygwin'):
- import socket
-
- class SockWaiter(BaseWaiter):
-
- def __init__(self, read_sock, write_sock):
- self.read_sock = read_sock
- self.write_sock = write_sock
-
- def _do_write(self):
- self.write_sock.send("\0")
-
- def _do_read(self):
- self.read_sock.recv(65536)
-
- def fileno(self):
- return self.read_sock.fileno()
-
- def close(self):
- if self.write_sock is not None:
- self.write_sock.close()
- self.write_sock = None
- self.read_sock.close()
- self.read_sock = None
-
- def __del__(self):
- self.close()
-
- def __repr__(self):
- return "SockWaiter(%r, %r)" % (self.read_sock, self.write_sock)
-
- def selectable_waiter():
- listener = socket.socket()
- listener.bind(('', 0))
- listener.listen(1)
- _, port = listener.getsockname()
- write_sock = socket.socket()
- write_sock.connect(("127.0.0.1", port))
- read_sock, _ = listener.accept()
- listener.close()
- return SockWaiter(read_sock, write_sock)
-else:
- import os
-
- class PipeWaiter(BaseWaiter):
-
- def __init__(self):
- self.read_fd, self.write_fd = os.pipe()
-
- def _do_write(self):
- os.write(self.write_fd, "\0")
-
- def _do_read(self):
- os.read(self.read_fd, 65536)
-
- def fileno(self):
- return self.read_fd
-
- def close(self):
- if self.write_fd is not None:
- os.close(self.write_fd)
- self.write_fd = None
- os.close(self.read_fd)
- self.read_fd = None
-
- def __del__(self):
- self.close()
-
- def __repr__(self):
- return "PipeWaiter(%r, %r)" % (self.read_fd, self.write_fd)
-
- def selectable_waiter():
- return PipeWaiter()
diff --git a/qpid/python/qpid/concurrency.py b/qpid/python/qpid/concurrency.py
deleted file mode 100644
index eefe0d445f..0000000000
--- a/qpid/python/qpid/concurrency.py
+++ /dev/null
@@ -1,106 +0,0 @@
-#
-# 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 compat, inspect, time
-
-def synchronized(meth):
- args, vargs, kwargs, defs = inspect.getargspec(meth)
- scope = {}
- scope["meth"] = meth
- exec """
-def %s%s:
- %s
- %s._lock.acquire()
- try:
- return meth%s
- finally:
- %s._lock.release()
-""" % (meth.__name__, inspect.formatargspec(args, vargs, kwargs, defs),
- repr(inspect.getdoc(meth)), args[0],
- inspect.formatargspec(args, vargs, kwargs, defs,
- formatvalue=lambda x: ""),
- args[0]) in scope
- return scope[meth.__name__]
-
-class Waiter(object):
-
- def __init__(self, condition):
- self.condition = condition
-
- def wait(self, predicate, timeout=None):
- passed = 0
- start = time.time()
- while not predicate():
- if timeout is None:
- # XXX: this timed wait thing is not necessary for the fast
- # condition from this module, only for the condition impl from
- # the threading module
-
- # using the timed wait prevents keyboard interrupts from being
- # blocked while waiting
- self.condition.wait(3)
- elif passed < timeout:
- self.condition.wait(timeout - passed)
- else:
- return bool(predicate())
- passed = time.time() - start
- return True
-
- def notify(self):
- self.condition.notify()
-
- def notifyAll(self):
- self.condition.notifyAll()
-
-class Condition:
-
- def __init__(self, lock):
- self.lock = lock
- self.waiters = []
- self.waiting = []
-
- def notify(self):
- assert self.lock._is_owned()
- if self.waiting:
- self.waiting[0].wakeup()
-
- def notifyAll(self):
- assert self.lock._is_owned()
- for w in self.waiting:
- w.wakeup()
-
- def wait(self, timeout=None):
- assert self.lock._is_owned()
- if not self.waiters:
- self.waiters.append(compat.selectable_waiter())
- sw = self.waiters.pop(0)
- self.waiting.append(sw)
- try:
- st = self.lock._release_save()
- sw.wait(timeout)
- finally:
- self.lock._acquire_restore(st)
- self.waiting.remove(sw)
- self.waiters.append(sw)
-
- def gc(self):
- assert self.lock._is_owned()
- while self.waiters:
- sw = self.waiters.pop(0)
- sw.close()
diff --git a/qpid/python/qpid/connection.py b/qpid/python/qpid/connection.py
deleted file mode 100644
index 2453f38c34..0000000000
--- a/qpid/python/qpid/connection.py
+++ /dev/null
@@ -1,250 +0,0 @@
-#
-# 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 datatypes, session
-from threading import Thread, Condition, RLock
-from util import wait, notify
-from codec010 import StringCodec
-from framing import *
-from session import Session
-from generator import control_invoker
-from exceptions import *
-from logging import getLogger
-import delegates, socket
-import sys
-
-class ChannelBusy(Exception): pass
-
-class ChannelsBusy(Exception): pass
-
-class SessionBusy(Exception): pass
-
-class ConnectionFailed(Exception): pass
-
-def client(*args, **kwargs):
- return delegates.Client(*args, **kwargs)
-
-def server(*args, **kwargs):
- return delegates.Server(*args, **kwargs)
-
-from framer import Framer
-
-class Connection(Framer):
-
- def __init__(self, sock, delegate=client, **args):
- Framer.__init__(self, sock)
- self.lock = RLock()
- self.attached = {}
- self.sessions = {}
-
- self.condition = Condition()
- # XXX: we should combine this into a single comprehensive state
- # model (whatever that means)
- self.opened = False
- self.failed = False
- self.closed = False
- self.close_code = (None, "connection aborted")
-
- self.thread = Thread(target=self.run)
- self.thread.setDaemon(True)
-
- self.channel_max = 65535
- self.user_id = None
-
- self.op_enc = OpEncoder()
- self.seg_enc = SegmentEncoder()
- self.frame_enc = FrameEncoder()
-
- self.delegate = delegate(self, **args)
-
- def attach(self, name, ch, delegate, force=False):
- self.lock.acquire()
- try:
- ssn = self.attached.get(ch.id)
- if ssn is not None:
- if ssn.name != name:
- raise ChannelBusy(ch, ssn)
- else:
- ssn = self.sessions.get(name)
- if ssn is None:
- ssn = Session(name, delegate=delegate)
- self.sessions[name] = ssn
- elif ssn.channel is not None:
- if force:
- del self.attached[ssn.channel.id]
- ssn.channel = None
- else:
- raise SessionBusy(ssn)
- self.attached[ch.id] = ssn
- ssn.channel = ch
- ch.session = ssn
- return ssn
- finally:
- self.lock.release()
-
- def detach(self, name, ch):
- self.lock.acquire()
- try:
- self.attached.pop(ch.id, None)
- ssn = self.sessions.pop(name, None)
- if ssn is not None:
- ssn.channel = None
- ssn.closed()
- return ssn
- finally:
- self.lock.release()
-
- def __channel(self):
- for i in xrange(1, self.channel_max):
- if not self.attached.has_key(i):
- return i
- else:
- raise ChannelsBusy()
-
- def session(self, name, timeout=None, delegate=session.client):
- self.lock.acquire()
- try:
- ch = Channel(self, self.__channel())
- ssn = self.attach(name, ch, delegate)
- ssn.channel.session_attach(name)
- if wait(ssn.condition, lambda: ssn.channel is not None, timeout):
- return ssn
- else:
- self.detach(name, ch)
- raise Timeout()
- finally:
- self.lock.release()
-
- def detach_all(self):
- self.lock.acquire()
- self.failed = True
- try:
- for ssn in self.attached.values():
- if self.close_code[0] != 200:
- ssn.exceptions.append(self.close_code)
- self.detach(ssn.name, ssn.channel)
- finally:
- self.lock.release()
-
- def start(self, timeout=None):
- self.delegate.start()
- self.thread.start()
- if not wait(self.condition, lambda: self.opened or self.failed, timeout):
- self.thread.join()
- raise Timeout()
- if self.failed:
- self.thread.join()
- raise ConnectionFailed(*self.close_code)
-
- def run(self):
- frame_dec = FrameDecoder()
- seg_dec = SegmentDecoder()
- op_dec = OpDecoder()
-
- while not self.closed:
- try:
- data = self.sock.recv(64*1024)
- if not data:
- self.detach_all()
- break
- # If we have a security layer and it sends us no decoded data,
- # that's OK as long as its return code is happy.
- if self.security_layer_rx:
- try:
- data = self.security_layer_rx.decode(data)
- except:
- self.detach_all()
- break
- # When we do not use SSL transport, we get periodic
- # spurious timeout events on the socket. When using SSL,
- # these events show up as timeout *errors*. Both should be
- # ignored unless we have aborted.
- except socket.timeout:
- if self.aborted():
- self.close_code = (None, "connection timed out")
- self.detach_all()
- break
- else:
- continue
- except socket.error, e:
- if self.aborted() or str(e) != "The read operation timed out":
- self.close_code = (None, str(e))
- self.detach_all()
- break
- else:
- continue
- frame_dec.write(data)
- seg_dec.write(*frame_dec.read())
- op_dec.write(*seg_dec.read())
- for op in op_dec.read():
- try:
- self.delegate.received(op)
- except Closed, e:
- self.close_code = (None, str(e))
- if not self.opened:
- self.failed = True
- self.closed = True
- notify(self.condition)
- self.sock.close()
-
- def write_op(self, op):
- self.sock_lock.acquire()
- try:
- self.op_enc.write(op)
- self.seg_enc.write(*self.op_enc.read())
- self.frame_enc.write(*self.seg_enc.read())
- bytes = self.frame_enc.read()
- self.write(bytes)
- self.flush()
- finally:
- self.sock_lock.release()
-
- def close(self, timeout=None):
- if not self.opened: return
- Channel(self, 0).connection_close(200)
- if not wait(self.condition, lambda: not self.opened, timeout):
- raise Timeout()
- self.thread.join(timeout=timeout)
-
- def __str__(self):
- return "%s:%s" % self.sock.getsockname()
-
- def __repr__(self):
- return str(self)
-
-log = getLogger("qpid.io.ctl")
-
-class Channel(control_invoker()):
-
- def __init__(self, connection, id):
- self.connection = connection
- self.id = id
- self.session = None
-
- def invoke(self, op, args, kwargs):
- ctl = op(*args, **kwargs)
- ctl.channel = self.id
- self.connection.write_op(ctl)
- log.debug("SENT %s", ctl)
-
- def __str__(self):
- return "%s[%s]" % (self.connection, self.id)
-
- def __repr__(self):
- return str(self)
diff --git a/qpid/python/qpid/connection08.py b/qpid/python/qpid/connection08.py
deleted file mode 100644
index 5f9f71abe8..0000000000
--- a/qpid/python/qpid/connection08.py
+++ /dev/null
@@ -1,600 +0,0 @@
-#
-# 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.
-#
-
-"""
-A Connection class containing socket code that uses the spec metadata
-to read and write Frame objects. This could be used by a client,
-server, or even a proxy implementation.
-"""
-
-import socket, codec, errno, qpid
-from cStringIO import StringIO
-from codec import EOF
-from compat import SHUT_RDWR
-from exceptions import VersionError
-from logging import getLogger, DEBUG
-
-log = getLogger("qpid.connection08")
-
-class SockIO:
-
- def __init__(self, sock):
- self.sock = sock
-
- def write(self, buf):
- if log.isEnabledFor(DEBUG):
- log.debug("OUT: %r", buf)
- self.sock.sendall(buf)
-
- def read(self, n):
- data = ""
- while len(data) < n:
- try:
- s = self.sock.recv(n - len(data))
- except socket.error:
- break
- if len(s) == 0:
- break
- data += s
- if log.isEnabledFor(DEBUG):
- log.debug("IN: %r", data)
- return data
-
- def flush(self):
- pass
-
- def close(self):
- try:
- try:
- self.sock.shutdown(SHUT_RDWR)
- except socket.error, e:
- if (e.errno == errno.ENOTCONN):
- pass
- else:
- raise
- finally:
- self.sock.close()
-
-class _OldSSLSock:
- """This is a wrapper around old (<=2.5) Python SSLObjects"""
-
- def __init__(self, sock, keyFile, certFile):
- self._sock = sock
- self._sslObj = socket.ssl(self._sock, self._keyFile, self._certFile)
- self._keyFile = keyFile
- self._certFile = certFile
-
- def sendall(self, buf):
- while buf:
- bytesWritten = self._sslObj.write(buf)
- buf = buf[bytesWritten:]
-
- def recv(self, n):
- return self._sslObj.read(n)
-
- def shutdown(self, how):
- self._sock.shutdown(how)
-
- def close(self):
- self._sock.close()
- self._sslObj = None
-
- def getpeercert(self):
- raise socket.error("This version of Python does not support SSL hostname verification. Please upgrade.")
-
-
-def connect(host, port, options = None):
- sock = socket.socket()
- sock.connect((host, port))
- sock.setblocking(1)
-
- if options and options.get("ssl", False):
- log.debug("Wrapping socket for SSL")
- ssl_certfile = options.get("ssl_certfile", None)
- ssl_keyfile = options.get("ssl_keyfile", ssl_certfile)
- ssl_trustfile = options.get("ssl_trustfile", None)
- ssl_require_trust = options.get("ssl_require_trust", True)
- ssl_verify_hostname = not options.get("ssl_skip_hostname_check", False)
-
- try:
- # Python 2.6 and 2.7
- from ssl import wrap_socket, CERT_REQUIRED, CERT_NONE
- try:
- # Python 2.7.9 and newer
- from ssl import match_hostname as verify_hostname
- except ImportError:
- # Before Python 2.7.9 we roll our own
- from qpid.messaging.transports import verify_hostname
-
- if ssl_require_trust or ssl_verify_hostname:
- validate = CERT_REQUIRED
- else:
- validate = CERT_NONE
- sock = wrap_socket(sock,
- keyfile=ssl_keyfile,
- certfile=ssl_certfile,
- ca_certs=ssl_trustfile,
- cert_reqs=validate)
- except ImportError, e:
- # Python 2.5 and older
- if ssl_verify_hostname:
- log.error("Your version of Python does not support ssl hostname verification. Please upgrade your version of Python.")
- raise e
- sock = _OldSSLSock(sock, ssl_keyfile, ssl_certfile)
-
- if ssl_verify_hostname:
- verify_hostname(sock.getpeercert(), host)
-
- return SockIO(sock)
-
-def listen(host, port, predicate = lambda: True):
- sock = socket.socket()
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- sock.bind((host, port))
- sock.listen(5)
- while predicate():
- s, a = sock.accept()
- yield SockIO(s)
-
-class FramingError(Exception):
- pass
-
-class Connection:
-
- def __init__(self, io, spec):
- self.codec = codec.Codec(io, spec)
- self.spec = spec
- self.FRAME_END = self.spec.constants.byname["frame_end"].id
- self.write = getattr(self, "write_%s_%s" % (self.spec.major, self.spec.minor))
- self.read = getattr(self, "read_%s_%s" % (self.spec.major, self.spec.minor))
- self.io = io
-
- def flush(self):
- self.codec.flush()
-
- INIT="!4s4B"
-
- def init(self):
- self.codec.pack(Connection.INIT, "AMQP", 1, 1, self.spec.major,
- self.spec.minor)
-
- def tini(self):
- self.codec.unpack(Connection.INIT)
-
- def write_8_0(self, frame):
- c = self.codec
- c.encode_octet(self.spec.constants.byname[frame.type].id)
- c.encode_short(frame.channel)
- body = StringIO()
- enc = codec.Codec(body, self.spec)
- frame.encode(enc)
- enc.flush()
- c.encode_longstr(body.getvalue())
- c.encode_octet(self.FRAME_END)
-
- def read_8_0(self):
- c = self.codec
- tid = c.decode_octet()
- try:
- type = self.spec.constants.byid[tid].name
- except KeyError:
- if tid == ord('A') and c.unpack("!3s") == "MQP":
- _, _, major, minor = c.unpack("4B")
- raise VersionError("client: %s-%s, server: %s-%s" %
- (self.spec.major, self.spec.minor, major, minor))
- else:
- raise FramingError("unknown frame type: %s" % tid)
- try:
- channel = c.decode_short()
- body = c.decode_longstr()
- dec = codec.Codec(StringIO(body), self.spec)
- frame = Frame.DECODERS[type].decode(self.spec, dec, len(body))
- frame.channel = channel
- end = c.decode_octet()
- if end != self.FRAME_END:
- garbage = ""
- while end != self.FRAME_END:
- garbage += chr(end)
- end = c.decode_octet()
- raise FramingError("frame error: expected %r, got %r" % (self.FRAME_END, garbage))
- return frame
- except EOF:
- # An EOF caught here can indicate an error decoding the frame,
- # rather than that a disconnection occurred,so it's worth logging it.
- log.exception("Error occurred when reading frame with tid %s" % tid)
- raise
-
- def write_0_9(self, frame):
- self.write_8_0(frame)
-
- def read_0_9(self):
- return self.read_8_0()
-
- def write_0_91(self, frame):
- self.write_8_0(frame)
-
- def read_0_91(self):
- return self.read_8_0()
-
- def write_0_10(self, frame):
- c = self.codec
- flags = 0
- if frame.bof: flags |= 0x08
- if frame.eof: flags |= 0x04
- if frame.bos: flags |= 0x02
- if frame.eos: flags |= 0x01
-
- c.encode_octet(flags) # TODO: currently fixed at ver=0, B=E=b=e=1
- c.encode_octet(self.spec.constants.byname[frame.type].id)
- body = StringIO()
- enc = codec.Codec(body, self.spec)
- frame.encode(enc)
- enc.flush()
- frame_size = len(body.getvalue()) + 12 # TODO: Magic number (frame header size)
- c.encode_short(frame_size)
- c.encode_octet(0) # Reserved
- c.encode_octet(frame.subchannel & 0x0f)
- c.encode_short(frame.channel)
- c.encode_long(0) # Reserved
- c.write(body.getvalue())
- c.encode_octet(self.FRAME_END)
-
- def read_0_10(self):
- c = self.codec
- flags = c.decode_octet() # TODO: currently ignoring flags
- framing_version = (flags & 0xc0) >> 6
- if framing_version != 0:
- raise FramingError("frame error: unknown framing version")
- type = self.spec.constants.byid[c.decode_octet()].name
- frame_size = c.decode_short()
- if frame_size < 12: # TODO: Magic number (frame header size)
- raise FramingError("frame error: frame size too small")
- reserved1 = c.decode_octet()
- field = c.decode_octet()
- subchannel = field & 0x0f
- channel = c.decode_short()
- reserved2 = c.decode_long() # TODO: reserved maybe need to ensure 0
- if (flags & 0x30) != 0 or reserved1 != 0 or (field & 0xf0) != 0:
- raise FramingError("frame error: reserved bits not all zero")
- body_size = frame_size - 12 # TODO: Magic number (frame header size)
- body = c.read(body_size)
- dec = codec.Codec(StringIO(body), self.spec)
- try:
- frame = Frame.DECODERS[type].decode(self.spec, dec, len(body))
- except EOF:
- raise FramingError("truncated frame body: %r" % body)
- frame.channel = channel
- frame.subchannel = subchannel
- end = c.decode_octet()
- if end != self.FRAME_END:
- garbage = ""
- while end != self.FRAME_END:
- garbage += chr(end)
- end = c.decode_octet()
- raise FramingError("frame error: expected %r, got %r" % (self.FRAME_END, garbage))
- return frame
-
- def write_99_0(self, frame):
- self.write_0_10(frame)
-
- def read_99_0(self):
- return self.read_0_10()
-
- def close(self):
- self.io.close();
-
-class Frame:
-
- DECODERS = {}
-
- class __metaclass__(type):
-
- def __new__(cls, name, bases, dict):
- for attr in ("encode", "decode", "type"):
- if not dict.has_key(attr):
- raise TypeError("%s must define %s" % (name, attr))
- dict["decode"] = staticmethod(dict["decode"])
- if dict.has_key("__init__"):
- __init__ = dict["__init__"]
- def init(self, *args, **kwargs):
- args = list(args)
- self.init(args, kwargs)
- __init__(self, *args, **kwargs)
- dict["__init__"] = init
- t = type.__new__(cls, name, bases, dict)
- if t.type != None:
- Frame.DECODERS[t.type] = t
- return t
-
- type = None
-
- def init(self, args, kwargs):
- self.channel = kwargs.pop("channel", 0)
- self.subchannel = kwargs.pop("subchannel", 0)
- self.bos = True
- self.eos = True
- self.bof = True
- self.eof = True
-
- def encode(self, enc): abstract
-
- def decode(spec, dec, size): abstract
-
-class Method(Frame):
-
- type = "frame_method"
-
- def __init__(self, method, args):
- if len(args) != len(method.fields):
- argspec = ["%s: %s" % (f.name, f.type)
- for f in method.fields]
- raise TypeError("%s.%s expecting (%s), got %s" %
- (method.klass.name, method.name, ", ".join(argspec),
- args))
- self.method = method
- self.method_type = method
- self.args = args
- self.eof = not method.content
-
- def encode(self, c):
- version = (c.spec.major, c.spec.minor)
- if version == (0, 10) or version == (99, 0):
- c.encode_octet(self.method.klass.id)
- c.encode_octet(self.method.id)
- else:
- c.encode_short(self.method.klass.id)
- c.encode_short(self.method.id)
- for field, arg in zip(self.method.fields, self.args):
- c.encode(field.type, arg)
-
- def decode(spec, c, size):
- version = (c.spec.major, c.spec.minor)
- if version == (0, 10) or version == (99, 0):
- klass = spec.classes.byid[c.decode_octet()]
- meth = klass.methods.byid[c.decode_octet()]
- else:
- klass = spec.classes.byid[c.decode_short()]
- meth = klass.methods.byid[c.decode_short()]
- args = tuple([c.decode(f.type) for f in meth.fields])
- return Method(meth, args)
-
- def __str__(self):
- return "[%s] %s %s" % (self.channel, self.method,
- ", ".join([str(a) for a in self.args]))
-
-class Request(Frame):
-
- type = "frame_request"
-
- def __init__(self, id, response_mark, method):
- self.id = id
- self.response_mark = response_mark
- self.method = method
- self.method_type = method.method_type
- self.args = method.args
-
- def encode(self, enc):
- enc.encode_longlong(self.id)
- enc.encode_longlong(self.response_mark)
- # reserved
- enc.encode_long(0)
- self.method.encode(enc)
-
- def decode(spec, dec, size):
- id = dec.decode_longlong()
- mark = dec.decode_longlong()
- # reserved
- dec.decode_long()
- method = Method.decode(spec, dec, size - 20)
- return Request(id, mark, method)
-
- def __str__(self):
- return "[%s] Request(%s) %s" % (self.channel, self.id, self.method)
-
-class Response(Frame):
-
- type = "frame_response"
-
- def __init__(self, id, request_id, batch_offset, method):
- self.id = id
- self.request_id = request_id
- self.batch_offset = batch_offset
- self.method = method
- self.method_type = method.method_type
- self.args = method.args
-
- def encode(self, enc):
- enc.encode_longlong(self.id)
- enc.encode_longlong(self.request_id)
- enc.encode_long(self.batch_offset)
- self.method.encode(enc)
-
- def decode(spec, dec, size):
- id = dec.decode_longlong()
- request_id = dec.decode_longlong()
- batch_offset = dec.decode_long()
- method = Method.decode(spec, dec, size - 20)
- return Response(id, request_id, batch_offset, method)
-
- def __str__(self):
- return "[%s] Response(%s,%s,%s) %s" % (self.channel, self.id, self.request_id, self.batch_offset, self.method)
-
-def uses_struct_encoding(spec):
- return (spec.major == 0 and spec.minor == 10) or (spec.major == 99 and spec.minor == 0)
-
-class Header(Frame):
-
- type = "frame_header"
-
- def __init__(self, klass, weight, size, properties):
- self.klass = klass
- self.weight = weight
- self.size = size
- self.properties = properties
- self.eof = size == 0
- self.bof = False
-
- def __getitem__(self, name):
- return self.properties[name]
-
- def __setitem__(self, name, value):
- self.properties[name] = value
-
- def __delitem__(self, name):
- del self.properties[name]
-
- def encode(self, c):
- if uses_struct_encoding(c.spec):
- self.encode_structs(c)
- else:
- self.encode_legacy(c)
-
- def encode_structs(self, c):
- # XXX
- structs = [qpid.Struct(c.spec.domains.byname["delivery_properties"].type),
- qpid.Struct(c.spec.domains.byname["message_properties"].type)]
-
- # XXX
- props = self.properties.copy()
- for k in self.properties:
- for s in structs:
- if s.exists(k):
- s.set(k, props.pop(k))
- if props:
- raise TypeError("no such property: %s" % (", ".join(props)))
-
- # message properties store the content-length now, and weight is
- # deprecated
- if self.size != None:
- structs[1].content_length = self.size
-
- for s in structs:
- c.encode_long_struct(s)
-
- def encode_legacy(self, c):
- c.encode_short(self.klass.id)
- c.encode_short(self.weight)
- c.encode_longlong(self.size)
-
- # property flags
- nprops = len(self.klass.fields)
- flags = 0
- for i in range(nprops):
- f = self.klass.fields.items[i]
- flags <<= 1
- if self.properties.get(f.name) != None:
- flags |= 1
- # the last bit indicates more flags
- if i > 0 and (i % 15) == 0:
- flags <<= 1
- if nprops > (i + 1):
- flags |= 1
- c.encode_short(flags)
- flags = 0
- flags <<= ((16 - (nprops % 15)) % 16)
- c.encode_short(flags)
-
- # properties
- for f in self.klass.fields:
- v = self.properties.get(f.name)
- if v != None:
- c.encode(f.type, v)
-
- def decode(spec, c, size):
- if uses_struct_encoding(spec):
- return Header.decode_structs(spec, c, size)
- else:
- return Header.decode_legacy(spec, c, size)
-
- def decode_structs(spec, c, size):
- structs = []
- start = c.nread
- while c.nread - start < size:
- structs.append(c.decode_long_struct())
-
- # XXX
- props = {}
- length = None
- for s in structs:
- for f in s.type.fields:
- if s.has(f.name):
- props[f.name] = s.get(f.name)
- if f.name == "content_length":
- length = s.get(f.name)
- return Header(None, 0, length, props)
-
- decode_structs = staticmethod(decode_structs)
-
- def decode_legacy(spec, c, size):
- klass = spec.classes.byid[c.decode_short()]
- weight = c.decode_short()
- size = c.decode_longlong()
-
- # property flags
- bits = []
- while True:
- flags = c.decode_short()
- for i in range(15, 0, -1):
- if flags >> i & 0x1 != 0:
- bits.append(True)
- else:
- bits.append(False)
- if flags & 0x1 == 0:
- break
-
- # properties
- properties = {}
- for b, f in zip(bits, klass.fields):
- if b:
- # Note: decode returns a unicode u'' string but only
- # plain '' strings can be used as keywords so we need to
- # stringify the names.
- properties[str(f.name)] = c.decode(f.type)
- return Header(klass, weight, size, properties)
-
- decode_legacy = staticmethod(decode_legacy)
-
- def __str__(self):
- return "%s %s %s %s" % (self.klass, self.weight, self.size,
- self.properties)
-
-class Body(Frame):
-
- type = "frame_body"
-
- def __init__(self, content):
- self.content = content
- self.eof = True
- self.bof = False
-
- def encode(self, enc):
- enc.write(self.content)
-
- def decode(spec, dec, size):
- return Body(dec.read(size))
-
- def __str__(self):
- return "Body(%r)" % self.content
-
-# TODO:
-# OOB_METHOD = "frame_oob_method"
-# OOB_HEADER = "frame_oob_header"
-# OOB_BODY = "frame_oob_body"
-# TRACE = "frame_trace"
-# HEARTBEAT = "frame_heartbeat"
diff --git a/qpid/python/qpid/content.py b/qpid/python/qpid/content.py
deleted file mode 100644
index 9391f4f1a8..0000000000
--- a/qpid/python/qpid/content.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#
-# 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.
-#
-
-"""
-A simple python representation for AMQP content.
-"""
-
-def default(val, defval):
- if val == None:
- return defval
- else:
- return val
-
-class Content:
-
- def __init__(self, body = "", children = None, properties = None):
- self.body = body
- self.children = default(children, [])
- self.properties = default(properties, {})
-
- def size(self):
- return len(self.body)
-
- def weight(self):
- return len(self.children)
-
- def __getitem__(self, name):
- return self.properties[name]
-
- def __setitem__(self, name, value):
- self.properties[name] = value
-
- def __delitem__(self, name):
- del self.properties[name]
-
- def __str__(self):
- if self.children:
- return "%s [%s] %s" % (self.properties,
- ", ".join(map(str, self.children)),
- self.body)
- else:
- return "%s %s" % (self.properties, self.body)
diff --git a/qpid/python/qpid/datatypes.py b/qpid/python/qpid/datatypes.py
deleted file mode 100644
index ca1466c261..0000000000
--- a/qpid/python/qpid/datatypes.py
+++ /dev/null
@@ -1,385 +0,0 @@
-#
-# 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 threading, struct, datetime, time
-from exceptions import Timeout
-
-class Struct:
-
- def __init__(self, _type, *args, **kwargs):
- if len(args) > len(_type.fields):
- raise TypeError("%s() takes at most %s arguments (%s given)" %
- (_type.name, len(_type.fields), len(args)))
-
- self._type = _type
-
- idx = 0
- for field in _type.fields:
- if idx < len(args):
- arg = args[idx]
- if kwargs.has_key(field.name):
- raise TypeError("%s() got multiple values for keyword argument '%s'" %
- (_type.name, field.name))
- elif kwargs.has_key(field.name):
- arg = kwargs.pop(field.name)
- else:
- arg = field.default()
- setattr(self, field.name, arg)
- idx += 1
-
- if kwargs:
- unexpected = kwargs.keys()[0]
- raise TypeError("%s() got an unexpected keyword argument '%s'" %
- (_type.name, unexpected))
-
- def __getitem__(self, name):
- return getattr(self, name)
-
- def __setitem__(self, name, value):
- if not hasattr(self, name):
- raise AttributeError("'%s' object has no attribute '%s'" %
- (self._type.name, name))
- setattr(self, name, value)
-
- def __repr__(self):
- fields = []
- for f in self._type.fields:
- v = self[f.name]
- if f.type.is_present(v):
- fields.append("%s=%r" % (f.name, v))
- return "%s(%s)" % (self._type.name, ", ".join(fields))
-
-class Message:
-
- def __init__(self, *args):
- if args:
- self.body = args[-1]
- else:
- self.body = None
- if len(args) > 1:
- self.headers = list(args[:-1])
- else:
- self.headers = None
- self.id = None
-
- def has(self, name):
- return self.get(name) != None
-
- def get(self, name):
- if self.headers:
- for h in self.headers:
- if h.NAME == name:
- return h
- return None
-
- def set(self, header):
- if self.headers is None:
- self.headers = []
- idx = 0
- while idx < len(self.headers):
- if self.headers[idx].NAME == header.NAME:
- self.headers[idx] = header
- return
- idx += 1
- self.headers.append(header)
-
- def clear(self, name):
- idx = 0
- while idx < len(self.headers):
- if self.headers[idx].NAME == name:
- del self.headers[idx]
- return
- idx += 1
-
- def __repr__(self):
- args = []
- if self.headers:
- args.extend(map(repr, self.headers))
- if self.body:
- args.append(repr(self.body))
- if self.id is not None:
- args.append("id=%s" % self.id)
- return "Message(%s)" % ", ".join(args)
-
-def serial(o):
- if isinstance(o, Serial):
- return o
- else:
- return Serial(o)
-
-class Serial:
-
- def __init__(self, value):
- self.value = value & 0xFFFFFFFFL
-
- def __hash__(self):
- return hash(self.value)
-
- def __cmp__(self, other):
- if other.__class__ not in (int, long, Serial):
- return 1
-
- other = serial(other)
-
- delta = (self.value - other.value) & 0xFFFFFFFFL
- neg = delta & 0x80000000L
- mag = delta & 0x7FFFFFFF
-
- if neg:
- return -mag
- else:
- return mag
-
- def __add__(self, other):
- return Serial(self.value + other)
-
- def __sub__(self, other):
- if isinstance(other, Serial):
- return self.value - other.value
- else:
- return Serial(self.value - other)
-
- def __repr__(self):
- return "serial(%s)" % self.value
-
- def __str__(self):
- return str(self.value)
-
-class Range:
-
- def __init__(self, lower, upper = None):
- self.lower = serial(lower)
- if upper is None:
- self.upper = self.lower
- else:
- self.upper = serial(upper)
-
- def __contains__(self, n):
- return self.lower <= n and n <= self.upper
-
- def __iter__(self):
- i = self.lower
- while i <= self.upper:
- yield i
- i += 1
-
- def touches(self, r):
- # XXX: are we doing more checks than we need?
- return (self.lower - 1 in r or
- self.upper + 1 in r or
- r.lower - 1 in self or
- r.upper + 1 in self or
- self.lower in r or
- self.upper in r or
- r.lower in self or
- r.upper in self)
-
- def span(self, r):
- return Range(min(self.lower, r.lower), max(self.upper, r.upper))
-
- def intersect(self, r):
- lower = max(self.lower, r.lower)
- upper = min(self.upper, r.upper)
- if lower > upper:
- return None
- else:
- return Range(lower, upper)
-
- def __repr__(self):
- return "%s-%s" % (self.lower, self.upper)
-
-class RangedSet:
-
- def __init__(self, *args):
- self.ranges = []
- for n in args:
- self.add(n)
-
- def __contains__(self, n):
- for r in self.ranges:
- if n in r:
- return True
- return False
-
- def add_range(self, range):
- idx = 0
- while idx < len(self.ranges):
- r = self.ranges[idx]
- if range.touches(r):
- del self.ranges[idx]
- range = range.span(r)
- elif range.upper < r.lower:
- self.ranges.insert(idx, range)
- return
- else:
- idx += 1
- self.ranges.append(range)
-
- def add(self, lower, upper = None):
- self.add_range(Range(lower, upper))
-
- def empty(self):
- for r in self.ranges:
- if r.lower <= r.upper:
- return False
- return True
-
- def max(self):
- if self.ranges:
- return self.ranges[-1].upper
- else:
- return None
-
- def min(self):
- if self.ranges:
- return self.ranges[0].lower
- else:
- return None
-
- def __iter__(self):
- return iter(self.ranges)
-
- def __repr__(self):
- return str(self.ranges)
-
-class Future:
- def __init__(self, initial=None, exception=Exception):
- self.value = initial
- self._error = None
- self._set = threading.Event()
- self.exception = exception
-
- def error(self, error):
- self._error = error
- self._set.set()
-
- def set(self, value):
- self.value = value
- self._set.set()
-
- def get(self, timeout=None):
- self._set.wait(timeout)
- if self._set.isSet():
- if self._error != None:
- raise self.exception(self._error)
- return self.value
- else:
- raise Timeout()
-
- def is_set(self):
- return self._set.isSet()
-
-try:
- from uuid import uuid4
- from uuid import UUID
-except ImportError:
- class UUID:
- def __init__(self, hex=None, bytes=None):
- if [hex, bytes].count(None) != 1:
- raise TypeErrror("need one of hex or bytes")
- if bytes is not None:
- self.bytes = bytes
- elif hex is not None:
- fields=hex.split("-")
- fields[4:5] = [fields[4][:4], fields[4][4:]]
- self.bytes = struct.pack("!LHHHHL", *[int(x,16) for x in fields])
-
- def __cmp__(self, other):
- if isinstance(other, UUID):
- return cmp(self.bytes, other.bytes)
- else:
- return -1
-
- def __str__(self):
- return "%08x-%04x-%04x-%04x-%04x%08x" % struct.unpack("!LHHHHL", self.bytes)
-
- def __repr__(self):
- return "UUID(%r)" % str(self)
-
- def __hash__(self):
- return self.bytes.__hash__()
-
- import os, random, socket, time
- rand = random.Random()
- rand.seed((os.getpid(), time.time(), socket.gethostname()))
- def random_uuid():
- bytes = [rand.randint(0, 255) for i in xrange(16)]
-
- # From RFC4122, the version bits are set to 0100
- bytes[7] &= 0x0F
- bytes[7] |= 0x40
-
- # From RFC4122, the top two bits of byte 8 get set to 01
- bytes[8] &= 0x3F
- bytes[8] |= 0x80
- return "".join(map(chr, bytes))
-
- def uuid4():
- return UUID(bytes=random_uuid())
-
-def parseUUID(str):
- return UUID(hex=str)
-
-class timestamp(float):
-
- def __new__(cls, obj=None):
- if obj is None:
- obj = time.time()
- elif isinstance(obj, datetime.datetime):
- obj = time.mktime(obj.timetuple()) + 1e-6 * obj.microsecond
- return super(timestamp, cls).__new__(cls, obj)
-
- def datetime(self):
- return datetime.datetime.fromtimestamp(self)
-
- def __add__(self, other):
- if isinstance(other, datetime.timedelta):
- return timestamp(self.datetime() + other)
- else:
- return timestamp(float(self) + other)
-
- def __sub__(self, other):
- if isinstance(other, datetime.timedelta):
- return timestamp(self.datetime() - other)
- else:
- return timestamp(float(self) - other)
-
- def __radd__(self, other):
- if isinstance(other, datetime.timedelta):
- return timestamp(self.datetime() + other)
- else:
- return timestamp(other + float(self))
-
- def __rsub__(self, other):
- if isinstance(other, datetime.timedelta):
- return timestamp(self.datetime() - other)
- else:
- return timestamp(other - float(self))
-
- def __neg__(self):
- return timestamp(-float(self))
-
- def __pos__(self):
- return self
-
- def __abs__(self):
- return timestamp(abs(float(self)))
-
- def __repr__(self):
- return "timestamp(%r)" % float(self)
diff --git a/qpid/python/qpid/debug.py b/qpid/python/qpid/debug.py
deleted file mode 100644
index b5dbd4d9d9..0000000000
--- a/qpid/python/qpid/debug.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#
-# 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 threading, traceback, signal, sys, time
-
-def stackdump(sig, frm):
- code = []
- for threadId, stack in sys._current_frames().items():
- code.append("\n# ThreadID: %s" % threadId)
- for filename, lineno, name, line in traceback.extract_stack(stack):
- code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
- if line:
- code.append(" %s" % (line.strip()))
- print "\n".join(code)
-
-signal.signal(signal.SIGQUIT, stackdump)
-
-class LoudLock:
-
- def __init__(self):
- self.lock = threading.RLock()
-
- def acquire(self, blocking=1):
- while not self.lock.acquire(blocking=0):
- time.sleep(1)
- print >> sys.out, "TRYING"
- traceback.print_stack(None, None, out)
- print >> sys.out, "TRYING"
- print >> sys.out, "ACQUIRED"
- traceback.print_stack(None, None, out)
- print >> sys.out, "ACQUIRED"
- return True
-
- def _is_owned(self):
- return self.lock._is_owned()
-
- def release(self):
- self.lock.release()
-
diff --git a/qpid/python/qpid/delegate.py b/qpid/python/qpid/delegate.py
deleted file mode 100644
index b447c4aa29..0000000000
--- a/qpid/python/qpid/delegate.py
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# 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.
-#
-
-"""
-Delegate implementation intended for use with the peer module.
-"""
-
-import threading, inspect, traceback, sys
-from connection08 import Method, Request, Response
-
-def _handler_name(method):
- return "%s_%s" % (method.klass.name, method.name)
-
-class Delegate:
-
- def __init__(self):
- self.handlers = {}
- self.invokers = {}
-
- def __call__(self, channel, frame):
- method = frame.method
-
- try:
- handler = self.handlers[method]
- except KeyError:
- name = _handler_name(method)
- handler = getattr(self, name)
- self.handlers[method] = handler
-
- try:
- return handler(channel, frame)
- except:
- print >> sys.stderr, "Error in handler: %s\n\n%s" % \
- (_handler_name(method), traceback.format_exc())
-
- def closed(self, reason):
- print "Connection closed: %s" % reason
diff --git a/qpid/python/qpid/delegates.py b/qpid/python/qpid/delegates.py
deleted file mode 100644
index ae7ed7f988..0000000000
--- a/qpid/python/qpid/delegates.py
+++ /dev/null
@@ -1,215 +0,0 @@
-#
-# 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 os, connection, session
-from util import notify, get_client_properties_with_defaults
-from datatypes import RangedSet
-from exceptions import VersionError, Closed
-from logging import getLogger
-from ops import Control
-import sys
-from qpid import sasl
-
-log = getLogger("qpid.io.ctl")
-
-class Delegate:
-
- def __init__(self, connection, delegate=session.client):
- self.connection = connection
- self.delegate = delegate
-
- def received(self, op):
- ssn = self.connection.attached.get(op.channel)
- if ssn is None:
- ch = connection.Channel(self.connection, op.channel)
- else:
- ch = ssn.channel
-
- if isinstance(op, Control):
- log.debug("RECV %s", op)
- getattr(self, op.NAME)(ch, op)
- elif ssn is None:
- ch.session_detached()
- else:
- ssn.received(op)
-
- def connection_close(self, ch, close):
- self.connection.close_code = (close.reply_code, close.reply_text)
- ch.connection_close_ok()
- raise Closed(close.reply_text)
-
- def connection_close_ok(self, ch, close_ok):
- self.connection.opened = False
- self.connection.closed = True
- notify(self.connection.condition)
-
- def connection_heartbeat(self, ch, hrt):
- pass
-
- def session_attach(self, ch, a):
- try:
- self.connection.attach(a.name, ch, self.delegate, a.force)
- ch.session_attached(a.name)
- except connection.ChannelBusy:
- ch.session_detached(a.name)
- except connection.SessionBusy:
- ch.session_detached(a.name)
-
- def session_attached(self, ch, a):
- notify(ch.session.condition)
-
- def session_detach(self, ch, d):
- #send back the confirmation of detachment before removing the
- #channel from the attached set; this avoids needing to hold the
- #connection lock during the sending of this control and ensures
- #that if the channel is immediately reused for a new session the
- #attach request will follow the detached notification.
- ch.session_detached(d.name)
- ssn = self.connection.detach(d.name, ch)
-
- def session_detached(self, ch, d):
- self.connection.detach(d.name, ch)
-
- def session_request_timeout(self, ch, rt):
- ch.session_timeout(rt.timeout);
-
- def session_command_point(self, ch, cp):
- ssn = ch.session
- ssn.receiver.next_id = cp.command_id
- ssn.receiver.next_offset = cp.command_offset
-
- def session_completed(self, ch, cmp):
- ch.session.sender.completed(cmp.commands)
- if cmp.timely_reply:
- ch.session_known_completed(cmp.commands)
- notify(ch.session.condition)
-
- def session_known_completed(self, ch, kn_cmp):
- ch.session.receiver.known_completed(kn_cmp.commands)
-
- def session_flush(self, ch, f):
- rcv = ch.session.receiver
- if f.expected:
- if rcv.next_id == None:
- exp = None
- else:
- exp = RangedSet(rcv.next_id)
- ch.session_expected(exp)
- if f.confirmed:
- ch.session_confirmed(rcv._completed)
- if f.completed:
- ch.session_completed(rcv._completed)
-
-class Server(Delegate):
-
- def start(self):
- self.connection.read_header()
- # XXX
- self.connection.write_header(0, 10)
- connection.Channel(self.connection, 0).connection_start(mechanisms=["ANONYMOUS"])
-
- def connection_start_ok(self, ch, start_ok):
- ch.connection_tune(channel_max=65535)
-
- def connection_tune_ok(self, ch, tune_ok):
- pass
-
- def connection_open(self, ch, open):
- self.connection.opened = True
- ch.connection_open_ok()
- notify(self.connection.condition)
-
-class Client(Delegate):
-
- def __init__(self, connection, username=None, password=None,
- mechanism=None, heartbeat=None, **kwargs):
- Delegate.__init__(self, connection)
- provided_client_properties = kwargs.get("client_properties")
- self.client_properties=get_client_properties_with_defaults(provided_client_properties)
-
- ##
- ## self.acceptableMechanisms is the list of SASL mechanisms that the client is willing to
- ## use. If it's None, then any mechanism is acceptable.
- ##
- self.acceptableMechanisms = None
- if mechanism:
- self.acceptableMechanisms = mechanism.split(" ")
- self.heartbeat = heartbeat
- self.username = username
- self.password = password
-
- self.sasl = sasl.Client()
- if username and len(username) > 0:
- self.sasl.setAttr("username", str(username))
- if password and len(password) > 0:
- self.sasl.setAttr("password", str(password))
- self.sasl.setAttr("service", str(kwargs.get("service", "qpidd")))
- if "host" in kwargs:
- self.sasl.setAttr("host", str(kwargs["host"]))
- if "min_ssf" in kwargs:
- self.sasl.setAttr("minssf", kwargs["min_ssf"])
- if "max_ssf" in kwargs:
- self.sasl.setAttr("maxssf", kwargs["max_ssf"])
- self.sasl.init()
-
- def start(self):
- # XXX
- cli_major = 0
- cli_minor = 10
- self.connection.write_header(cli_major, cli_minor)
- magic, _, _, major, minor = self.connection.read_header()
- if not (magic == "AMQP" and major == cli_major and minor == cli_minor):
- raise VersionError("client: %s-%s, server: %s-%s" %
- (cli_major, cli_minor, major, minor))
-
- def connection_start(self, ch, start):
- mech_list = ""
- for mech in start.mechanisms:
- if (not self.acceptableMechanisms) or mech in self.acceptableMechanisms:
- mech_list += str(mech) + " "
- mech = None
- initial = None
- try:
- mech, initial = self.sasl.start(mech_list)
- except Exception, e:
- raise Closed(str(e))
- ch.connection_start_ok(client_properties=self.client_properties,
- mechanism=mech, response=initial)
-
- def connection_secure(self, ch, secure):
- resp = None
- try:
- resp = self.sasl.step(secure.challenge)
- except Exception, e:
- raise Closed(str(e))
- ch.connection_secure_ok(response=resp)
-
- def connection_tune(self, ch, tune):
- ch.connection_tune_ok(heartbeat=self.heartbeat)
- ch.connection_open()
- self.connection.user_id = self.sasl.auth_username()
- self.connection.security_layer_tx = self.sasl
-
- def connection_open_ok(self, ch, open_ok):
- self.connection.security_layer_rx = self.sasl
- self.connection.opened = True
- notify(self.connection.condition)
-
- def connection_heartbeat(self, ch, hrt):
- ch.connection_heartbeat()
diff --git a/qpid/python/qpid/disp.py b/qpid/python/qpid/disp.py
deleted file mode 100644
index d1340b8a05..0000000000
--- a/qpid/python/qpid/disp.py
+++ /dev/null
@@ -1,236 +0,0 @@
-#!/usr/bin/env 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.
-#
-
-from time import strftime, gmtime
-
-class Header:
- """ """
- NONE = 1
- KMG = 2
- YN = 3
- Y = 4
- TIME_LONG = 5
- TIME_SHORT = 6
- DURATION = 7
-
- def __init__(self, text, format=NONE):
- self.text = text
- self.format = format
-
- def __repr__(self):
- return self.text
-
- def __str__(self):
- return self.text
-
- def formatted(self, value):
- try:
- if value == None:
- return ''
- if self.format == Header.NONE:
- return value
- if self.format == Header.KMG:
- return self.num(value)
- if self.format == Header.YN:
- if value:
- return 'Y'
- return 'N'
- if self.format == Header.Y:
- if value:
- return 'Y'
- return ''
- if self.format == Header.TIME_LONG:
- return strftime("%c", gmtime(value / 1000000000))
- if self.format == Header.TIME_SHORT:
- return strftime("%X", gmtime(value / 1000000000))
- if self.format == Header.DURATION:
- if value < 0: value = 0
- sec = value / 1000000000
- min = sec / 60
- hour = min / 60
- day = hour / 24
- result = ""
- if day > 0:
- result = "%dd " % day
- if hour > 0 or result != "":
- result += "%dh " % (hour % 24)
- if min > 0 or result != "":
- result += "%dm " % (min % 60)
- result += "%ds" % (sec % 60)
- return result
- except:
- return "?"
-
- def numCell(self, value, tag):
- fp = float(value) / 1000.
- if fp < 10.0:
- return "%1.2f%c" % (fp, tag)
- if fp < 100.0:
- return "%2.1f%c" % (fp, tag)
- return "%4d%c" % (value / 1000, tag)
-
- def num(self, value):
- if value < 1000:
- return "%4d" % value
- if value < 1000000:
- return self.numCell(value, 'k')
- value /= 1000
- if value < 1000000:
- return self.numCell(value, 'm')
- value /= 1000
- return self.numCell(value, 'g')
-
-
-class Display:
- """ Display formatting for QPID Management CLI """
-
- def __init__(self, spacing=2, prefix=" "):
- self.tableSpacing = spacing
- self.tablePrefix = prefix
- self.timestampFormat = "%X"
-
- def formattedTable(self, title, heads, rows):
- fRows = []
- for row in rows:
- fRow = []
- col = 0
- for cell in row:
- fRow.append(heads[col].formatted(cell))
- col += 1
- fRows.append(fRow)
- headtext = []
- for head in heads:
- headtext.append(head.text)
- self.table(title, headtext, fRows)
-
- def table(self, title, heads, rows):
- """ Print a table with autosized columns """
-
- # Pad the rows to the number of heads
- for row in rows:
- diff = len(heads) - len(row)
- for idx in range(diff):
- row.append("")
-
- print title
- if len (rows) == 0:
- return
- colWidth = []
- col = 0
- line = self.tablePrefix
- for head in heads:
- width = len (head)
- for row in rows:
- cellWidth = len (unicode (row[col]))
- if cellWidth > width:
- width = cellWidth
- colWidth.append (width + self.tableSpacing)
- line = line + head
- if col < len (heads) - 1:
- for i in range (colWidth[col] - len (head)):
- line = line + " "
- col = col + 1
- print line
- line = self.tablePrefix
- for width in colWidth:
- line = line + "=" * width
- line = line[:255]
- print line
-
- for row in rows:
- line = self.tablePrefix
- col = 0
- for width in colWidth:
- line = line + unicode (row[col])
- if col < len (heads) - 1:
- for i in range (width - len (unicode (row[col]))):
- line = line + " "
- col = col + 1
- print line
-
- def do_setTimeFormat (self, fmt):
- """ Select timestamp format """
- if fmt == "long":
- self.timestampFormat = "%c"
- elif fmt == "short":
- self.timestampFormat = "%X"
-
- def timestamp (self, nsec):
- """ Format a nanosecond-since-the-epoch timestamp for printing """
- return strftime (self.timestampFormat, gmtime (nsec / 1000000000))
-
- def duration(self, nsec):
- if nsec < 0: nsec = 0
- sec = nsec / 1000000000
- min = sec / 60
- hour = min / 60
- day = hour / 24
- result = ""
- if day > 0:
- result = "%dd " % day
- if hour > 0 or result != "":
- result += "%dh " % (hour % 24)
- if min > 0 or result != "":
- result += "%dm " % (min % 60)
- result += "%ds" % (sec % 60)
- return result
-
-class Sortable:
- """ """
- def __init__(self, row, sortIndex):
- self.row = row
- self.sortIndex = sortIndex
- if sortIndex >= len(row):
- raise Exception("sort index exceeds row boundary")
-
- def __cmp__(self, other):
- return cmp(self.row[self.sortIndex], other.row[self.sortIndex])
-
- def getRow(self):
- return self.row
-
-class Sorter:
- """ """
- def __init__(self, heads, rows, sortCol, limit=0, inc=True):
- col = 0
- for head in heads:
- if head.text == sortCol:
- break
- col += 1
- if col == len(heads):
- raise Exception("sortCol '%s', not found in headers" % sortCol)
-
- list = []
- for row in rows:
- list.append(Sortable(row, col))
- list.sort()
- if not inc:
- list.reverse()
- count = 0
- self.sorted = []
- for row in list:
- self.sorted.append(row.getRow())
- count += 1
- if count == limit:
- break
-
- def getSorted(self):
- return self.sorted
diff --git a/qpid/python/qpid/exceptions.py b/qpid/python/qpid/exceptions.py
deleted file mode 100644
index 2bd80b7ffe..0000000000
--- a/qpid/python/qpid/exceptions.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# 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.
-#
-
-class Closed(Exception): pass
-class Timeout(Exception): pass
-class VersionError(Exception): pass
diff --git a/qpid/python/qpid/framer.py b/qpid/python/qpid/framer.py
deleted file mode 100644
index 08e172287f..0000000000
--- a/qpid/python/qpid/framer.py
+++ /dev/null
@@ -1,128 +0,0 @@
-#
-# 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 struct, socket
-from exceptions import Closed
-from packer import Packer
-from threading import RLock
-from logging import getLogger
-
-raw = getLogger("qpid.io.raw")
-frm = getLogger("qpid.io.frm")
-
-class FramingError(Exception): pass
-
-class Framer(Packer):
-
- HEADER="!4s4B"
-
- def __init__(self, sock):
- self.sock = sock
- self.sock_lock = RLock()
- self.tx_buf = ""
- self.rx_buf = ""
- self.security_layer_tx = None
- self.security_layer_rx = None
- self.maxbufsize = 65535
-
- def aborted(self):
- return False
-
- def write(self, buf):
- self.tx_buf += buf
-
- def flush(self):
- self.sock_lock.acquire()
- try:
- if self.security_layer_tx:
- try:
- cipher_buf = self.security_layer_tx.encode(self.tx_buf)
- except SASLError, e:
- raise Closed(str(e))
- self._write(cipher_buf)
- else:
- self._write(self.tx_buf)
- self.tx_buf = ""
- frm.debug("FLUSHED")
- finally:
- self.sock_lock.release()
-
- def _write(self, buf):
- while buf:
- try:
- n = self.sock.send(buf)
- except socket.timeout:
- if self.aborted():
- raise Closed()
- else:
- continue
- raw.debug("SENT %r", buf[:n])
- buf = buf[n:]
-
- ##
- ## Implementation Note:
- ##
- ## This function was modified to use the SASL security layer for content
- ## decryption. As such, the socket read should read in "self.maxbufsize"
- ## instead of "n" (the requested number of octets). However, since this
- ## is one of two places in the code where the socket is read, the read
- ## size had to be left at "n". This is because this function is
- ## apparently only used to read the first 8 octets from a TCP socket. If
- ## we read beyond "n" octets, the remaing octets won't be processed and
- ## the connection handshake will fail.
- ##
- def read(self, n):
- while len(self.rx_buf) < n:
- try:
- # QPID-5808: never consume more than n bytes from the socket,
- # otherwise the extra bytes are discarded.
- s = self.sock.recv(n - len(self.rx_buf))
- if self.security_layer_rx:
- try:
- s = self.security_layer_rx.decode(s)
- except SASLError, e:
- raise Closed(str(e))
- except socket.timeout:
- if self.aborted():
- raise Closed()
- else:
- continue
- except socket.error, e:
- if self.rx_buf != "":
- raise e
- else:
- raise Closed()
- if len(s) == 0:
- raise Closed()
- self.rx_buf += s
- raw.debug("RECV %r", s)
- data = self.rx_buf[0:n]
- self.rx_buf = self.rx_buf[n:]
- return data
-
- def read_header(self):
- return self.unpack(Framer.HEADER)
-
- def write_header(self, major, minor):
- self.sock_lock.acquire()
- try:
- self.pack(Framer.HEADER, "AMQP", 1, 1, major, minor)
- self.flush()
- finally:
- self.sock_lock.release()
diff --git a/qpid/python/qpid/framing.py b/qpid/python/qpid/framing.py
deleted file mode 100644
index 389b607853..0000000000
--- a/qpid/python/qpid/framing.py
+++ /dev/null
@@ -1,313 +0,0 @@
-#
-# 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 struct
-
-FIRST_SEG = 0x08
-LAST_SEG = 0x04
-FIRST_FRM = 0x02
-LAST_FRM = 0x01
-
-class Frame:
-
- HEADER = "!2BHxBH4x"
- HEADER_SIZE = struct.calcsize(HEADER)
- MAX_PAYLOAD = 65535 - struct.calcsize(HEADER)
-
- def __init__(self, flags, type, track, channel, payload):
- if len(payload) > Frame.MAX_PAYLOAD:
- raise ValueError("max payload size exceeded: %s" % len(payload))
- self.flags = flags
- self.type = type
- self.track = track
- self.channel = channel
- self.payload = payload
-
- def isFirstSegment(self):
- return bool(FIRST_SEG & self.flags)
-
- def isLastSegment(self):
- return bool(LAST_SEG & self.flags)
-
- def isFirstFrame(self):
- return bool(FIRST_FRM & self.flags)
-
- def isLastFrame(self):
- return bool(LAST_FRM & self.flags)
-
- def __repr__(self):
- return "%s%s%s%s %s %s %s %r" % (int(self.isFirstSegment()),
- int(self.isLastSegment()),
- int(self.isFirstFrame()),
- int(self.isLastFrame()),
- self.type,
- self.track,
- self.channel,
- self.payload)
-
-class Segment:
-
- def __init__(self, first, last, type, track, channel, payload):
- self.id = None
- self.offset = None
- self.first = first
- self.last = last
- self.type = type
- self.track = track
- self.channel = channel
- self.payload = payload
-
- def __repr__(self):
- return "%s%s %s %s %s %r" % (int(self.first), int(self.last), self.type,
- self.track, self.channel, self.payload)
-
-class FrameDecoder:
-
- def __init__(self):
- self.input = ""
- self.output = []
- self.parse = self.__frame_header
-
- def write(self, bytes):
- self.input += bytes
- while True:
- next = self.parse()
- if next is None:
- break
- else:
- self.parse = next
-
- def __consume(self, n):
- result = self.input[:n]
- self.input = self.input[n:]
- return result
-
- def __frame_header(self):
- if len(self.input) >= Frame.HEADER_SIZE:
- st = self.__consume(Frame.HEADER_SIZE)
- self.flags, self.type, self.size, self.track, self.channel = \
- struct.unpack(Frame.HEADER, st)
- return self.__frame_body
-
- def __frame_body(self):
- size = self.size - Frame.HEADER_SIZE
- if len(self.input) >= size:
- payload = self.__consume(size)
- frame = Frame(self.flags, self.type, self.track, self.channel, payload)
- self.output.append(frame)
- return self.__frame_header
-
- def read(self):
- result = self.output
- self.output = []
- return result
-
-class FrameEncoder:
-
- def __init__(self):
- self.output = ""
-
- def write(self, *frames):
- for frame in frames:
- size = len(frame.payload) + Frame.HEADER_SIZE
- track = frame.track & 0x0F
- self.output += struct.pack(Frame.HEADER, frame.flags, frame.type, size,
- track, frame.channel)
- self.output += frame.payload
-
- def read(self):
- result = self.output
- self.output = ""
- return result
-
-class SegmentDecoder:
-
- def __init__(self):
- self.fragments = {}
- self.segments = []
-
- def write(self, *frames):
- for frm in frames:
- key = (frm.channel, frm.track)
- seg = self.fragments.get(key)
-
- if seg == None:
- seg = Segment(frm.isFirstSegment(), frm.isLastSegment(),
- frm.type, frm.track, frm.channel, "")
- self.fragments[key] = seg
-
- seg.payload += frm.payload
-
- if frm.isLastFrame():
- self.fragments.pop(key)
- self.segments.append(seg)
-
- def read(self):
- result = self.segments
- self.segments = []
- return result
-
-class SegmentEncoder:
-
- def __init__(self, max_payload=Frame.MAX_PAYLOAD):
- self.max_payload = max_payload
- self.frames = []
-
- def write(self, *segments):
- for seg in segments:
- remaining = seg.payload
-
- first = True
- while first or remaining:
- payload = remaining[:self.max_payload]
- remaining = remaining[self.max_payload:]
-
- flags = 0
- if first:
- flags |= FIRST_FRM
- first = False
- if not remaining:
- flags |= LAST_FRM
- if seg.first:
- flags |= FIRST_SEG
- if seg.last:
- flags |= LAST_SEG
-
- frm = Frame(flags, seg.type, seg.track, seg.channel, payload)
- self.frames.append(frm)
-
- def read(self):
- result = self.frames
- self.frames = []
- return result
-
-from ops import COMMANDS, CONTROLS, COMPOUND, Header, segment_type, track
-
-from codec010 import StringCodec
-
-class OpEncoder:
-
- def __init__(self):
- self.segments = []
-
- def write(self, *ops):
- for op in ops:
- if COMMANDS.has_key(op.NAME):
- seg_type = segment_type.command
- seg_track = track.command
- enc = self.encode_command(op)
- elif CONTROLS.has_key(op.NAME):
- seg_type = segment_type.control
- seg_track = track.control
- enc = self.encode_compound(op)
- else:
- raise ValueError(op)
- seg = Segment(True, False, seg_type, seg_track, op.channel, enc)
- self.segments.append(seg)
- if hasattr(op, "headers") and op.headers is not None:
- hdrs = ""
- for h in op.headers:
- hdrs += self.encode_compound(h)
- seg = Segment(False, False, segment_type.header, seg_track, op.channel,
- hdrs)
- self.segments.append(seg)
- if hasattr(op, "payload") and op.payload is not None:
- self.segments.append(Segment(False, False, segment_type.body, seg_track,
- op.channel, op.payload))
- self.segments[-1].last = True
-
- def encode_command(self, cmd):
- sc = StringCodec()
- sc.write_uint16(cmd.CODE)
- sc.write_compound(Header(sync=cmd.sync))
- sc.write_fields(cmd)
- return sc.encoded
-
- def encode_compound(self, op):
- sc = StringCodec()
- sc.write_compound(op)
- return sc.encoded
-
- def read(self):
- result = self.segments
- self.segments = []
- return result
-
-class OpDecoder:
-
- def __init__(self):
- self.current_op = {}
- self.ops = []
-
- def write(self, *segments):
- for seg in segments:
- op = self.current_op.get(seg.track)
- if seg.first:
- if seg.type == segment_type.command:
- op = self.decode_command(seg.payload)
- elif seg.type == segment_type.control:
- op = self.decode_control(seg.payload)
- else:
- raise ValueError(seg)
- op.channel = seg.channel
- elif seg.type == segment_type.header:
- if op.headers is None:
- op.headers = []
- op.headers.extend(self.decode_headers(seg.payload))
- elif seg.type == segment_type.body:
- if op.payload is None:
- op.payload = seg.payload
- else:
- op.payload += seg.payload
- if seg.last:
- self.ops.append(op)
- if seg.track in self.current_op:
- del self.current_op[seg.track]
- else:
- self.current_op[seg.track] = op
-
- def decode_command(self, encoded):
- sc = StringCodec(encoded)
- code = sc.read_uint16()
- cls = COMMANDS[code]
- hdr = sc.read_compound(Header)
- cmd = cls()
- sc.read_fields(cmd)
- cmd.sync = hdr.sync
- return cmd
-
- def decode_control(self, encoded):
- sc = StringCodec(encoded)
- code = sc.read_uint16()
- cls = CONTROLS[code]
- ctl = cls()
- sc.read_fields(ctl)
- return ctl
-
- def decode_headers(self, encoded):
- sc = StringCodec(encoded)
- result = []
- while sc.encoded:
- result.append(sc.read_struct32())
- return result
-
- def read(self):
- result = self.ops
- self.ops = []
- return result
diff --git a/qpid/python/qpid/generator.py b/qpid/python/qpid/generator.py
deleted file mode 100644
index 02d11e5005..0000000000
--- a/qpid/python/qpid/generator.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# 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 sys
-
-from ops import *
-
-def METHOD(module, op):
- method = lambda self, *args, **kwargs: self.invoke(op, args, kwargs)
- if sys.version_info[:2] > (2, 3):
- method.__name__ = op.__name__
- method.__doc__ = op.__doc__
- method.__module__ = module
- return method
-
-def generate(module, operations):
- dict = {}
-
- for name, enum in ENUMS.items():
- if isinstance(name, basestring):
- dict[name] = enum
-
- for name, op in COMPOUND.items():
- if isinstance(name, basestring):
- dict[name] = METHOD(module, op)
-
- for name, op in operations.items():
- if isinstance(name, basestring):
- dict[name] = METHOD(module, op)
-
- return dict
-
-def invoker(name, operations):
- return type(name, (), generate(invoker.__module__, operations))
-
-def command_invoker():
- return invoker("CommandInvoker", COMMANDS)
-
-def control_invoker():
- return invoker("ControlInvoker", CONTROLS)
diff --git a/qpid/python/qpid/harness.py b/qpid/python/qpid/harness.py
deleted file mode 100644
index ce48481612..0000000000
--- a/qpid/python/qpid/harness.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# 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.
-#
-
-class Skipped(Exception): pass
diff --git a/qpid/python/qpid/lexer.py b/qpid/python/qpid/lexer.py
deleted file mode 100644
index ec28bbb91a..0000000000
--- a/qpid/python/qpid/lexer.py
+++ /dev/null
@@ -1,118 +0,0 @@
-#
-# 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 re
-
-class Type:
-
- def __init__(self, name, pattern=None):
- self.name = name
- self.pattern = pattern
-
- def __repr__(self):
- return self.name
-
-class Lexicon:
-
- def __init__(self):
- self.types = []
- self._eof = None
-
- def define(self, name, pattern):
- t = Type(name, pattern)
- self.types.append(t)
- return t
-
- def eof(self, name):
- t = Type(name)
- self._eof = t
- return t
-
- def compile(self):
- types = self.types[:]
- joined = "|".join(["(%s)" % t.pattern for t in types])
- rexp = re.compile(joined)
- return Lexer(types, self._eof, rexp)
-
-class Token:
-
- def __init__(self, type, value, input, position):
- self.type = type
- self.value = value
- self.input = input
- self.position = position
-
- def line_info(self):
- return line_info(self.input, self.position)
-
- def __repr__(self):
- if self.value is None:
- return repr(self.type)
- else:
- return "%s(%s)" % (self.type, self.value)
-
-
-class LexError(Exception):
- pass
-
-def line_info(st, pos):
- idx = 0
- lineno = 1
- column = 0
- line_pos = 0
- while idx < pos:
- if st[idx] == "\n":
- lineno += 1
- column = 0
- line_pos = idx
- column += 1
- idx += 1
-
- end = st.find("\n", line_pos)
- if end < 0:
- end = len(st)
- line = st[line_pos:end]
-
- return line, lineno, column
-
-class Lexer:
-
- def __init__(self, types, eof, rexp):
- self.types = types
- self.eof = eof
- self.rexp = rexp
- self.byname = {}
- for t in self.types + [eof]:
- self.byname[t.name] = t
-
- def type(self, name):
- return self.byname[name]
-
- def lex(self, st):
- pos = 0
- while pos < len(st):
- m = self.rexp.match(st, pos)
- if m is None:
- line, ln, col = line_info(st, pos)
- raise LexError("unrecognized characters line:%s,%s: %s" % (ln, col, line))
- else:
- idx = m.lastindex
- t = Token(self.types[idx - 1], m.group(idx), st, pos)
- yield t
- pos = m.end()
- yield Token(self.eof, None, st, pos)
diff --git a/qpid/python/qpid/log.py b/qpid/python/qpid/log.py
deleted file mode 100644
index 1fd7d74136..0000000000
--- a/qpid/python/qpid/log.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# 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.
-#
-
-from logging import getLogger, StreamHandler, Formatter
-from logging import DEBUG, INFO, WARN, ERROR, CRITICAL
-
-def enable(name=None, level=WARN, file=None):
- log = getLogger(name)
- handler = StreamHandler(file)
- handler.setFormatter(Formatter("%(asctime)s %(levelname)s %(message)s"))
- log.addHandler(handler)
- log.setLevel(level)
diff --git a/qpid/python/qpid/management.py b/qpid/python/qpid/management.py
deleted file mode 100644
index 3de8da9d49..0000000000
--- a/qpid/python/qpid/management.py
+++ /dev/null
@@ -1,922 +0,0 @@
-#
-# 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.
-#
-
-###############################################################################
-## This file is being obsoleted by qmf/console.py
-###############################################################################
-
-"""
-Management API for Qpid
-"""
-
-import qpid
-import struct
-import socket
-from threading import Thread
-from datatypes import Message, RangedSet
-from time import time
-from cStringIO import StringIO
-from codec010 import StringCodec as Codec
-from threading import Lock, Condition
-
-
-class SequenceManager:
- """ Manage sequence numbers for asynchronous method calls """
- def __init__ (self):
- self.lock = Lock ()
- self.sequence = 0
- self.pending = {}
-
- def reserve (self, data):
- """ Reserve a unique sequence number """
- self.lock.acquire ()
- result = self.sequence
- self.sequence = self.sequence + 1
- self.pending[result] = data
- self.lock.release ()
- return result
-
- def release (self, seq):
- """ Release a reserved sequence number """
- data = None
- self.lock.acquire ()
- if seq in self.pending:
- data = self.pending[seq]
- del self.pending[seq]
- self.lock.release ()
- return data
-
-
-class mgmtObject (object):
- """ Generic object that holds the contents of a management object with its
- attributes set as object attributes. """
-
- def __init__ (self, classKey, timestamps, row):
- self.classKey = classKey
- self.timestamps = timestamps
- for cell in row:
- setattr (self, cell[0], cell[1])
-
-class objectId(object):
- """ Object that represents QMF object identifiers """
-
- def __init__(self, codec, first=0, second=0):
- if codec:
- self.first = codec.read_uint64()
- self.second = codec.read_uint64()
- else:
- self.first = first
- self.second = second
-
- def __cmp__(self, other):
- if other == None:
- return 1
- if self.first < other.first:
- return -1
- if self.first > other.first:
- return 1
- if self.second < other.second:
- return -1
- if self.second > other.second:
- return 1
- return 0
-
-
- def index(self):
- return (self.first, self.second)
-
- def getFlags(self):
- return (self.first & 0xF000000000000000) >> 60
-
- def getSequence(self):
- return (self.first & 0x0FFF000000000000) >> 48
-
- def getBroker(self):
- return (self.first & 0x0000FFFFF0000000) >> 28
-
- def getBank(self):
- return self.first & 0x000000000FFFFFFF
-
- def getObject(self):
- return self.second
-
- def isDurable(self):
- return self.getSequence() == 0
-
- def encode(self, codec):
- codec.write_uint64(self.first)
- codec.write_uint64(self.second)
-
-
-class methodResult:
- """ Object that contains the result of a method call """
-
- def __init__ (self, status, sText, args):
- self.status = status
- self.statusText = sText
- for arg in args:
- setattr (self, arg, args[arg])
-
-class brokerInfo:
- """ Object that contains information about a broker and the session to it """
-
- def __init__ (self, brokerId, sessionId):
- self.brokerId = brokerId
- self.sessionId = sessionId
-
-class managementChannel:
- """ This class represents a connection to an AMQP broker. """
-
- def __init__ (self, ssn, topicCb, replyCb, exceptionCb, cbContext, _detlife=0):
- """ Given a channel on an established AMQP broker connection, this method
- opens a session and performs all of the declarations and bindings needed
- to participate in the management protocol. """
- self.enabled = True
- self.ssn = ssn
- self.sessionId = ssn.name
- self.topicName = "mgmt-%s" % self.sessionId
- self.replyName = "repl-%s" % self.sessionId
- self.qpidChannel = ssn
- self.tcb = topicCb
- self.rcb = replyCb
- self.ecb = exceptionCb
- self.context = cbContext
- self.reqsOutstanding = 0
- self.brokerInfo = None
-
- ssn.auto_sync = False
- ssn.queue_declare (queue=self.topicName, exclusive=True, auto_delete=True)
- ssn.queue_declare (queue=self.replyName, exclusive=True, auto_delete=True)
-
- ssn.exchange_bind (exchange="amq.direct",
- queue=self.replyName, binding_key=self.replyName)
- ssn.message_subscribe (queue=self.topicName, destination="tdest",
- accept_mode=ssn.accept_mode.none,
- acquire_mode=ssn.acquire_mode.pre_acquired)
- ssn.message_subscribe (queue=self.replyName, destination="rdest",
- accept_mode=ssn.accept_mode.none,
- acquire_mode=ssn.acquire_mode.pre_acquired)
-
- ssn.incoming ("tdest").listen (self.topicCb, self.exceptionCb)
- ssn.incoming ("rdest").listen (self.replyCb)
-
- ssn.message_set_flow_mode (destination="tdest", flow_mode=1)
- ssn.message_flow (destination="tdest", unit=0, value=0xFFFFFFFFL)
- ssn.message_flow (destination="tdest", unit=1, value=0xFFFFFFFFL)
-
- ssn.message_set_flow_mode (destination="rdest", flow_mode=1)
- ssn.message_flow (destination="rdest", unit=0, value=0xFFFFFFFFL)
- ssn.message_flow (destination="rdest", unit=1, value=0xFFFFFFFFL)
-
- def setBrokerInfo (self, data):
- self.brokerInfo = data
-
- def shutdown (self):
- self.enabled = False
- self.ssn.incoming("tdest").stop()
- self.ssn.incoming("rdest").stop()
-
- def topicCb (self, msg):
- """ Receive messages via the topic queue on this channel. """
- if self.enabled:
- self.tcb (self, msg)
- self.ssn.receiver._completed.add(msg.id)
- self.ssn.channel.session_completed(self.ssn.receiver._completed)
-
- def replyCb (self, msg):
- """ Receive messages via the reply queue on this channel. """
- if self.enabled:
- self.rcb (self, msg)
- self.ssn.receiver._completed.add(msg.id)
- self.ssn.channel.session_completed(self.ssn.receiver._completed)
-
- def exceptionCb (self, data):
- if self.ecb != None:
- self.ecb (self, data)
-
- def send (self, exchange, msg):
- if self.enabled:
- self.qpidChannel.message_transfer (destination=exchange, message=msg)
-
- def message (self, body, routing_key="broker"):
- dp = self.qpidChannel.delivery_properties()
- dp.routing_key = routing_key
- mp = self.qpidChannel.message_properties()
- mp.content_type = "application/octet-stream"
- mp.reply_to = self.qpidChannel.reply_to("amq.direct", self.replyName)
- return Message(dp, mp, body)
-
-
-class managementClient:
- """ This class provides an API for access to management data on the AMQP
- network. It implements the management protocol and manages the management
- schemas as advertised by the various management agents in the network. """
-
- CTRL_BROKER_INFO = 1
- CTRL_SCHEMA_LOADED = 2
- CTRL_USER = 3
- CTRL_HEARTBEAT = 4
-
- SYNC_TIME = 10.0
-
- #========================================================
- # User API - interacts with the class's user
- #========================================================
- def __init__ (self, unused=None, ctrlCb=None, configCb=None, instCb=None, methodCb=None, closeCb=None):
- self.ctrlCb = ctrlCb
- self.configCb = configCb
- self.instCb = instCb
- self.methodCb = methodCb
- self.closeCb = closeCb
- self.schemaCb = None
- self.eventCb = None
- self.channels = []
- self.seqMgr = SequenceManager ()
- self.schema = {}
- self.packages = {}
- self.cv = Condition ()
- self.syncInFlight = False
- self.syncSequence = 0
- self.syncResult = None
-
- def schemaListener (self, schemaCb):
- """ Optionally register a callback to receive details of the schema of
- managed objects in the network. """
- self.schemaCb = schemaCb
-
- def eventListener (self, eventCb):
- """ Optionally register a callback to receive events from managed objects
- in the network. """
- self.eventCb = eventCb
-
- def addChannel (self, channel, cbContext=None):
- """ Register a new channel. """
- mch = managementChannel (channel, self.topicCb, self.replyCb, self.exceptCb, cbContext)
-
- self.channels.append (mch)
- self.incOutstanding (mch)
- codec = Codec ()
- self.setHeader (codec, ord ('B'))
- msg = mch.message(codec.encoded)
- mch.send ("qpid.management", msg)
- return mch
-
- def removeChannel (self, mch):
- """ Remove a previously added channel from management. """
- mch.shutdown ()
- self.channels.remove (mch)
-
- def callMethod (self, channel, userSequence, objId, className, methodName, args=None):
- """ Invoke a method on a managed object. """
- self.method (channel, userSequence, objId, className, methodName, args)
-
- def getObjects (self, channel, userSequence, className, bank=0):
- """ Request immediate content from broker """
- codec = Codec ()
- self.setHeader (codec, ord ('G'), userSequence)
- ft = {}
- ft["_class"] = className
- codec.write_map (ft)
- msg = channel.message(codec.encoded, routing_key="agent.1.%d" % bank)
- channel.send ("qpid.management", msg)
-
- def syncWaitForStable (self, channel):
- """ Synchronous (blocking) call to wait for schema stability on a channel """
- self.cv.acquire ()
- if channel.reqsOutstanding == 0:
- self.cv.release ()
- return channel.brokerInfo
-
- self.syncInFlight = True
- starttime = time ()
- while channel.reqsOutstanding != 0:
- self.cv.wait (self.SYNC_TIME)
- if time () - starttime > self.SYNC_TIME:
- self.cv.release ()
- raise RuntimeError ("Timed out waiting for response on channel")
- self.cv.release ()
- return channel.brokerInfo
-
- def syncCallMethod (self, channel, objId, className, methodName, args=None):
- """ Synchronous (blocking) method call """
- self.cv.acquire ()
- self.syncInFlight = True
- self.syncResult = None
- self.syncSequence = self.seqMgr.reserve ("sync")
- self.cv.release ()
- self.callMethod (channel, self.syncSequence, objId, className, methodName, args)
- self.cv.acquire ()
- starttime = time ()
- while self.syncInFlight:
- self.cv.wait (self.SYNC_TIME)
- if time () - starttime > self.SYNC_TIME:
- self.cv.release ()
- raise RuntimeError ("Timed out waiting for response on channel")
- result = self.syncResult
- self.cv.release ()
- return result
-
- def syncGetObjects (self, channel, className, bank=0):
- """ Synchronous (blocking) get call """
- self.cv.acquire ()
- self.syncInFlight = True
- self.syncResult = []
- self.syncSequence = self.seqMgr.reserve ("sync")
- self.cv.release ()
- self.getObjects (channel, self.syncSequence, className, bank)
- self.cv.acquire ()
- starttime = time ()
- while self.syncInFlight:
- self.cv.wait (self.SYNC_TIME)
- if time () - starttime > self.SYNC_TIME:
- self.cv.release ()
- raise RuntimeError ("Timed out waiting for response on channel")
- result = self.syncResult
- self.cv.release ()
- return result
-
- #========================================================
- # Channel API - interacts with registered channel objects
- #========================================================
- def topicCb (self, ch, msg):
- """ Receive messages via the topic queue of a particular channel. """
- codec = Codec (msg.body)
- while True:
- hdr = self.checkHeader (codec)
- if hdr == None:
- return
-
- if hdr[0] == 'p':
- self.handlePackageInd (ch, codec)
- elif hdr[0] == 'q':
- self.handleClassInd (ch, codec)
- elif hdr[0] == 'h':
- self.handleHeartbeat (ch, codec)
- elif hdr[0] == 'e':
- self.handleEvent (ch, codec)
- else:
- self.parse (ch, codec, hdr[0], hdr[1])
-
- def replyCb (self, ch, msg):
- """ Receive messages via the reply queue of a particular channel. """
- codec = Codec (msg.body)
- while True:
- hdr = self.checkHeader (codec)
- if hdr == None:
- return
-
- if hdr[0] == 'm':
- self.handleMethodReply (ch, codec, hdr[1])
- elif hdr[0] == 'z':
- self.handleCommandComplete (ch, codec, hdr[1])
- elif hdr[0] == 'b':
- self.handleBrokerResponse (ch, codec)
- elif hdr[0] == 'p':
- self.handlePackageInd (ch, codec)
- elif hdr[0] == 'q':
- self.handleClassInd (ch, codec)
- else:
- self.parse (ch, codec, hdr[0], hdr[1])
-
- def exceptCb (self, ch, data):
- if self.closeCb != None:
- self.closeCb (ch.context, data)
-
- #========================================================
- # Internal Functions
- #========================================================
- def setHeader (self, codec, opcode, seq = 0):
- """ Compose the header of a management message. """
- codec.write_uint8 (ord ('A'))
- codec.write_uint8 (ord ('M'))
- codec.write_uint8 (ord ('2'))
- codec.write_uint8 (opcode)
- codec.write_uint32 (seq)
-
- def checkHeader (self, codec):
- """ Check the header of a management message and extract the opcode and class. """
- try:
- octet = chr (codec.read_uint8 ())
- if octet != 'A':
- return None
- octet = chr (codec.read_uint8 ())
- if octet != 'M':
- return None
- octet = chr (codec.read_uint8 ())
- if octet != '2':
- return None
- opcode = chr (codec.read_uint8 ())
- seq = codec.read_uint32 ()
- return (opcode, seq)
- except:
- return None
-
- def encodeValue (self, codec, value, typecode):
- """ Encode, into the codec, a value based on its typecode. """
- if typecode == 1:
- codec.write_uint8 (int (value))
- elif typecode == 2:
- codec.write_uint16 (int (value))
- elif typecode == 3:
- codec.write_uint32 (long (value))
- elif typecode == 4:
- codec.write_uint64 (long (value))
- elif typecode == 5:
- codec.write_uint8 (int (value))
- elif typecode == 6:
- codec.write_str8 (value)
- elif typecode == 7:
- codec.write_str16 (value)
- elif typecode == 8: # ABSTIME
- codec.write_uint64 (long (value))
- elif typecode == 9: # DELTATIME
- codec.write_uint64 (long (value))
- elif typecode == 10: # REF
- value.encode(codec)
- elif typecode == 11: # BOOL
- codec.write_uint8 (int (value))
- elif typecode == 12: # FLOAT
- codec.write_float (float (value))
- elif typecode == 13: # DOUBLE
- codec.write_double (float (value))
- elif typecode == 14: # UUID
- codec.write_uuid (value)
- elif typecode == 15: # FTABLE
- codec.write_map (value)
- elif typecode == 16:
- codec.write_int8 (int(value))
- elif typecode == 17:
- codec.write_int16 (int(value))
- elif typecode == 18:
- codec.write_int32 (int(value))
- elif typecode == 19:
- codec.write_int64 (int(value))
- else:
- raise ValueError ("Invalid type code: %d" % typecode)
-
- def decodeValue (self, codec, typecode):
- """ Decode, from the codec, a value based on its typecode. """
- if typecode == 1:
- data = codec.read_uint8 ()
- elif typecode == 2:
- data = codec.read_uint16 ()
- elif typecode == 3:
- data = codec.read_uint32 ()
- elif typecode == 4:
- data = codec.read_uint64 ()
- elif typecode == 5:
- data = codec.read_uint8 ()
- elif typecode == 6:
- data = codec.read_str8 ()
- elif typecode == 7:
- data = codec.read_str16 ()
- elif typecode == 8: # ABSTIME
- data = codec.read_uint64 ()
- elif typecode == 9: # DELTATIME
- data = codec.read_uint64 ()
- elif typecode == 10: # REF
- data = objectId(codec)
- elif typecode == 11: # BOOL
- data = codec.read_uint8 ()
- elif typecode == 12: # FLOAT
- data = codec.read_float ()
- elif typecode == 13: # DOUBLE
- data = codec.read_double ()
- elif typecode == 14: # UUID
- data = codec.read_uuid ()
- elif typecode == 15: # FTABLE
- data = codec.read_map ()
- elif typecode == 16:
- data = codec.read_int8 ()
- elif typecode == 17:
- data = codec.read_int16 ()
- elif typecode == 18:
- data = codec.read_int32 ()
- elif typecode == 19:
- data = codec.read_int64 ()
- else:
- raise ValueError ("Invalid type code: %d" % typecode)
- return data
-
- def incOutstanding (self, ch):
- self.cv.acquire ()
- ch.reqsOutstanding = ch.reqsOutstanding + 1
- self.cv.release ()
-
- def decOutstanding (self, ch):
- self.cv.acquire ()
- ch.reqsOutstanding = ch.reqsOutstanding - 1
- if ch.reqsOutstanding == 0 and self.syncInFlight:
- self.syncInFlight = False
- self.cv.notify ()
- self.cv.release ()
-
- if ch.reqsOutstanding == 0:
- if self.ctrlCb != None:
- self.ctrlCb (ch.context, self.CTRL_SCHEMA_LOADED, None)
- ch.ssn.exchange_bind (exchange="qpid.management",
- queue=ch.topicName, binding_key="console.#")
- ch.ssn.exchange_bind (exchange="qpid.management",
- queue=ch.topicName, binding_key="schema.#")
-
-
- def handleMethodReply (self, ch, codec, sequence):
- status = codec.read_uint32 ()
- sText = codec.read_str16 ()
-
- data = self.seqMgr.release (sequence)
- if data == None:
- return
-
- (userSequence, classId, methodName) = data
- args = {}
- context = self.seqMgr.release (userSequence)
-
- if status == 0:
- schemaClass = self.schema[classId]
- ms = schemaClass['M']
- arglist = None
- for mname in ms:
- (mdesc, margs) = ms[mname]
- if mname == methodName:
- arglist = margs
- if arglist == None:
- return
-
- for arg in arglist:
- if arg[2].find("O") != -1:
- args[arg[0]] = self.decodeValue (codec, arg[1])
-
- if context == "sync" and userSequence == self.syncSequence:
- self.cv.acquire ()
- self.syncInFlight = False
- self.syncResult = methodResult (status, sText, args)
- self.cv.notify ()
- self.cv.release ()
- elif self.methodCb != None:
- self.methodCb (ch.context, userSequence, status, sText, args)
-
- def handleCommandComplete (self, ch, codec, seq):
- code = codec.read_uint32 ()
- text = codec.read_str8 ()
- data = (seq, code, text)
- context = self.seqMgr.release (seq)
- if context == "outstanding":
- self.decOutstanding (ch)
- elif context == "sync" and seq == self.syncSequence:
- self.cv.acquire ()
- self.syncInFlight = False
- self.cv.notify ()
- self.cv.release ()
- elif self.ctrlCb != None:
- self.ctrlCb (ch.context, self.CTRL_USER, data)
-
- def handleBrokerResponse (self, ch, codec):
- uuid = codec.read_uuid ()
- ch.brokerInfo = brokerInfo (uuid, ch.sessionId)
- if self.ctrlCb != None:
- self.ctrlCb (ch.context, self.CTRL_BROKER_INFO, ch.brokerInfo)
-
- # Send a package request
- sendCodec = Codec ()
- seq = self.seqMgr.reserve ("outstanding")
- self.setHeader (sendCodec, ord ('P'), seq)
- smsg = ch.message(sendCodec.encoded)
- ch.send ("qpid.management", smsg)
-
- def handlePackageInd (self, ch, codec):
- pname = codec.read_str8 ()
- if pname not in self.packages:
- self.packages[pname] = {}
-
- # Send a class request
- sendCodec = Codec ()
- seq = self.seqMgr.reserve ("outstanding")
- self.setHeader (sendCodec, ord ('Q'), seq)
- self.incOutstanding (ch)
- sendCodec.write_str8 (pname)
- smsg = ch.message(sendCodec.encoded)
- ch.send ("qpid.management", smsg)
-
- def handleClassInd (self, ch, codec):
- kind = codec.read_uint8()
- if kind != 1: # This API doesn't handle new-style events
- return
- pname = codec.read_str8()
- cname = codec.read_str8()
- hash = codec.read_bin128()
- if pname not in self.packages:
- return
-
- if (cname, hash) not in self.packages[pname]:
- # Send a schema request
- sendCodec = Codec ()
- seq = self.seqMgr.reserve ("outstanding")
- self.setHeader (sendCodec, ord ('S'), seq)
- self.incOutstanding (ch)
- sendCodec.write_str8 (pname)
- sendCodec.write_str8 (cname)
- sendCodec.write_bin128 (hash)
- smsg = ch.message(sendCodec.encoded)
- ch.send ("qpid.management", smsg)
-
- def handleHeartbeat (self, ch, codec):
- timestamp = codec.read_uint64()
- if self.ctrlCb != None:
- self.ctrlCb (ch.context, self.CTRL_HEARTBEAT, timestamp)
-
- def handleEvent (self, ch, codec):
- if self.eventCb == None:
- return
- timestamp = codec.read_uint64()
- objId = objectId(codec)
- packageName = codec.read_str8()
- className = codec.read_str8()
- hash = codec.read_bin128()
- name = codec.read_str8()
- classKey = (packageName, className, hash)
- if classKey not in self.schema:
- return;
- schemaClass = self.schema[classKey]
- row = []
- es = schemaClass['E']
- arglist = None
- for ename in es:
- (edesc, eargs) = es[ename]
- if ename == name:
- arglist = eargs
- if arglist == None:
- return
- for arg in arglist:
- row.append((arg[0], self.decodeValue(codec, arg[1])))
- self.eventCb(ch.context, classKey, objId, name, row)
-
- def parseSchema (self, ch, codec):
- """ Parse a received schema-description message. """
- self.decOutstanding (ch)
- kind = codec.read_uint8()
- if kind != 1: # This API doesn't handle new-style events
- return
- packageName = codec.read_str8 ()
- className = codec.read_str8 ()
- hash = codec.read_bin128 ()
- hasSupertype = 0 #codec.read_uint8()
- configCount = codec.read_uint16 ()
- instCount = codec.read_uint16 ()
- methodCount = codec.read_uint16 ()
- if hasSupertype != 0:
- supertypePackage = codec.read_str8()
- supertypeClass = codec.read_str8()
- supertypeHash = codec.read_bin128()
-
- if packageName not in self.packages:
- return
- if (className, hash) in self.packages[packageName]:
- return
-
- classKey = (packageName, className, hash)
- if classKey in self.schema:
- return
-
- configs = []
- insts = []
- methods = {}
-
- configs.append (("id", 4, "", "", 1, 1, None, None, None, None, None))
- insts.append (("id", 4, None, None))
-
- for idx in range (configCount):
- ft = codec.read_map ()
- name = str (ft["name"])
- type = ft["type"]
- access = ft["access"]
- index = ft["index"]
- optional = ft["optional"]
- unit = None
- min = None
- max = None
- maxlen = None
- desc = None
-
- for key, value in ft.items ():
- if key == "unit":
- unit = str (value)
- elif key == "min":
- min = value
- elif key == "max":
- max = value
- elif key == "maxlen":
- maxlen = value
- elif key == "desc":
- desc = str (value)
-
- config = (name, type, unit, desc, access, index, min, max, maxlen, optional)
- configs.append (config)
-
- for idx in range (instCount):
- ft = codec.read_map ()
- name = str (ft["name"])
- type = ft["type"]
- unit = None
- desc = None
-
- for key, value in ft.items ():
- if key == "unit":
- unit = str (value)
- elif key == "desc":
- desc = str (value)
-
- inst = (name, type, unit, desc)
- insts.append (inst)
-
- for idx in range (methodCount):
- ft = codec.read_map ()
- mname = str (ft["name"])
- argCount = ft["argCount"]
- if "desc" in ft:
- mdesc = str (ft["desc"])
- else:
- mdesc = None
-
- args = []
- for aidx in range (argCount):
- ft = codec.read_map ()
- name = str (ft["name"])
- type = ft["type"]
- dir = str (ft["dir"].upper ())
- unit = None
- min = None
- max = None
- maxlen = None
- desc = None
- default = None
-
- for key, value in ft.items ():
- if key == "unit":
- unit = str (value)
- elif key == "min":
- min = value
- elif key == "max":
- max = value
- elif key == "maxlen":
- maxlen = value
- elif key == "desc":
- desc = str (value)
- elif key == "default":
- default = str (value)
-
- arg = (name, type, dir, unit, desc, min, max, maxlen, default)
- args.append (arg)
- methods[mname] = (mdesc, args)
-
- schemaClass = {}
- schemaClass['C'] = configs
- schemaClass['I'] = insts
- schemaClass['M'] = methods
- self.schema[classKey] = schemaClass
-
- if self.schemaCb != None:
- self.schemaCb (ch.context, classKey, configs, insts, methods, {})
-
- def parsePresenceMasks(self, codec, schemaClass):
- """ Generate a list of not-present properties """
- excludeList = []
- bit = 0
- for element in schemaClass['C'][1:]:
- if element[9] == 1:
- if bit == 0:
- mask = codec.read_uint8()
- bit = 1
- if (mask & bit) == 0:
- excludeList.append(element[0])
- bit = bit * 2
- if bit == 256:
- bit = 0
- return excludeList
-
- def parseContent (self, ch, cls, codec, seq=0):
- """ Parse a received content message. """
- if (cls == 'C' or (cls == 'B' and seq == 0)) and self.configCb == None:
- return
- if cls == 'I' and self.instCb == None:
- return
-
- packageName = codec.read_str8 ()
- className = codec.read_str8 ()
- hash = codec.read_bin128 ()
- classKey = (packageName, className, hash)
-
- if classKey not in self.schema:
- return
-
- row = []
- timestamps = []
-
- timestamps.append (codec.read_uint64 ()) # Current Time
- timestamps.append (codec.read_uint64 ()) # Create Time
- timestamps.append (codec.read_uint64 ()) # Delete Time
- objId = objectId(codec)
- schemaClass = self.schema[classKey]
- if cls == 'C' or cls == 'B':
- notPresent = self.parsePresenceMasks(codec, schemaClass)
-
- if cls == 'C' or cls == 'B':
- row.append(("id", objId))
- for element in schemaClass['C'][1:]:
- tc = element[1]
- name = element[0]
- if name in notPresent:
- row.append((name, None))
- else:
- data = self.decodeValue(codec, tc)
- row.append((name, data))
-
- if cls == 'I' or cls == 'B':
- if cls == 'I':
- row.append(("id", objId))
- for element in schemaClass['I'][1:]:
- tc = element[1]
- name = element[0]
- data = self.decodeValue (codec, tc)
- row.append ((name, data))
-
- if cls == 'C' or (cls == 'B' and seq != self.syncSequence):
- self.configCb (ch.context, classKey, row, timestamps)
- elif cls == 'B' and seq == self.syncSequence:
- if timestamps[2] == 0:
- obj = mgmtObject (classKey, timestamps, row)
- self.syncResult.append (obj)
- elif cls == 'I':
- self.instCb (ch.context, classKey, row, timestamps)
-
- def parse (self, ch, codec, opcode, seq):
- """ Parse a message received from the topic queue. """
- if opcode == 's':
- self.parseSchema (ch, codec)
- elif opcode == 'c':
- self.parseContent (ch, 'C', codec)
- elif opcode == 'i':
- self.parseContent (ch, 'I', codec)
- elif opcode == 'g':
- self.parseContent (ch, 'B', codec, seq)
- else:
- raise ValueError ("Unknown opcode: %c" % opcode);
-
- def method (self, channel, userSequence, objId, classId, methodName, args):
- """ Invoke a method on an object """
- codec = Codec ()
- sequence = self.seqMgr.reserve ((userSequence, classId, methodName))
- self.setHeader (codec, ord ('M'), sequence)
- objId.encode(codec)
- codec.write_str8 (classId[0])
- codec.write_str8 (classId[1])
- codec.write_bin128 (classId[2])
- codec.write_str8 (methodName)
- bank = "%d.%d" % (objId.getBroker(), objId.getBank())
-
- # Encode args according to schema
- if classId not in self.schema:
- self.seqMgr.release (sequence)
- raise ValueError ("Unknown class name: %s" % classId)
-
- schemaClass = self.schema[classId]
- ms = schemaClass['M']
- arglist = None
- for mname in ms:
- (mdesc, margs) = ms[mname]
- if mname == methodName:
- arglist = margs
- if arglist == None:
- self.seqMgr.release (sequence)
- raise ValueError ("Unknown method name: %s" % methodName)
-
- for arg in arglist:
- if arg[2].find("I") != -1:
- value = arg[8] # default
- if arg[0] in args:
- value = args[arg[0]]
- if value == None:
- self.seqMgr.release (sequence)
- raise ValueError ("Missing non-defaulted argument: %s" % arg[0])
- self.encodeValue (codec, value, arg[1])
-
- packageName = classId[0]
- className = classId[1]
- msg = channel.message(codec.encoded, "agent." + bank)
- channel.send ("qpid.management", msg)
diff --git a/qpid/python/qpid/managementdata.py b/qpid/python/qpid/managementdata.py
deleted file mode 100644
index 61cb10c134..0000000000
--- a/qpid/python/qpid/managementdata.py
+++ /dev/null
@@ -1,773 +0,0 @@
-#!/usr/bin/env 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.
-#
-
-
-###############################################################################
-## This file is being obsoleted by qmf/console.py
-###############################################################################
-
-import qpid
-import re
-import socket
-import struct
-import os
-import platform
-import locale
-from qpid.connection import Timeout
-from qpid.management import managementChannel, managementClient
-from threading import Lock
-from disp import Display
-from shlex import split
-from qpid.connection import Connection
-from qpid.util import connect
-
-class Broker:
- def __init__ (self, text):
- rex = re.compile(r"""
- # [ <user> [ / <password> ] @] <host> [ :<port> ]
- ^ (?: ([^/]*) (?: / ([^@]*) )? @)? ([^:]+) (?: :([0-9]+))?$""", re.X)
- match = rex.match(text)
- if not match: raise ValueError("'%s' is not a valid broker url" % (text))
- user, password, host, port = match.groups()
-
- if port: self.port = int(port)
- else: self.port = 5672
- for addr in socket.getaddrinfo(host, self.port):
- if addr[1] == socket.AF_INET:
- self.host = addr[4][0]
- self.username = user or "guest"
- self.password = password or "guest"
-
- def name (self):
- return self.host + ":" + str (self.port)
-
-class ManagementData:
-
- #
- # Data Structure:
- #
- # Please note that this data structure holds only the most recent
- # configuration and instrumentation data for each object. It does
- # not hold the detailed historical data that is sent from the broker.
- # The only historical data it keeps are the high and low watermarks
- # for hi-lo statistics.
- #
- # tables :== {class-key}
- # {<obj-id>}
- # (timestamp, config-record, inst-record)
- # class-key :== (<package-name>, <class-name>, <class-hash>)
- # timestamp :== (<last-interval-time>, <create-time>, <delete-time>)
- # config-record :== [element]
- # inst-record :== [element]
- # element :== (<element-name>, <element-value>)
- #
-
- def registerObjId (self, objId):
- if not objId.index() in self.idBackMap:
- self.idBackMap[objId.index()] = self.nextId
- self.idMap[self.nextId] = objId
- self.nextId += 1
-
- def displayObjId (self, objIdIndex):
- if objIdIndex in self.idBackMap:
- return self.idBackMap[objIdIndex]
- else:
- return 0
-
- def rawObjId (self, displayId):
- if displayId in self.idMap:
- return self.idMap[displayId]
- else:
- return None
-
- def displayClassName (self, cls):
- (packageName, className, hash) = cls
- rev = self.schema[cls][4]
- if rev == 0:
- suffix = ""
- else:
- suffix = ".%d" % rev
- return packageName + ":" + className + suffix
-
- def dataHandler (self, context, className, list, timestamps):
- """ Callback for configuration and instrumentation data updates """
- self.lock.acquire ()
- try:
- # If this class has not been seen before, create an empty dictionary to
- # hold objects of this class
- if className not in self.tables:
- self.tables[className] = {}
-
- # Register the ID so a more friendly presentation can be displayed
- objId = list[0][1]
- oidx = objId.index()
- self.registerObjId (objId)
-
- # If this object hasn't been seen before, create a new object record with
- # the timestamps and empty lists for configuration and instrumentation data.
- if oidx not in self.tables[className]:
- self.tables[className][oidx] = (timestamps, [], [])
-
- (unused, oldConf, oldInst) = self.tables[className][oidx]
-
- # For config updates, simply replace old config list with the new one.
- if context == 0: #config
- self.tables[className][oidx] = (timestamps, list, oldInst)
-
- # For instrumentation updates, carry the minimum and maximum values for
- # "hi-lo" stats forward.
- elif context == 1: #inst
- if len (oldInst) == 0:
- newInst = list
- else:
- newInst = []
- for idx in range (len (list)):
- (key, value) = list[idx]
- if key.find ("High") == len (key) - 4:
- if oldInst[idx][1] > value:
- value = oldInst[idx][1]
- if key.find ("Low") == len (key) - 3:
- if oldInst[idx][1] < value:
- value = oldInst[idx][1]
- newInst.append ((key, value))
- self.tables[className][oidx] = (timestamps, oldConf, newInst)
-
- finally:
- self.lock.release ()
-
- def ctrlHandler (self, context, op, data):
- if op == self.mclient.CTRL_BROKER_INFO:
- pass
- elif op == self.mclient.CTRL_HEARTBEAT:
- pass
-
- def configHandler (self, context, className, list, timestamps):
- self.dataHandler (0, className, list, timestamps);
-
- def instHandler (self, context, className, list, timestamps):
- self.dataHandler (1, className, list, timestamps);
-
- def methodReply (self, broker, sequence, status, sText, args):
- """ Callback for method-reply messages """
- self.lock.acquire ()
- try:
- line = "Call Result: " + self.methodsPending[sequence] + \
- " " + str (status) + " (" + sText + ")"
- print line, args
- del self.methodsPending[sequence]
- finally:
- self.lock.release ()
-
- def closeHandler (self, context, reason):
- if self.operational:
- print "Connection to broker lost:", reason
- self.operational = False
- if self.cli != None:
- self.cli.setPromptMessage ("Broker Disconnected")
-
- def schemaHandler (self, context, classKey, configs, insts, methods, events):
- """ Callback for schema updates """
- if classKey not in self.schema:
- schemaRev = 0
- for key in self.schema:
- if classKey[0] == key[0] and classKey[1] == key[1]:
- schemaRev += 1
- self.schema[classKey] = (configs, insts, methods, events, schemaRev)
-
- def setCli (self, cliobj):
- self.cli = cliobj
-
- def __init__ (self, disp, host, username="guest", password="guest"):
- self.lock = Lock ()
- self.tables = {}
- self.schema = {}
- self.bootSequence = 0
- self.operational = False
- self.disp = disp
- self.cli = None
- self.lastUnit = None
- self.methodSeq = 1
- self.methodsPending = {}
- self.sessionId = "%s.%d" % (platform.uname()[1], os.getpid())
-
- self.broker = Broker (host)
- sock = connect (self.broker.host, self.broker.port)
- oldTimeout = sock.gettimeout()
- sock.settimeout(10)
- self.conn = Connection (sock,
- username=self.broker.username, password=self.broker.password)
- def aborted():
- raise Timeout("Waiting for connection to be established with broker")
- oldAborted = self.conn.aborted
- self.conn.aborted = aborted
-
- self.conn.start ()
-
- sock.settimeout(oldTimeout)
- self.conn.aborted = oldAborted
-
- self.mclient = managementClient ("unused", self.ctrlHandler, self.configHandler,
- self.instHandler, self.methodReply, self.closeHandler)
- self.mclient.schemaListener (self.schemaHandler)
- self.mch = self.mclient.addChannel (self.conn.session(self.sessionId))
- self.operational = True
- self.idMap = {}
- self.idBackMap = {}
- self.nextId = 101
-
- def close (self):
- pass
-
- def refName (self, oid):
- if oid == None:
- return "NULL"
- return str (self.displayObjId (oid.index()))
-
- def valueDisplay (self, classKey, key, value):
- if value == None:
- return "<NULL>"
- for kind in range (2):
- schema = self.schema[classKey][kind]
- for item in schema:
- if item[0] == key:
- typecode = item[1]
- unit = item[2]
- if (typecode >= 1 and typecode <= 5) or typecode == 12 or typecode == 13 or \
- (typecode >= 16 and typecode <= 19):
- if unit == None or unit == self.lastUnit:
- return str (value)
- else:
- self.lastUnit = unit
- suffix = ""
- if value != 1:
- suffix = "s"
- return str (value) + " " + unit + suffix
- elif typecode == 6 or typecode == 7: # strings
- return value
- elif typecode == 8:
- if value == 0:
- return "--"
- return self.disp.timestamp (value)
- elif typecode == 9:
- return str (value)
- elif typecode == 10:
- return self.refName (value)
- elif typecode == 11:
- if value == 0:
- return "False"
- else:
- return "True"
- elif typecode == 14:
- return str (value)
- elif typecode == 15:
- return str (value)
- return "*type-error*"
-
- def getObjIndex (self, classKey, config):
- """ Concatenate the values from index columns to form a unique object name """
- result = ""
- schemaConfig = self.schema[classKey][0]
- for item in schemaConfig:
- if item[5] == 1 and item[0] != "id":
- if result != "":
- result = result + "."
- for key,val in config:
- if key == item[0]:
- result = result + self.valueDisplay (classKey, key, val)
- return result
-
- def getClassKey (self, className):
- delimPos = className.find(":")
- if delimPos == -1:
- schemaRev = 0
- delim = className.find(".")
- if delim != -1:
- schemaRev = int(className[delim + 1:])
- name = className[0:delim]
- else:
- name = className
- for key in self.schema:
- if key[1] == name and self.schema[key][4] == schemaRev:
- return key
- else:
- package = className[0:delimPos]
- name = className[delimPos + 1:]
- schemaRev = 0
- delim = name.find(".")
- if delim != -1:
- schemaRev = int(name[delim + 1:])
- name = name[0:delim]
- for key in self.schema:
- if key[0] == package and key[1] == name:
- if self.schema[key][4] == schemaRev:
- return key
- return None
-
- def classCompletions (self, prefix):
- """ Provide a list of candidate class names for command completion """
- self.lock.acquire ()
- complist = []
- try:
- for name in self.tables:
- if name.find (prefix) == 0:
- complist.append (name)
- finally:
- self.lock.release ()
- return complist
-
- def typeName (self, typecode):
- """ Convert type-codes to printable strings """
- if typecode == 1:
- return "uint8"
- elif typecode == 2:
- return "uint16"
- elif typecode == 3:
- return "uint32"
- elif typecode == 4:
- return "uint64"
- elif typecode == 5:
- return "bool"
- elif typecode == 6:
- return "short-string"
- elif typecode == 7:
- return "long-string"
- elif typecode == 8:
- return "abs-time"
- elif typecode == 9:
- return "delta-time"
- elif typecode == 10:
- return "reference"
- elif typecode == 11:
- return "boolean"
- elif typecode == 12:
- return "float"
- elif typecode == 13:
- return "double"
- elif typecode == 14:
- return "uuid"
- elif typecode == 15:
- return "field-table"
- elif typecode == 16:
- return "int8"
- elif typecode == 17:
- return "int16"
- elif typecode == 18:
- return "int32"
- elif typecode == 19:
- return "int64"
- elif typecode == 20:
- return "object"
- elif typecode == 21:
- return "list"
- elif typecode == 22:
- return "array"
- else:
- raise ValueError ("Invalid type code: %d" % typecode)
-
- def accessName (self, code):
- """ Convert element access codes to printable strings """
- if code == 1:
- return "ReadCreate"
- elif code == 2:
- return "ReadWrite"
- elif code == 3:
- return "ReadOnly"
- else:
- raise ValueError ("Invalid access code: %d" %code)
-
- def notNone (self, text):
- if text == None:
- return ""
- else:
- return text
-
- def isOid (self, id):
- for char in str (id):
- if not char.isdigit () and not char == '-':
- return False
- return True
-
- def listOfIds (self, classKey, tokens):
- """ Generate a tuple of object ids for a classname based on command tokens. """
- list = []
- if len(tokens) == 0 or tokens[0] == "all":
- for id in self.tables[classKey]:
- list.append (self.displayObjId (id))
-
- elif tokens[0] == "active":
- for id in self.tables[classKey]:
- if self.tables[classKey][id][0][2] == 0:
- list.append (self.displayObjId (id))
-
- else:
- for token in tokens:
- if self.isOid (token):
- if token.find ("-") != -1:
- ids = token.split("-", 2)
- for id in range (int (ids[0]), int (ids[1]) + 1):
- if self.getClassForId (self.rawObjId (long (id))) == classKey:
- list.append (id)
- else:
- list.append (int(token))
-
- list.sort ()
- result = ()
- for item in list:
- result = result + (item,)
- return result
-
- def listClasses (self):
- """ Generate a display of the list of classes """
- self.lock.acquire ()
- try:
- rows = []
- sorted = self.tables.keys ()
- sorted.sort ()
- for name in sorted:
- active = 0
- deleted = 0
- for record in self.tables[name]:
- isdel = False
- ts = self.tables[name][record][0]
- if ts[2] > 0:
- isdel = True
- if isdel:
- deleted = deleted + 1
- else:
- active = active + 1
- rows.append ((self.displayClassName (name), active, deleted))
- if len (rows) != 0:
- self.disp.table ("Management Object Types:",
- ("ObjectType", "Active", "Deleted"), rows)
- else:
- print "Waiting for next periodic update"
- finally:
- self.lock.release ()
-
- def listObjects (self, tokens):
- """ Generate a display of a list of objects in a class """
- if len(tokens) == 0:
- print "Error - No class name provided"
- return
-
- self.lock.acquire ()
- try:
- classKey = self.getClassKey (tokens[0])
- if classKey == None:
- print ("Object type %s not known" % tokens[0])
- else:
- rows = []
- if classKey in self.tables:
- ids = self.listOfIds(classKey, tokens[1:])
- for objId in ids:
- (ts, config, inst) = self.tables[classKey][self.rawObjId(objId).index()]
- createTime = self.disp.timestamp (ts[1])
- destroyTime = "-"
- if ts[2] > 0:
- destroyTime = self.disp.timestamp (ts[2])
- objIndex = self.getObjIndex (classKey, config)
- row = (objId, createTime, destroyTime, objIndex)
- rows.append (row)
- self.disp.table ("Objects of type %s" % self.displayClassName(classKey),
- ("ID", "Created", "Destroyed", "Index"),
- rows)
- finally:
- self.lock.release ()
-
- def showObjects (self, tokens):
- """ Generate a display of object data for a particular class """
- self.lock.acquire ()
- try:
- self.lastUnit = None
- if self.isOid (tokens[0]):
- if tokens[0].find ("-") != -1:
- rootId = int (tokens[0][0:tokens[0].find ("-")])
- else:
- rootId = int (tokens[0])
-
- classKey = self.getClassForId (self.rawObjId (rootId))
- remaining = tokens
- if classKey == None:
- print "Id not known: %d" % int (tokens[0])
- raise ValueError ()
- else:
- classKey = self.getClassKey (tokens[0])
- remaining = tokens[1:]
- if classKey not in self.tables:
- print "Class not known: %s" % tokens[0]
- raise ValueError ()
-
- userIds = self.listOfIds (classKey, remaining)
- if len (userIds) == 0:
- print "No object IDs supplied"
- raise ValueError ()
-
- ids = []
- for id in userIds:
- if self.getClassForId (self.rawObjId (long (id))) == classKey:
- ids.append (self.rawObjId (long (id)))
-
- rows = []
- timestamp = None
- config = self.tables[classKey][ids[0].index()][1]
- for eIdx in range (len (config)):
- key = config[eIdx][0]
- if key != "id":
- row = ("property", key)
- for id in ids:
- if timestamp == None or \
- timestamp < self.tables[classKey][id.index()][0][0]:
- timestamp = self.tables[classKey][id.index()][0][0]
- (key, value) = self.tables[classKey][id.index()][1][eIdx]
- row = row + (self.valueDisplay (classKey, key, value),)
- rows.append (row)
-
- inst = self.tables[classKey][ids[0].index()][2]
- for eIdx in range (len (inst)):
- key = inst[eIdx][0]
- if key != "id":
- row = ("statistic", key)
- for id in ids:
- (key, value) = self.tables[classKey][id.index()][2][eIdx]
- row = row + (self.valueDisplay (classKey, key, value),)
- rows.append (row)
-
- titleRow = ("Type", "Element")
- for id in ids:
- titleRow = titleRow + (self.refName(id),)
- caption = "Object of type %s:" % self.displayClassName(classKey)
- if timestamp != None:
- caption = caption + " (last sample time: " + self.disp.timestamp (timestamp) + ")"
- self.disp.table (caption, titleRow, rows)
-
- except:
- pass
- self.lock.release ()
-
- def schemaSummary (self):
- """ Generate a display of the list of classes in the schema """
- self.lock.acquire ()
- try:
- rows = []
- sorted = self.schema.keys ()
- sorted.sort ()
- for classKey in sorted:
- tuple = self.schema[classKey]
- row = (self.displayClassName(classKey), len (tuple[0]), len (tuple[1]),
- len (tuple[2]))
- rows.append (row)
- self.disp.table ("Classes in Schema:",
- ("Class", "Properties", "Statistics", "Methods"),
- rows)
- finally:
- self.lock.release ()
-
- def schemaTable (self, className):
- """ Generate a display of details of the schema of a particular class """
- self.lock.acquire ()
- try:
- classKey = self.getClassKey (className)
- if classKey == None:
- print ("Class name %s not known" % className)
- raise ValueError ()
-
- rows = []
- schemaRev = self.schema[classKey][4]
- for config in self.schema[classKey][0]:
- name = config[0]
- if name != "id":
- typename = self.typeName(config[1])
- unit = self.notNone (config[2])
- desc = self.notNone (config[3])
- access = self.accessName (config[4])
- extra = ""
- if config[5] == 1:
- extra += "index "
- if config[6] != None:
- extra += "Min: " + str(config[6]) + " "
- if config[7] != None:
- extra += "Max: " + str(config[7]) + " "
- if config[8] != None:
- extra += "MaxLen: " + str(config[8]) + " "
- if config[9] == 1:
- extra += "optional "
- rows.append ((name, typename, unit, access, extra, desc))
-
- for config in self.schema[classKey][1]:
- name = config[0]
- if name != "id":
- typename = self.typeName(config[1])
- unit = self.notNone (config[2])
- desc = self.notNone (config[3])
- rows.append ((name, typename, unit, "", "", desc))
-
- titles = ("Element", "Type", "Unit", "Access", "Notes", "Description")
- self.disp.table ("Schema for class '%s':" % self.displayClassName(classKey), titles, rows)
-
- for mname in self.schema[classKey][2]:
- (mdesc, args) = self.schema[classKey][2][mname]
- caption = "\nMethod '%s' %s" % (mname, self.notNone (mdesc))
- rows = []
- for arg in args:
- name = arg[0]
- typename = self.typeName (arg[1])
- dir = arg[2]
- unit = self.notNone (arg[3])
- desc = self.notNone (arg[4])
- extra = ""
- if arg[5] != None:
- extra = extra + "Min: " + str (arg[5])
- if arg[6] != None:
- extra = extra + "Max: " + str (arg[6])
- if arg[7] != None:
- extra = extra + "MaxLen: " + str (arg[7])
- if arg[8] != None:
- extra = extra + "Default: " + str (arg[8])
- rows.append ((name, typename, dir, unit, extra, desc))
- titles = ("Argument", "Type", "Direction", "Unit", "Notes", "Description")
- self.disp.table (caption, titles, rows)
-
- except Exception,e:
- pass
- self.lock.release ()
-
- def getClassForId (self, objId):
- """ Given an object ID, return the class key for the referenced object """
- for classKey in self.tables:
- if objId.index() in self.tables[classKey]:
- return classKey
- return None
-
- def callMethod (self, userOid, methodName, args):
- self.lock.acquire ()
- methodOk = True
- try:
- classKey = self.getClassForId (self.rawObjId (userOid))
- if classKey == None:
- raise ValueError ()
-
- if methodName not in self.schema[classKey][2]:
- print "Method '%s' not valid for class '%s'" % (methodName, self.displayClassName(classKey))
- raise ValueError ()
-
- schemaMethod = self.schema[classKey][2][methodName]
- count = 0
- for arg in range(len(schemaMethod[1])):
- if schemaMethod[1][arg][2].find("I") != -1:
- count += 1
- if len (args) != count:
- print "Wrong number of method args: Need %d, Got %d" % (count, len (args))
- raise ValueError ()
-
- namedArgs = {}
- idx = 0
- for arg in range(len(schemaMethod[1])):
- if schemaMethod[1][arg][2].find("I") != -1:
- namedArgs[schemaMethod[1][arg][0]] = args[idx]
- idx += 1
-
- self.methodSeq = self.methodSeq + 1
- self.methodsPending[self.methodSeq] = methodName
- except Exception, e:
- methodOk = False
- self.lock.release ()
- if methodOk:
-# try:
- self.mclient.callMethod (self.mch, self.methodSeq, self.rawObjId (userOid), classKey,
- methodName, namedArgs)
-# except ValueError, e:
-# print "Error invoking method:", e
-
- def makeIdRow (self, displayId):
- if displayId in self.idMap:
- objId = self.idMap[displayId]
- else:
- return None
- if objId.getFlags() == 0:
- flags = ""
- else:
- flags = str(objId.getFlags())
- seq = objId.getSequence()
- if seq == 0:
- seqText = "<durable>"
- else:
- seqText = str(seq)
- return (displayId, flags, seqText, objId.getBroker(), objId.getBank(), hex(objId.getObject()))
-
- def listIds (self, select):
- rows = []
- if select == 0:
- sorted = self.idMap.keys()
- sorted.sort()
- for displayId in sorted:
- row = self.makeIdRow (displayId)
- rows.append(row)
- else:
- row = self.makeIdRow (select)
- if row == None:
- print "Display Id %d not known" % select
- return
- rows.append(row)
- self.disp.table("Translation of Display IDs:",
- ("DisplayID", "Flags", "BootSequence", "Broker", "Bank", "Object"),
- rows)
-
- def do_list (self, data):
- tokens = data.split ()
- if len (tokens) == 0:
- self.listClasses ()
- else:
- self.listObjects (tokens)
-
- def do_show (self, data):
- tokens = data.split ()
- self.showObjects (tokens)
-
- def do_schema (self, data):
- if data == "":
- self.schemaSummary ()
- else:
- self.schemaTable (data)
-
- def do_call (self, data):
- encTokens = data.split ()
- try:
- tokens = [a.decode(locale.getpreferredencoding()) for a in encArgs]
- except:
- tokens = encTokens
- if len (tokens) < 2:
- print "Not enough arguments supplied"
- return
-
- displayId = long (tokens[0])
- methodName = tokens[1]
- args = tokens[2:]
- self.callMethod (displayId, methodName, args)
-
- def do_id (self, data):
- if data == "":
- select = 0
- else:
- select = int(data)
- self.listIds(select)
-
- def do_exit (self):
- self.mclient.removeChannel (self.mch)
diff --git a/qpid/python/qpid/message.py b/qpid/python/qpid/message.py
deleted file mode 100644
index 4d31da2846..0000000000
--- a/qpid/python/qpid/message.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#
-# 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.
-#
-from connection08 import Method, Request
-
-class Message:
-
- def __init__(self, channel, frame, content = None):
- self.channel = channel
- self.frame = frame
- self.method = frame.method_type
- self.content = content
- if self.method.is_l4_command():
- self.command_id = self.channel.incoming_completion.sequence.next()
- #print "allocated: ", self.command_id, "to ", self.method.klass.name, "_", self.method.name
-
- def __len__(self):
- return len(self.frame.args)
-
- def _idx(self, idx):
- if idx < 0: idx += len(self)
- if idx < 0 or idx > len(self):
- raise IndexError(idx)
- return idx
-
- def __getitem__(self, idx):
- return self.frame.args[idx]
-
- def __getattr__(self, attr):
- fields = self.method.fields.byname
- if fields.has_key(attr):
- f = fields[attr]
- result = self[self.method.fields.index(f)]
- else:
- for r in self.method.responses:
- if attr == r.name:
- def respond(*args, **kwargs):
- batch=0
- if kwargs.has_key("batchoffset"):
- batch=kwargs.pop("batchoffset")
- self.channel.respond(Method(r, r.arguments(*args, **kwargs)), batch, self.frame)
- result = respond
- break
- else:
- raise AttributeError(attr)
- return result
-
- STR = "%s %s content = %s"
- REPR = STR.replace("%s", "%r")
-
- def __str__(self):
- return Message.STR % (self.method, self.frame.args, self.content)
-
- def __repr__(self):
- return Message.REPR % (self.method, self.frame.args, self.content)
-
- def complete(self, cumulative=True):
- self.channel.incoming_completion.complete(mark=self.command_id, cumulative=cumulative)
diff --git a/qpid/python/qpid/messaging/__init__.py b/qpid/python/qpid/messaging/__init__.py
deleted file mode 100644
index f9ddda2e80..0000000000
--- a/qpid/python/qpid/messaging/__init__.py
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# 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.
-#
-
-"""
-A candidate high level messaging API for python.
-
-Areas that still need work:
-
- - definition of the arguments for L{Session.sender} and L{Session.receiver}
- - standard L{Message} properties
- - L{Message} content encoding
- - protocol negotiation/multiprotocol impl
-"""
-
-from qpid.datatypes import timestamp, uuid4, Serial
-from qpid.messaging.constants import *
-from qpid.messaging.endpoints import *
-from qpid.messaging.exceptions import *
-from qpid.messaging.message import *
diff --git a/qpid/python/qpid/messaging/address.py b/qpid/python/qpid/messaging/address.py
deleted file mode 100644
index e423f09193..0000000000
--- a/qpid/python/qpid/messaging/address.py
+++ /dev/null
@@ -1,172 +0,0 @@
-#
-# 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 re
-from qpid.lexer import Lexicon, LexError
-from qpid.parser import Parser, ParseError
-
-l = Lexicon()
-
-LBRACE = l.define("LBRACE", r"\{")
-RBRACE = l.define("RBRACE", r"\}")
-LBRACK = l.define("LBRACK", r"\[")
-RBRACK = l.define("RBRACK", r"\]")
-COLON = l.define("COLON", r":")
-SEMI = l.define("SEMI", r";")
-SLASH = l.define("SLASH", r"/")
-COMMA = l.define("COMMA", r",")
-NUMBER = l.define("NUMBER", r'[+-]?[0-9]*\.?[0-9]+')
-ID = l.define("ID", r'[a-zA-Z_](?:[a-zA-Z0-9_-]*[a-zA-Z0-9_])?')
-STRING = l.define("STRING", r""""(?:[^\\"]|\\.)*"|'(?:[^\\']|\\.)*'""")
-ESC = l.define("ESC", r"\\[^ux]|\\x[0-9a-fA-F][0-9a-fA-F]|\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]")
-SYM = l.define("SYM", r"[.#*%@$^!+-]")
-WSPACE = l.define("WSPACE", r"[ \n\r\t]+")
-EOF = l.eof("EOF")
-
-LEXER = l.compile()
-
-def lex(st):
- return LEXER.lex(st)
-
-def tok2str(tok):
- if tok.type is STRING:
- return eval(tok.value)
- elif tok.type is ESC:
- if tok.value[1] == "x":
- return eval('"%s"' % tok.value)
- elif tok.value[1] == "u":
- return eval('u"%s"' % tok.value)
- else:
- return tok.value[1]
- else:
- return tok.value
-
-CONSTANTS = {
- "True": True,
- "true": True,
- "False": False,
- "false": False,
- "None": None
- }
-
-def tok2obj(tok):
- if tok.type == ID:
- return CONSTANTS.get(tok.value, tok.value)
- elif tok.type in (STRING, NUMBER):
- return eval(tok.value)
- else:
- return tok.value
-
-def toks2str(toks):
- if toks:
- return "".join(map(tok2str, toks))
- else:
- return None
-
-class AddressParser(Parser):
-
- def __init__(self, tokens):
- Parser.__init__(self, [t for t in tokens if t.type is not WSPACE])
-
- def parse(self):
- result = self.address()
- self.eat(EOF)
- return result
-
- def address(self):
- name = toks2str(self.eat_until(SLASH, SEMI, EOF))
-
- if name is None:
- raise ParseError(self.next())
-
- if self.matches(SLASH):
- self.eat(SLASH)
- subject = toks2str(self.eat_until(SEMI, EOF))
- else:
- subject = None
-
- if self.matches(SEMI):
- self.eat(SEMI)
- options = self.map()
- else:
- options = None
- return name, subject, options
-
- def map(self):
- self.eat(LBRACE)
-
- result = {}
- while True:
- if self.matches(NUMBER, STRING, ID, LBRACE, LBRACK):
- n, v = self.keyval()
- result[n] = v
- if self.matches(COMMA):
- self.eat(COMMA)
- elif self.matches(RBRACE):
- break
- else:
- raise ParseError(self.next(), COMMA, RBRACE)
- elif self.matches(RBRACE):
- break
- else:
- raise ParseError(self.next(), NUMBER, STRING, ID, LBRACE, LBRACK,
- RBRACE)
-
- self.eat(RBRACE)
- return result
-
- def keyval(self):
- key = self.value()
- self.eat(COLON)
- val = self.value()
- return (key, val)
-
- def value(self):
- if self.matches(NUMBER, STRING, ID):
- return tok2obj(self.eat())
- elif self.matches(LBRACE):
- return self.map()
- elif self.matches(LBRACK):
- return self.list()
- else:
- raise ParseError(self.next(), NUMBER, STRING, ID, LBRACE, LBRACK)
-
- def list(self):
- self.eat(LBRACK)
-
- result = []
-
- while True:
- if self.matches(RBRACK):
- break
- else:
- result.append(self.value())
- if self.matches(COMMA):
- self.eat(COMMA)
- elif self.matches(RBRACK):
- break
- else:
- raise ParseError(self.next(), COMMA, RBRACK)
-
- self.eat(RBRACK)
- return result
-
-def parse(addr):
- return AddressParser(lex(addr)).parse()
-
-__all__ = ["parse", "ParseError"]
diff --git a/qpid/python/qpid/messaging/constants.py b/qpid/python/qpid/messaging/constants.py
deleted file mode 100644
index f230c4def8..0000000000
--- a/qpid/python/qpid/messaging/constants.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# 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.
-#
-
-__SELF__ = object()
-
-class Constant:
-
- def __init__(self, name, value=__SELF__):
- self.name = name
- if value is __SELF__:
- self.value = self
- else:
- self.value = value
-
- def __repr__(self):
- return self.name
-
-AMQP_PORT = 5672
-AMQPS_PORT = 5671
-
-UNLIMITED = Constant("UNLIMITED", 0xFFFFFFFFL)
-
-REJECTED = Constant("REJECTED")
-RELEASED = Constant("RELEASED")
diff --git a/qpid/python/qpid/messaging/driver.py b/qpid/python/qpid/messaging/driver.py
deleted file mode 100644
index 146b8188ab..0000000000
--- a/qpid/python/qpid/messaging/driver.py
+++ /dev/null
@@ -1,1451 +0,0 @@
-#
-# 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 socket, struct, sys, time
-from logging import getLogger, DEBUG
-from qpid import compat
-from qpid import sasl
-from qpid.concurrency import synchronized
-from qpid.datatypes import RangedSet, Serial
-from qpid.framing import OpEncoder, SegmentEncoder, FrameEncoder, \
- FrameDecoder, SegmentDecoder, OpDecoder
-from qpid.messaging import address, transports
-from qpid.messaging.constants import UNLIMITED, REJECTED, RELEASED
-from qpid.messaging.exceptions import *
-from qpid.messaging.message import get_codec, Disposition, Message
-from qpid.messaging.endpoints import MangledString
-from qpid.ops import *
-from qpid.selector import Selector
-from qpid.util import URL, default,get_client_properties_with_defaults
-from qpid.validator import And, Context, List, Map, Types, Values
-from threading import Condition, Thread
-
-log = getLogger("qpid.messaging")
-rawlog = getLogger("qpid.messaging.io.raw")
-opslog = getLogger("qpid.messaging.io.ops")
-
-def addr2reply_to(addr):
- name, subject, options = address.parse(addr)
- if options:
- type = options.get("node", {}).get("type")
- else:
- type = None
-
- if type == "topic":
- return ReplyTo(name, subject)
- else:
- return ReplyTo(None, name)
-
-def reply_to2addr(reply_to):
- if reply_to.exchange in (None, ""):
- return reply_to.routing_key
- elif reply_to.routing_key is None:
- return "%s; {node: {type: topic}}" % reply_to.exchange
- else:
- return "%s/%s; {node: {type: topic}}" % (reply_to.exchange, reply_to.routing_key)
-
-class Attachment:
-
- def __init__(self, target):
- self.target = target
-
-# XXX
-
-DURABLE_DEFAULT=False
-
-# XXX
-
-class Pattern:
- """
- The pattern filter matches the supplied wildcard pattern against a
- message subject.
- """
-
- def __init__(self, value):
- self.value = value
-
- # XXX: this should become part of the driver
- def _bind(self, sst, exchange, queue):
- from qpid.ops import ExchangeBind
-
- sst.write_cmd(ExchangeBind(exchange=exchange, queue=queue,
- binding_key=self.value.replace("*", "#")))
-
-SUBJECT_DEFAULTS = {
- "topic": "#"
- }
-
-def noop(): pass
-def sync_noop(): pass
-
-class SessionState:
-
- def __init__(self, driver, session, name, channel):
- self.driver = driver
- self.session = session
- self.name = name
- self.channel = channel
- self.detached = False
- self.committing = False
- self.aborting = False
-
- # sender state
- self.sent = Serial(0)
- self.acknowledged = RangedSet()
- self.actions = {}
- self.min_completion = self.sent
- self.max_completion = self.sent
- self.results = {}
- self.need_sync = False
-
- # receiver state
- self.received = None
- self.executed = RangedSet()
-
- # XXX: need to periodically exchange completion/known_completion
-
- self.destinations = {}
-
- def write_query(self, query, handler, obj):
- id = self.sent
- self.write_cmd(query, lambda: handler(self.results.pop(id), obj))
-
- def apply_overrides(self, cmd, overrides):
- for k, v in overrides.items():
- cmd[k.replace('-', '_')] = v
-
- def write_cmd(self, cmd, action=noop, overrides=None, sync=True):
- if overrides:
- self.apply_overrides(cmd, overrides)
-
- if action != noop:
- cmd.sync = sync
- if self.detached:
- raise Exception("detached")
- cmd.id = self.sent
- self.sent += 1
- self.actions[cmd.id] = action
- self.max_completion = cmd.id
- self.write_op(cmd)
- self.need_sync = not cmd.sync
-
- def write_cmds(self, cmds, action=noop):
- if cmds:
- for cmd in cmds[:-1]:
- self.write_cmd(cmd)
- self.write_cmd(cmds[-1], action)
- else:
- action()
-
- def write_op(self, op):
- op.channel = self.channel
- self.driver.write_op(op)
-
-POLICIES = Values("always", "sender", "receiver", "never")
-RELIABILITY = Values("unreliable", "at-most-once", "at-least-once",
- "exactly-once")
-
-DECLARE = Map({}, restricted=False)
-BINDINGS = List(Map({
- "exchange": Types(basestring),
- "queue": Types(basestring),
- "key": Types(basestring),
- "arguments": Map({}, restricted=False)
- }))
-
-COMMON_OPTS = {
- "create": POLICIES,
- "delete": POLICIES,
- "assert": POLICIES,
- "node": Map({
- "type": Values("queue", "topic"),
- "durable": Types(bool),
- "x-declare": DECLARE,
- "x-bindings": BINDINGS
- }),
- "link": Map({
- "name": Types(basestring),
- "durable": Types(bool),
- "reliability": RELIABILITY,
- "x-declare": DECLARE,
- "x-bindings": BINDINGS,
- "x-subscribe": Map({}, restricted=False)
- })
- }
-
-RECEIVE_MODES = Values("browse", "consume")
-
-SOURCE_OPTS = COMMON_OPTS.copy()
-SOURCE_OPTS.update({
- "mode": RECEIVE_MODES
- })
-
-TARGET_OPTS = COMMON_OPTS.copy()
-
-class LinkIn:
-
- ADDR_NAME = "source"
- DIR_NAME = "receiver"
- VALIDATOR = Map(SOURCE_OPTS)
-
- def init_link(self, sst, rcv, _rcv):
- _rcv.destination = str(rcv.id)
- sst.destinations[_rcv.destination] = _rcv
- _rcv.draining = False
- _rcv.bytes_open = False
- _rcv.on_unlink = []
-
- def do_link(self, sst, rcv, _rcv, type, subtype, action):
- link_opts = _rcv.options.get("link", {})
- if type == "topic":
- default_reliability = "unreliable"
- else:
- default_reliability = "at-least-once"
- reliability = link_opts.get("reliability", default_reliability)
- declare = link_opts.get("x-declare", {})
- subscribe = link_opts.get("x-subscribe", {})
- acq_mode = acquire_mode.pre_acquired
- if reliability in ("unreliable", "at-most-once"):
- rcv._accept_mode = accept_mode.none
- else:
- rcv._accept_mode = accept_mode.explicit
-
- if type == "topic":
- default_name = "%s.%s" % (rcv.session.name, _rcv.destination)
- _rcv._queue = link_opts.get("name", default_name)
- sst.write_cmd(QueueDeclare(queue=_rcv._queue,
- durable=link_opts.get("durable", False),
- exclusive=True,
- auto_delete=(reliability == "unreliable")),
- overrides=declare)
- if declare.get("exclusive", True): _rcv.on_unlink = [QueueDelete(_rcv._queue)]
- subject = _rcv.subject or SUBJECT_DEFAULTS.get(subtype)
- bindings = get_bindings(link_opts, _rcv._queue, _rcv.name, subject)
- if not bindings:
- sst.write_cmd(ExchangeBind(_rcv._queue, _rcv.name, subject))
-
- elif type == "queue":
- _rcv._queue = _rcv.name
- if _rcv.options.get("mode", "consume") == "browse":
- acq_mode = acquire_mode.not_acquired
- bindings = get_bindings(link_opts, queue=_rcv._queue)
-
-
- sst.write_cmds(bindings)
- sst.write_cmd(MessageSubscribe(queue=_rcv._queue,
- destination=_rcv.destination,
- acquire_mode = acq_mode,
- accept_mode = rcv._accept_mode),
- overrides=subscribe)
- sst.write_cmd(MessageSetFlowMode(_rcv.destination, flow_mode.credit), action)
-
- def do_unlink(self, sst, rcv, _rcv, action=noop):
- link_opts = _rcv.options.get("link", {})
- reliability = link_opts.get("reliability")
- cmds = [MessageCancel(_rcv.destination)]
- cmds.extend(_rcv.on_unlink)
- msgs = [] #release back messages for the closing receiver
- msg = rcv.session._pop(rcv)
- while msg is not None:
- msgs.append(msg)
- msg = rcv.session._pop(rcv)
- if len(msgs) > 0:
- ids = RangedSet(*[m._transfer_id for m in msgs])
- log.debug("releasing back messages: %s, as receiver is closing", ids)
- cmds.append(MessageRelease(ids, True))
- sst.write_cmds(cmds, action)
-
- def del_link(self, sst, rcv, _rcv):
- del sst.destinations[_rcv.destination]
-
-class LinkOut:
-
- ADDR_NAME = "target"
- DIR_NAME = "sender"
- VALIDATOR = Map(TARGET_OPTS)
-
- def init_link(self, sst, snd, _snd):
- _snd.closing = False
- _snd.pre_ack = False
-
- def do_link(self, sst, snd, _snd, type, subtype, action):
- link_opts = _snd.options.get("link", {})
- reliability = link_opts.get("reliability", "at-least-once")
- _snd.pre_ack = reliability in ("unreliable", "at-most-once")
- if type == "topic":
- _snd._exchange = _snd.name
- _snd._routing_key = _snd.subject
- bindings = get_bindings(link_opts, exchange=_snd.name, key=_snd.subject)
- elif type == "queue":
- _snd._exchange = ""
- _snd._routing_key = _snd.name
- bindings = get_bindings(link_opts, queue=_snd.name)
- sst.write_cmds(bindings, action)
-
- def do_unlink(self, sst, snd, _snd, action=noop):
- action()
-
- def del_link(self, sst, snd, _snd):
- pass
-
-class Cache:
-
- def __init__(self, ttl):
- self.ttl = ttl
- self.entries = {}
-
- def __setitem__(self, key, value):
- self.entries[key] = time.time(), value
-
- def __getitem__(self, key):
- tstamp, value = self.entries[key]
- if time.time() - tstamp >= self.ttl:
- del self.entries[key]
- raise KeyError(key)
- else:
- return value
-
- def __delitem__(self, key):
- del self.entries[key]
-
-# XXX
-HEADER="!4s4B"
-
-EMPTY_DP = DeliveryProperties()
-EMPTY_MP = MessageProperties()
-
-SUBJECT = "qpid.subject"
-
-CLOSED = "CLOSED"
-READ_ONLY = "READ_ONLY"
-WRITE_ONLY = "WRITE_ONLY"
-OPEN = "OPEN"
-
-class Driver:
-
- def __init__(self, connection):
- self.connection = connection
- self.log_id = "%x" % id(self.connection)
- self._lock = self.connection._lock
-
- self._selector = Selector.default()
- self._attempts = 0
- self._delay = self.connection.reconnect_interval_min
- self._reconnect_log = self.connection.reconnect_log
- self._host = 0
- self._retrying = False
- self._next_retry = None
- self._transport = None
-
- self._timeout = None
-
- self.engine = None
-
- def _next_host(self):
- urls = [URL(u) for u in self.connection.reconnect_urls]
- hosts = [(self.connection.host, default(self.connection.port, 5672))] + \
- [(u.host, default(u.port, 5672)) for u in urls]
- if self._host >= len(hosts):
- self._host = 0
- self._last_host = hosts[self._host]
- if self._host == 0:
- self._attempts += 1
- self._host = self._host + 1
- return self._last_host
-
- def _num_hosts(self):
- return len(self.connection.reconnect_urls) + 1
-
- @synchronized
- def wakeup(self):
- self.dispatch()
- self._selector.wakeup()
-
- def start(self):
- self._selector.register(self)
-
- def stop(self):
- self._selector.unregister(self)
- if self._transport:
- self.st_closed()
-
- def fileno(self):
- return self._transport.fileno()
-
- @synchronized
- def reading(self):
- """Called by the Selector I/O thread to determine if the driver needs to
- wait on the arrival of network data (call self.readable() callback)
- """
- return self._transport is not None and \
- self._transport.reading(True)
-
- @synchronized
- def writing(self):
- """Called by the Selector I/O thread to determine if it should block
- waiting for output bandwidth (call the self.writeable() callback)
- """
- return self._transport is not None and \
- self._transport.writing(self.engine.pending())
-
- @synchronized
- def timing(self):
- """Called by the Selector I/O thread to determine if it should wake up the
- driver (call the timeout() callback
- """
- return self._timeout
-
- @synchronized
- def abort(self, exc, info):
- """Called if the Selector I/O thread hits an unrecoverable error and fails.
- """
- try:
- self.connection.error = exc
- log.error("I/O Thread Fatal error: %s\n%s" % (str(exc), info))
- except:
- pass
-
- def _check_retry_ok(self):
- """We consider a reconnect to have suceeded only when we have received
- open-ok from the peer.
-
- If we declared success as soon as the transport connected, then we could get
- into an infinite heartbeat loop if the remote process is hung and never
- sends us any data. We would fail the connection after 2 missed heartbeats,
- reconnect the transport, declare the reconnect ok, then fail again after 2
- missed heartbeats and so on.
- """
- if self._retrying and self.engine._connected: # Means we have received open-ok.
- if self._reconnect_log:
- log.warn("reconnect succeeded: %s:%s", *self._last_host)
- self._next_retry = None
- self._attempts = 0
- self._delay = self.connection.reconnect_interval_min
- self._retrying = False
-
- @synchronized
- def readable(self):
- try:
- data = self._transport.recv(64*1024)
- if data is None:
- return
- elif data:
- rawlog.debug("READ[%s]: %r", self.log_id, data)
- self.engine.write(data)
- self._check_retry_ok()
- else:
- self.close_engine()
- except socket.error, e:
- self.close_engine(ConnectionError(text=str(e)))
-
- self.update_status()
-
- self._notify()
-
- def _notify(self):
- if self.connection.error:
- self.connection._condition.gc()
- self.connection._waiter.notifyAll()
-
- def close_engine(self, e=None):
- if e is None:
- e = ConnectionError(text="connection aborted")
-
- if (self.connection.reconnect and
- (self.connection.reconnect_limit is None or
- self.connection.reconnect_limit <= 0 or
- self._attempts <= self.connection.reconnect_limit)):
- if self._host < self._num_hosts():
- delay = 0
- else:
- delay = self._delay
- self._delay = min(2*self._delay,
- self.connection.reconnect_interval_max)
- self._next_retry = time.time() + delay
- if self._reconnect_log:
- log.warn("recoverable error[attempt %s]: %s" % (self._attempts, e))
- if delay > 0:
- log.warn("sleeping %s seconds" % delay)
- self._retrying = True
- self.engine.close()
- else:
- self.engine.close(e)
-
- self.schedule()
-
- def update_status(self):
- if not self.engine: return False
- status = self.engine.status()
- return getattr(self, "st_%s" % status.lower())()
-
- def st_closed(self):
- # XXX: this log statement seems to sometimes hit when the socket is not connected
- # XXX: rawlog.debug("CLOSE[%s]: %s", self.log_id, self._socket.getpeername())
- if self._transport: self._transport.close()
- self._transport = None
- self.engine = None
- return True
-
- def st_open(self):
- return False
-
- @synchronized
- def writeable(self):
- notify = False
- try:
- n = self._transport.send(self.engine.peek())
- if n == 0: return
- sent = self.engine.read(n)
- rawlog.debug("SENT[%s]: %r", self.log_id, sent)
- except socket.error, e:
- self.close_engine(e)
- notify = True
-
- if self.update_status() or notify:
- self._notify()
-
- @synchronized
- def timeout(self):
- self.dispatch()
- self.update_status()
- self._notify()
- self.schedule()
-
- def schedule(self):
- times = []
- if self.connection.heartbeat:
- times.append(time.time() + self.connection.heartbeat)
- if self._next_retry:
- times.append(self._next_retry)
- if times:
- self._timeout = min(times)
- else:
- self._timeout = None
-
- def dispatch(self):
- try:
- if self._transport is None:
- if self.connection._connected and not self.connection.error:
- self.connect()
- else:
- self.engine.dispatch()
- except HeartbeatTimeout, e:
- self.close_engine(e)
- except ContentError, e:
- msg = compat.format_exc()
- self.connection.error = ContentError(text=msg)
- except:
- # XXX: Does socket get leaked if this occurs?
- msg = compat.format_exc()
- self.connection.error = InternalError(text=msg)
-
- def connect(self):
- if self._retrying and time.time() < self._next_retry:
- return
-
- try:
- # XXX: should make this non blocking
- host, port = self._next_host()
- if self._retrying and self._reconnect_log:
- log.warn("trying: %s:%s", host, port)
- self.engine = Engine(self.connection)
- self.engine.open()
- rawlog.debug("OPEN[%s]: %s:%s", self.log_id, host, port)
- trans = transports.TRANSPORTS.get(self.connection.transport)
- if trans:
- self._transport = trans(self.connection, host, port)
- else:
- raise ConnectError("no such transport: %s" % self.connection.transport)
- self.schedule()
- except socket.error, e:
- self.close_engine(ConnectError(text=str(e)))
-
-DEFAULT_DISPOSITION = Disposition(None)
-
-def get_bindings(opts, queue=None, exchange=None, key=None):
- bindings = opts.get("x-bindings", [])
- cmds = []
- for b in bindings:
- exchange = b.get("exchange", exchange)
- queue = b.get("queue", queue)
- key = b.get("key", key)
- args = b.get("arguments", {})
- cmds.append(ExchangeBind(queue, exchange, key, args))
- return cmds
-
-CONNECTION_ERRS = {
- # anythong not here (i.e. everything right now) will default to
- # connection error
- }
-
-SESSION_ERRS = {
- # anything not here will default to session error
- error_code.unauthorized_access: UnauthorizedAccess,
- error_code.not_found: NotFound,
- error_code.resource_locked: ReceiverError,
- error_code.resource_limit_exceeded: TargetCapacityExceeded,
- error_code.internal_error: ServerError
- }
-
-class Engine:
-
- def __init__(self, connection):
- self.connection = connection
- self.log_id = "%x" % id(self.connection)
- self._closing = False
- self._connected = False
- self._reconnecting = bool(connection.sessions)
- self._attachments = {}
-
- self._in = LinkIn()
- self._out = LinkOut()
-
- self._channel_max = 65536
- self._channels = 0
- self._sessions = {}
-
- self.address_cache = Cache(self.connection.address_ttl)
-
- self._status = CLOSED
- self._buf = ""
- self._hdr = ""
- # Set _last_in and _last_out here so heartbeats will be timed from the
- # beginning of connection if no data is sent/received.
- self._last_in = time.time()
- self._last_out = time.time()
- self._op_enc = OpEncoder()
- self._seg_enc = SegmentEncoder()
- self._frame_enc = FrameEncoder()
- self._frame_dec = FrameDecoder()
- self._seg_dec = SegmentDecoder()
- self._op_dec = OpDecoder()
-
- self._sasl = sasl.Client()
- if self.connection.username:
- self._sasl.setAttr("username", self.connection.username)
- if self.connection.password:
- self._sasl.setAttr("password", self.connection.password)
- if self.connection.host:
- self._sasl.setAttr("host", self.connection.host)
- self._sasl.setAttr("service", self.connection.sasl_service)
- if self.connection.sasl_min_ssf is not None:
- self._sasl.setAttr("minssf", self.connection.sasl_min_ssf)
- if self.connection.sasl_max_ssf is not None:
- self._sasl.setAttr("maxssf", self.connection.sasl_max_ssf)
- self._sasl.init()
- self._sasl_encode = False
- self._sasl_decode = False
-
- def _reset(self):
- self.connection._transport_connected = False
-
- for ssn in self.connection.sessions.values():
- for m in ssn.acked + ssn.unacked + ssn.incoming:
- m._transfer_id = None
- for snd in ssn.senders:
- snd.linked = False
- for rcv in ssn.receivers:
- rcv.impending = rcv.received
- rcv.linked = False
-
- def status(self):
- return self._status
-
- def write(self, data):
- self._last_in = time.time()
- try:
- if self._sasl_decode:
- data = self._sasl.decode(data)
-
- if len(self._hdr) < 8:
- r = 8 - len(self._hdr)
- self._hdr += data[:r]
- data = data[r:]
-
- if len(self._hdr) == 8:
- self.do_header(self._hdr)
-
- self._frame_dec.write(data)
- self._seg_dec.write(*self._frame_dec.read())
- self._op_dec.write(*self._seg_dec.read())
- for op in self._op_dec.read():
- self.assign_id(op)
- opslog.debug("RCVD[%s]: %r", self.log_id, op)
- op.dispatch(self)
- self.dispatch()
- except MessagingError, e:
- self.close(e)
- except:
- self.close(InternalError(text=compat.format_exc()))
-
- def close(self, e=None):
- self._reset()
- # We cannot re-establish transactional sessions, they must be aborted.
- # We could re-do transactional enqueues, but not dequeues.
- for ssn in self.connection.sessions.values():
- if ssn.transactional:
- if ssn.committing:
- ssn.error = TransactionUnknown(text="Transaction outcome unknown due to transport failure")
- else:
- ssn.error = TransactionAborted(text="Transaction aborted due to transport failure")
- ssn.closed = True
- if e:
- self.connection.error = e
- self._status = CLOSED
-
- def assign_id(self, op):
- if isinstance(op, Command):
- sst = self.get_sst(op)
- op.id = sst.received
- sst.received += 1
-
- def pending(self):
- return len(self._buf)
-
- def read(self, n):
- result = self._buf[:n]
- self._buf = self._buf[n:]
- return result
-
- def peek(self):
- return self._buf
-
- def write_op(self, op):
- opslog.debug("SENT[%s]: %r", self.log_id, op)
- self._op_enc.write(op)
- self._seg_enc.write(*self._op_enc.read())
- self._frame_enc.write(*self._seg_enc.read())
- bytes = self._frame_enc.read()
- if self._sasl_encode:
- bytes = self._sasl.encode(bytes)
- self._buf += bytes
- self._last_out = time.time()
-
- def do_header(self, hdr):
- cli_major = 0; cli_minor = 10
- magic, _, _, major, minor = struct.unpack(HEADER, hdr)
- if major != cli_major or minor != cli_minor:
- raise VersionError(text="client: %s-%s, server: %s-%s" %
- (cli_major, cli_minor, major, minor))
-
- def do_connection_start(self, start):
- if self.connection.sasl_mechanisms:
- permitted = self.connection.sasl_mechanisms.split()
- mechs = [m for m in start.mechanisms if m in permitted]
- else:
- mechs = start.mechanisms
- try:
- mech, initial = self._sasl.start(" ".join(mechs))
- except sasl.SASLError, e:
- if "ANONYMOUS" not in mechs and self.connection.username is None:
- _text="Anonymous connections disabled, missing credentials"
- else:
- _text=str(e)
- raise AuthenticationFailure(text=_text)
-
- client_properties = get_client_properties_with_defaults(provided_client_properties=self.connection.client_properties);
- self.write_op(ConnectionStartOk(client_properties=client_properties,
- mechanism=mech, response=initial))
-
- def do_connection_secure(self, secure):
- resp = self._sasl.step(secure.challenge)
- self.write_op(ConnectionSecureOk(response=resp))
-
- def do_connection_tune(self, tune):
- # XXX: is heartbeat protocol specific?
- if tune.channel_max is not None:
- self.channel_max = tune.channel_max
- self.write_op(ConnectionTuneOk(heartbeat=self.connection.heartbeat,
- channel_max=self.channel_max))
- self.write_op(ConnectionOpen())
- self._sasl_encode = True
-
- def do_connection_open_ok(self, open_ok):
- self.connection.auth_username = self._sasl.auth_username()
- self._connected = True
- self._sasl_decode = True
- self.connection._transport_connected = True
-
- def do_connection_heartbeat(self, hrt):
- pass
-
- def do_connection_close(self, close):
- self.write_op(ConnectionCloseOk())
- if close.reply_code != close_code.normal:
- exc = CONNECTION_ERRS.get(close.reply_code, ConnectionError)
- self.connection.error = exc(close.reply_code, close.reply_text)
- # XXX: should we do a half shutdown on the socket here?
- # XXX: we really need to test this, we may end up reporting a
- # connection abort after this, if we were to do a shutdown on read
- # and stop reading, then we wouldn't report the abort, that's
- # probably the right thing to do
-
- def do_connection_close_ok(self, close_ok):
- self.close()
-
- def do_session_attached(self, atc):
- pass
-
- def do_session_command_point(self, cp):
- sst = self.get_sst(cp)
- sst.received = cp.command_id
-
- def do_session_completed(self, sc):
- sst = self.get_sst(sc)
- for r in sc.commands:
- sst.acknowledged.add(r.lower, r.upper)
-
- if not sc.commands.empty():
- while sst.min_completion in sc.commands:
- if sst.actions.has_key(sst.min_completion):
- sst.actions.pop(sst.min_completion)()
- sst.min_completion += 1
-
- def session_known_completed(self, kcmp):
- sst = self.get_sst(kcmp)
- executed = RangedSet()
- for e in sst.executed.ranges:
- for ke in kcmp.ranges:
- if e.lower in ke and e.upper in ke:
- break
- else:
- executed.add_range(e)
- sst.executed = completed
-
- def do_session_flush(self, sf):
- sst = self.get_sst(sf)
- if sf.expected:
- if sst.received is None:
- exp = None
- else:
- exp = RangedSet(sst.received)
- sst.write_op(SessionExpected(exp))
- if sf.confirmed:
- sst.write_op(SessionConfirmed(sst.executed))
- if sf.completed:
- sst.write_op(SessionCompleted(sst.executed))
-
- def do_session_request_timeout(self, rt):
- sst = self.get_sst(rt)
- sst.write_op(SessionTimeout(timeout=0))
-
- def do_execution_result(self, er):
- sst = self.get_sst(er)
- sst.results[er.command_id] = er.value
- sst.executed.add(er.id)
-
- def do_execution_exception(self, ex):
- sst = self.get_sst(ex)
- exc = SESSION_ERRS.get(ex.error_code, SessionError)
- sst.session.error = exc(ex.error_code, ex.description)
-
- def dispatch(self):
- if not self.connection._connected and not self._closing and self._status != CLOSED:
- self.disconnect()
-
- if self._connected and not self._closing:
- for ssn in self.connection.sessions.values():
- self.attach(ssn)
- self.process(ssn)
-
- # We need to check heartbeat even if not self._connected since we may have
- # heartbeat timeout before receiving an open-ok
- if self.connection.heartbeat and self._status != CLOSED and not self._closing:
- now = time.time()
- if now - self._last_in > 2*self.connection.heartbeat:
- raise HeartbeatTimeout(text="heartbeat timeout")
- # Only send heartbeats if we are connected.
- if self._connected and now - self._last_out >= self.connection.heartbeat/2.0:
- self.write_op(ConnectionHeartbeat())
-
- def open(self):
- self._reset()
- self._status = OPEN
- self._buf += struct.pack(HEADER, "AMQP", 1, 1, 0, 10)
-
- def disconnect(self):
- self.write_op(ConnectionClose(close_code.normal))
- self._closing = True
-
- def attach(self, ssn):
- if ssn.closed: return
- sst = self._attachments.get(ssn)
- if sst is None:
- for i in xrange(0, self.channel_max):
- if not self._sessions.has_key(i):
- ch = i
- break
- else:
- raise RuntimeError("all channels used")
- sst = SessionState(self, ssn, ssn.name, ch)
- sst.write_op(SessionAttach(name=ssn.name, force=self._reconnecting))
- sst.write_op(SessionCommandPoint(sst.sent, 0))
- self._reconnecting = False
- sst.outgoing_idx = 0
- sst.acked = []
- sst.acked_idx = 0
- if ssn.transactional:
- sst.write_cmd(TxSelect())
- self._attachments[ssn] = sst
- self._sessions[sst.channel] = sst
-
- for snd in ssn.senders:
- self.link(snd, self._out, snd.target)
- for rcv in ssn.receivers:
- self.link(rcv, self._in, rcv.source)
-
- if sst is not None and ssn.closing and not sst.detached:
- sst.detached = True
- sst.write_op(SessionDetach(name=ssn.name))
-
- def get_sst(self, op):
- return self._sessions[op.channel]
-
- def do_session_detached(self, dtc):
- sst = self._sessions.pop(dtc.channel)
- ssn = sst.session
- del self._attachments[ssn]
- ssn.closed = True
-
- def do_session_detach(self, dtc):
- sst = self.get_sst(dtc)
- sst.write_op(SessionDetached(name=dtc.name))
- self.do_session_detached(dtc)
-
- def link(self, lnk, dir, addr):
- sst = self._attachments.get(lnk.session)
- _lnk = self._attachments.get(lnk)
-
- if _lnk is None and not lnk.closed:
- _lnk = Attachment(lnk)
- _lnk.closing = False
- dir.init_link(sst, lnk, _lnk)
-
- err = self.parse_address(_lnk, dir, addr) or self.validate_options(_lnk, dir)
- if err:
- lnk.error = err
- lnk.closed = True
- return
-
- def linked():
- lnk.linked = True
-
- def resolved(type, subtype):
- dir.do_link(sst, lnk, _lnk, type, subtype, linked)
-
- self.resolve_declare(sst, _lnk, dir.DIR_NAME, resolved)
- self._attachments[lnk] = _lnk
-
- if lnk.linked and lnk.closing and not lnk.closed:
- if not _lnk.closing:
- def unlinked():
- dir.del_link(sst, lnk, _lnk)
- del self._attachments[lnk]
- lnk.closed = True
- if _lnk.options.get("delete") in ("always", dir.DIR_NAME):
- dir.do_unlink(sst, lnk, _lnk)
- requested_type = _lnk.options.get("node", {}).get("type")
- self.delete(sst, _lnk.name, unlinked, node_type=requested_type)
- else:
- dir.do_unlink(sst, lnk, _lnk, unlinked)
- _lnk.closing = True
- elif not lnk.linked and lnk.closing and not lnk.closed:
- if lnk.error: lnk.closed = True
-
- def parse_address(self, lnk, dir, addr):
- if addr is None:
- return MalformedAddress(text="%s is None" % dir.ADDR_NAME)
- else:
- try:
- lnk.name, lnk.subject, lnk.options = address.parse(addr)
- # XXX: subject
- if lnk.options is None:
- lnk.options = {}
- if isinstance(addr, MangledString):
- lnk.options['create'] = "always"
- if 'node' not in lnk.options:
- lnk.options['node'] = {}
- if 'x-declare' not in lnk.options['node']:
- lnk.options['node']['x-declare'] = {}
- xdeclare = lnk.options['node']['x-declare']
- if 'auto-delete' not in xdeclare:
- xdeclare['auto-delete'] = "True"
- if 'exclusive' not in xdeclare:
- xdeclare['exclusive'] = "True"
- except address.LexError, e:
- return MalformedAddress(text=str(e))
- except address.ParseError, e:
- return MalformedAddress(text=str(e))
-
- def validate_options(self, lnk, dir):
- ctx = Context()
- err = dir.VALIDATOR.validate(lnk.options, ctx)
- if err: return InvalidOption(text="error in options: %s" % err)
-
- def resolve_declare(self, sst, lnk, dir, action):
- declare = lnk.options.get("create") in ("always", dir)
- assrt = lnk.options.get("assert") in ("always", dir)
- requested_type = lnk.options.get("node", {}).get("type")
- def do_resolved(type, subtype):
- err = None
- if type is None:
- if declare:
- err = self.declare(sst, lnk, action, True)
- else:
- err = NotFound(text="no such %s: %s" % (requested_type or "queue", lnk.name))
- else:
- if assrt:
- expected = lnk.options.get("node", {}).get("type")
- if expected and type != expected:
- if declare:
- err = self.declare(sst, lnk, action, True)
- else:
- err = AssertionFailed(text="expected %s, got %s" % (expected, type))
- if "node" in lnk.options and "x-bindings" in lnk.options["node"]:
- err = self.declare(sst, lnk, action, False)
- if err is None:
- action(type, subtype)
-
- if err:
- tgt = lnk.target
- tgt.error = err
- del self._attachments[tgt]
- tgt.closed = True
- return
- self.resolve(sst, lnk.name, do_resolved, node_type=requested_type, force=declare)
-
- def resolve(self, sst, name, action, force=False, node_type=None, delete=False):
- if not force and not node_type:
- try:
- type, subtype = self.address_cache[name]
- action(type, subtype)
- return
- except KeyError:
- pass
-
- args = { "topic":None, "queue":None }
- def do_result(r, obj):
- args[obj] = r
- def do_action():
- er = args["topic"]
- qr = args["queue"]
- if node_type == "topic" and er and not er.not_found:
- type, subtype = "topic", er.type
- elif node_type == "queue" and qr and qr.queue:
- type, subtype = "queue", None
- elif (er and er.not_found) and qr and not qr.queue:
- type, subtype = None, None
- elif (qr and qr.queue):
- if node_type == "topic" and force:
- type, subtype = None, None
- else:
- type, subtype = "queue", None
- elif (er and not er.not_found):
- if node_type == "queue" and force:
- type, subtype = None, None
- else:
- type, subtype = "topic", er.type
- elif er:
- if er.not_found:
- type, subtype = None, None
- else:
- type, subtype = "topic", er.type
- else:
- type, subtype = None, None
- if type is not None:
- self.address_cache[name] = (type, subtype)
- action(type, subtype)
- def do_result_and_action(r, obj):
- do_result(r, obj)
- do_action()
- if (node_type is None): # we don't know the type, let check broker
- sst.write_query(ExchangeQuery(name), do_result, "topic")
- sst.write_query(QueueQuery(name), do_result_and_action, "queue")
- elif force and not delete: # we forcefully declare known type, dont ask broker
- do_action()
- elif node_type == "topic":
- sst.write_query(ExchangeQuery(name), do_result_and_action, "topic")
- else:
- sst.write_query(QueueQuery(name), do_result_and_action, "queue")
-
- def declare(self, sst, lnk, action, create_node):
- name = lnk.name
- props = lnk.options.get("node", {})
- durable = props.get("durable", DURABLE_DEFAULT)
- type = props.get("type", "queue")
- declare = props.get("x-declare", {})
-
- cmd = None
- if type == "topic":
- if create_node: cmd = ExchangeDeclare(exchange=name, durable=durable)
- bindings = get_bindings(props, exchange=name)
- elif type == "queue":
- if create_node: cmd = QueueDeclare(queue=name, durable=durable)
- bindings = get_bindings(props, queue=name)
- else:
- raise ValueError(type)
-
- if cmd is not None:
- sst.apply_overrides(cmd, declare)
- if type == "topic":
- if cmd.type is None:
- cmd.type = "topic"
- subtype = cmd.type
- else:
- subtype = None
- cmds = [cmd]
- else:
- cmds = []
-
- cmds.extend(bindings)
-
- def declared():
- if create_node:
- self.address_cache[name] = (type, subtype)
- action(type, subtype)
-
- sst.write_cmds(cmds, declared)
-
- def delete(self, sst, name, action, node_type=None):
- def deleted():
- del self.address_cache[name]
- action()
-
- def do_delete(type, subtype):
- if type == "topic":
- sst.write_cmd(ExchangeDelete(name), deleted)
- elif type == "queue":
- sst.write_cmd(QueueDelete(name), deleted)
- elif type is None:
- action()
- else:
- raise ValueError(type)
- self.resolve(sst, name, do_delete, force=True, node_type=node_type, delete=True)
-
- def process(self, ssn):
- if ssn.closed or ssn.closing: return
-
- sst = self._attachments[ssn]
-
- while sst.outgoing_idx < len(ssn.outgoing):
- msg = ssn.outgoing[sst.outgoing_idx]
- snd = msg._sender
- # XXX: should check for sender error here
- _snd = self._attachments.get(snd)
- if _snd and snd.linked:
- self.send(snd, msg)
- sst.outgoing_idx += 1
- else:
- break
-
- for snd in ssn.senders:
- # XXX: should included snd.acked in this
- if snd.synced >= snd.queued and sst.need_sync:
- sst.write_cmd(ExecutionSync(), sync_noop)
-
- for rcv in ssn.receivers:
- self.process_receiver(rcv)
-
- if ssn.acked:
- messages = ssn.acked[sst.acked_idx:]
- if messages:
- ids = RangedSet()
-
- disposed = [(DEFAULT_DISPOSITION, [])]
- acked = []
- for m in messages:
- # XXX: we're ignoring acks that get lost when disconnected,
- # could we deal this via some message-id based purge?
- if m._transfer_id is None:
- acked.append(m)
- continue
- ids.add(m._transfer_id)
- if m._receiver._accept_mode is accept_mode.explicit:
- disp = m._disposition or DEFAULT_DISPOSITION
- last, msgs = disposed[-1]
- if disp.type is last.type and disp.options == last.options:
- msgs.append(m)
- else:
- disposed.append((disp, [m]))
- else:
- acked.append(m)
-
- for range in ids:
- sst.executed.add_range(range)
- sst.write_op(SessionCompleted(sst.executed))
-
- def ack_acker(msgs):
- def ack_ack():
- for m in msgs:
- ssn.acked.remove(m)
- sst.acked_idx -= 1
- # XXX: should this check accept_mode too?
- if not ssn.transactional:
- sst.acked.remove(m)
- return ack_ack
-
- for disp, msgs in disposed:
- if not msgs: continue
- if disp.type is None:
- op = MessageAccept
- elif disp.type is RELEASED:
- op = MessageRelease
- elif disp.type is REJECTED:
- op = MessageReject
- sst.write_cmd(op(RangedSet(*[m._transfer_id for m in msgs]),
- **disp.options),
- ack_acker(msgs))
- if log.isEnabledFor(DEBUG):
- for m in msgs:
- log.debug("SACK[%s]: %s, %s", ssn.log_id, m, m._disposition)
-
- sst.acked.extend(messages)
- sst.acked_idx += len(messages)
- ack_acker(acked)()
-
- if ssn.committing and not sst.committing:
- def commit_ok():
- del sst.acked[:]
- ssn.committing = False
- ssn.committed = True
- ssn.aborting = False
- ssn.aborted = False
- sst.committing = False
- sst.write_cmd(TxCommit(), commit_ok)
- sst.committing = True
-
- if ssn.aborting and not sst.aborting:
- sst.aborting = True
- def do_rb():
- messages = sst.acked + ssn.unacked + ssn.incoming
- ids = RangedSet(*[m._transfer_id for m in messages])
- for range in ids:
- sst.executed.add_range(range)
- sst.write_op(SessionCompleted(sst.executed))
- sst.write_cmd(MessageRelease(ids, True))
- sst.write_cmd(TxRollback(), do_rb_ok)
-
- def do_rb_ok():
- del ssn.incoming[:]
- del ssn.unacked[:]
- del sst.acked[:]
-
- for rcv in ssn.receivers:
- rcv.impending = rcv.received
- rcv.returned = rcv.received
- # XXX: do we need to update granted here as well?
-
- for rcv in ssn.receivers:
- self.process_receiver(rcv)
-
- ssn.aborting = False
- ssn.aborted = True
- ssn.committing = False
- ssn.committed = False
- sst.aborting = False
-
- for rcv in ssn.receivers:
- _rcv = self._attachments[rcv]
- sst.write_cmd(MessageStop(_rcv.destination))
- sst.write_cmd(ExecutionSync(), do_rb)
-
- def grant(self, rcv):
- sst = self._attachments[rcv.session]
- _rcv = self._attachments.get(rcv)
- if _rcv is None or not rcv.linked or _rcv.closing or _rcv.draining:
- return
-
- if rcv.granted is UNLIMITED:
- if rcv.impending is UNLIMITED:
- delta = 0
- else:
- delta = UNLIMITED
- elif rcv.impending is UNLIMITED:
- delta = -1
- else:
- delta = max(rcv.granted, rcv.received) - rcv.impending
-
- if delta is UNLIMITED:
- if not _rcv.bytes_open:
- sst.write_cmd(MessageFlow(_rcv.destination, credit_unit.byte, UNLIMITED.value))
- _rcv.bytes_open = True
- sst.write_cmd(MessageFlow(_rcv.destination, credit_unit.message, UNLIMITED.value))
- rcv.impending = UNLIMITED
- elif delta > 0:
- if not _rcv.bytes_open:
- sst.write_cmd(MessageFlow(_rcv.destination, credit_unit.byte, UNLIMITED.value))
- _rcv.bytes_open = True
- sst.write_cmd(MessageFlow(_rcv.destination, credit_unit.message, delta))
- rcv.impending += delta
- elif delta < 0 and not rcv.draining:
- _rcv.draining = True
- def do_stop():
- rcv.impending = rcv.received
- _rcv.draining = False
- _rcv.bytes_open = False
- self.grant(rcv)
- sst.write_cmd(MessageStop(_rcv.destination), do_stop)
-
- if rcv.draining:
- _rcv.draining = True
- def do_flush():
- rcv.impending = rcv.received
- rcv.granted = rcv.impending
- _rcv.draining = False
- _rcv.bytes_open = False
- rcv.draining = False
- sst.write_cmd(MessageFlush(_rcv.destination), do_flush)
-
-
- def process_receiver(self, rcv):
- if rcv.closed: return
- self.grant(rcv)
-
- def send(self, snd, msg):
- sst = self._attachments[snd.session]
- _snd = self._attachments[snd]
-
- if msg.subject is None or _snd._exchange == "":
- rk = _snd._routing_key
- else:
- rk = msg.subject
-
- if msg.subject is None:
- subject = _snd.subject
- else:
- subject = msg.subject
-
- # XXX: do we need to query to figure out how to create the reply-to interoperably?
- if msg.reply_to:
- rt = addr2reply_to(msg.reply_to)
- else:
- rt = None
- content_encoding = msg.properties.get("x-amqp-0-10.content-encoding")
- dp = DeliveryProperties(routing_key=rk)
- mp = MessageProperties(message_id=msg.id,
- user_id=msg.user_id,
- reply_to=rt,
- correlation_id=msg.correlation_id,
- app_id = msg.properties.get("x-amqp-0-10.app-id"),
- content_type=msg.content_type,
- content_encoding=content_encoding,
- application_headers=msg.properties)
- if subject is not None:
- if mp.application_headers is None:
- mp.application_headers = {}
- mp.application_headers[SUBJECT] = subject
- if msg.durable is not None:
- if msg.durable:
- dp.delivery_mode = delivery_mode.persistent
- else:
- dp.delivery_mode = delivery_mode.non_persistent
- if msg.priority is not None:
- dp.priority = msg.priority
- if msg.ttl is not None:
- dp.ttl = long(msg.ttl*1000)
- enc, dec = get_codec(msg.content_type)
- try:
- body = enc(msg.content)
- except AttributeError, e:
- # convert to non-blocking EncodeError
- raise EncodeError(e)
-
- # XXX: this is not safe for out of order, can this be triggered by pre_ack?
- def msg_acked():
- # XXX: should we log the ack somehow too?
- snd.acked += 1
- m = snd.session.outgoing.pop(0)
- sst.outgoing_idx -= 1
- log.debug("RACK[%s]: %s", sst.session.log_id, msg)
- assert msg == m
-
- xfr = MessageTransfer(destination=_snd._exchange, headers=(dp, mp),
- payload=body)
-
- if _snd.pre_ack:
- sst.write_cmd(xfr)
- else:
- sst.write_cmd(xfr, msg_acked, sync=msg._sync)
-
- log.debug("SENT[%s]: %s", sst.session.log_id, msg)
-
- if _snd.pre_ack:
- msg_acked()
-
- def do_message_transfer(self, xfr):
- sst = self.get_sst(xfr)
- ssn = sst.session
-
- msg = self._decode(xfr)
- rcv = sst.destinations[xfr.destination].target
- msg._receiver = rcv
- if rcv.closing or rcv.closed: # release message to a closing receiver
- ids = RangedSet(*[msg._transfer_id])
- log.debug("releasing back %s message: %s, as receiver is closing", ids, msg)
- sst.write_cmd(MessageRelease(ids, True))
- return
- if rcv.impending is not UNLIMITED:
- assert rcv.received < rcv.impending, "%s, %s" % (rcv.received, rcv.impending)
- rcv.received += 1
- log.debug("RCVD[%s]: %s", ssn.log_id, msg)
- ssn._notify_message_received(msg)
-
-
- def _decode(self, xfr):
- dp = EMPTY_DP
- mp = EMPTY_MP
-
- for h in xfr.headers:
- if isinstance(h, DeliveryProperties):
- dp = h
- elif isinstance(h, MessageProperties):
- mp = h
-
- ap = mp.application_headers
- enc, dec = get_codec(mp.content_type)
- try:
- content = dec(xfr.payload)
- except Exception, e:
- raise DecodeError(e)
- msg = Message(content)
- msg.id = mp.message_id
- if ap is not None:
- msg.subject = ap.get(SUBJECT)
- msg.user_id = mp.user_id
- if mp.reply_to is not None:
- msg.reply_to = reply_to2addr(mp.reply_to)
- msg.correlation_id = mp.correlation_id
- if dp.delivery_mode is not None:
- msg.durable = dp.delivery_mode == delivery_mode.persistent
- msg.priority = dp.priority
- if dp.ttl is not None:
- msg.ttl = dp.ttl/1000.0
- msg.redelivered = dp.redelivered
- msg.properties = mp.application_headers or {}
- if mp.app_id is not None:
- msg.properties["x-amqp-0-10.app-id"] = mp.app_id
- if mp.content_encoding is not None:
- msg.properties["x-amqp-0-10.content-encoding"] = mp.content_encoding
- if dp.routing_key is not None:
- msg.properties["x-amqp-0-10.routing-key"] = dp.routing_key
- if dp.timestamp is not None:
- msg.properties["x-amqp-0-10.timestamp"] = dp.timestamp
- msg.content_type = mp.content_type
- msg._transfer_id = xfr.id
- return msg
diff --git a/qpid/python/qpid/messaging/endpoints.py b/qpid/python/qpid/messaging/endpoints.py
deleted file mode 100644
index 885b95a814..0000000000
--- a/qpid/python/qpid/messaging/endpoints.py
+++ /dev/null
@@ -1,1195 +0,0 @@
-#
-# 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.
-#
-
-"""
-A high level messaging API for python.
-
-Areas that still need work:
-
- - definition of the arguments for L{Session.sender} and L{Session.receiver}
- - standard L{Message} properties
- - L{Message} content encoding
- - protocol negotiation/multiprotocol impl
-"""
-
-from logging import getLogger
-from math import ceil
-from qpid.codec010 import StringCodec
-from qpid.concurrency import synchronized, Waiter, Condition
-from qpid.datatypes import Serial, uuid4
-from qpid.messaging.constants import *
-from qpid.messaging.exceptions import *
-from qpid.messaging.message import *
-from qpid.ops import PRIMITIVE
-from qpid.util import default, URL
-from threading import Thread, RLock
-
-log = getLogger("qpid.messaging")
-
-static = staticmethod
-
-class Endpoint(object):
- """
- Base class for all endpoint objects types.
- @undocumented: __init__, __setattr__
- """
- def __init__(self):
- self._async_exception_notify_handler = None
- self.error = None
-
- def _ecwait(self, predicate, timeout=None):
- result = self._ewait(lambda: self.closed or predicate(), timeout)
- self.check_closed()
- return result
-
- @synchronized
- def set_async_exception_notify_handler(self, handler):
- """
- Register a callable that will be invoked when the driver thread detects an
- error on the Endpoint. The callable is invoked with the instance of the
- Endpoint object passed as the first argument. The second argument is an
- Exception instance describing the failure.
-
- @param handler: invoked by the driver thread when an error occurs.
- @type handler: callable object taking an Endpoint and an Exception as
- arguments.
- @return: None
- @note: The exception will also be raised the next time the application
- invokes one of the blocking messaging APIs.
- @warning: B{Use with caution} This callback is invoked in the context of
- the driver thread. It is B{NOT} safe to call B{ANY} of the messaging APIs
- from within this callback. This includes any of the Endpoint's methods. The
- intent of the handler is to provide an efficient way to notify the
- application that an exception has occurred in the driver thread. This can
- be useful for those applications that periodically poll the messaging layer
- for events. In this case the callback can be used to schedule a task that
- retrieves the error using the Endpoint's get_error() or check_error()
- methods.
- """
- self._async_exception_notify_handler = handler
-
- def __setattr__(self, name, value):
- """
- Intercept any attempt to set the endpoint error flag and invoke the
- callback if registered.
- """
- super(Endpoint, self).__setattr__(name, value)
- if name == 'error' and value is not None:
- if self._async_exception_notify_handler:
- self._async_exception_notify_handler(self, value)
-
-
-class Connection(Endpoint):
-
- """
- A Connection manages a group of L{Sessions<Session>} and connects
- them with a remote endpoint.
- """
-
- @static
- def establish(url=None, timeout=None, **options):
- """
- Constructs a L{Connection} with the supplied parameters and opens
- it.
- """
- conn = Connection(url, **options)
- conn.open(timeout=timeout)
- return conn
-
- def __init__(self, url=None, **options):
- """
- Creates a connection. A newly created connection must be opened
- with the Connection.open() method before it can be used.
-
- @type url: str
- @param url: [ <username> [ / <password> ] @ ] <host> [ : <port> ]
- @type host: str
- @param host: the name or ip address of the remote host (overriden by url)
- @type port: int
- @param port: the port number of the remote host (overriden by url)
- @type transport: str
- @param transport: one of tcp, tcp+tls, or ssl (alias for tcp+tls)
- @type heartbeat: int
- @param heartbeat: heartbeat interval in seconds
-
- @type username: str
- @param username: the username for authentication (overriden by url)
- @type password: str
- @param password: the password for authentication (overriden by url)
- @type sasl_mechanisms: str
- @param sasl_mechanisms: space separated list of permitted sasl mechanisms
- @type sasl_service: str
- @param sasl_service: the service name if needed by the SASL mechanism in use
- @type sasl_min_ssf: int
- @param sasl_min_ssf: the minimum acceptable security strength factor
- @type sasl_max_ssf: int
- @param sasl_max_ssf: the maximum acceptable security strength factor
-
- @type reconnect: bool
- @param reconnect: enable/disable automatic reconnect
- @type reconnect_timeout: float
- @param reconnect_timeout: total time to attempt reconnect
- @type reconnect_interval_min: float
- @param reconnect_interval_min: minimum interval between reconnect attempts
- @type reconnect_interval_max: float
- @param reconnect_interval_max: maximum interval between reconnect attempts
- @type reconnect_interval: float
- @param reconnect_interval: set both min and max reconnect intervals
- @type reconnect_limit: int
- @param reconnect_limit: limit the total number of reconnect attempts
- @type reconnect_urls: list[str]
- @param reconnect_urls: list of backup hosts specified as urls
-
- @type address_ttl: float
- @param address_ttl: time until cached address resolution expires
-
- @type ssl_keyfile: str
- @param ssl_keyfile: file with client's private key (PEM format)
- @type ssl_certfile: str
- @param ssl_certfile: file with client's public (eventually priv+pub) key (PEM format)
- @type ssl_trustfile: str
- @param ssl_trustfile: file trusted certificates to validate the server
- @type ssl_skip_hostname_check: bool
- @param ssl_skip_hostname_check: disable verification of hostname in
- certificate. Use with caution - disabling hostname checking leaves you
- vulnerable to Man-in-the-Middle attacks.
-
- @rtype: Connection
- @return: a disconnected Connection
- """
- super(Connection, self).__init__()
- # List of all attributes
- opt_keys = ['host', 'transport', 'port', 'heartbeat', 'username', 'password', 'sasl_mechanisms', 'sasl_service', 'sasl_min_ssf', 'sasl_max_ssf', 'reconnect', 'reconnect_timeout', 'reconnect_interval', 'reconnect_interval_min', 'reconnect_interval_max', 'reconnect_limit', 'reconnect_urls', 'reconnect_log', 'address_ttl', 'tcp_nodelay', 'ssl_keyfile', 'ssl_certfile', 'ssl_trustfile', 'ssl_skip_hostname_check', 'client_properties', 'protocol' ]
- # Create all attributes on self and set to None.
- for key in opt_keys:
- setattr(self, key, None)
- # Get values from options, check for invalid options
- for (key, value) in options.iteritems():
- if key in opt_keys:
- setattr(self, key, value)
- else:
- raise ConnectionError("Unknown connection option %s with value %s" %(key, value))
-
- # Now handle items that need special treatment or have speical defaults:
- if self.host:
- url = default(url, self.host)
- if isinstance(url, basestring):
- url = URL(url)
- self.host = url.host
-
- if self.transport is None:
- if url.scheme == url.AMQP:
- self.transport = "tcp"
- elif url.scheme == url.AMQPS:
- self.transport = "ssl"
- else:
- self.transport = "tcp"
- if self.transport in ("ssl", "tcp+tls"):
- self.port = default(url.port, default(self.port, AMQPS_PORT))
- else:
- self.port = default(url.port, default(self.port, AMQP_PORT))
-
- if self.protocol and self.protocol != "amqp0-10":
- raise ConnectionError("Connection option 'protocol' value '" + value + "' unsupported (must be amqp0-10)")
-
- self.username = default(url.user, self.username)
- self.password = default(url.password, self.password)
- self.auth_username = None
- self.sasl_service = default(self.sasl_service, "qpidd")
-
- self.reconnect = default(self.reconnect, False)
- self.reconnect_interval_min = default(self.reconnect_interval_min,
- default(self.reconnect_interval, 1))
- self.reconnect_interval_max = default(self.reconnect_interval_max,
- default(self.reconnect_interval, 2*60))
- self.reconnect_urls = default(self.reconnect_urls, [])
- self.reconnect_log = default(self.reconnect_log, True)
-
- self.address_ttl = default(self.address_ttl, 60)
- self.tcp_nodelay = default(self.tcp_nodelay, False)
-
- self.ssl_keyfile = default(self.ssl_keyfile, None)
- self.ssl_certfile = default(self.ssl_certfile, None)
- self.ssl_trustfile = default(self.ssl_trustfile, None)
- # if ssl_skip_hostname_check was not explicitly set, this will be None
- self._ssl_skip_hostname_check_actual = options.get("ssl_skip_hostname_check")
- self.ssl_skip_hostname_check = default(self.ssl_skip_hostname_check, False)
- self.client_properties = default(self.client_properties, {})
-
- self.options = options
-
-
- self.id = str(uuid4())
- self.session_counter = 0
- self.sessions = {}
- self._open = False
- self._connected = False
- self._transport_connected = False
- self._lock = RLock()
- self._condition = Condition(self._lock)
- self._waiter = Waiter(self._condition)
- self._modcount = Serial(0)
- from driver import Driver
- self._driver = Driver(self)
-
- def _wait(self, predicate, timeout=None):
- return self._waiter.wait(predicate, timeout=timeout)
-
- def _wakeup(self):
- self._modcount += 1
- self._driver.wakeup()
-
- def check_error(self):
- if self.error:
- self._condition.gc()
- e = self.error
- if isinstance(e, ContentError):
- """ forget the content error. It will be
- raised this time but won't block future calls
- """
- self.error = None
- raise e
-
- def get_error(self):
- return self.error
-
- def _ewait(self, predicate, timeout=None):
- result = self._wait(lambda: self.error or predicate(), timeout)
- self.check_error()
- return result
-
- def check_closed(self):
- if not self._connected:
- self._condition.gc()
- raise ConnectionClosed()
-
- @synchronized
- def session(self, name=None, transactional=False):
- """
- Creates or retrieves the named session. If the name is omitted or
- None, then a unique name is chosen based on a randomly generated
- uuid.
-
- @type name: str
- @param name: the session name
- @rtype: Session
- @return: the named Session
- """
-
- if name is None:
- name = "%s:%s" % (self.id, self.session_counter)
- self.session_counter += 1
- else:
- name = "%s:%s" % (self.id, name)
-
- if self.sessions.has_key(name):
- return self.sessions[name]
- else:
- ssn = Session(self, name, transactional)
- self.sessions[name] = ssn
- self._wakeup()
- return ssn
-
- @synchronized
- def _remove_session(self, ssn):
- self.sessions.pop(ssn.name, 0)
-
- @synchronized
- def open(self, timeout=None):
- """
- Opens a connection.
- """
- if self._open:
- raise ConnectionError("already open")
- self._open = True
- if self.reconnect and self.reconnect_timeout > 0:
- timeout = self.reconnect_timeout
- self.attach(timeout=timeout)
-
- @synchronized
- def opened(self):
- """
- Return true if the connection is open, false otherwise.
- """
- return self._open
-
- @synchronized
- def attach(self, timeout=None):
- """
- Attach to the remote endpoint.
- """
- if not self._connected:
- self._connected = True
- self._driver.start()
- self._wakeup()
- if not self._ewait(lambda: self._transport_connected and not self._unlinked(), timeout=timeout):
- self.reconnect = False
- raise Timeout("Connection attach timed out")
-
- def _unlinked(self):
- return [l
- for ssn in self.sessions.values()
- if not (ssn.error or ssn.closed)
- for l in ssn.senders + ssn.receivers
- if not (l.linked or l.error or l.closed)]
-
- @synchronized
- def detach(self, timeout=None):
- """
- Detach from the remote endpoint.
- """
- if self._connected:
- self._connected = False
- self._wakeup()
- cleanup = True
- else:
- cleanup = False
- try:
- if not self._wait(lambda: not self._transport_connected, timeout=timeout):
- raise Timeout("detach timed out")
- finally:
- if cleanup:
- self._driver.stop()
- self._condition.gc()
-
- @synchronized
- def attached(self):
- """
- Return true if the connection is attached, false otherwise.
- """
- return self._connected
-
- @synchronized
- def close(self, timeout=None):
- """
- Close the connection and all sessions.
- """
- try:
- for ssn in self.sessions.values():
- ssn.close(timeout=timeout)
- finally:
- self.detach(timeout=timeout)
- self._open = False
-
-
-class Session(Endpoint):
-
- """
- Sessions provide a linear context for sending and receiving
- L{Messages<Message>}. L{Messages<Message>} are sent and received
- using the L{Sender.send} and L{Receiver.fetch} methods of the
- L{Sender} and L{Receiver} objects associated with a Session.
-
- Each L{Sender} and L{Receiver} is created by supplying either a
- target or source address to the L{sender} and L{receiver} methods of
- the Session. The address is supplied via a string syntax documented
- below.
-
- Addresses
- =========
-
- An address identifies a source or target for messages. In its
- simplest form this is just a name. In general a target address may
- also be used as a source address, however not all source addresses
- may be used as a target, e.g. a source might additionally have some
- filtering criteria that would not be present in a target.
-
- A subject may optionally be specified along with the name. When an
- address is used as a target, any subject specified in the address is
- used as the default subject of outgoing messages for that target.
- When an address is used as a source, any subject specified in the
- address is pattern matched against the subject of available messages
- as a filter for incoming messages from that source.
-
- The options map contains additional information about the address
- including:
-
- - policies for automatically creating, and deleting the node to
- which an address refers
-
- - policies for asserting facts about the node to which an address
- refers
-
- - extension points that can be used for sender/receiver
- configuration
-
- Mapping to AMQP 0-10
- --------------------
- The name is resolved to either an exchange or a queue by querying
- the broker.
-
- The subject is set as a property on the message. Additionally, if
- the name refers to an exchange, the routing key is set to the
- subject.
-
- Syntax
- ------
- The following regular expressions define the tokens used to parse
- addresses::
- LBRACE: \\{
- RBRACE: \\}
- LBRACK: \\[
- RBRACK: \\]
- COLON: :
- SEMI: ;
- SLASH: /
- COMMA: ,
- NUMBER: [+-]?[0-9]*\\.?[0-9]+
- ID: [a-zA-Z_](?:[a-zA-Z0-9_-]*[a-zA-Z0-9_])?
- STRING: "(?:[^\\\\"]|\\\\.)*"|\'(?:[^\\\\\']|\\\\.)*\'
- ESC: \\\\[^ux]|\\\\x[0-9a-fA-F][0-9a-fA-F]|\\\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]
- SYM: [.#*%@$^!+-]
- WSPACE: [ \\n\\r\\t]+
-
- The formal grammar for addresses is given below::
- address = name [ "/" subject ] [ ";" options ]
- name = ( part | quoted )+
- subject = ( part | quoted | "/" )*
- quoted = STRING / ESC
- part = LBRACE / RBRACE / COLON / COMMA / NUMBER / ID / SYM
- options = map
- map = "{" ( keyval ( "," keyval )* )? "}"
- keyval = ID ":" value
- value = NUMBER / STRING / ID / map / list
- list = "[" ( value ( "," value )* )? "]"
-
- This grammar resuls in the following informal syntax::
-
- <name> [ / <subject> ] [ ; <options> ]
-
- Where options is::
-
- { <key> : <value>, ... }
-
- And values may be:
- - numbers
- - single, double, or non quoted strings
- - maps (dictionaries)
- - lists
-
- Options
- -------
- The options map permits the following parameters::
-
- <name> [ / <subject> ] ; {
- create: always | sender | receiver | never,
- delete: always | sender | receiver | never,
- assert: always | sender | receiver | never,
- mode: browse | consume,
- node: {
- type: queue | topic,
- durable: True | False,
- x-declare: { ... <declare-overrides> ... },
- x-bindings: [<binding_1>, ... <binding_n>]
- },
- link: {
- name: <link-name>,
- durable: True | False,
- reliability: unreliable | at-most-once | at-least-once | exactly-once,
- x-declare: { ... <declare-overrides> ... },
- x-bindings: [<binding_1>, ... <binding_n>],
- x-subscribe: { ... <subscribe-overrides> ... }
- }
- }
-
- Bindings are specified as a map with the following options::
-
- {
- exchange: <exchange>,
- queue: <queue>,
- key: <key>,
- arguments: <arguments>
- }
-
- The create, delete, and assert policies specify who should perfom
- the associated action:
-
- - I{always}: the action will always be performed
- - I{sender}: the action will only be performed by the sender
- - I{receiver}: the action will only be performed by the receiver
- - I{never}: the action will never be performed (this is the default)
-
- The node-type is one of:
-
- - I{topic}: a topic node will default to the topic exchange,
- x-declare may be used to specify other exchange types
- - I{queue}: this is the default node-type
-
- The x-declare map permits protocol specific keys and values to be
- specified when exchanges or queues are declared. These keys and
- values are passed through when creating a node or asserting facts
- about an existing node.
-
- Examples
- --------
- A simple name resolves to any named node, usually a queue or a
- topic::
-
- my-queue-or-topic
-
- A simple name with a subject will also resolve to a node, but the
- presence of the subject will cause a sender using this address to
- set the subject on outgoing messages, and receivers to filter based
- on the subject::
-
- my-queue-or-topic/my-subject
-
- A subject pattern can be used and will cause filtering if used by
- the receiver. If used for a sender, the literal value gets set as
- the subject::
-
- my-queue-or-topic/my-*
-
- In all the above cases, the address is resolved to an existing node.
- If you want the node to be auto-created, then you can do the
- following. By default nonexistent nodes are assumed to be queues::
-
- my-queue; {create: always}
-
- You can customize the properties of the queue::
-
- my-queue; {create: always, node: {durable: True}}
-
- You can create a topic instead if you want::
-
- my-queue; {create: always, node: {type: topic}}
-
- You can assert that the address resolves to a node with particular
- properties::
-
- my-transient-topic; {
- assert: always,
- node: {
- type: topic,
- durable: False
- }
- }
- """
-
- def __init__(self, connection, name, transactional):
- super(Session, self).__init__()
- self.connection = connection
- self.name = name
- self.log_id = "%x" % id(self)
-
- self.transactional = transactional
-
- self.committing = False
- self.committed = True
- self.aborting = False
- self.aborted = False
-
- self.next_sender_id = 0
- self.senders = []
- self.next_receiver_id = 0
- self.receivers = []
- self.outgoing = []
- self.incoming = []
- self.unacked = []
- self.acked = []
- # XXX: I hate this name.
- self.ack_capacity = UNLIMITED
-
- self.closing = False
- self.closed = False
-
- self._lock = connection._lock
- self._msg_received_notify_handler = None
-
- def __repr__(self):
- return "<Session %s>" % self.name
-
- def _wait(self, predicate, timeout=None):
- return self.connection._wait(predicate, timeout=timeout)
-
- def _wakeup(self):
- self.connection._wakeup()
-
- def check_error(self):
- self.connection.check_error()
- if self.error:
- raise self.error
-
- def get_error(self):
- err = self.connection.get_error()
- if err:
- return err
- else:
- return self.error
-
- def _ewait(self, predicate, timeout=None):
- result = self.connection._ewait(lambda: self.error or predicate(), timeout)
- self.check_error()
- return result
-
- def check_closed(self):
- if self.closed:
- raise SessionClosed()
-
- def _notify_message_received(self, msg):
- self.incoming.append(msg)
- if self._msg_received_notify_handler:
- try:
- # new callback parameter: the Session
- self._msg_received_notify_handler(self)
- except TypeError:
- # backward compatibility with old API, no Session
- self._msg_received_notify_handler()
-
- @synchronized
- def sender(self, target, **options):
- """
- Creates a L{Sender} that may be used to send L{Messages<Message>}
- to the specified target.
-
- @type target: str
- @param target: the target to which messages will be sent
- @rtype: Sender
- @return: a new Sender for the specified target
- """
- target = _mangle(target)
- sender = Sender(self, self.next_sender_id, target, options)
- self.next_sender_id += 1
- self.senders.append(sender)
- if not self.closed and self.connection._connected:
- self._wakeup()
- try:
- sender._ewait(lambda: sender.linked)
- except LinkError, e:
- sender.close()
- raise e
- return sender
-
- @synchronized
- def receiver(self, source, **options):
- """
- Creates a receiver that may be used to fetch L{Messages<Message>}
- from the specified source.
-
- @type source: str
- @param source: the source of L{Messages<Message>}
- @rtype: Receiver
- @return: a new Receiver for the specified source
- """
- source = _mangle(source)
- receiver = Receiver(self, self.next_receiver_id, source, options)
- self.next_receiver_id += 1
- self.receivers.append(receiver)
- if not self.closed and self.connection._connected:
- self._wakeup()
- try:
- receiver._ewait(lambda: receiver.linked)
- except LinkError, e:
- receiver.close()
- raise e
- return receiver
-
- @synchronized
- def _count(self, predicate):
- result = 0
- for msg in self.incoming:
- if predicate(msg):
- result += 1
- return result
-
- def _peek(self, receiver):
- for msg in self.incoming:
- if msg._receiver == receiver:
- return msg
-
- def _pop(self, receiver):
- i = 0
- while i < len(self.incoming):
- msg = self.incoming[i]
- if msg._receiver == receiver:
- del self.incoming[i]
- return msg
- else:
- i += 1
-
- @synchronized
- def _get(self, receiver, timeout=None):
- if self._ewait(lambda: ((self._peek(receiver) is not None) or
- self.closing or receiver.closed),
- timeout):
- msg = self._pop(receiver)
- if msg is not None:
- msg._receiver.returned += 1
- self.unacked.append(msg)
- log.debug("RETR[%s]: %s", self.log_id, msg)
- return msg
- return None
-
- @synchronized
- def set_message_received_notify_handler(self, handler):
- """
- Register a callable that will be invoked when a Message arrives on the
- Session.
-
- @param handler: invoked by the driver thread when an error occurs.
- @type handler: a callable object taking a Session instance as its only
- argument
- @return: None
-
- @note: When using this method it is recommended to also register
- asynchronous error callbacks on all endpoint objects. Doing so will cause
- the application to be notified if an error is raised by the driver
- thread. This is necessary as after a driver error occurs the message received
- callback may never be invoked again. See
- L{Endpoint.set_async_exception_notify_handler}
-
- @warning: B{Use with caution} This callback is invoked in the context of
- the driver thread. It is B{NOT} safe to call B{ANY} of the public
- messaging APIs from within this callback, including any of the passed
- Session's methods. The intent of the handler is to provide an efficient
- way to notify the application that a message has arrived. This can be
- useful for those applications that need to schedule a task to poll for
- received messages without blocking in the messaging API. The scheduled
- task may then retrieve the message using L{next_receiver} and
- L{Receiver.fetch}
- """
- self._msg_received_notify_handler = handler
-
- @synchronized
- def set_message_received_handler(self, handler):
- """@deprecated: Use L{set_message_received_notify_handler} instead.
- """
- self._msg_received_notify_handler = handler
-
- @synchronized
- def next_receiver(self, timeout=None):
- if self._ecwait(lambda: self.incoming, timeout):
- return self.incoming[0]._receiver
- else:
- raise Empty
-
- @synchronized
- def acknowledge(self, message=None, disposition=None, sync=True):
- """
- Acknowledge the given L{Message}. If message is None, then all
- unacknowledged messages on the session are acknowledged.
-
- @type message: Message
- @param message: the message to acknowledge or None
- @type sync: boolean
- @param sync: if true then block until the message(s) are acknowledged
- """
- if message is None:
- messages = self.unacked[:]
- else:
- messages = [message]
-
- for m in messages:
- if self.ack_capacity is not UNLIMITED:
- if self.ack_capacity <= 0:
- # XXX: this is currently a SendError, maybe it should be a SessionError?
- raise InsufficientCapacity("ack_capacity = %s" % self.ack_capacity)
- self._wakeup()
- self._ecwait(lambda: len(self.acked) < self.ack_capacity)
- m._disposition = disposition
- self.unacked.remove(m)
- self.acked.append(m)
-
- self._wakeup()
- if sync:
- self._ecwait(lambda: not [m for m in messages if m in self.acked])
-
- @synchronized
- def commit(self, timeout=None):
- """
- Commit outstanding transactional work. This consists of all
- message sends and receives since the prior commit or rollback.
- """
- if not self.transactional:
- raise NontransactionalSession()
- self.committing = True
- self._wakeup()
- try:
- if not self._ecwait(lambda: not self.committing, timeout=timeout):
- raise Timeout("commit timed out")
- except TransactionError:
- raise
- except Exception, e:
- self.error = TransactionAborted(text="Transaction aborted: %s"%e)
- raise self.error
- if self.aborted:
- raise TransactionAborted()
- assert self.committed
-
- @synchronized
- def rollback(self, timeout=None):
- """
- Rollback outstanding transactional work. This consists of all
- message sends and receives since the prior commit or rollback.
- """
- if not self.transactional:
- raise NontransactionalSession()
- self.aborting = True
- self._wakeup()
- if not self._ecwait(lambda: not self.aborting, timeout=timeout):
- raise Timeout("rollback timed out")
- assert self.aborted
-
- @synchronized
- def sync(self, timeout=None):
- """
- Sync the session.
- """
- for snd in self.senders:
- snd.sync(timeout=timeout)
- if not self._ewait(lambda: not self.outgoing and not self.acked, timeout=timeout):
- raise Timeout("session sync timed out")
-
- @synchronized
- def close(self, timeout=None):
- """
- Close the session.
- """
- if self.error: return
- self.sync(timeout=timeout)
-
- for link in self.receivers + self.senders:
- link.close(timeout=timeout)
-
- if not self.closing:
- self.closing = True
- self._wakeup()
-
- try:
- if not self._ewait(lambda: self.closed, timeout=timeout):
- raise Timeout("session close timed out")
- finally:
- self.connection._remove_session(self)
-
-
-class MangledString(str): pass
-
-def _mangle(addr):
- if addr and addr.startswith("#"):
- return MangledString(str(uuid4()) + addr)
- else:
- return addr
-
-class Sender(Endpoint):
-
- """
- Sends outgoing messages.
- """
-
- def __init__(self, session, id, target, options):
- super(Sender, self).__init__()
- self.session = session
- self.id = id
- self.target = target
- self.options = options
- self.capacity = options.get("capacity", UNLIMITED)
- self.threshold = 0.5
- self.durable = options.get("durable")
- self.queued = Serial(0)
- self.synced = Serial(0)
- self.acked = Serial(0)
- self.linked = False
- self.closing = False
- self.closed = False
- self._lock = self.session._lock
-
- def _wakeup(self):
- self.session._wakeup()
-
- def check_error(self):
- self.session.check_error()
- if self.error:
- raise self.error
-
- def get_error(self):
- err = self.session.get_error()
- if err:
- return err
- else:
- return self.error
-
- def _ewait(self, predicate, timeout=None):
- result = self.session._ewait(lambda: self.error or predicate(), timeout)
- self.check_error()
- return result
-
- def check_closed(self):
- if self.closed:
- raise LinkClosed()
-
- @synchronized
- def unsettled(self):
- """
- Returns the number of messages awaiting acknowledgment.
- @rtype: int
- @return: the number of unacknowledged messages
- """
- return self.queued - self.acked
-
- @synchronized
- def available(self):
- if self.capacity is UNLIMITED:
- return UNLIMITED
- else:
- return self.capacity - self.unsettled()
-
- @synchronized
- def send(self, object, sync=True, timeout=None):
- """
- Send a message. If the object passed in is of type L{unicode},
- L{str}, L{list}, or L{dict}, it will automatically be wrapped in a
- L{Message} and sent. If it is of type L{Message}, it will be sent
- directly. If the sender capacity is not L{UNLIMITED} then send
- will block until there is available capacity to send the message.
- If the timeout parameter is specified, then send will throw an
- L{InsufficientCapacity} exception if capacity does not become
- available within the specified time.
-
- @type object: unicode, str, list, dict, Message
- @param object: the message or content to send
-
- @type sync: boolean
- @param sync: if true then block until the message is sent
-
- @type timeout: float
- @param timeout: the time to wait for available capacity
- """
-
- if not self.session.connection._connected or self.session.closing:
- raise Detached()
-
- self._ecwait(lambda: self.linked, timeout=timeout)
-
- if isinstance(object, Message):
- message = object
- else:
- message = Message(object)
-
- if message.durable is None:
- message.durable = self.durable
-
- if self.capacity is not UNLIMITED:
- if self.capacity <= 0:
- raise InsufficientCapacity("capacity = %s" % self.capacity)
- if not self._ecwait(self.available, timeout=timeout):
- raise InsufficientCapacity("capacity = %s" % self.capacity)
-
- # XXX: what if we send the same message to multiple senders?
- message._sender = self
- if self.capacity is not UNLIMITED:
- message._sync = sync or self.available() <= int(ceil(self.threshold*self.capacity))
- else:
- message._sync = sync
- self.session.outgoing.append(message)
- self.queued += 1
-
- if sync:
- self.sync(timeout=timeout)
- assert message not in self.session.outgoing
- else:
- self._wakeup()
-
- @synchronized
- def sync(self, timeout=None):
- mno = self.queued
- if self.synced < mno:
- self.synced = mno
- self._wakeup()
- try:
- if not self._ewait(lambda: self.acked >= mno, timeout=timeout):
- raise Timeout("sender sync timed out")
- except ContentError:
- # clean bad message so we can continue
- self.acked = mno
- self.session.outgoing.pop(0)
- raise
-
- @synchronized
- def close(self, timeout=None):
- """
- Close the Sender.
- """
- # avoid erroring out when closing a sender that was never
- # established
- if self.acked < self.queued:
- self.sync(timeout=timeout)
-
- if not self.closing:
- self.closing = True
- self._wakeup()
-
- try:
- if not self.session._ewait(lambda: self.closed, timeout=timeout):
- raise Timeout("sender close timed out")
- finally:
- try:
- self.session.senders.remove(self)
- except ValueError:
- pass
-
-
-class Receiver(Endpoint):
-
- """
- Receives incoming messages from a remote source. Messages may be
- fetched with L{fetch}.
- """
-
- def __init__(self, session, id, source, options):
- super(Receiver, self).__init__()
- self.session = session
- self.id = id
- self.source = source
- self.options = options
-
- self.granted = Serial(0)
- self.draining = False
- self.impending = Serial(0)
- self.received = Serial(0)
- self.returned = Serial(0)
-
- self.linked = False
- self.closing = False
- self.closed = False
- self._lock = self.session._lock
- self._capacity = 0
- self._set_capacity(options.get("capacity", 0), False)
- self.threshold = 0.5
-
- @synchronized
- def _set_capacity(self, c, wakeup=True):
- if c is UNLIMITED:
- self._capacity = c.value
- else:
- self._capacity = c
- self._grant()
- if wakeup:
- self._wakeup()
-
- def _get_capacity(self):
- if self._capacity == UNLIMITED.value:
- return UNLIMITED
- else:
- return self._capacity
-
- capacity = property(_get_capacity, _set_capacity)
-
- def _wakeup(self):
- self.session._wakeup()
-
- def check_error(self):
- self.session.check_error()
- if self.error:
- raise self.error
-
- def get_error(self):
- err = self.session.get_error()
- if err:
- return err
- else:
- return self.error
-
- def _ewait(self, predicate, timeout=None):
- result = self.session._ewait(lambda: self.error or predicate(), timeout)
- self.check_error()
- return result
-
- def check_closed(self):
- if self.closed:
- raise LinkClosed()
-
- @synchronized
- def unsettled(self):
- """
- Returns the number of acknowledged messages awaiting confirmation.
- """
- return len([m for m in self.session.acked if m._receiver is self])
-
- @synchronized
- def available(self):
- """
- Returns the number of messages available to be fetched by the
- application.
-
- @rtype: int
- @return: the number of available messages
- """
- return self.received - self.returned
-
- @synchronized
- def fetch(self, timeout=None):
- """
- Fetch and return a single message. A timeout of None will block
- forever waiting for a message to arrive, a timeout of zero will
- return immediately if no messages are available.
-
- @type timeout: float
- @param timeout: the time to wait for a message to be available
- """
-
- self._ecwait(lambda: self.linked)
-
- if self._capacity == 0:
- self.granted = self.returned + 1
- self._wakeup()
- self._ecwait(lambda: self.impending >= self.granted)
- msg = self.session._get(self, timeout=timeout)
- if msg is None:
- self.check_closed()
- self.draining = True
- self._wakeup()
- self._ecwait(lambda: not self.draining)
- msg = self.session._get(self, timeout=0)
- self._grant()
- self._wakeup()
- if msg is None:
- raise Empty()
- elif self._capacity not in (0, UNLIMITED.value):
- t = int(ceil(self.threshold * self._capacity))
- if self.received - self.returned <= t:
- self.granted = self.returned + self._capacity
- self._wakeup()
- return msg
-
- def _grant(self):
- if self._capacity == UNLIMITED.value:
- self.granted = UNLIMITED
- else:
- self.granted = self.returned + self._capacity
-
- @synchronized
- def close(self, timeout=None):
- """
- Close the receiver.
- """
- if not self.closing:
- self.closing = True
- self._wakeup()
-
- try:
- if not self.session._ewait(lambda: self.closed, timeout=timeout):
- raise Timeout("receiver close timed out")
- finally:
- try:
- self.session.receivers.remove(self)
- except ValueError:
- pass
-
-
-__all__ = ["Connection", "Endpoint", "Session", "Sender", "Receiver"]
diff --git a/qpid/python/qpid/messaging/exceptions.py b/qpid/python/qpid/messaging/exceptions.py
deleted file mode 100644
index 2284d7cde9..0000000000
--- a/qpid/python/qpid/messaging/exceptions.py
+++ /dev/null
@@ -1,179 +0,0 @@
-#
-# 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.
-#
-
-class Timeout(Exception):
- pass
-
-## Messaging Errors
-
-class MessagingError(Exception):
-
- def __init__(self, code=None, text=None, **info):
- self.code = code
- self.text = text
- self.info = info
- if self.code is None:
- msg = self.text
- else:
- msg = "%s(%s)" % (self.text, self.code)
- if info:
- msg += " " + ", ".join(["%s=%r" % (k, v) for k, v in self.info.items()])
- Exception.__init__(self, msg)
-class InternalError(MessagingError):
- pass
-
-## Connection Errors
-
-class ConnectionError(MessagingError):
- """
- The base class for all connection related exceptions.
- """
- pass
-
-class ConnectError(ConnectionError):
- """
- Exception raised when there is an error connecting to the remote
- peer.
- """
- pass
-
-class VersionError(ConnectError):
- pass
-
-class AuthenticationFailure(ConnectError):
- pass
-
-class ConnectionClosed(ConnectionError):
- pass
-
-class HeartbeatTimeout(ConnectionError):
- pass
-
-## Session Errors
-
-class SessionError(MessagingError):
- pass
-
-class Detached(SessionError):
- """
- Exception raised when an operation is attempted that is illegal when
- detached.
- """
- pass
-
-class NontransactionalSession(SessionError):
- """
- Exception raised when commit or rollback is attempted on a non
- transactional session.
- """
- pass
-
-class TransactionError(SessionError):
- """Base class for transactional errors"""
- pass
-
-class TransactionAborted(TransactionError):
- """The transaction was automatically rolled back. This could be due to an error
- on the broker, such as a store failure, or a connection failure during the
- transaction"""
- pass
-
-class TransactionUnknown(TransactionError):
- """ The outcome of the transaction on the broker (commit or roll-back) is not
- known. This occurs when the connection fails after we sent the commit but
- before we received a response."""
- pass
-
-class UnauthorizedAccess(SessionError):
- pass
-
-class ServerError(SessionError):
- pass
-
-class SessionClosed(SessionError):
- pass
-
-## Link Errors
-
-class LinkError(MessagingError):
- pass
-
-class InsufficientCapacity(LinkError):
- pass
-
-class AddressError(LinkError):
- pass
-
-class MalformedAddress(AddressError):
- pass
-
-class InvalidOption(AddressError):
- pass
-
-class ResolutionError(AddressError):
- pass
-
-class AssertionFailed(ResolutionError):
- pass
-
-class NotFound(ResolutionError):
- pass
-
-class LinkClosed(LinkError):
- pass
-
-## Sender Errors
-
-class SenderError(LinkError):
- pass
-
-class SendError(SenderError):
- pass
-
-class TargetCapacityExceeded(SendError):
- pass
-
-## Receiver Errors
-
-class ReceiverError(LinkError):
- pass
-
-class FetchError(ReceiverError):
- pass
-
-class Empty(FetchError):
- """
- Exception raised by L{Receiver.fetch} when there is no message
- available within the alloted time.
- """
- pass
-
-## Message Content errors
-class ContentError(MessagingError):
- """
- This type of exception will be returned to the application
- once, and will not block further requests
- """
- pass
-
-class EncodeError(ContentError):
- pass
-
-class DecodeError(ContentError):
- pass
diff --git a/qpid/python/qpid/messaging/message.py b/qpid/python/qpid/messaging/message.py
deleted file mode 100644
index b70b365c16..0000000000
--- a/qpid/python/qpid/messaging/message.py
+++ /dev/null
@@ -1,173 +0,0 @@
-#
-# 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.
-#
-
-from qpid.codec010 import StringCodec
-from qpid.ops import PRIMITIVE
-
-def codec(name):
- type = PRIMITIVE[name]
-
- def encode(x):
- sc = StringCodec()
- sc.write_primitive(type, x)
- return sc.encoded
-
- def decode(x):
- sc = StringCodec(x)
- return sc.read_primitive(type)
-
- return encode, decode
-
-# XXX: need to correctly parse the mime type and deal with
-# content-encoding header
-
-TYPE_MAPPINGS={
- dict: "amqp/map",
- list: "amqp/list",
- unicode: "text/plain; charset=utf8",
- unicode: "text/plain",
- buffer: None,
- str: None,
- None.__class__: None
- }
-
-DEFAULT_CODEC = (lambda x: x, lambda x: x)
-
-def encode_text_plain(x):
- if x is None:
- return None
- else:
- return x.encode("utf8")
-
-def decode_text_plain(x):
- if x is None:
- return None
- else:
- return x.decode("utf8")
-
-TYPE_CODEC={
- "amqp/map": codec("map"),
- "amqp/list": codec("list"),
- "text/plain; charset=utf8": (encode_text_plain, decode_text_plain),
- "text/plain": (encode_text_plain, decode_text_plain),
- "": DEFAULT_CODEC,
- None: DEFAULT_CODEC
- }
-
-def get_type(content):
- return TYPE_MAPPINGS[content.__class__]
-
-def get_codec(content_type):
- return TYPE_CODEC.get(content_type, DEFAULT_CODEC)
-
-UNSPECIFIED = object()
-
-class Message:
-
- """
- A message consists of a standard set of fields, an application
- defined set of properties, and some content.
-
- @type id: str
- @ivar id: the message id
- @type subject: str
- @ivar subject: message subject
- @type user_id: str
- @ivar user_id: the user-id of the message producer
- @type reply_to: str
- @ivar reply_to: the address to send replies
- @type correlation_id: str
- @ivar correlation_id: a correlation-id for the message
- @type durable: bool
- @ivar durable: message durability
- @type priority: int
- @ivar priority: message priority
- @type ttl: float
- @ivar ttl: time-to-live measured in seconds
- @type properties: dict
- @ivar properties: application specific message properties
- @type content_type: str
- @ivar content_type: the content-type of the message
- @type content: str, unicode, buffer, dict, list
- @ivar content: the message content
- """
-
- def __init__(self, content=None, content_type=UNSPECIFIED, id=None,
- subject=None, user_id=None, reply_to=None, correlation_id=None,
- durable=None, priority=None, ttl=None, properties=None):
- """
- Construct a new message with the supplied content. The
- content-type of the message will be automatically inferred from
- type of the content parameter.
-
- @type content: str, unicode, buffer, dict, list
- @param content: the message content
-
- @type content_type: str
- @param content_type: the content-type of the message
- """
- self.id = id
- self.subject = subject
- self.user_id = user_id
- self.reply_to = reply_to
- self.correlation_id = correlation_id
- self.durable = durable
- self.priority = priority
- self.ttl = ttl
- self.redelivered = False
- if properties is None:
- self.properties = {}
- else:
- self.properties = properties
- if content_type is UNSPECIFIED:
- self.content_type = get_type(content)
- else:
- self.content_type = content_type
- self.content = content
-
- def __repr__(self):
- args = []
- for name in ["id", "subject", "user_id", "reply_to", "correlation_id",
- "priority", "ttl"]:
- value = self.__dict__[name]
- if value is not None: args.append("%s=%r" % (name, value))
- for name in ["durable", "redelivered", "properties"]:
- value = self.__dict__[name]
- if value: args.append("%s=%r" % (name, value))
- if self.content_type != get_type(self.content):
- args.append("content_type=%r" % self.content_type)
- if self.content is not None:
- if args:
- args.append("content=%r" % self.content)
- else:
- args.append(repr(self.content))
- return "Message(%s)" % ", ".join(args)
-
-class Disposition:
-
- def __init__(self, type, **options):
- self.type = type
- self.options = options
-
- def __repr__(self):
- args = [str(self.type)] + \
- ["%s=%r" % (k, v) for k, v in self.options.items()]
- return "Disposition(%s)" % ", ".join(args)
-
-__all__ = ["Message", "Disposition"]
diff --git a/qpid/python/qpid/messaging/transports.py b/qpid/python/qpid/messaging/transports.py
deleted file mode 100644
index c4e7c6834e..0000000000
--- a/qpid/python/qpid/messaging/transports.py
+++ /dev/null
@@ -1,236 +0,0 @@
-#
-# 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 socket
-from qpid.util import connect
-
-TRANSPORTS = {}
-
-class SocketTransport:
-
- def __init__(self, conn, host, port):
- self.socket = connect(host, port)
- if conn.tcp_nodelay:
- self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
-
- def fileno(self):
- return self.socket.fileno()
-
-class tcp(SocketTransport):
-
- def reading(self, reading):
- return reading
-
- def writing(self, writing):
- return writing
-
- def send(self, bytes):
- return self.socket.send(bytes)
-
- def recv(self, n):
- return self.socket.recv(n)
-
- def close(self):
- self.socket.close()
-
-TRANSPORTS["tcp"] = tcp
-
-try:
- from ssl import wrap_socket, SSLError, SSL_ERROR_WANT_READ, \
- SSL_ERROR_WANT_WRITE, CERT_REQUIRED, CERT_NONE
-except ImportError:
-
- ## try the older python SSL api:
- from socket import ssl
-
- class old_ssl(SocketTransport):
- def __init__(self, conn, host, port):
- SocketTransport.__init__(self, conn, host, port)
- # Bug (QPID-4337): this is the "old" version of python SSL.
- # The private key is required. If a certificate is given, but no
- # keyfile, assume the key is contained in the certificate
- ssl_keyfile = conn.ssl_keyfile
- ssl_certfile = conn.ssl_certfile
- if ssl_certfile and not ssl_keyfile:
- ssl_keyfile = ssl_certfile
-
- # this version of SSL does NOT perform certificate validation. If the
- # connection has been configured with CA certs (via ssl_trustfile), then
- # the application expects the certificate to be validated against the
- # supplied CA certs. Since this version cannot validate, the peer cannot
- # be trusted.
- if conn.ssl_trustfile:
- raise socket.error("This version of Python does not support verification of the peer's certificate.")
-
- self.ssl = ssl(self.socket, keyfile=ssl_keyfile, certfile=ssl_certfile)
- self.socket.setblocking(1)
-
- def reading(self, reading):
- return reading
-
- def writing(self, writing):
- return writing
-
- def recv(self, n):
- return self.ssl.read(n)
-
- def send(self, s):
- return self.ssl.write(s)
-
- def close(self):
- self.socket.close()
-
- TRANSPORTS["ssl"] = old_ssl
- TRANSPORTS["tcp+tls"] = old_ssl
-
-else:
- class tls(SocketTransport):
-
- def __init__(self, conn, host, port):
- SocketTransport.__init__(self, conn, host, port)
- if conn.ssl_trustfile:
- validate = CERT_REQUIRED
- else:
- validate = CERT_NONE
-
- # if user manually set flag to false then require cert
- actual = getattr(conn, "_ssl_skip_hostname_check_actual", None)
- if actual is not None and conn.ssl_skip_hostname_check is False:
- validate = CERT_REQUIRED
-
- self.tls = wrap_socket(self.socket, keyfile=conn.ssl_keyfile,
- certfile=conn.ssl_certfile,
- ca_certs=conn.ssl_trustfile,
- cert_reqs=validate)
-
- if validate == CERT_REQUIRED and not conn.ssl_skip_hostname_check:
- verify_hostname(self.tls.getpeercert(), host)
-
- self.socket.setblocking(0)
- self.state = None
- # See qpid-4872: need to store the parameters last passed to tls.write()
- # in case the calls fail with an SSL_ERROR_WANT_* error and we have to
- # retry the call with the same parameters.
- self.write_retry = None # buffer passed to last call of tls.write()
-
- def reading(self, reading):
- if self.state is None:
- return reading
- else:
- return self.state == SSL_ERROR_WANT_READ
-
- def writing(self, writing):
- if self.state is None:
- return writing
- else:
- return self.state == SSL_ERROR_WANT_WRITE
-
- def send(self, bytes):
- if self.write_retry is None:
- self.write_retry = bytes
- self._clear_state()
- try:
- n = self.tls.write( self.write_retry )
- self.write_retry = None
- return n
- except SSLError, e:
- if self._update_state(e.args[0]):
- # will retry on next invokation
- return 0
- self.write_retry = None
- raise
- except:
- self.write_retry = None
- raise
-
- def recv(self, n):
- self._clear_state()
- try:
- return self.tls.read(n)
- except SSLError, e:
- if self._update_state(e.args[0]):
- # will retry later:
- return None
- else:
- raise
-
- def _clear_state(self):
- self.state = None
-
- def _update_state(self, code):
- if code in (SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE):
- self.state = code
- return True
- else:
- return False
-
- def close(self):
- self.socket.setblocking(1)
- # this closes the underlying socket
- self.tls.close()
-
- def verify_hostname(peer_certificate, hostname):
- match_found = False
- peer_names = []
- if peer_certificate:
- if 'subjectAltName' in peer_certificate:
- for san in peer_certificate['subjectAltName']:
- if san[0] == 'DNS':
- peer_names.append(san[1].lower())
- if 'subject' in peer_certificate:
- for sub in peer_certificate['subject']:
- while isinstance(sub, tuple) and isinstance(sub[0], tuple):
- sub = sub[0] # why the extra level of indirection???
- if sub[0] == 'commonName':
- peer_names.append(sub[1].lower())
- for pattern in peer_names:
- if _match_dns_pattern(hostname.lower(), pattern):
- match_found = True
- break
- if not match_found:
- raise SSLError("Connection hostname '%s' does not match names from peer certificate: %s" % (hostname, peer_names))
-
- def _match_dns_pattern( hostname, pattern ):
- """ For checking the hostnames provided by the peer's certificate
- """
- if pattern.find("*") == -1:
- return hostname == pattern
-
- # DNS wildcarded pattern - see RFC2818
- h_labels = hostname.split(".")
- p_labels = pattern.split(".")
-
- while h_labels and p_labels:
- if p_labels[0].find("*") == -1:
- if p_labels[0] != h_labels[0]:
- return False
- else:
- p = p_labels[0].split("*")
- if not h_labels[0].startswith(p[0]):
- return False
- if not h_labels[0].endswith(p[1]):
- return False
- h_labels.pop(0)
- p_labels.pop(0)
-
- return not h_labels and not p_labels
-
-
- TRANSPORTS["ssl"] = tls
- TRANSPORTS["tcp+tls"] = tls
diff --git a/qpid/python/qpid/messaging/util.py b/qpid/python/qpid/messaging/util.py
deleted file mode 100644
index 726cfd5172..0000000000
--- a/qpid/python/qpid/messaging/util.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#
-# 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.
-#
-
-"""
-Add-on utilities for the L{qpid.messaging} API.
-"""
-
-from qpid.messaging import *
-from logging import getLogger
-from threading import Thread
-
-log = getLogger("qpid.messaging.util")
-
-def auto_fetch_reconnect_urls(conn):
- ssn = conn.session("auto-fetch-reconnect-urls")
- rcv = ssn.receiver("amq.failover")
- rcv.capacity = 10
-
- def main():
- while True:
- try:
- msg = rcv.fetch()
- except LinkClosed:
- return
- set_reconnect_urls(conn, msg)
- ssn.acknowledge(msg, sync=False)
-
- thread = Thread(name="auto-fetch-reconnect-urls", target=main)
- thread.setDaemon(True)
- thread.start()
-
-
-def set_reconnect_urls(conn, msg):
- reconnect_urls = []
- urls = msg.properties["amq.failover"]
- for u in urls:
- # FIXME aconway 2012-06-12: Nasty hack parsing of the C++ broker's URL format.
- if u.startswith("amqp:"):
- for a in u[5:].split(","):
- parts = a.split(":")
- # Handle IPv6 addresses which have : in the host part.
- port = parts[-1] # Last : separated field is port
- host = ":".join(parts[1:-1]) # First : separated field is protocol, host is the rest.
- reconnect_urls.append("%s:%s" % (host, port))
- conn.reconnect_urls = reconnect_urls
- log.warn("set reconnect_urls for conn %s: %s", conn, reconnect_urls)
-
-__all__ = ["auto_fetch_reconnect_urls", "set_reconnect_urls"]
diff --git a/qpid/python/qpid/mimetype.py b/qpid/python/qpid/mimetype.py
deleted file mode 100644
index f512996b9f..0000000000
--- a/qpid/python/qpid/mimetype.py
+++ /dev/null
@@ -1,106 +0,0 @@
-#
-# 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 re, rfc822
-from lexer import Lexicon, LexError
-from parser import Parser, ParseError
-
-l = Lexicon()
-
-LPAREN = l.define("LPAREN", r"\(")
-RPAREN = l.define("LPAREN", r"\)")
-SLASH = l.define("SLASH", r"/")
-SEMI = l.define("SEMI", r";")
-EQUAL = l.define("EQUAL", r"=")
-TOKEN = l.define("TOKEN", r'[^()<>@,;:\\"/\[\]?= ]+')
-STRING = l.define("STRING", r'"(?:[^\\"]|\\.)*"')
-WSPACE = l.define("WSPACE", r"[ \n\r\t]+")
-EOF = l.eof("EOF")
-
-LEXER = l.compile()
-
-def lex(st):
- return LEXER.lex(st)
-
-class MimeTypeParser(Parser):
-
- def __init__(self, tokens):
- Parser.__init__(self, [t for t in tokens if t.type is not WSPACE])
-
- def parse(self):
- result = self.mimetype()
- self.eat(EOF)
- return result
-
- def mimetype(self):
- self.remove_comments()
- self.reset()
-
- type = self.eat(TOKEN).value.lower()
- self.eat(SLASH)
- subtype = self.eat(TOKEN).value.lower()
-
- params = []
- while True:
- if self.matches(SEMI):
- params.append(self.parameter())
- else:
- break
-
- return type, subtype, params
-
- def remove_comments(self):
- while True:
- self.eat_until(LPAREN, EOF)
- if self.matches(LPAREN):
- self.remove(*self.comment())
- else:
- break
-
- def comment(self):
- start = self.eat(LPAREN)
-
- while True:
- self.eat_until(LPAREN, RPAREN)
- if self.matches(LPAREN):
- self.comment()
- else:
- break
-
- end = self.eat(RPAREN)
- return start, end
-
- def parameter(self):
- self.eat(SEMI)
- name = self.eat(TOKEN).value
- self.eat(EQUAL)
- value = self.value()
- return name, value
-
- def value(self):
- if self.matches(TOKEN):
- return self.eat().value
- elif self.matches(STRING):
- return rfc822.unquote(self.eat().value)
- else:
- raise ParseError(self.next(), TOKEN, STRING)
-
-def parse(addr):
- return MimeTypeParser(lex(addr)).parse()
-
-__all__ = ["parse", "ParseError"]
diff --git a/qpid/python/qpid/ops.py b/qpid/python/qpid/ops.py
deleted file mode 100644
index 390552be6d..0000000000
--- a/qpid/python/qpid/ops.py
+++ /dev/null
@@ -1,294 +0,0 @@
-#
-# 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 os, mllib, cPickle as pickle, sys
-from util import fill
-
-class Primitive(object):
- pass
-
-class Enum(object):
-
- # XXX: for backwards compatibility
- def values(cls):
- print >> sys.stderr, "warning, please use .VALUES instead of .values()"
- return cls.VALUES
- # we can't use the backport preprocessor here because this code gets
- # called by setup.py
- values = classmethod(values)
-
-class Field:
-
- def __init__(self, name, type, default=None):
- self.name = name
- self.type = type
- self.default = default
-
- def __repr__(self):
- return "%s: %s" % (self.name, self.type)
-
-class Compound(object):
-
- UNENCODED=[]
-
- def __init__(self, *args, **kwargs):
- args = list(args)
- for f in self.ARGS:
- if args:
- a = args.pop(0)
- else:
- a = kwargs.pop(f.name, f.default)
- setattr(self, f.name, a)
- if args:
- raise TypeError("%s takes at most %s arguments (%s given))" %
- (self.__class__.__name__, len(self.ARGS),
- len(self.ARGS) + len(args)))
- if kwargs:
- raise TypeError("got unexpected keyword argument '%s'" % kwargs.keys()[0])
-
- def fields(self):
- result = {}
- for f in self.FIELDS:
- result[f.name] = getattr(self, f.name)
- return result
-
- def args(self):
- result = {}
- for f in self.ARGS:
- result[f.name] = getattr(self, f.name)
- return result
-
- def __getitem__(self, attr):
- return getattr(self, attr)
-
- def __setitem__(self, attr, value):
- setattr(self, attr, value)
-
- def dispatch(self, target, *args):
- handler = "do_%s" % self.NAME
- getattr(target, handler)(self, *args)
-
- def __repr__(self, extras=()):
- return "%s(%s)" % (self.__class__.__name__,
- ", ".join(["%s=%r" % (f.name, getattr(self, f.name))
- for f in self.ARGS
- if getattr(self, f.name) != f.default]))
-
-class Command(Compound):
- UNENCODED=[Field("channel", "uint16", 0),
- Field("id", "sequence-no", None),
- Field("sync", "bit", False),
- Field("headers", None, None),
- Field("payload", None, None)]
-
-class Control(Compound):
- UNENCODED=[Field("channel", "uint16", 0)]
-
-def pythonize(st):
- if st is None:
- return None
- else:
- return str(st.replace("-", "_"))
-
-def pydoc(op, children=()):
- doc = "\n\n".join([fill(p.text(), 0) for p in op.query["doc"]])
- for ch in children:
- doc += "\n\n " + pythonize(ch["@name"]) + " -- " + str(ch["@label"])
- ch_descs ="\n\n".join([fill(p.text(), 4) for p in ch.query["doc"]])
- if ch_descs:
- doc += "\n\n" + ch_descs
- return doc
-
-def studly(st):
- return "".join([p.capitalize() for p in st.split("-")])
-
-def klass(nd):
- while nd.parent is not None:
- if hasattr(nd.parent, "name") and nd.parent.name == "class":
- return nd.parent
- else:
- nd = nd.parent
-
-def included(nd):
- cls = klass(nd)
- if cls is None:
- return True
- else:
- return cls["@name"] not in ("file", "stream")
-
-def num(s):
- if s: return int(s, 0)
-
-def code(nd):
- c = num(nd["@code"])
- if c is None:
- return None
- else:
- cls = klass(nd)
- if cls is None:
- return c
- else:
- return c | (num(cls["@code"]) << 8)
-
-def default(f):
- if f["@type"] == "bit":
- return False
- else:
- return None
-
-def make_compound(decl, base, domains):
- dict = {}
- fields = decl.query["field"]
- dict["__doc__"] = pydoc(decl, fields)
- dict["NAME"] = pythonize(decl["@name"])
- dict["SIZE"] = num(decl["@size"])
- dict["CODE"] = code(decl)
- dict["PACK"] = num(decl["@pack"])
- dict["FIELDS"] = [Field(pythonize(f["@name"]), resolve(f, domains),
- default(f))
- for f in fields]
- dict["ARGS"] = dict["FIELDS"] + base.UNENCODED
- return str(studly(decl["@name"])), (base,), dict
-
-def make_restricted(decl, domains):
- name = pythonize(decl["@name"])
- dict = {}
- choices = decl.query["choice"]
- dict["__doc__"] = pydoc(decl, choices)
- dict["NAME"] = name
- dict["TYPE"] = str(decl.parent["@type"])
- values = []
- for ch in choices:
- val = int(ch["@value"], 0)
- dict[pythonize(ch["@name"])] = val
- values.append(val)
- dict["VALUES"] = values
- return name, (Enum,), dict
-
-def make_type(decl, domains):
- name = pythonize(decl["@name"])
- dict = {}
- dict["__doc__"] = pydoc(decl)
- dict["NAME"] = name
- dict["CODE"] = code(decl)
- return str(studly(decl["@name"])), (Primitive,), dict
-
-def make_command(decl, domains):
- decl.set_attr("name", "%s-%s" % (decl.parent["@name"], decl["@name"]))
- decl.set_attr("size", "0")
- decl.set_attr("pack", "2")
- name, bases, dict = make_compound(decl, Command, domains)
- dict["RESULT"] = pythonize(decl["result/@type"]) or pythonize(decl["result/struct/@name"])
- return name, bases, dict
-
-def make_control(decl, domains):
- decl.set_attr("name", "%s-%s" % (decl.parent["@name"], decl["@name"]))
- decl.set_attr("size", "0")
- decl.set_attr("pack", "2")
- return make_compound(decl, Control, domains)
-
-def make_struct(decl, domains):
- return make_compound(decl, Compound, domains)
-
-def make_enum(decl, domains):
- decl.set_attr("name", decl.parent["@name"])
- return make_restricted(decl, domains)
-
-
-vars = globals()
-
-def make(nd, domains):
- return vars["make_%s" % nd.name](nd, domains)
-
-def qualify(nd, field="@name"):
- cls = klass(nd)
- if cls is None:
- return pythonize(nd[field])
- else:
- return pythonize("%s.%s" % (cls["@name"], nd[field]))
-
-def resolve(nd, domains):
- candidates = qualify(nd, "@type"), pythonize(nd["@type"])
- for c in candidates:
- if domains.has_key(c):
- while domains.has_key(c):
- c = domains[c]
- return c
- else:
- return c
-
-def load_types_from_xml(file):
- spec = mllib.xml_parse(file)
- domains = dict([(qualify(d), pythonize(d["@type"]))
- for d in spec.query["amqp/domain", included] + \
- spec.query["amqp/class/domain", included]])
- type_decls = \
- spec.query["amqp/class/command", included] + \
- spec.query["amqp/class/control", included] + \
- spec.query["amqp/class/command/result/struct", included] + \
- spec.query["amqp/class/struct", included] + \
- spec.query["amqp/class/domain/enum", included] + \
- spec.query["amqp/domain/enum", included] + \
- spec.query["amqp/type"]
- types = [make(nd, domains) for nd in type_decls]
- return types
-
-def load_types(file):
- base, ext = os.path.splitext(file)
- pclfile = "%s.pcl" % base
- if os.path.exists(pclfile) and \
- os.path.getmtime(pclfile) > os.path.getmtime(file):
- f = open(pclfile, "rb")
- types = pickle.load(f)
- f.close()
- else:
- types = load_types_from_xml(file)
- if os.access(os.path.dirname(os.path.abspath(pclfile)), os.W_OK):
- f = open(pclfile, "wb")
- pickle.dump(types, f)
- f.close()
- return types
-
-from specs_config import amqp_spec as file
-types = load_types(file)
-
-ENUMS = {}
-PRIMITIVE = {}
-COMPOUND = {}
-COMMANDS = {}
-CONTROLS = {}
-
-for name, bases, _dict in types:
- t = type(name, bases, _dict)
- vars[name] = t
-
- if issubclass(t, Command):
- COMMANDS[t.NAME] = t
- COMMANDS[t.CODE] = t
- elif issubclass(t, Control):
- CONTROLS[t.NAME] = t
- CONTROLS[t.CODE] = t
- elif issubclass(t, Compound):
- COMPOUND[t.NAME] = t
- if t.CODE is not None:
- COMPOUND[t.CODE] = t
- elif issubclass(t, Primitive):
- PRIMITIVE[t.NAME] = t
- PRIMITIVE[t.CODE] = t
- elif issubclass(t, Enum):
- ENUMS[t.NAME] = t
diff --git a/qpid/python/qpid/packer.py b/qpid/python/qpid/packer.py
deleted file mode 100644
index 22c16918dc..0000000000
--- a/qpid/python/qpid/packer.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# 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 struct
-
-class Packer:
-
- def read(self, n): abstract
-
- def write(self, s): abstract
-
- def unpack(self, fmt):
- values = struct.unpack(fmt, self.read(struct.calcsize(fmt)))
- if len(values) == 1:
- return values[0]
- else:
- return values
-
- def pack(self, fmt, *args):
- self.write(struct.pack(fmt, *args))
diff --git a/qpid/python/qpid/parser.py b/qpid/python/qpid/parser.py
deleted file mode 100644
index 233f0a8469..0000000000
--- a/qpid/python/qpid/parser.py
+++ /dev/null
@@ -1,68 +0,0 @@
-#
-# 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.
-#
-
-class ParseError(Exception):
-
- def __init__(self, token, *expected):
- line, ln, col = token.line_info()
- exp = ", ".join(map(str, expected))
- if len(expected) > 1:
- exp = "(%s)" % exp
- if expected:
- msg = "expecting %s, got %s line:%s,%s:%s" % (exp, token, ln, col, line)
- else:
- msg = "unexpected token %s line:%s,%s:%s" % (token, ln, col, line)
- Exception.__init__(self, msg)
- self.token = token
- self.expected = expected
-
-class Parser:
-
- def __init__(self, tokens):
- self.tokens = tokens
- self.idx = 0
-
- def next(self):
- return self.tokens[self.idx]
-
- def matches(self, *types):
- return self.next().type in types
-
- def eat(self, *types):
- if types and not self.matches(*types):
- raise ParseError(self.next(), *types)
- else:
- t = self.next()
- self.idx += 1
- return t
-
- def eat_until(self, *types):
- result = []
- while not self.matches(*types):
- result.append(self.eat())
- return result
-
- def remove(self, start, end):
- start_idx = self.tokens.index(start)
- end_idx = self.tokens.index(end) + 1
- del self.tokens[start_idx:end_idx]
- self.idx -= end_idx - start_idx
-
- def reset(self):
- self.idx = 0
diff --git a/qpid/python/qpid/peer.py b/qpid/python/qpid/peer.py
deleted file mode 100644
index fcad0f3ae6..0000000000
--- a/qpid/python/qpid/peer.py
+++ /dev/null
@@ -1,533 +0,0 @@
-#
-# 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.
-#
-
-"""
-This module contains a skeletal peer implementation useful for
-implementing an AMQP server, client, or proxy. The peer implementation
-sorts incoming frames to their intended channels, and dispatches
-incoming method frames to a delegate.
-"""
-
-import threading, traceback, socket, sys
-from connection08 import EOF, Method, Header, Body, Request, Response, VersionError
-from message import Message
-from queue import Queue, Closed as QueueClosed
-from content import Content
-from cStringIO import StringIO
-from time import time
-from exceptions import Closed, Timeout
-from logging import getLogger
-
-log = getLogger("qpid.peer")
-
-class Sequence:
-
- def __init__(self, start, step = 1):
- # we should keep start for wrap around
- self._next = start
- self.step = step
- self.lock = threading.Lock()
-
- def next(self):
- self.lock.acquire()
- try:
- result = self._next
- self._next += self.step
- return result
- finally:
- self.lock.release()
-
-class Peer:
-
- def __init__(self, conn, delegate, channel_factory=None, channel_options=None):
- self.conn = conn
- self.delegate = delegate
- self.outgoing = Queue(0)
- self.work = Queue(0)
- self.channels = {}
- self.lock = threading.Lock()
- if channel_factory:
- self.channel_factory = channel_factory
- else:
- self.channel_factory = Channel
- if channel_options is None:
- channel_options = {}
- self.channel_options = channel_options
-
- def channel(self, id):
- self.lock.acquire()
- try:
- try:
- ch = self.channels[id]
- except KeyError:
- ch = self.channel_factory(id, self.outgoing, self.conn.spec, self.channel_options)
- self.channels[id] = ch
- finally:
- self.lock.release()
- return ch
-
- def start(self):
- self.writer_thread = threading.Thread(target=self.writer)
- self.writer_thread.daemon = True
- self.writer_thread.start()
-
- self.reader_thread = threading.Thread(target=self.reader)
- self.reader_thread.daemon = True
- self.reader_thread.start()
-
- self.worker_thread = threading.Thread(target=self.worker)
- self.worker_thread.daemon = True
- self.worker_thread.start()
-
- def fatal(self, message=None):
- """Call when an unexpected exception occurs that will kill a thread."""
- self.closed("Fatal error: %s\n%s" % (message or "", traceback.format_exc()))
-
- def reader(self):
- try:
- while True:
- try:
- frame = self.conn.read()
- except EOF, e:
- self.work.close()
- break
- ch = self.channel(frame.channel)
- ch.receive(frame, self.work)
- except VersionError, e:
- self.closed(e)
- except:
- self.fatal()
-
- def closed(self, reason):
- # We must close the delegate first because closing channels
- # may wake up waiting threads and we don't want them to see
- # the delegate as open.
- self.delegate.closed(reason)
- for ch in self.channels.values():
- ch.closed(reason)
-
- def writer(self):
- try:
- while True:
- try:
- message = self.outgoing.get()
- self.conn.write(message)
- except socket.error, e:
- self.closed(e)
- break
- self.conn.flush()
- except QueueClosed:
- pass
- except:
- self.fatal()
-
- def worker(self):
- try:
- while True:
- queue = self.work.get()
- frame = queue.get()
- channel = self.channel(frame.channel)
- if frame.method_type.content:
- content = read_content(queue)
- else:
- content = None
-
- self.delegate(channel, Message(channel, frame, content))
- except QueueClosed:
- self.closed("worker closed")
- except:
- self.fatal()
-
- def stop(self):
- try:
- self.work.close();
- self.outgoing.close();
- self.conn.close();
- finally:
- timeout = 1;
- self.worker_thread.join(timeout);
- if self.worker_thread.isAlive():
- log.warn("Worker thread failed to shutdown within timeout")
- self.reader_thread.join(timeout);
- if self.reader_thread.isAlive():
- log.warn("Reader thread failed to shutdown within timeout")
- self.writer_thread.join(timeout);
- if self.writer_thread.isAlive():
- log.warn("Writer thread failed to shutdown within timeout")
-
-class Requester:
-
- def __init__(self, writer):
- self.write = writer
- self.sequence = Sequence(1)
- self.mark = 0
- # request_id -> listener
- self.outstanding = {}
-
- def request(self, method, listener, content = None):
- frame = Request(self.sequence.next(), self.mark, method)
- self.outstanding[frame.id] = listener
- self.write(frame, content)
-
- def receive(self, channel, frame):
- listener = self.outstanding.pop(frame.request_id)
- listener(channel, frame)
-
-class Responder:
-
- def __init__(self, writer):
- self.write = writer
- self.sequence = Sequence(1)
-
- def respond(self, method, batch, request):
- if isinstance(request, Method):
- self.write(method)
- else:
- # allow batching from frame at either end
- if batch<0:
- frame = Response(self.sequence.next(), request.id+batch, -batch, method)
- else:
- frame = Response(self.sequence.next(), request.id, batch, method)
- self.write(frame)
-
-class Channel:
-
- def __init__(self, id, outgoing, spec, options):
- self.id = id
- self.outgoing = outgoing
- self.spec = spec
- self.incoming = Queue(0)
- self.responses = Queue(0)
- self.queue = None
- self.content_queue = None
- self._closed = False
- self.reason = None
-
- self.requester = Requester(self.write)
- self.responder = Responder(self.write)
-
- self.completion = OutgoingCompletion()
- self.incoming_completion = IncomingCompletion(self)
- self.futures = {}
- self.control_queue = Queue(0)#used for incoming methods that appas may want to handle themselves
-
- self.invoker = self.invoke_method
- self.use_execution_layer = (spec.major == 0 and spec.minor == 10) or (spec.major == 99 and spec.minor == 0)
- self.synchronous = True
-
- self._flow_control_wait_failure = options.get("qpid.flow_control_wait_failure", 60)
- self._flow_control_wait_condition = threading.Condition()
- self._flow_control = False
-
- def closed(self, reason):
- if self._closed:
- return
- self._closed = True
- self.reason = reason
- self.incoming.close()
- self.responses.close()
- self.completion.close()
- self.incoming_completion.reset()
- for f in self.futures.values():
- f.put_response(self, reason)
-
- def write(self, frame, content = None):
- if self._closed:
- raise Closed(self.reason)
- frame.channel = self.id
- self.outgoing.put(frame)
- if (isinstance(frame, (Method, Request))
- and content == None
- and frame.method_type.content):
- content = Content()
- if content != None:
- self.write_content(frame.method_type.klass, content)
-
- def write_content(self, klass, content):
- header = Header(klass, content.weight(), content.size(), content.properties)
- self.write(header)
- for child in content.children:
- self.write_content(klass, child)
- # should split up if content.body exceeds max frame size
- if content.body:
- self.write(Body(content.body))
-
- def receive(self, frame, work):
- if isinstance(frame, Method):
- if frame.method_type.content:
- if frame.method.response:
- self.content_queue = self.responses
- else:
- self.content_queue = self.incoming
- if frame.method.response:
- self.queue = self.responses
- else:
- self.queue = self.incoming
- work.put(self.incoming)
- elif isinstance(frame, Request):
- self.queue = self.incoming
- work.put(self.incoming)
- elif isinstance(frame, Response):
- self.requester.receive(self, frame)
- if frame.method_type.content:
- self.queue = self.responses
- return
- elif isinstance(frame, Body) or isinstance(frame, Header):
- self.queue = self.content_queue
- self.queue.put(frame)
-
- def queue_response(self, channel, frame):
- channel.responses.put(frame.method)
-
- def request(self, method, listener, content = None):
- self.requester.request(method, listener, content)
-
- def respond(self, method, batch, request):
- self.responder.respond(method, batch, request)
-
- def invoke(self, type, args, kwargs):
- if (type.klass.name in ["channel", "session"]) and (type.name in ["close", "open", "closed"]):
- self.completion.reset()
- self.incoming_completion.reset()
- self.completion.next_command(type)
-
- content = kwargs.pop("content", None)
- frame = Method(type, type.arguments(*args, **kwargs))
- return self.invoker(frame, content)
-
- # used for 0-9
- def invoke_reliable(self, frame, content = None):
- if not self.synchronous:
- future = Future()
- self.request(frame, future.put_response, content)
- if not frame.method.responses: return None
- else: return future
-
- self.request(frame, self.queue_response, content)
- if not frame.method.responses:
- if self.use_execution_layer and frame.method_type.is_l4_command():
- self.execution_sync()
- self.completion.wait()
- if self._closed:
- raise Closed(self.reason)
- return None
- try:
- resp = self.responses.get()
- if resp.method_type.content:
- return Message(self, resp, read_content(self.responses))
- else:
- return Message(self, resp)
- except QueueClosed, e:
- if self._closed:
- raise Closed(self.reason)
- else:
- raise e
-
- # used for 0-8 and 0-10
- def invoke_method(self, frame, content = None):
- if frame.method.result:
- cmd_id = self.completion.command_id
- future = Future()
- self.futures[cmd_id] = future
-
- if frame.method.klass.name == "basic" and frame.method.name == "publish":
- self._flow_control_wait_condition.acquire()
- try:
- self.check_flow_control()
- self.write(frame, content)
- finally:
- self._flow_control_wait_condition.release()
- else:
- self.write(frame, content)
-
- try:
- # here we depend on all nowait fields being named nowait
- f = frame.method.fields.byname["nowait"]
- nowait = frame.args[frame.method.fields.index(f)]
- except KeyError:
- nowait = False
-
- try:
- if not nowait and frame.method.responses:
- resp = self.responses.get()
- if resp.method.content:
- content = read_content(self.responses)
- else:
- content = None
- if resp.method in frame.method.responses:
- return Message(self, resp, content)
- else:
- raise ValueError(resp)
- elif frame.method.result:
- if self.synchronous:
- fr = future.get_response(timeout=10)
- if self._closed:
- raise Closed(self.reason)
- return fr
- else:
- return future
- elif self.synchronous and not frame.method.response \
- and self.use_execution_layer and frame.method.is_l4_command():
- self.execution_sync()
- completed = self.completion.wait(timeout=10)
- if self._closed:
- raise Closed(self.reason)
- if not completed:
- self.closed("Timed-out waiting for completion of %s" % frame)
- except QueueClosed, e:
- if self._closed:
- raise Closed(self.reason)
- else:
- raise e
-
- # part of flow control for AMQP 0-8, 0-9, and 0-9-1
- def set_flow_control(self, value):
- self._flow_control_wait_condition.acquire()
- self._flow_control = value
- if value == False:
- self._flow_control_wait_condition.notify()
- self._flow_control_wait_condition.release()
-
- # part of flow control for AMQP 0-8, 0-9, and 0-9-1
- def check_flow_control(self):
- if self._flow_control:
- self._flow_control_wait_condition.wait(self._flow_control_wait_failure)
- if self._flow_control:
- raise Timeout("Unable to send message for " + str(self._flow_control_wait_failure) + " seconds due to broker enforced flow control")
-
- def __getattr__(self, name):
- type = self.spec.method(name)
- if type == None: raise AttributeError(name)
- method = lambda *args, **kwargs: self.invoke(type, args, kwargs)
- self.__dict__[name] = method
- return method
-
-def read_content(queue):
- header = queue.get()
- children = []
- for i in range(header.weight):
- children.append(read_content(queue))
- buf = StringIO()
- readbytes = 0
- while readbytes < header.size:
- body = queue.get()
- content = body.content
- buf.write(content)
- readbytes += len(content)
- return Content(buf.getvalue(), children, header.properties.copy())
-
-class Future:
- def __init__(self):
- self.completed = threading.Event()
-
- def put_response(self, channel, response):
- self.response = response
- self.completed.set()
-
- def get_response(self, timeout=None):
- self.completed.wait(timeout)
- if self.completed.isSet():
- return self.response
- else:
- return None
-
- def is_complete(self):
- return self.completed.isSet()
-
-class OutgoingCompletion:
- """
- Manages completion of outgoing commands i.e. command sent by this peer
- """
-
- def __init__(self):
- self.condition = threading.Condition()
-
- #todo, implement proper wraparound
- self.sequence = Sequence(0) #issues ids for outgoing commands
- self.command_id = -1 #last issued id
- self.mark = -1 #commands up to this mark are known to be complete
- self._closed = False
-
- def next_command(self, method):
- #the following test is a hack until the track/sub-channel is available
- if method.is_l4_command():
- self.command_id = self.sequence.next()
-
- def reset(self):
- self.sequence = Sequence(0) #reset counter
-
- def close(self):
- self.reset()
- self.condition.acquire()
- try:
- self._closed = True
- self.condition.notifyAll()
- finally:
- self.condition.release()
-
- def complete(self, mark):
- self.condition.acquire()
- try:
- self.mark = mark
- #print "set mark to %s [%s] " % (self.mark, self)
- self.condition.notifyAll()
- finally:
- self.condition.release()
-
- def wait(self, point_of_interest=-1, timeout=None):
- if point_of_interest == -1: point_of_interest = self.command_id
- start_time = time()
- remaining = timeout
- self.condition.acquire()
- try:
- while not self._closed and point_of_interest > self.mark:
- #print "waiting for %s, mark = %s [%s]" % (point_of_interest, self.mark, self)
- self.condition.wait(remaining)
- if not self._closed and point_of_interest > self.mark and timeout:
- if (start_time + timeout) < time(): break
- else: remaining = timeout - (time() - start_time)
- finally:
- self.condition.release()
- return point_of_interest <= self.mark
-
-class IncomingCompletion:
- """
- Manages completion of incoming commands i.e. command received by this peer
- """
-
- def __init__(self, channel):
- self.sequence = Sequence(0) #issues ids for incoming commands
- self.mark = -1 #id of last command of whose completion notification was sent to the other peer
- self.channel = channel
-
- def reset(self):
- self.sequence = Sequence(0) #reset counter
-
- def complete(self, mark, cumulative=True):
- if cumulative:
- if mark > self.mark:
- self.mark = mark
- self.channel.execution_complete(cumulative_execution_mark=self.mark)
- else:
- #TODO: record and manage the ranges properly
- range = [mark, mark]
- if (self.mark == -1):#hack until wraparound is implemented
- self.channel.execution_complete(cumulative_execution_mark=0xFFFFFFFFL, ranged_execution_set=range)
- else:
- self.channel.execution_complete(cumulative_execution_mark=self.mark, ranged_execution_set=range)
diff --git a/qpid/python/qpid/queue.py b/qpid/python/qpid/queue.py
deleted file mode 100644
index 63a7684843..0000000000
--- a/qpid/python/qpid/queue.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#
-# 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.
-#
-
-"""
-This module augments the standard python multithreaded Queue
-implementation to add a close() method so that threads blocking on the
-content of a queue can be notified if the queue is no longer in use.
-"""
-
-from Queue import Queue as BaseQueue, Empty, Full
-from threading import Thread
-from exceptions import Closed
-
-class Queue(BaseQueue):
-
- END = object()
- STOP = object()
-
- def __init__(self, *args, **kwargs):
- BaseQueue.__init__(self, *args, **kwargs)
- self.error = None
- self.listener = None
- self.exc_listener = None
- self.thread = None
-
- def close(self, error = None):
- self.error = error
- self.put(Queue.END)
- if self.thread is not None:
- self.thread.join()
- self.thread = None
-
- def get(self, block = True, timeout = None):
- result = BaseQueue.get(self, block, timeout)
- if result == Queue.END:
- # this guarantees that any other waiting threads or any future
- # calls to get will also result in a Closed exception
- self.put(Queue.END)
- raise Closed(self.error)
- else:
- return result
-
- def listen(self, listener, exc_listener = None):
- if listener is None and exc_listener is not None:
- raise ValueError("cannot set exception listener without setting listener")
-
- if listener is None:
- if self.thread is not None:
- self.put(Queue.STOP)
- # loop and timed join permit keyboard interrupts to work
- while self.thread.isAlive():
- self.thread.join(3)
- self.thread = None
-
- self.listener = listener
- self.exc_listener = exc_listener
-
- if listener is not None and self.thread is None:
- self.thread = Thread(target = self.run)
- self.thread.setDaemon(True)
- self.thread.start()
-
- def run(self):
- while True:
- try:
- o = self.get()
- if o == Queue.STOP: break
- self.listener(o)
- except Closed, e:
- if self.exc_listener is not None:
- self.exc_listener(e)
- break
diff --git a/qpid/python/qpid/reference.py b/qpid/python/qpid/reference.py
deleted file mode 100644
index 48ecb67656..0000000000
--- a/qpid/python/qpid/reference.py
+++ /dev/null
@@ -1,117 +0,0 @@
-#!/usr/bin/env 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.
-#
-
-"""
-Support for amqp 'reference' content (as opposed to inline content)
-"""
-
-import threading
-from queue import Queue, Closed
-
-class NotOpened(Exception): pass
-
-class AlreadyOpened(Exception): pass
-
-"""
-A representation of a reference id; can be passed wherever amqp
-content is required in place of inline data
-"""
-class ReferenceId:
-
- def __init__(self, id):
- self.id = id
-
-"""
-Holds content received through 'reference api'. Instances of this
-class will be placed in the consumers queue on receiving a transfer
-(assuming the reference has been opened). Data can be retrieved in
-chunks (as append calls are received) or in full (after reference has
-been closed signalling data s complete).
-"""
-
-class Reference:
-
- def __init__(self, id):
- self.id = id
- self.chunks = Queue(0)
-
- def close(self):
- self.chunks.close()
-
- def append(self, bytes):
- self.chunks.put(bytes)
-
- def get_chunk(self):
- return self.chunks.get()
-
- def get_complete(self):
- data = ""
- for chunk in self:
- data += chunk
- return data
-
- def next(self):
- try:
- return self.get_chunk()
- except Closed, e:
- raise StopIteration
-
- def __iter__(self):
- return self
-
-"""
-Manages a set of opened references. New references can be opened and
-existing references can be retrieved or closed.
-"""
-class References:
-
- def __init__(self):
- self.map = {}
- self.lock = threading.Lock()
-
- def get(self, id):
- self.lock.acquire()
- try:
- try:
- ref = self.map[id]
- except KeyError:
- raise NotOpened()
- finally:
- self.lock.release()
- return ref
-
- def open(self, id):
- self.lock.acquire()
- try:
- if id in self.map: raise AlreadyOpened()
- self.map[id] = Reference(id)
- finally:
- self.lock.release()
-
-
- def close(self, id):
- self.get(id).close()
- self.lock.acquire()
- try:
- self.map.pop(id)
- finally:
- self.lock.release()
-
diff --git a/qpid/python/qpid/sasl.py b/qpid/python/qpid/sasl.py
deleted file mode 100644
index a2147e3cc4..0000000000
--- a/qpid/python/qpid/sasl.py
+++ /dev/null
@@ -1,119 +0,0 @@
-#
-# 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 socket
-
-class SASLError(Exception):
- pass
-
-class WrapperClient:
-
- def __init__(self):
- self._cli = _Client()
-
- def setAttr(self, name, value):
- # Allow unicode user names and passwords
- if isinstance(value, unicode):
- value = value.encode('utf8')
- status = self._cli.setAttr(str(name), str(value))
- if status and name == 'username':
- status = self._cli.setAttr('externaluser', str(value))
-
- if not status:
- raise SASLError(self._cli.getError())
-
- def init(self):
- status = self._cli.init()
- if not status:
- raise SASLError(self._cli.getError())
-
- def start(self, mechanisms):
- status, mech, initial = self._cli.start(str(mechanisms))
- if status:
- return mech, initial
- else:
- raise SASLError(self._cli.getError())
-
- def step(self, challenge):
- status, response = self._cli.step(challenge)
- if status:
- return response
- else:
- raise SASLError(self._cli.getError())
-
- def encode(self, bytes):
- status, result = self._cli.encode(bytes)
- if status:
- return result
- else:
- raise SASLError(self._cli.getError())
-
- def decode(self, bytes):
- status, result = self._cli.decode(bytes)
- if status:
- return result
- else:
- raise SASLError(self._cli.getError())
-
- def auth_username(self):
- status, result = self._cli.getUserId()
- if status:
- return result
- else:
- raise SASLError(self._cli.getError())
-
-class PlainClient:
-
- def __init__(self):
- self.attrs = {}
-
- def setAttr(self, name, value):
- self.attrs[name] = value
-
- def init(self):
- pass
-
- def start(self, mechanisms):
- mechs = mechanisms.split()
- if self.attrs.get("username") and "PLAIN" in mechs:
- return "PLAIN", "\0%s\0%s" % (self.attrs.get("username"), self.attrs.get("password"))
- elif "ANONYMOUS" in mechs:
- return "ANONYMOUS", "%s@%s" % (self.attrs.get("username"), socket.gethostname())
- elif "EXTERNAL" in mechs:
- return "EXTERNAL", "%s" % (self.attrs.get("username"))
- else:
- raise SASLError("sasl negotiation failed: no mechanism agreed")
-
- def step(self, challenge):
- pass
-
- def encode(self, bytes):
- return bytes
-
- def decode(self, bytes):
- return bytes
-
- def auth_username(self):
- return self.attrs.get("username")
-
-try:
- from saslwrapper import Client as _Client
- Client = WrapperClient
-except ImportError:
- Client = PlainClient
diff --git a/qpid/python/qpid/saslmech/__init__.py b/qpid/python/qpid/saslmech/__init__.py
deleted file mode 100644
index ebcab03ca2..0000000000
--- a/qpid/python/qpid/saslmech/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# 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.
-#
-
-"""Pure python implementations of SASL mechanisms"""
-
-
diff --git a/qpid/python/qpid/saslmech/amqplain.py b/qpid/python/qpid/saslmech/amqplain.py
deleted file mode 100644
index 731f6b6628..0000000000
--- a/qpid/python/qpid/saslmech/amqplain.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# 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.
-#
-
-from sasl import Sasl
-
-class AMQPLAIN(Sasl):
-
- def initialResponse(self):
- return {"LOGIN": self.user, "PASSWORD": self.password}
-
- def priority(self):
- return 0 \ No newline at end of file
diff --git a/qpid/python/qpid/saslmech/anonymous.py b/qpid/python/qpid/saslmech/anonymous.py
deleted file mode 100644
index 1002a3aa0a..0000000000
--- a/qpid/python/qpid/saslmech/anonymous.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# 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.
-#
-
-from sasl import Sasl
-
-class ANONYMOUS(Sasl):
-
- def prerequisitesOk(self):
- return True
-
-
diff --git a/qpid/python/qpid/saslmech/cram_md5.py b/qpid/python/qpid/saslmech/cram_md5.py
deleted file mode 100644
index a351f43838..0000000000
--- a/qpid/python/qpid/saslmech/cram_md5.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# 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.
-#
-
-from sasl import Sasl
-from hmac import HMAC
-
-class CRAM_MD5(Sasl):
-
- def response(self, challenge):
- digest = HMAC( self.password, challenge).hexdigest()
- return "%s %s" % (self.user, digest)
diff --git a/qpid/python/qpid/saslmech/cram_md5_hex.py b/qpid/python/qpid/saslmech/cram_md5_hex.py
deleted file mode 100644
index 03463db083..0000000000
--- a/qpid/python/qpid/saslmech/cram_md5_hex.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# 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.
-#
-
-from sasl import Sasl
-from hmac import HMAC
-from hashlib import md5
-
-class CRAM_MD5_HEX(Sasl):
-
- def response(self, challenge):
- m = md5()
- m.update(self.password)
- digest = HMAC( m.hexdigest(), challenge).hexdigest()
- return "%s %s" % (self.user, digest)
diff --git a/qpid/python/qpid/saslmech/external.py b/qpid/python/qpid/saslmech/external.py
deleted file mode 100644
index 51c8d97530..0000000000
--- a/qpid/python/qpid/saslmech/external.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# 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.
-#
-
-from sasl import Sasl
-
-
-class EXTERNAL(Sasl):
- """Sasl mechanism used when SSL with client-auth is in use"""
-
- def prerequisitesOk(self):
- return True
diff --git a/qpid/python/qpid/saslmech/finder.py b/qpid/python/qpid/saslmech/finder.py
deleted file mode 100644
index 1dda9ec48f..0000000000
--- a/qpid/python/qpid/saslmech/finder.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#
-# 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.
-#
-
-
-from logging import getLogger
-
-log = getLogger("qpid.saslmech")
-
-def get_sasl_mechanism(mechanismNames, username, password, namespace="qpid.saslmech", sasl_options=None):
- """Given a list of SASL mechanism names, dynamically loads a SASL implementation
- from namespace qpid.sasl.mech respecting a mechanism priority"""
-
- log.debug("Supported mechanism : %s", mechanismNames)
-
- instances = []
- for mechanismName in mechanismNames:
- convertedName = mechanismName.replace("-","_")
- canonicalName = "%s.%s.%s" % (namespace, convertedName.lower(), convertedName)
- try:
- log.debug("Checking for SASL implementation %s for mechanism %s", canonicalName, mechanismName)
- clazz = _get_class(canonicalName)
- log.debug("Found SASL implementation")
- instance = clazz(username, password, mechanismName, sasl_options)
- if (instance.prerequisitesOk()):
- instances.append(instance)
- else:
- log.debug("SASL mechanism %s unavailable as the prerequistes for this mechanism have not been met", mechanismName)
- except (ImportError, AttributeError), e:
- # Unknown mechanism - this is normal if the server supports mechanism that the client does not
- log.debug("Could not load implementation for %s", canonicalName)
- pass
-
- if instances:
- instances.sort(key=lambda x : x.priority(), reverse=True)
- sasl = instances[0]
- log.debug("Selected SASL mechanism %s", sasl.mechanismName())
- return sasl
- else:
- return None
-
-def _get_class( kls ):
- parts = kls.split('.')
- module = ".".join(parts[:-1])
- m = __import__( module )
- for comp in parts[1:]:
- m = getattr(m, comp)
- return m
-
-
-
diff --git a/qpid/python/qpid/saslmech/plain.py b/qpid/python/qpid/saslmech/plain.py
deleted file mode 100644
index 8e6fb74f33..0000000000
--- a/qpid/python/qpid/saslmech/plain.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# 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.
-#
-
-from sasl import Sasl
-
-class PLAIN(Sasl):
-
- def initialResponse(self):
- return "\x00" + self.user + "\x00" + self.password
-
- def priority(self):
- return 0 \ No newline at end of file
diff --git a/qpid/python/qpid/saslmech/sasl.py b/qpid/python/qpid/saslmech/sasl.py
deleted file mode 100644
index 7b1ae058db..0000000000
--- a/qpid/python/qpid/saslmech/sasl.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# 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.
-#
-
-class SaslException(Exception): pass
-
-class Sasl:
-
- def __init__(self, user, password, name, sasl_options = None):
- self.user = user
- self.password = password
- self.name = name
- self.sasl_options = sasl_options
-
- def prerequisitesOk(self):
- return self.user is not None and self.password is not None
-
- def initialResponse(self):
- return
-
- def response(self, challenge):
- return
-
- def priority(self):
- """Priority of the mechanism. Mechanism with a higher value will be chosen in preference to those with a lower priority"""
- return 1
-
- def mechanismName(self):
- return self.name
diff --git a/qpid/python/qpid/saslmech/scram.py b/qpid/python/qpid/saslmech/scram.py
deleted file mode 100644
index 11a2d2fbe4..0000000000
--- a/qpid/python/qpid/saslmech/scram.py
+++ /dev/null
@@ -1,91 +0,0 @@
-#
-# 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.
-#
-
-from hmac import HMAC
-from binascii import b2a_hex
-from sasl import Sasl
-import os
-import base64
-
-class SCRAM_base(Sasl):
-
- def __init__(self, algorithm, user, password, name, sasl_options=None):
- Sasl.__init__(self, user, password, name, sasl_options)
- self.algorithm = algorithm
- self.client_nonce = b2a_hex(os.urandom(16))
- self.server_signature = None
-
- def initialResponse(self):
- name = self.user.replace("=","=3D").replace(",","=2C")
- self.client_first_message = "n=" + name + ",r=" + self.client_nonce
- return "n,," + self.client_first_message
-
-
- def response(self, challenge):
- if(self.server_signature):
- self.evaluateOutcome(challenge)
- return ""
- else:
- serverChallenge, salt, iterations = challenge.split(",")
- self.server_nonce = serverChallenge[2:]
- if self.server_nonce.find(self.client_nonce) != 0:
- raise SaslException("Server nonce does not start with client nonce")
- self.salt = base64.b64decode(salt[2:])
-
- iterations = int(iterations[2:])
-
- hmac = HMAC(key=self.password.replace("=","=3D").replace(",","=2C"),digestmod=self.algorithm)
-
- hmac.update(self.salt)
- hmac.update("\x00\x00\x00\x01")
-
- saltedPassword = hmac.digest()
- previous = saltedPassword
-
- for i in range(1,iterations):
- hmac = HMAC(key=self.password.replace("=","=3D").replace(",","=2C"),digestmod=self.algorithm)
- hmac.update(previous)
- previous = hmac.digest()
- saltedPassword = ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(saltedPassword,previous))
-
- clientFinalMessageWithoutProof = "c=" + base64.b64encode("n,,") + ",r=" + self.server_nonce
- authMessage = self.client_first_message + "," + challenge + "," + clientFinalMessageWithoutProof
-
- clientKey = HMAC(key=saltedPassword,msg="Client Key",digestmod=self.algorithm).digest()
- hashFunc = self.algorithm()
- hashFunc.update(clientKey)
- storedKey = hashFunc.digest()
-
- clientSignature = HMAC(key=storedKey, msg=authMessage, digestmod=self.algorithm).digest()
-
- clientProof = ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(clientKey,clientSignature))
-
- serverKey = HMAC(key=saltedPassword,msg="Server Key",digestmod=self.algorithm).digest()
-
- self.server_signature = HMAC(key=serverKey,msg=authMessage,digestmod=self.algorithm).digest()
- return clientFinalMessageWithoutProof + ",p=" + base64.b64encode(clientProof)
-
-
- def evaluateOutcome(self, challenge):
- serverVerification = challenge.split(",")[0]
-
- serverSignature = base64.b64decode(serverVerification[2:])
- if serverSignature != self.server_signature:
- raise SaslException("Server verification failed")
- return
diff --git a/qpid/python/qpid/saslmech/scram_sha_1.py b/qpid/python/qpid/saslmech/scram_sha_1.py
deleted file mode 100644
index 83f58f8e76..0000000000
--- a/qpid/python/qpid/saslmech/scram_sha_1.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# 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.
-#
-
-from scram import SCRAM_base
-from hashlib import sha1
-
-class SCRAM_SHA_1(SCRAM_base):
-
- def __init__(self, user, password, name, sasl_options=None):
- SCRAM_base.__init__(self, sha1, user, password, name, sasl_options)
-
diff --git a/qpid/python/qpid/saslmech/scram_sha_256.py b/qpid/python/qpid/saslmech/scram_sha_256.py
deleted file mode 100644
index cc894895c0..0000000000
--- a/qpid/python/qpid/saslmech/scram_sha_256.py
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# 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.
-#
-
-from scram import SCRAM_base
-import hashlib
-
-class SCRAM_SHA_256(SCRAM_base):
- def __init__(self, user, password, name, sasl_options=None):
- SCRAM_base.__init__(self,hashlib.sha256,user,password, name, sasl_options) \ No newline at end of file
diff --git a/qpid/python/qpid/selector.py b/qpid/python/qpid/selector.py
deleted file mode 100644
index 4a15d56662..0000000000
--- a/qpid/python/qpid/selector.py
+++ /dev/null
@@ -1,167 +0,0 @@
-#
-# 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 atexit, time, errno, os
-from compat import select, SelectError, set, selectable_waiter, format_exc
-from threading import Thread, Lock
-from logging import getLogger
-
-log = getLogger("qpid.messaging")
-
-class Acceptor:
-
- def __init__(self, sock, handler):
- self.sock = sock
- self.handler = handler
-
- def fileno(self):
- return self.sock.fileno()
-
- def reading(self):
- return True
-
- def writing(self):
- return False
-
- def readable(self):
- sock, addr = self.sock.accept()
- self.handler(sock)
-
-class Selector:
-
- lock = Lock()
- DEFAULT = None
- _current_pid = None
-
- @staticmethod
- def default():
- Selector.lock.acquire()
- try:
- if Selector.DEFAULT is None or Selector._current_pid != os.getpid():
- sel = Selector()
- atexit.register(sel.stop)
- sel.start()
- Selector.DEFAULT = sel
- Selector._current_pid = os.getpid()
- return Selector.DEFAULT
- finally:
- Selector.lock.release()
-
- def __init__(self):
- self.selectables = set()
- self.reading = set()
- self.writing = set()
- self.waiter = selectable_waiter()
- self.reading.add(self.waiter)
- self.stopped = False
- self.thread = None
- self.exception = None
-
- def wakeup(self):
- self.waiter.wakeup()
-
- def register(self, selectable):
- self.selectables.add(selectable)
- self.modify(selectable)
-
- def _update(self, selectable):
- if selectable.reading():
- self.reading.add(selectable)
- else:
- self.reading.discard(selectable)
- if selectable.writing():
- self.writing.add(selectable)
- else:
- self.writing.discard(selectable)
- return selectable.timing()
-
- def modify(self, selectable):
- self._update(selectable)
- self.wakeup()
-
- def unregister(self, selectable):
- self.reading.discard(selectable)
- self.writing.discard(selectable)
- self.selectables.discard(selectable)
- self.wakeup()
-
- def start(self):
- self.stopped = False
- self.thread = Thread(target=self.run)
- self.thread.setDaemon(True)
- self.thread.start();
-
- def run(self):
- try:
- while not self.stopped:
- wakeup = None
- for sel in self.selectables.copy():
- t = self._update(sel)
- if t is not None:
- if wakeup is None:
- wakeup = t
- else:
- wakeup = min(wakeup, t)
-
- rd = []
- wr = []
- ex = []
-
- while True:
- try:
- if wakeup is None:
- timeout = None
- else:
- timeout = max(0, wakeup - time.time())
- rd, wr, ex = select(self.reading, self.writing, (), timeout)
- break
- except SelectError, e:
- # Repeat the select call if we were interrupted.
- if e[0] == errno.EINTR:
- continue
- else:
- # unrecoverable: promote to outer try block
- raise
-
- for sel in wr:
- if sel.writing():
- sel.writeable()
-
- for sel in rd:
- if sel.reading():
- sel.readable()
-
- now = time.time()
- for sel in self.selectables.copy():
- w = sel.timing()
- if w is not None and now > w:
- sel.timeout()
- except Exception, e:
- self.exception = e
- info = format_exc()
- log.error("qpid.messaging I/O thread has died: %s" % str(e))
- for sel in self.selectables.copy():
- if hasattr(sel, "abort"):
- sel.abort(e, info)
- raise
-
- def stop(self, timeout=None):
- self.stopped = True
- self.wakeup()
- self.thread.join(timeout)
- self.thread = None
diff --git a/qpid/python/qpid/session.py b/qpid/python/qpid/session.py
deleted file mode 100644
index 95714a128a..0000000000
--- a/qpid/python/qpid/session.py
+++ /dev/null
@@ -1,308 +0,0 @@
-#
-# 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.
-#
-
-from threading import Condition, RLock, Lock, currentThread
-from generator import command_invoker
-from datatypes import RangedSet, Struct, Future
-from codec010 import StringCodec
-from queue import Queue
-from datatypes import Message, serial
-from ops import Command, MessageTransfer
-from util import wait, notify
-from exceptions import *
-from logging import getLogger
-
-log = getLogger("qpid.io.cmd")
-msg = getLogger("qpid.io.msg")
-
-class SessionException(Exception): pass
-class SessionClosed(SessionException): pass
-class SessionDetached(SessionException): pass
-
-def client(*args):
- return Client(*args)
-
-def server(*args):
- return Server(*args)
-
-INCOMPLETE = object()
-
-class Session(command_invoker()):
-
- def __init__(self, name, auto_sync=True, timeout=10, delegate=client):
- self.name = name
- self.auto_sync = auto_sync
- self.need_sync = True
- self.timeout = timeout
- self.channel = None
- self.invoke_lock = Lock()
- self._closing = False
- self._closed = False
-
- self.condition = Condition()
-
- self.send_id = True
- self.receiver = Receiver(self)
- self.sender = Sender(self)
-
- self.lock = RLock()
- self._incoming = {}
- self.results = {}
- self.exceptions = []
-
- self.delegate = delegate(self)
-
- def incoming(self, destination):
- self.lock.acquire()
- try:
- queue = self._incoming.get(destination)
- if queue == None:
- queue = Incoming(self, destination)
- self._incoming[destination] = queue
- return queue
- finally:
- self.lock.release()
-
- def error(self):
- exc = self.exceptions[:]
- if len(exc) == 0:
- return None
- elif len(exc) == 1:
- return exc[0]
- else:
- return tuple(exc)
-
- def sync(self, timeout=None):
- ch = self.channel
- if ch is not None and currentThread() == ch.connection.thread:
- raise SessionException("deadlock detected")
- if self.need_sync:
- self.execution_sync(sync=True)
- last = self.sender.next_id - 1
- if not wait(self.condition, lambda:
- last in self.sender._completed or self.exceptions,
- timeout):
- raise Timeout()
- if self.exceptions:
- raise SessionException(self.error())
-
- def close(self, timeout=None):
- self.invoke_lock.acquire()
- try:
- self._closing = True
- self.channel.session_detach(self.name)
- finally:
- self.invoke_lock.release()
- if not wait(self.condition, lambda: self._closed, timeout):
- raise Timeout()
-
- def closed(self):
- self.lock.acquire()
- try:
- if self._closed: return
-
- error = self.error()
- for id in self.results:
- f = self.results[id]
- f.error(error)
- self.results.clear()
-
- for q in self._incoming.values():
- q.close(error)
-
- self._closed = True
- notify(self.condition)
- finally:
- self.lock.release()
-
- def invoke(self, op, args, kwargs):
- if issubclass(op, Command):
- self.invoke_lock.acquire()
- try:
- return self.do_invoke(op, args, kwargs)
- finally:
- self.invoke_lock.release()
- else:
- return op(*args, **kwargs)
-
- def do_invoke(self, op, args, kwargs):
- if self._closing:
- raise SessionClosed()
-
- ch = self.channel
- if ch == None:
- raise SessionDetached()
-
- if op == MessageTransfer:
- if len(args) == len(op.FIELDS) + 1:
- message = args[-1]
- args = args[:-1]
- else:
- message = kwargs.pop("message", None)
- if message is not None:
- kwargs["headers"] = message.headers
- kwargs["payload"] = message.body
-
- cmd = op(*args, **kwargs)
- cmd.sync = self.auto_sync or cmd.sync
- self.need_sync = not cmd.sync
- cmd.channel = ch.id
-
- if op.RESULT:
- result = Future(exception=SessionException)
- self.results[self.sender.next_id] = result
-
- self.send(cmd)
-
- log.debug("SENT %s", cmd)
- if op == MessageTransfer:
- msg.debug("SENT %s", cmd)
-
- if op.RESULT:
- if self.auto_sync:
- return result.get(self.timeout)
- else:
- return result
- elif self.auto_sync:
- self.sync(self.timeout)
-
- def received(self, cmd):
- self.receiver.received(cmd)
- self.dispatch(cmd)
-
- def dispatch(self, cmd):
- log.debug("RECV %s", cmd)
-
- result = getattr(self.delegate, cmd.NAME)(cmd)
- if result is INCOMPLETE:
- return
- elif result is not None:
- self.execution_result(cmd.id, result)
-
- self.receiver.completed(cmd)
- # XXX: don't forget to obey sync for manual completion as well
- if cmd.sync:
- self.channel.session_completed(self.receiver._completed)
-
- def send(self, cmd):
- self.sender.send(cmd)
-
- def __repr__(self):
- return '<Session: %s, %s>' % (self.name, self.channel)
-
-class Receiver:
-
- def __init__(self, session):
- self.session = session
- self.next_id = None
- self._completed = RangedSet()
-
- def received(self, cmd):
- if self.next_id == None:
- raise Exception("todo")
- cmd.id = self.next_id
- self.next_id += 1
-
- def completed(self, cmd):
- if cmd.id == None:
- raise ValueError("cannot complete unidentified command")
- self._completed.add(cmd.id)
-
- def known_completed(self, commands):
- completed = RangedSet()
- for c in self._completed.ranges:
- for kc in commands.ranges:
- if c.lower in kc and c.upper in kc:
- break
- else:
- completed.add_range(c)
- self._completed = completed
-
-class Sender:
-
- def __init__(self, session):
- self.session = session
- self.next_id = serial(0)
- self.commands = []
- self._completed = RangedSet()
-
- def send(self, cmd):
- ch = self.session.channel
- if ch is None:
- raise SessionDetached()
- cmd.id = self.next_id
- self.next_id += 1
- if self.session.send_id:
- self.session.send_id = False
- ch.session_command_point(cmd.id, 0)
- self.commands.append(cmd)
- ch.connection.write_op(cmd)
-
- def completed(self, commands):
- idx = 0
- while idx < len(self.commands):
- cmd = self.commands[idx]
- if cmd.id in commands:
- del self.commands[idx]
- else:
- idx += 1
- for range in commands.ranges:
- self._completed.add(range.lower, range.upper)
-
-class Incoming(Queue):
-
- def __init__(self, session, destination):
- Queue.__init__(self)
- self.session = session
- self.destination = destination
-
- def start(self):
- self.session.message_set_flow_mode(self.destination, self.session.flow_mode.credit)
- for unit in self.session.credit_unit.VALUES:
- self.session.message_flow(self.destination, unit, 0xFFFFFFFFL)
-
- def stop(self):
- self.session.message_cancel(self.destination)
- self.listen(None)
-
-class Delegate:
-
- def __init__(self, session):
- self.session = session
-
- #XXX: do something with incoming accepts
- def message_accept(self, ma): None
-
- def execution_result(self, er):
- future = self.session.results.pop(er.command_id)
- future.set(er.value)
-
- def execution_exception(self, ex):
- self.session.exceptions.append(ex)
-
-class Client(Delegate):
-
- def message_transfer(self, cmd):
- m = Message(cmd.payload)
- m.headers = cmd.headers
- m.id = cmd.id
- messages = self.session.incoming(cmd.destination)
- messages.put(m)
- msg.debug("RECV %s", m)
- return INCOMPLETE
diff --git a/qpid/python/qpid/spec08.py b/qpid/python/qpid/spec08.py
deleted file mode 100644
index a0047e7107..0000000000
--- a/qpid/python/qpid/spec08.py
+++ /dev/null
@@ -1,504 +0,0 @@
-#
-# 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.
-#
-
-"""
-This module loads protocol metadata into python objects. It provides
-access to spec metadata via a python object model, and can also
-dynamically creating python methods, classes, and modules based on the
-spec metadata. All the generated methods have proper signatures and
-doc strings based on the spec metadata so the python help system can
-be used to browse the spec documentation. The generated methods all
-dispatch to the self.invoke(meth, args) callback of the containing
-class so that the generated code can be reused in a variety of
-situations.
-"""
-
-import re, new, mllib, qpid
-from util import fill
-
-class SpecContainer:
-
- def __init__(self):
- self.items = []
- self.byname = {}
- self.byid = {}
- self.indexes = {}
-
- def add(self, item):
- if self.byname.has_key(item.name):
- raise ValueError("duplicate name: %s" % item)
- if item.id == None:
- item.id = len(self)
- elif self.byid.has_key(item.id):
- raise ValueError("duplicate id: %s" % item)
- self.indexes[item] = len(self.items)
- self.items.append(item)
- self.byname[item.name] = item
- self.byid[item.id] = item
-
- def index(self, item):
- try:
- return self.indexes[item]
- except KeyError:
- raise ValueError(item)
-
- def __iter__(self):
- return iter(self.items)
-
- def __len__(self):
- return len(self.items)
-
-class Metadata:
-
- PRINT = []
-
- def __init__(self):
- pass
-
- def __str__(self):
- args = map(lambda f: "%s=%s" % (f, getattr(self, f)), self.PRINT)
- return "%s(%s)" % (self.__class__.__name__, ", ".join(args))
-
- def __repr__(self):
- return str(self)
-
-class Spec(Metadata):
-
- PRINT=["major", "minor", "file"]
-
- def __init__(self, major, minor, file):
- Metadata.__init__(self)
- self.major = major
- self.minor = minor
- self.file = file
- self.constants = SpecContainer()
- self.domains = SpecContainer()
- self.classes = SpecContainer()
- # methods indexed by classname_methname
- self.methods = {}
- # structs by type code
- self.structs = {}
-
- def post_load(self):
- self.module = self.define_module("amqp%s%s" % (self.major, self.minor))
- self.klass = self.define_class("Amqp%s%s" % (self.major, self.minor))
-
- def method(self, name):
- if not self.methods.has_key(name):
- for cls in self.classes:
- clen = len(cls.name)
- if name.startswith(cls.name) and name[clen] == "_":
- end = name[clen + 1:]
- if cls.methods.byname.has_key(end):
- self.methods[name] = cls.methods.byname[end]
- return self.methods.get(name)
-
- def parse_method(self, name):
- parts = re.split(r"\s*\.\s*", name)
- if len(parts) != 2:
- raise ValueError(name)
- klass, meth = parts
- return self.classes.byname[klass].methods.byname[meth]
-
- def struct(self, name, *args, **kwargs):
- type = self.domains.byname[name].type
- return qpid.Struct(type, *args, **kwargs)
-
- def define_module(self, name, doc = None):
- module = new.module(name, doc)
- module.__file__ = self.file
- for c in self.classes:
- cls = c.define_class(c.name)
- cls.__module__ = module.__name__
- setattr(module, c.name, cls)
- return module
-
- def define_class(self, name):
- methods = {}
- for c in self.classes:
- for m in c.methods:
- meth = m.klass.name + "_" + m.name
- methods[meth] = m.define_method(meth)
- return type(name, (), methods)
-
-class Constant(Metadata):
-
- PRINT=["name", "id"]
-
- def __init__(self, spec, name, id, klass, docs):
- Metadata.__init__(self)
- self.spec = spec
- self.name = name
- self.id = id
- self.klass = klass
- self.docs = docs
-
-class Domain(Metadata):
-
- PRINT=["name", "type"]
-
- def __init__(self, spec, name, type, description, docs):
- Metadata.__init__(self)
- self.spec = spec
- self.id = None
- self.name = name
- self.type = type
- self.description = description
- self.docs = docs
-
-class Struct(Metadata):
-
- PRINT=["size", "type", "pack"]
-
- def __init__(self, size, type, pack):
- Metadata.__init__(self)
- self.size = size
- self.type = type
- self.pack = pack
- self.fields = SpecContainer()
-
-class Class(Metadata):
-
- PRINT=["name", "id"]
-
- def __init__(self, spec, name, id, handler, docs):
- Metadata.__init__(self)
- self.spec = spec
- self.name = name
- self.id = id
- self.handler = handler
- self.fields = SpecContainer()
- self.methods = SpecContainer()
- self.docs = docs
-
- def define_class(self, name):
- methods = {}
- for m in self.methods:
- methods[m.name] = m.define_method(m.name)
- return type(name, (), methods)
-
-class Method(Metadata):
-
- PRINT=["name", "id"]
-
- def __init__(self, klass, name, id, content, responses, result, synchronous,
- description, docs):
- Metadata.__init__(self)
- self.klass = klass
- self.name = name
- self.id = id
- self.content = content
- self.responses = responses
- self.result = result
- self.synchronous = synchronous
- self.fields = SpecContainer()
- self.description = description
- self.docs = docs
- self.response = False
-
- def is_l4_command(self):
- return self.klass.name not in ["execution", "channel", "connection", "session"]
-
- def arguments(self, *args, **kwargs):
- nargs = len(args) + len(kwargs)
- maxargs = len(self.fields)
- if nargs > maxargs:
- self._type_error("takes at most %s arguments (%s) given", maxargs, nargs)
- result = []
- for f in self.fields:
- idx = self.fields.index(f)
- if idx < len(args):
- result.append(args[idx])
- elif kwargs.has_key(f.name):
- result.append(kwargs.pop(f.name))
- else:
- result.append(Method.DEFAULTS[f.type])
- for key, value in kwargs.items():
- if self.fields.byname.has_key(key):
- self._type_error("got multiple values for keyword argument '%s'", key)
- else:
- self._type_error("got an unexpected keyword argument '%s'", key)
- return tuple(result)
-
- def _type_error(self, msg, *args):
- raise TypeError("%s %s" % (self.name, msg % args))
-
- def docstring(self):
- s = "\n\n".join([fill(d, 2) for d in [self.description] + self.docs])
- for f in self.fields:
- if f.docs:
- s += "\n\n" + "\n\n".join([fill(f.docs[0], 4, f.name)] +
- [fill(d, 4) for d in f.docs[1:]])
- if self.responses:
- s += "\n\nValid responses: "
- for r in self.responses:
- s += r.name + " "
- return s
-
- METHOD = "__method__"
- DEFAULTS = {"bit": False,
- "shortstr": "",
- "longstr": "",
- "table": {},
- "array": [],
- "octet": 0,
- "short": 0,
- "long": 0,
- "longlong": 0,
- "timestamp": 0,
- "content": None,
- "uuid": "",
- "rfc1982_long": 0,
- "rfc1982_long_set": [],
- "long_struct": None}
-
- def define_method(self, name):
- g = {Method.METHOD: self}
- l = {}
- args = [(f.name, Method.DEFAULTS[f.type]) for f in self.fields]
- methargs = args[:]
- if self.content:
- args += [("content", None)]
- code = "def %s(self, %s):\n" % \
- (name, ", ".join(["%s = %r" % a for a in args]))
- code += " %r\n" % self.docstring()
- argnames = ", ".join([a[0] for a in methargs])
- code += " return self.invoke(%s" % Method.METHOD
- if argnames:
- code += ", (%s,)" % argnames
- else:
- code += ", ()"
- if self.content:
- code += ", content"
- code += ")"
- exec code in g, l
- return l[name]
-
-class Field(Metadata):
-
- PRINT=["name", "id", "type"]
-
- def __init__(self, name, id, type, domain, description, docs):
- Metadata.__init__(self)
- self.name = name
- self.id = id
- self.type = type
- self.domain = domain
- self.description = description
- self.docs = docs
-
- def default(self):
- if isinstance(self.type, Struct):
- return None
- else:
- return Method.DEFAULTS[self.type]
-
-WIDTHS = {
- "octet": 1,
- "short": 2,
- "long": 4
- }
-
-def width(st, default=None):
- if st in (None, "none", ""):
- return default
- else:
- return WIDTHS[st]
-
-def get_result(nd, spec):
- result = nd["result"]
- if not result: return None
- name = result["@domain"]
- if name != None: return spec.domains.byname[name]
- st_nd = result["struct"]
- st = Struct(width(st_nd["@size"]), int(result.parent.parent["@index"])*256 +
- int(st_nd["@type"]), width(st_nd["@pack"], 2))
- spec.structs[st.type] = st
- load_fields(st_nd, st.fields, spec.domains.byname)
- return st
-
-def get_desc(nd):
- label = nd["@label"]
- if not label:
- label = nd.text()
- if label:
- label = label.strip()
- return label
-
-def get_docs(nd):
- return [n.text() for n in nd.query["doc"]]
-
-def load_fields(nd, l, domains):
- for f_nd in nd.query["field"]:
- type = f_nd["@domain"]
- if type == None:
- type = f_nd["@type"]
- type = pythonize(type)
- domain = None
- while domains.has_key(type) and domains[type].type != type:
- domain = domains[type]
- type = domain.type
- l.add(Field(pythonize(f_nd["@name"]), f_nd.index(), type, domain,
- get_desc(f_nd), get_docs(f_nd)))
-
-def load(specfile, *errata):
- doc = mllib.xml_parse(specfile)
- spec_root = doc["amqp"]
- spec = Spec(int(spec_root["@major"]), int(spec_root["@minor"]), specfile)
-
- for root in [spec_root] + map(lambda x: mllib.xml_parse(x)["amqp"], errata):
- # constants
- for nd in root.query["constant"]:
- val = nd["@value"]
- if val.startswith("0x"): val = int(val, 16)
- else: val = int(val)
- const = Constant(spec, pythonize(nd["@name"]), val, nd["@class"],
- get_docs(nd))
- try:
- spec.constants.add(const)
- except ValueError, e:
- pass
- #print "Warning:", e
-
- # domains are typedefs
- structs = []
- for nd in root.query["domain"]:
- type = nd["@type"]
- if type == None:
- st_nd = nd["struct"]
- code = st_nd["@type"]
- if code not in (None, "", "none"):
- code = int(code)
- type = Struct(width(st_nd["@size"]), code, width(st_nd["@pack"], 2))
- if type.type != None:
- spec.structs[type.type] = type
- structs.append((type, st_nd))
- else:
- type = pythonize(type)
- domain = Domain(spec, pythonize(nd["@name"]), type, get_desc(nd),
- get_docs(nd))
- spec.domains.add(domain)
-
- # structs
- for st, st_nd in structs:
- load_fields(st_nd, st.fields, spec.domains.byname)
-
- # classes
- for c_nd in root.query["class"]:
- cname = pythonize(c_nd["@name"])
- if spec.classes.byname.has_key(cname):
- klass = spec.classes.byname[cname]
- else:
- klass = Class(spec, cname, int(c_nd["@index"]), c_nd["@handler"],
- get_docs(c_nd))
- spec.classes.add(klass)
-
- added_methods = []
- load_fields(c_nd, klass.fields, spec.domains.byname)
- for m_nd in c_nd.query["method"]:
- mname = pythonize(m_nd["@name"])
- if klass.methods.byname.has_key(mname):
- meth = klass.methods.byname[mname]
- else:
- meth = Method(klass, mname,
- int(m_nd["@index"]),
- m_nd["@content"] == "1",
- [pythonize(nd["@name"]) for nd in m_nd.query["response"]],
- get_result(m_nd, spec),
- m_nd["@synchronous"] == "1",
- get_desc(m_nd),
- get_docs(m_nd))
- klass.methods.add(meth)
- added_methods.append(meth)
- load_fields(m_nd, meth.fields, spec.domains.byname)
- # resolve the responses
- for m in added_methods:
- m.responses = [klass.methods.byname[r] for r in m.responses]
- for resp in m.responses:
- resp.response = True
-
- spec.post_load()
- return spec
-
-REPLACE = {" ": "_", "-": "_"}
-KEYWORDS = {"global": "global_",
- "return": "return_"}
-
-def pythonize(name):
- name = str(name)
- for key, val in REPLACE.items():
- name = name.replace(key, val)
- try:
- name = KEYWORDS[name]
- except KeyError:
- pass
- return name
-
-class Rule(Metadata):
-
- PRINT = ["text", "implement", "tests"]
-
- def __init__(self, text, implement, tests, path):
- self.text = text
- self.implement = implement
- self.tests = tests
- self.path = path
-
-def find_rules(node, rules):
- if node.name == "rule":
- rules.append(Rule(node.text, node.get("@implement"),
- [ch.text for ch in node if ch.name == "test"],
- node.path()))
- if node.name == "doc" and node.get("@name") == "rule":
- tests = []
- if node.has("@test"):
- tests.append(node["@test"])
- rules.append(Rule(node.text, None, tests, node.path()))
- for child in node:
- find_rules(child, rules)
-
-def load_rules(specfile):
- rules = []
- find_rules(xmlutil.parse(specfile), rules)
- return rules
-
-def test_summary():
- template = """
- <html><head><title>AMQP Tests</title></head>
- <body>
- <table width="80%%" align="center">
- %s
- </table>
- </body>
- </html>
- """
- rows = []
- for rule in load_rules("amqp.org/specs/amqp7.xml"):
- if rule.tests:
- tests = ", ".join(rule.tests)
- else:
- tests = "&nbsp;"
- rows.append('<tr bgcolor="#EEEEEE"><td><b>Path:</b> %s</td>'
- '<td><b>Implement:</b> %s</td>'
- '<td><b>Tests:</b> %s</td></tr>' %
- (rule.path[len("/root/amqp"):], rule.implement, tests))
- rows.append('<tr><td colspan="3">%s</td></tr>' % rule.text)
- rows.append('<tr><td colspan="3">&nbsp;</td></tr>')
-
- print template % "\n".join(rows)
diff --git a/qpid/python/qpid/specs/amqp-0-10-qpid-errata-stripped.xml b/qpid/python/qpid/specs/amqp-0-10-qpid-errata-stripped.xml
deleted file mode 100644
index 83ddf709e9..0000000000
--- a/qpid/python/qpid/specs/amqp-0-10-qpid-errata-stripped.xml
+++ /dev/null
@@ -1,1203 +0,0 @@
-<?xml version="1.0"?>
-
-<!--
-(c) Copyright Cisco Systems, Credit Suisse, Deutsche Borse Systems,
-Envoy Technologies, Inc., Goldman Sachs, IONA Technologies PLC, iMatix
-Corporation sprl.,JPMorgan Chase Bank Inc. N.A, Novell, Rabbit
-Technologies Ltd., Red Hat, Inc., TWIST Process Innovations ltd, and
-29West Inc. 2006, 2007.
-
-Copyright (c) 2009 AMQP Working Group.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
-derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--->
-
-<amqp major="0" xmlns="http://www.amqp.org/schema/amqp.xsd" port="5672" minor="10">
- <type name="bin8" code="0x00" fixed-width="1"/>
- <type name="int8" code="0x01" fixed-width="1"/>
- <type name="uint8" code="0x02" fixed-width="1"/>
- <type name="char" code="0x04" fixed-width="1"/>
- <type name="boolean" code="0x08" fixed-width="1"/>
- <type name="bin16" code="0x10" fixed-width="2"/>
- <type name="int16" code="0x11" fixed-width="2"/>
- <type name="uint16" code="0x12" fixed-width="2"/>
- <type name="bin32" code="0x20" fixed-width="4"/>
- <type name="int32" code="0x21" fixed-width="4"/>
- <type name="uint32" code="0x22" fixed-width="4"/>
- <type name="float" code="0x23" fixed-width="4"/>
- <type name="char-utf32" code="0x27" fixed-width="4"/>
- <type name="sequence-no" fixed-width="4"/>
- <type name="bin64" code="0x30" fixed-width="8"/>
- <type name="int64" code="0x31" fixed-width="8"/>
- <type name="uint64" code="0x32" fixed-width="8"/>
- <type name="double" code="0x33" fixed-width="8"/>
- <type name="datetime" code="0x38" fixed-width="8"/>
- <type name="bin128" code="0x40" fixed-width="16"/>
- <type name="uuid" code="0x48" fixed-width="16"/>
- <type name="bin256" code="0x50" fixed-width="32"/>
- <type name="bin512" code="0x60" fixed-width="64"/>
- <type name="bin1024" code="0x70" fixed-width="128"/>
- <type name="vbin8" code="0x80" variable-width="1"/>
- <type name="str8-latin" code="0x84" variable-width="1"/>
- <type name="str8" code="0x85" variable-width="1"/>
- <type name="str8-utf16" code="0x86" variable-width="1"/>
- <type name="vbin16" code="0x90" variable-width="2"/>
- <type name="str16-latin" code="0x94" variable-width="2"/>
- <type name="str16" code="0x95" variable-width="2"/>
- <type name="str16-utf16" code="0x96" variable-width="2"/>
- <type name="byte-ranges" variable-width="2"/>
- <type name="sequence-set" variable-width="2"/>
- <type name="vbin32" code="0xa0" variable-width="4"/>
- <type name="map" code="0xa8" variable-width="4"/>
- <type name="list" code="0xa9" variable-width="4"/>
- <type name="array" code="0xaa" variable-width="4"/>
- <type name="struct32" code="0xab" variable-width="4"/>
- <type name="bin40" code="0xc0" fixed-width="5"/>
- <type name="dec32" code="0xc8" fixed-width="5"/>
- <type name="bin72" code="0xd0" fixed-width="9"/>
- <type name="dec64" code="0xd8" fixed-width="9"/>
- <type name="void" code="0xf0" fixed-width="0"/>
- <type name="bit" code="0xf1" fixed-width="0"/>
- <constant name="MIN-MAX-FRAME-SIZE" value="4096"/>
- <domain name="segment-type" type="uint8">
- <enum>
- <choice name="control" value="0"/>
- <choice name="command" value="1"/>
- <choice name="header" value="2"/>
- <choice name="body" value="3"/>
- </enum>
- </domain>
- <domain name="track" type="uint8">
- <enum>
- <choice name="control" value="0"/>
- <choice name="command" value="1"/>
- </enum>
- </domain>
- <domain name="str16-array" type="array"/>
- <class name="connection" code="0x1">
- <role name="server" implement="MUST"/>
- <role name="client" implement="MUST"/>
- <domain name="close-code" type="uint16">
- <enum>
- <choice name="normal" value="200"/>
- <choice name="connection-forced" value="320"/>
- <choice name="invalid-path" value="402"/>
- <choice name="framing-error" value="501"/>
- </enum>
- </domain>
- <domain name="amqp-host-url" type="str16"/>
- <domain name="amqp-host-array" type="array"/>
- <control name="start" code="0x1">
- <rule name="protocol-name"/>
- <rule name="client-support"/>
- <implement role="client" handle="MUST"/>
- <response name="start-ok"/>
- <field name="server-properties" type="map">
- <rule name="required-fields"/>
- </field>
- <field name="mechanisms" type="str16-array" required="true"/>
- <field name="locales" type="str16-array" required="true">
- <rule name="required-support"/>
- </field>
- </control>
- <control name="start-ok" code="0x2">
- <implement role="server" handle="MUST"/>
- <field name="client-properties" type="map">
- <rule name="required-fields"/>
- </field>
- <field name="mechanism" type="str8" required="true">
- <rule name="security"/>
- <rule name="validity"/>
- </field>
- <field name="response" type="vbin32" required="true"/>
- <field name="locale" type="str8" required="true"/>
- </control>
- <control name="secure" code="0x3">
- <implement role="client" handle="MUST"/>
- <response name="secure-ok"/>
- <field name="challenge" type="vbin32" required="true"/>
- </control>
- <control name="secure-ok" code="0x4">
- <implement role="server" handle="MUST"/>
- <field name="response" type="vbin32" required="true"/>
- </control>
- <control name="tune" code="0x5">
- <implement role="client" handle="MUST"/>
- <response name="tune-ok"/>
- <field name="channel-max" type="uint16"/>
- <field name="max-frame-size" type="uint16">
- <rule name="minimum"/>
- </field>
- <field name="heartbeat-min" type="uint16"/>
- <field name="heartbeat-max" type="uint16">
- <rule name="permitted-range"/>
- <rule name="no-heartbeat-min"/>
- </field>
- </control>
- <control name="tune-ok" code="0x6">
- <implement role="server" handle="MUST"/>
- <field name="channel-max" type="uint16" required="true">
- <rule name="upper-limit"/>
- <rule name="available-channels"/>
- </field>
- <field name="max-frame-size" type="uint16">
- <rule name="minimum"/>
- <rule name="upper-limit"/>
- <rule name="max-frame-size"/>
- </field>
- <field name="heartbeat" type="uint16">
- <rule name="permitted-range"/>
- <rule name="no-heartbeat-min"/>
- </field>
- </control>
- <control name="open" code="0x7">
- <implement role="server" handle="MUST"/>
- <response name="open-ok"/>
- <response name="redirect"/>
- <field name="virtual-host" type="str8" required="true">
- <rule name="separation"/>
- <rule name="security"/>
- </field>
- <field name="capabilities" type="str16-array"/>
- <field name="insist" type="bit">
- <rule name="behavior"/>
- </field>
- </control>
- <control name="open-ok" code="0x8">
- <implement role="client" handle="MUST"/>
- <field name="known-hosts" type="amqp-host-array"/>
- </control>
- <control name="redirect" code="0x9">
- <rule name="usage"/>
- <implement role="client" handle="MUST"/>
- <field name="host" type="amqp-host-url" required="true"/>
- <field name="known-hosts" type="amqp-host-array"/>
- </control>
- <control name="heartbeat" code="0xa">
- <implement role="client" handle="MAY"/>
- <implement role="server" handle="MAY"/>
- </control>
- <control name="close" code="0xb">
- <implement role="client" handle="MUST"/>
- <implement role="server" handle="MUST"/>
- <response name="close-ok"/>
- <field name="reply-code" type="close-code" required="true"/>
- <field name="reply-text" type="str8"/>
- </control>
- <control name="close-ok" code="0xc">
- <rule name="reporting"/>
- <implement role="client" handle="MUST"/>
- <implement role="server" handle="MUST"/>
- </control>
- </class>
- <class name="session" code="0x2">
- <rule name="attachment"/>
- <role name="server" implement="MUST"/>
- <role name="client" implement="MUST"/>
- <role name="sender" implement="MUST"/>
- <role name="receiver" implement="MUST"/>
- <domain name="name" type="vbin16"/>
- <domain name="detach-code" type="uint8">
- <enum>
- <choice name="normal" value="0"/>
- <choice name="session-busy" value="1"/>
- <choice name="transport-busy" value="2"/>
- <choice name="not-attached" value="3"/>
- <choice name="unknown-ids" value="4"/>
- </enum>
- </domain>
- <domain name="commands" type="sequence-set"/>
- <struct name="header" size="1" pack="1">
- <field name="sync" type="bit"/>
- </struct>
- <struct name="command-fragment" size="0" pack="0">
- <field name="command-id" type="sequence-no" required="true"/>
- <field name="byte-ranges" type="byte-ranges" required="true"/>
- </struct>
- <domain name="command-fragments" type="array"/>
- <control name="attach" code="0x1">
- <rule name="one-transport-per-session"/>
- <rule name="one-session-per-transport"/>
- <rule name="idempotence"/>
- <rule name="scoping"/>
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MAY"/>
- <response name="attached"/>
- <response name="detached"/>
- <field name="name" type="name" required="true"/>
- <field name="force" type="bit"/>
- </control>
- <control name="attached" code="0x2">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="name" type="name" required="true"/>
- </control>
- <control name="detach" code="0x3">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <response name="detached"/>
- <field name="name" type="name" required="true"/>
- </control>
- <control name="detached" code="0x4">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="name" type="name" required="true"/>
- <field name="code" type="detach-code" required="true"/>
- </control>
- <control name="request-timeout" code="0x5">
- <rule name="maximum-granted-timeout"/>
- <implement role="sender" handle="MUST"/>
- <implement role="receiver" handle="MUST"/>
- <response name="timeout"/>
- <field name="timeout" type="uint32"/>
- </control>
- <control name="timeout" code="0x6">
- <implement role="sender" handle="MUST"/>
- <implement role="receiver" handle="MUST"/>
- <field name="timeout" type="uint32"/>
- </control>
- <control name="command-point" code="0x7">
- <rule name="newly-attached-transports"/>
- <rule name="zero-offset"/>
- <rule name="nonzero-offset"/>
- <implement role="receiver" handle="MUST"/>
- <field name="command-id" type="sequence-no" required="true"/>
- <field name="command-offset" type="uint64" required="true"/>
- </control>
- <control name="expected" code="0x8">
- <rule name="include-next-command"/>
- <rule name="commands-empty-means-new-session"/>
- <rule name="no-overlaps"/>
- <rule name="minimal-fragments"/>
- <implement role="sender" handle="MUST"/>
- <field name="commands" type="commands" required="true"/>
- <field name="fragments" type="command-fragments"/>
- </control>
- <control name="confirmed" code="0x9">
- <rule name="durability"/>
- <rule name="no-overlaps"/>
- <rule name="minimal-fragments"/>
- <implement role="sender" handle="MUST"/>
- <field name="commands" type="commands">
- <rule name="exclude-known-complete"/>
- </field>
- <field name="fragments" type="command-fragments"/>
- </control>
- <control name="completed" code="0xa">
- <rule name="known-completed-reply"/>
- <rule name="delayed-reply"/>
- <rule name="merged-reply"/>
- <implement role="sender" handle="MUST"/>
- <field name="commands" type="commands">
- <rule name="completed-implies-confirmed"/>
- <rule name="exclude-known-complete"/>
- </field>
- <field name="timely-reply" type="bit"/>
- </control>
- <control name="known-completed" code="0xb">
- <rule name="stateless"/>
- <implement role="receiver" handle="MUST"/>
- <field name="commands" type="commands">
- <rule name="known-completed-implies-known-confirmed"/>
- </field>
- </control>
- <control name="flush" code="0xc">
- <implement role="receiver" handle="MUST"/>
- <field name="expected" type="bit"/>
- <field name="confirmed" type="bit"/>
- <field name="completed" type="bit"/>
- </control>
- <control name="gap" code="0xd">
- <rule name="gap-confirmation-and-completion"/>
- <rule name="aborted-commands"/>
- <rule name="completed-or-confirmed-commands"/>
- <implement role="receiver" handle="MUST"/>
- <field name="commands" type="commands"/>
- </control>
- </class>
- <class name="execution" code="0x3">
- <role name="server" implement="MUST"/>
- <role name="client" implement="MUST"/>
- <domain name="error-code" type="uint16">
- <enum>
- <choice name="unauthorized-access" value="403"/>
- <choice name="not-found" value="404"/>
- <choice name="resource-locked" value="405"/>
- <choice name="precondition-failed" value="406"/>
- <choice name="resource-deleted" value="408"/>
- <choice name="illegal-state" value="409"/>
- <choice name="command-invalid" value="503"/>
- <choice name="resource-limit-exceeded" value="506"/>
- <choice name="not-allowed" value="530"/>
- <choice name="illegal-argument" value="531"/>
- <choice name="not-implemented" value="540"/>
- <choice name="internal-error" value="541"/>
- <choice name="invalid-argument" value="542"/>
- </enum>
- </domain>
- <command name="sync" code="0x1">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- </command>
- <command name="result" code="0x2">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="command-id" type="sequence-no" required="true"/>
- <field name="value" type="struct32"/>
- </command>
- <command name="exception" code="0x3">
- <implement role="client" handle="MUST"/>
- <implement role="server" handle="MUST"/>
- <field name="error-code" type="error-code" required="true"/>
- <field name="command-id" type="sequence-no"/>
- <field name="class-code" type="uint8"/>
- <field name="command-code" type="uint8"/>
- <field name="field-index" type="uint8"/>
- <field name="description" type="str16"/>
- <field name="error-info" type="map"/>
- </command>
- </class>
- <class name="message" code="0x4">
- <rule name="persistent-message"/>
- <rule name="no-persistent-message-discard"/>
- <rule name="throttling"/>
- <rule name="non-persistent-message-overflow"/>
- <rule name="non-persistent-message-discard"/>
- <rule name="min-priority-levels"/>
- <rule name="priority-level-implementation"/>
- <rule name="priority-delivery"/>
- <role name="server" implement="MUST"/>
- <role name="client" implement="MUST"/>
- <domain name="destination" type="str8"/>
- <domain name="accept-mode" type="uint8">
- <enum>
- <choice name="explicit" value="0"/>
- <choice name="none" value="1"/>
- </enum>
- </domain>
- <domain name="acquire-mode" type="uint8">
- <enum>
- <choice name="pre-acquired" value="0"/>
- <choice name="not-acquired" value="1"/>
- </enum>
- </domain>
- <domain name="reject-code" type="uint16">
- <enum>
- <choice name="unspecified" value="0"/>
- <choice name="unroutable" value="1"/>
- <choice name="immediate" value="2"/>
- </enum>
- </domain>
- <domain name="resume-id" type="str16"/>
- <domain name="delivery-mode" type="uint8">
- <enum>
- <choice name="non-persistent" value="1"/>
- <choice name="persistent" value="2"/>
- </enum>
- </domain>
- <domain name="delivery-priority" type="uint8">
- <enum>
- <choice name="lowest" value="0"/>
- <choice name="lower" value="1"/>
- <choice name="low" value="2"/>
- <choice name="below-average" value="3"/>
- <choice name="medium" value="4"/>
- <choice name="above-average" value="5"/>
- <choice name="high" value="6"/>
- <choice name="higher" value="7"/>
- <choice name="very-high" value="8"/>
- <choice name="highest" value="9"/>
- </enum>
- </domain>
- <struct name="delivery-properties" code="0x1" size="4" pack="2">
- <field name="discard-unroutable" type="bit"/>
- <field name="immediate" type="bit"/>
- <field name="redelivered" type="bit">
- <rule name="implementation"/>
- <rule name="hinting"/>
- </field>
- <field name="priority" type="delivery-priority" required="true"/>
- <field name="delivery-mode" type="delivery-mode" required="true"/>
- <field name="ttl" type="uint64">
- <rule name="ttl-decrement"/>
- </field>
- <field name="timestamp" type="datetime"/>
- <field name="expiration" type="datetime"/>
- <field name="exchange" type="exchange.name"/>
- <field name="routing-key" type="str8"/>
- <field name="resume-id" type="resume-id"/>
- <field name="resume-ttl" type="uint64"/>
- </struct>
- <struct name="fragment-properties" code="0x2" size="4" pack="2">
- <field name="first" type="bit" default="1"/>
- <field name="last" type="bit" default="1"/>
- <field name="fragment-size" type="uint64"/>
- </struct>
- <struct name="reply-to" size="2" pack="2">
- <field name="exchange" type="exchange.name"/>
- <field name="routing-key" type="str8"/>
- </struct>
- <struct name="message-properties" code="0x3" size="4" pack="2">
- <field name="content-length" type="uint64"/>
- <field name="message-id" type="uuid">
- <rule name="unique"/>
- <rule name="immutable"/>
- </field>
- <field name="correlation-id" type="vbin16"/>
- <field name="reply-to" type="reply-to"/>
- <field name="content-type" type="str8"/>
- <field name="content-encoding" type="str8"/>
- <field name="user-id" type="vbin16">
- <rule name="authentication"/>
- </field>
- <field name="app-id" type="vbin16"/>
- <field name="application-headers" type="map"/>
- </struct>
- <domain name="flow-mode" type="uint8">
- <enum>
- <choice name="credit" value="0"/>
- <choice name="window" value="1"/>
- </enum>
- </domain>
- <domain name="credit-unit" type="uint8">
- <enum>
- <choice name="message" value="0"/>
- <choice name="byte" value="1"/>
- </enum>
- </domain>
- <command name="transfer" code="0x1">
- <rule name="transactional-publish"/>
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="destination" type="destination">
- <rule name="blank-destination"/>
- <exception name="nonexistent-exchange" error-code="not-found"/>
- </field>
- <field name="accept-mode" type="accept-mode" required="true"/>
- <field name="acquire-mode" type="acquire-mode" required="true"/>
- <segments>
- <header>
- <entry type="delivery-properties"/>
- <entry type="fragment-properties"/>
- <entry type="message-properties"/>
- </header>
- <body/>
- </segments>
- </command>
- <command name="accept" code="0x2">
- <rule name="acquisition"/>
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="transfers" type="session.commands" required="true"/>
- </command>
- <command name="reject" code="0x3">
- <rule name="alternate-exchange"/>
- <rule name="acquisition"/>
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="transfers" type="session.commands" required="true"/>
- <field name="code" type="reject-code" required="true"/>
- <field name="text" type="str8"/>
- </command>
- <command name="release" code="0x4">
- <rule name="ordering"/>
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MAY"/>
- <field name="transfers" type="session.commands" required="true"/>
- <field name="set-redelivered" type="bit"/>
- </command>
- <command name="acquire" code="0x5">
- <rule name="one-to-one"/>
- <implement role="server" handle="MUST"/>
- <field name="transfers" type="session.commands" required="true"/>
- <result>
- <struct name="acquired" code="0x4" size="4" pack="2">
- <field name="transfers" type="session.commands" required="true"/>
- </struct>
- </result>
- </command>
- <command name="resume" code="0x6">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="destination" type="destination">
- <exception name="destination-not-found" error-code="not-found"/>
- </field>
- <field name="resume-id" type="resume-id" required="true">
- <rule name="unknown-resume-id"/>
- </field>
- <result>
- <struct name="message-resume-result" code="0x5" size="4" pack="2">
- <field name="offset" type="uint64"/>
- </struct>
- </result>
- </command>
- <command name="subscribe" code="0x7">
- <rule name="simultaneous-subscriptions"/>
- <rule name="default-flow-mode"/>
- <exception name="queue-deletion" error-code="resource-deleted"/>
- <exception name="queue-not-found" error-code="not-found"/>
- <rule name="initial-credit"/>
- <implement role="server" handle="MUST"/>
- <field name="queue" type="queue.name" required="true"/>
- <field name="destination" type="destination">
- <exception name="unique-subscriber-destination" error-code="not-allowed"/>
- </field>
- <field name="accept-mode" type="accept-mode" required="true"/>
- <field name="acquire-mode" type="acquire-mode" required="true"/>
- <field name="exclusive" type="bit">
- <exception name="in-use" error-code="resource-locked"/>
- </field>
- <field name="resume-id" type="resume-id"/>
- <field name="resume-ttl" type="uint64"/>
- <field name="arguments" type="map"/>
- </command>
- <command name="cancel" code="0x8">
- <rule name="post-cancel-transfer-resolution"/>
- <implement role="server" handle="MUST"/>
- <field name="destination" type="destination" required="true">
- <exception name="subscription-not-found" error-code="not-found"/>
- </field>
- </command>
- <command name="set-flow-mode" code="0x9">
- <rule name="byte-accounting"/>
- <rule name="mode-switching"/>
- <rule name="default-flow-mode"/>
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="destination" type="destination"/>
- <field name="flow-mode" type="flow-mode" required="true"/>
- </command>
- <command name="flow" code="0xa">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="destination" type="destination"/>
- <field name="unit" type="credit-unit" required="true"/>
- <field name="value" type="uint32"/>
- </command>
- <command name="flush" code="0xb">
- <implement role="server" handle="MUST"/>
- <field name="destination" type="destination"/>
- </command>
- <command name="stop" code="0xc">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="destination" type="destination"/>
- </command>
- </class>
- <class name="tx" code="0x5">
- <rule name="duplicate-tracking"/>
- <role name="server" implement="SHOULD"/>
- <command name="select" code="0x1">
- <exception name="exactly-once" error-code="illegal-state"/>
- <exception name="no-dtx" error-code="illegal-state"/>
- <exception name="explicit-accepts" error-code="not-allowed"/>
- <implement role="server" handle="MUST"/>
- </command>
- <command name="commit" code="0x2">
- <exception name="select-required" error-code="illegal-state"/>
- <implement role="server" handle="MUST"/>
- </command>
- <command name="rollback" code="0x3">
- <exception name="select-required" error-code="illegal-state"/>
- <implement role="server" handle="MUST"/>
- </command>
- </class>
- <class name="dtx" code="0x6">
- <rule name="transactionality"/>
- <role name="server" implement="MAY"/>
- <role name="client" implement="MAY"/>
- <domain name="xa-status" type="uint16">
- <enum>
- <choice name="xa-ok" value="0"/>
- <choice name="xa-rbrollback" value="1"/>
- <choice name="xa-rbtimeout" value="2"/>
- <choice name="xa-heurhaz" value="3"/>
- <choice name="xa-heurcom" value="4"/>
- <choice name="xa-heurrb" value="5"/>
- <choice name="xa-heurmix" value="6"/>
- <choice name="xa-rdonly" value="7"/>
- </enum>
- </domain>
- <struct name="xa-result" code="0x1" size="4" pack="2">
- <field name="status" type="xa-status" required="true"/>
- </struct>
- <struct name="xid" code="0x4" size="4" pack="2">
- <field name="format" type="uint32" required="true"/>
- <field name="global-id" type="vbin8" required="true"/>
- <field name="branch-id" type="vbin8" required="true"/>
- </struct>
- <command name="select" code="0x1">
- <implement role="server" handle="MAY"/>
- </command>
- <command name="start" code="0x2">
- <exception name="illegal-state" error-code="illegal-state"/>
- <exception name="already-known" error-code="not-allowed"/>
- <exception name="join-and-resume" error-code="not-allowed"/>
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="unknown-xid" error-code="not-allowed"/>
- </field>
- <field name="join" type="bit">
- <exception name="unsupported" error-code="not-implemented"/>
- </field>
- <field name="resume" type="bit"/>
- <result type="xa-result"/>
- </command>
- <command name="end" code="0x3">
- <exception name="illegal-state" error-code="illegal-state"/>
- <exception name="suspend-and-fail" error-code="not-allowed"/>
- <rule name="success"/>
- <rule name="session-closed"/>
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="not-associated" error-code="illegal-state"/>
- </field>
- <field name="fail" type="bit">
- <rule name="failure"/>
- </field>
- <field name="suspend" type="bit">
- <rule name="resume"/>
- </field>
- <result type="xa-result"/>
- </command>
- <command name="commit" code="0x4">
- <exception name="illegal-state" error-code="illegal-state"/>
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="unknown-xid" error-code="not-found"/>
- <exception name="not-disassociated" error-code="illegal-state"/>
- </field>
- <field name="one-phase" type="bit">
- <exception name="one-phase" error-code="illegal-state"/>
- <exception name="two-phase" error-code="illegal-state"/>
- </field>
- <result type="xa-result"/>
- </command>
- <command name="forget" code="0x5">
- <exception name="illegal-state" error-code="illegal-state"/>
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="unknown-xid" error-code="not-found"/>
- <exception name="not-disassociated" error-code="illegal-state"/>
- </field>
- </command>
- <command name="get-timeout" code="0x6">
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="unknown-xid" error-code="not-found"/>
- </field>
- <result>
- <struct name="get-timeout-result" code="0x2" size="4" pack="2">
- <field name="timeout" type="uint32" required="true"/>
- </struct>
- </result>
- </command>
- <command name="prepare" code="0x7">
- <exception name="illegal-state" error-code="illegal-state"/>
- <rule name="obligation-1"/>
- <rule name="obligation-2"/>
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="unknown-xid" error-code="not-found"/>
- <exception name="not-disassociated" error-code="illegal-state"/>
- </field>
- <result type="xa-result"/>
- </command>
- <command name="recover" code="0x8">
- <implement role="server" handle="MAY"/>
- <result>
- <struct name="recover-result" code="0x3" size="4" pack="2">
- <field name="in-doubt" type="array" required="true"/>
- </struct>
- </result>
- </command>
- <command name="rollback" code="0x9">
- <exception name="illegal-state" error-code="illegal-state"/>
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="unknown-xid" error-code="not-found"/>
- <exception name="not-disassociated" error-code="illegal-state"/>
- </field>
- <result type="xa-result"/>
- </command>
- <command name="set-timeout" code="0xa">
- <rule name="effective"/>
- <rule name="reset"/>
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="unknown-xid" error-code="not-found"/>
- </field>
- <field name="timeout" type="uint32" required="true"/>
- </command>
- </class>
- <class name="exchange" code="0x7">
- <rule name="required-types"/>
- <rule name="recommended-types"/>
- <rule name="required-instances"/>
- <rule name="default-exchange"/>
- <rule name="default-access"/>
- <rule name="extensions"/>
- <role name="server" implement="MUST"/>
- <role name="client" implement="MUST"/>
- <domain name="name" type="str8"/>
- <command name="declare" code="0x1">
- <rule name="minimum"/>
- <implement role="server" handle="MUST"/>
- <field name="exchange" type="name" required="true">
- <exception name="reserved-names" error-code="not-allowed"/>
- <exception name="exchange-name-required" error-code="invalid-argument"/>
- </field>
- <field name="type" type="str8" required="true">
- <exception name="typed" error-code="not-allowed"/>
- <exception name="exchange-type-not-found" error-code="not-found"/>
- </field>
- <field name="alternate-exchange" type="name">
- <rule name="empty-name"/>
- <exception name="pre-existing-exchange" error-code="not-allowed"/>
- <rule name="double-failure"/>
- </field>
- <field name="passive" type="bit">
- <exception name="not-found" error-code="not-found"/>
- </field>
- <field name="durable" type="bit">
- <rule name="support"/>
- <rule name="sticky"/>
- </field>
- <field name="auto-delete" type="bit">
- <rule name="sticky"/>
- </field>
- <field name="arguments" type="map">
- <exception name="unknown-argument" error-code="not-implemented"/>
- </field>
- </command>
- <command name="delete" code="0x2">
- <implement role="server" handle="MUST"/>
- <field name="exchange" type="name" required="true">
- <exception name="exists" error-code="not-found"/>
- <exception name="exchange-name-required" error-code="invalid-argument"/>
- <exception name="used-as-alternate" error-code="not-allowed"/>
- </field>
- <field name="if-unused" type="bit">
- <exception name="exchange-in-use" error-code="precondition-failed"/>
- </field>
- </command>
- <command name="query" code="0x3">
- <implement role="server" handle="MUST"/>
- <field name="name" type="str8"/>
- <result>
- <struct name="exchange-query-result" code="0x1" size="4" pack="2">
- <field name="type" type="str8"/>
- <field name="durable" type="bit"/>
- <field name="not-found" type="bit"/>
- <field name="arguments" type="map"/>
- </struct>
- </result>
- </command>
- <command name="bind" code="0x4">
- <rule name="duplicates"/>
- <rule name="durable-exchange"/>
- <rule name="binding-count"/>
- <rule name="multiple-bindings"/>
- <implement role="server" handle="MUST"/>
- <field name="queue" type="queue.name" required="true">
- <exception name="empty-queue" error-code="invalid-argument"/>
- <exception name="queue-existence" error-code="not-found"/>
- </field>
- <field name="exchange" type="name" required="true">
- <exception name="exchange-existence" error-code="not-found"/>
- <exception name="exchange-name-required" error-code="invalid-argument"/>
- </field>
- <field name="binding-key" type="str8" required="true"/>
- <field name="arguments" type="map">
- <exception name="unknown-argument" error-code="not-implemented"/>
- </field>
- </command>
- <command name="unbind" code="0x5">
- <implement role="server" handle="MUST"/>
- <field name="queue" type="queue.name" required="true">
- <exception name="non-existent-queue" error-code="not-found"/>
- </field>
- <field name="exchange" type="name" required="true">
- <exception name="non-existent-exchange" error-code="not-found"/>
- <exception name="exchange-name-required" error-code="invalid-argument"/>
- </field>
- <field name="binding-key" type="str8" required="true">
- <exception name="non-existent-binding-key" error-code="not-found"/>
- </field>
- </command>
- <command name="bound" code="0x6">
- <implement role="server" handle="MUST"/>
- <field name="exchange" type="str8"/>
- <field name="queue" type="str8" required="true"/>
- <field name="binding-key" type="str8"/>
- <field name="arguments" type="map"/>
- <result>
- <struct name="exchange-bound-result" code="0x2" size="4" pack="2">
- <field name="exchange-not-found" type="bit"/>
- <field name="queue-not-found" type="bit"/>
- <field name="queue-not-matched" type="bit"/>
- <field name="key-not-matched" type="bit"/>
- <field name="args-not-matched" type="bit"/>
- </struct>
- </result>
- </command>
- </class>
- <class name="queue" code="0x8">
- <rule name="any-content"/>
- <role name="server" implement="MUST"/>
- <role name="client" implement="MUST"/>
- <domain name="name" type="str8"/>
- <command name="declare" code="0x1">
- <rule name="default-binding"/>
- <rule name="minimum-queues"/>
- <implement role="server" handle="MUST"/>
- <field name="queue" type="name" required="true">
- <exception name="reserved-prefix" error-code="not-allowed"/>
- </field>
- <field name="alternate-exchange" type="exchange.name">
- <exception name="pre-existing-exchange" error-code="not-allowed"/>
- <exception name="unknown-exchange" error-code="not-found"/>
- </field>
- <field name="passive" type="bit">
- <exception name="passive" error-code="not-found"/>
- </field>
- <field name="durable" type="bit">
- <rule name="persistence"/>
- <rule name="types"/>
- <rule name="pre-existence"/>
- </field>
- <field name="exclusive" type="bit">
- <rule name="types"/>
- <exception name="in-use" error-code="resource-locked"/>
- </field>
- <field name="auto-delete" type="bit">
- <rule name="pre-existence"/>
- </field>
- <field name="arguments" type="map">
- <exception name="unknown-argument" error-code="not-implemented"/>
- </field>
- </command>
- <command name="delete" code="0x2">
- <implement role="server" handle="MUST"/>
- <field name="queue" type="name" required="true">
- <exception name="empty-name" error-code="invalid-argument"/>
- <exception name="queue-exists" error-code="not-found"/>
- </field>
- <field name="if-unused" type="bit">
- <exception name="if-unused-flag" error-code="precondition-failed"/>
- </field>
- <field name="if-empty" type="bit">
- <exception name="not-empty" error-code="precondition-failed"/>
- </field>
- </command>
- <command name="purge" code="0x3">
- <rule name="empty"/>
- <rule name="pending-messages"/>
- <rule name="purge-recovery"/>
- <implement role="server" handle="MUST"/>
- <field name="queue" type="name" required="true">
- <exception name="empty-name" error-code="invalid-argument"/>
- <exception name="queue-exists" error-code="not-found"/>
- </field>
- </command>
- <command name="query" code="0x4">
- <implement role="server" handle="MUST"/>
- <field name="queue" type="name" required="true"/>
- <result>
- <struct name="queue-query-result" code="0x1" size="4" pack="2">
- <field name="queue" type="name" required="true"/>
- <field name="alternate-exchange" type="exchange.name"/>
- <field name="durable" type="bit"/>
- <field name="exclusive" type="bit"/>
- <field name="auto-delete" type="bit"/>
- <field name="arguments" type="map"/>
- <field name="message-count" type="uint32" required="true"/>
- <field name="subscriber-count" type="uint32" required="true"/>
- </struct>
- </result>
- </command>
- </class>
- <class name="file" code="0x9">
- <rule name="reliable-storage"/>
- <rule name="no-discard"/>
- <rule name="priority-levels"/>
- <rule name="acknowledgement-support"/>
- <role name="server" implement="MAY"/>
- <role name="client" implement="MAY"/>
- <struct name="file-properties" code="0x1" size="4" pack="2">
- <field name="content-type" type="str8"/>
- <field name="content-encoding" type="str8"/>
- <field name="headers" type="map"/>
- <field name="priority" type="uint8"/>
- <field name="reply-to" type="str8"/>
- <field name="message-id" type="str8"/>
- <field name="filename" type="str8"/>
- <field name="timestamp" type="datetime"/>
- <field name="cluster-id" type="str8"/>
- </struct>
- <domain name="return-code" type="uint16">
- <enum>
- <choice name="content-too-large" value="311"/>
- <choice name="no-route" value="312"/>
- <choice name="no-consumers" value="313"/>
- </enum>
- </domain>
- <command name="qos" code="0x1">
- <implement role="server" handle="MUST"/>
- <response name="qos-ok"/>
- <field name="prefetch-size" type="uint32"/>
- <field name="prefetch-count" type="uint16">
- <rule name="prefetch-discretion"/>
- </field>
- <field name="global" type="bit"/>
- </command>
- <command name="qos-ok" code="0x2">
- <implement role="client" handle="MUST"/>
- </command>
- <command name="consume" code="0x3">
- <rule name="min-consumers"/>
- <implement role="server" handle="MUST"/>
- <response name="consume-ok"/>
- <field name="queue" type="queue.name">
- <exception name="queue-exists-if-empty" error-code="not-allowed"/>
- </field>
- <field name="consumer-tag" type="str8">
- <exception name="not-existing-consumer" error-code="not-allowed"/>
- <exception name="not-empty-consumer-tag" error-code="not-allowed"/>
- </field>
- <field name="no-local" type="bit"/>
- <field name="no-ack" type="bit"/>
- <field name="exclusive" type="bit">
- <exception name="in-use" error-code="resource-locked"/>
- </field>
- <field name="nowait" type="bit"/>
- <field name="arguments" type="map"/>
- </command>
- <command name="consume-ok" code="0x4">
- <implement role="client" handle="MUST"/>
- <field name="consumer-tag" type="str8"/>
- </command>
- <command name="cancel" code="0x5">
- <implement role="server" handle="MUST"/>
- <field name="consumer-tag" type="str8"/>
- </command>
- <command name="open" code="0x6">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <response name="open-ok"/>
- <field name="identifier" type="str8"/>
- <field name="content-size" type="uint64">
- <rule name="content-size"/>
- </field>
- </command>
- <command name="open-ok" code="0x7">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <response name="stage"/>
- <field name="staged-size" type="uint64">
- <rule name="behavior"/>
- <rule name="staging"/>
- </field>
- </command>
- <command name="stage" code="0x8">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <segments>
- <header required="true">
- <entry type="file-properties"/>
- </header>
- <body/>
- </segments>
- </command>
- <command name="publish" code="0x9">
- <implement role="server" handle="MUST"/>
- <field name="exchange" type="exchange.name">
- <rule name="default"/>
- <exception name="refusal" error-code="not-implemented"/>
- </field>
- <field name="routing-key" type="str8"/>
- <field name="mandatory" type="bit">
- <rule name="implementation"/>
- </field>
- <field name="immediate" type="bit">
- <rule name="implementation"/>
- </field>
- <field name="identifier" type="str8"/>
- </command>
- <command name="return" code="0xa">
- <implement role="client" handle="MUST"/>
- <field name="reply-code" type="return-code"/>
- <field name="reply-text" type="str8"/>
- <field name="exchange" type="exchange.name"/>
- <field name="routing-key" type="str8"/>
- <segments>
- <header required="true">
- <entry type="file-properties"/>
- </header>
- <body/>
- </segments>
- </command>
- <command name="deliver" code="0xb">
- <rule name="redelivery-tracking"/>
- <implement role="client" handle="MUST"/>
- <field name="consumer-tag" type="str8"/>
- <field name="delivery-tag" type="uint64">
- <rule name="non-zero"/>
- </field>
- <field name="redelivered" type="bit"/>
- <field name="exchange" type="exchange.name"/>
- <field name="routing-key" type="str8"/>
- <field name="identifier" type="str8"/>
- </command>
- <command name="ack" code="0xc">
- <implement role="server" handle="MUST"/>
- <field name="delivery-tag" type="uint64">
- <rule name="session-local"/>
- </field>
- <field name="multiple" type="bit">
- <rule name="validation"/>
- </field>
- </command>
- <command name="reject" code="0xd">
- <rule name="server-interpretation"/>
- <rule name="not-selection"/>
- <implement role="server" handle="MUST"/>
- <field name="delivery-tag" type="uint64">
- <rule name="session-local"/>
- </field>
- <field name="requeue" type="bit">
- <rule name="requeue-strategy"/>
- </field>
- </command>
- </class>
- <class name="stream" code="0xa">
- <rule name="overflow-discard"/>
- <rule name="priority-levels"/>
- <rule name="acknowledgement-support"/>
- <role name="server" implement="MAY"/>
- <role name="client" implement="MAY"/>
- <struct name="stream-properties" code="0x1" size="4" pack="2">
- <field name="content-type" type="str8"/>
- <field name="content-encoding" type="str8"/>
- <field name="headers" type="map"/>
- <field name="priority" type="uint8"/>
- <field name="timestamp" type="datetime"/>
- </struct>
- <domain name="return-code" type="uint16">
- <enum>
- <choice name="content-too-large" value="311"/>
- <choice name="no-route" value="312"/>
- <choice name="no-consumers" value="313"/>
- </enum>
- </domain>
- <command name="qos" code="0x1">
- <implement role="server" handle="MUST"/>
- <response name="qos-ok"/>
- <field name="prefetch-size" type="uint32"/>
- <field name="prefetch-count" type="uint16"/>
- <field name="consume-rate" type="uint32">
- <rule name="ignore-prefetch"/>
- <rule name="drop-by-priority"/>
- </field>
- <field name="global" type="bit"/>
- </command>
- <command name="qos-ok" code="0x2">
- <implement role="client" handle="MUST"/>
- </command>
- <command name="consume" code="0x3">
- <rule name="min-consumers"/>
- <rule name="priority-based-delivery"/>
- <implement role="server" handle="MUST"/>
- <response name="consume-ok"/>
- <field name="queue" type="queue.name">
- <exception name="queue-exists-if-empty" error-code="not-allowed"/>
- </field>
- <field name="consumer-tag" type="str8">
- <exception name="not-existing-consumer" error-code="not-allowed"/>
- <exception name="not-empty-consumer-tag" error-code="not-allowed"/>
- </field>
- <field name="no-local" type="bit"/>
- <field name="exclusive" type="bit">
- <exception name="in-use" error-code="resource-locked"/>
- </field>
- <field name="nowait" type="bit"/>
- <field name="arguments" type="map"/>
- </command>
- <command name="consume-ok" code="0x4">
- <implement role="client" handle="MUST"/>
- <field name="consumer-tag" type="str8"/>
- </command>
- <command name="cancel" code="0x5">
- <implement role="server" handle="MUST"/>
- <field name="consumer-tag" type="str8"/>
- </command>
- <command name="publish" code="0x6">
- <implement role="server" handle="MUST"/>
- <field name="exchange" type="exchange.name">
- <rule name="default"/>
- <exception name="refusal" error-code="not-implemented"/>
- </field>
- <field name="routing-key" type="str8"/>
- <field name="mandatory" type="bit">
- <rule name="implementation"/>
- </field>
- <field name="immediate" type="bit">
- <rule name="implementation"/>
- </field>
- <segments>
- <header required="true">
- <entry type="stream-properties"/>
- </header>
- <body/>
- </segments>
- </command>
- <command name="return" code="0x7">
- <implement role="client" handle="MUST"/>
- <field name="reply-code" type="return-code"/>
- <field name="reply-text" type="str8"/>
- <field name="exchange" type="exchange.name"/>
- <field name="routing-key" type="str8"/>
- <segments>
- <header required="true">
- <entry type="stream-properties"/>
- </header>
- <body/>
- </segments>
- </command>
- <command name="deliver" code="0x8">
- <implement role="client" handle="MUST"/>
- <field name="consumer-tag" type="str8"/>
- <field name="delivery-tag" type="uint64">
- <rule name="session-local"/>
- </field>
- <field name="exchange" type="exchange.name"/>
- <field name="queue" type="queue.name" required="true"/>
- <segments>
- <header required="true">
- <entry type="stream-properties"/>
- </header>
- <body/>
- </segments>
- </command>
- </class>
-</amqp>
diff --git a/qpid/python/qpid/specs/amqp-0-10-stripped.xml b/qpid/python/qpid/specs/amqp-0-10-stripped.xml
deleted file mode 100644
index 1c53608138..0000000000
--- a/qpid/python/qpid/specs/amqp-0-10-stripped.xml
+++ /dev/null
@@ -1,1200 +0,0 @@
-<?xml version="1.0"?>
-
-<!--
-(c) Copyright Cisco Systems, Credit Suisse, Deutsche Borse Systems,
-Envoy Technologies, Inc., Goldman Sachs, IONA Technologies PLC, iMatix
-Corporation sprl.,JPMorgan Chase Bank Inc. N.A, Novell, Rabbit
-Technologies Ltd., Red Hat, Inc., TWIST Process Innovations ltd, and
-29West Inc. 2006, 2007.
-
-Copyright (c) 2009 AMQP Working Group.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
-derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--->
-
-<amqp major="0" xmlns="http://www.amqp.org/schema/amqp.xsd" port="5672" minor="10">
- <type name="bin8" code="0x00" fixed-width="1"/>
- <type name="int8" code="0x01" fixed-width="1"/>
- <type name="uint8" code="0x02" fixed-width="1"/>
- <type name="char" code="0x04" fixed-width="1"/>
- <type name="boolean" code="0x08" fixed-width="1"/>
- <type name="bin16" code="0x10" fixed-width="2"/>
- <type name="int16" code="0x11" fixed-width="2"/>
- <type name="uint16" code="0x12" fixed-width="2"/>
- <type name="bin32" code="0x20" fixed-width="4"/>
- <type name="int32" code="0x21" fixed-width="4"/>
- <type name="uint32" code="0x22" fixed-width="4"/>
- <type name="float" code="0x23" fixed-width="4"/>
- <type name="char-utf32" code="0x27" fixed-width="4"/>
- <type name="sequence-no" fixed-width="4"/>
- <type name="bin64" code="0x30" fixed-width="8"/>
- <type name="int64" code="0x31" fixed-width="8"/>
- <type name="uint64" code="0x32" fixed-width="8"/>
- <type name="double" code="0x33" fixed-width="8"/>
- <type name="datetime" code="0x38" fixed-width="8"/>
- <type name="bin128" code="0x40" fixed-width="16"/>
- <type name="uuid" code="0x48" fixed-width="16"/>
- <type name="bin256" code="0x50" fixed-width="32"/>
- <type name="bin512" code="0x60" fixed-width="64"/>
- <type name="bin1024" code="0x70" fixed-width="128"/>
- <type name="vbin8" code="0x80" variable-width="1"/>
- <type name="str8-latin" code="0x84" variable-width="1"/>
- <type name="str8" code="0x85" variable-width="1"/>
- <type name="str8-utf16" code="0x86" variable-width="1"/>
- <type name="vbin16" code="0x90" variable-width="2"/>
- <type name="str16-latin" code="0x94" variable-width="2"/>
- <type name="str16" code="0x95" variable-width="2"/>
- <type name="str16-utf16" code="0x96" variable-width="2"/>
- <type name="byte-ranges" variable-width="2"/>
- <type name="sequence-set" variable-width="2"/>
- <type name="vbin32" code="0xa0" variable-width="4"/>
- <type name="map" code="0xa8" variable-width="4"/>
- <type name="list" code="0xa9" variable-width="4"/>
- <type name="array" code="0xaa" variable-width="4"/>
- <type name="struct32" code="0xab" variable-width="4"/>
- <type name="bin40" code="0xc0" fixed-width="5"/>
- <type name="dec32" code="0xc8" fixed-width="5"/>
- <type name="bin72" code="0xd0" fixed-width="9"/>
- <type name="dec64" code="0xd8" fixed-width="9"/>
- <type name="void" code="0xf0" fixed-width="0"/>
- <type name="bit" code="0xf1" fixed-width="0"/>
- <constant name="MIN-MAX-FRAME-SIZE" value="4096"/>
- <domain name="segment-type" type="uint8">
- <enum>
- <choice name="control" value="0"/>
- <choice name="command" value="1"/>
- <choice name="header" value="2"/>
- <choice name="body" value="3"/>
- </enum>
- </domain>
- <domain name="track" type="uint8">
- <enum>
- <choice name="control" value="0"/>
- <choice name="command" value="1"/>
- </enum>
- </domain>
- <domain name="str16-array" type="array"/>
- <class name="connection" code="0x1">
- <role name="server" implement="MUST"/>
- <role name="client" implement="MUST"/>
- <domain name="close-code" type="uint16">
- <enum>
- <choice name="normal" value="200"/>
- <choice name="connection-forced" value="320"/>
- <choice name="invalid-path" value="402"/>
- <choice name="framing-error" value="501"/>
- </enum>
- </domain>
- <domain name="amqp-host-url" type="str16"/>
- <domain name="amqp-host-array" type="array"/>
- <control name="start" code="0x1">
- <rule name="protocol-name"/>
- <rule name="client-support"/>
- <implement role="client" handle="MUST"/>
- <response name="start-ok"/>
- <field name="server-properties" type="map">
- <rule name="required-fields"/>
- </field>
- <field name="mechanisms" type="str16-array" required="true"/>
- <field name="locales" type="str16-array" required="true">
- <rule name="required-support"/>
- </field>
- </control>
- <control name="start-ok" code="0x2">
- <implement role="server" handle="MUST"/>
- <field name="client-properties" type="map">
- <rule name="required-fields"/>
- </field>
- <field name="mechanism" type="str8" required="true">
- <rule name="security"/>
- <rule name="validity"/>
- </field>
- <field name="response" type="vbin32" required="true"/>
- <field name="locale" type="str8" required="true"/>
- </control>
- <control name="secure" code="0x3">
- <implement role="client" handle="MUST"/>
- <response name="secure-ok"/>
- <field name="challenge" type="vbin32" required="true"/>
- </control>
- <control name="secure-ok" code="0x4">
- <implement role="server" handle="MUST"/>
- <field name="response" type="vbin32" required="true"/>
- </control>
- <control name="tune" code="0x5">
- <implement role="client" handle="MUST"/>
- <response name="tune-ok"/>
- <field name="channel-max" type="uint16"/>
- <field name="max-frame-size" type="uint16">
- <rule name="minimum"/>
- </field>
- <field name="heartbeat-min" type="uint16"/>
- <field name="heartbeat-max" type="uint16">
- <rule name="permitted-range"/>
- <rule name="no-heartbeat-min"/>
- </field>
- </control>
- <control name="tune-ok" code="0x6">
- <implement role="server" handle="MUST"/>
- <field name="channel-max" type="uint16" required="true">
- <rule name="upper-limit"/>
- <rule name="available-channels"/>
- </field>
- <field name="max-frame-size" type="uint16">
- <rule name="minimum"/>
- <rule name="upper-limit"/>
- <rule name="max-frame-size"/>
- </field>
- <field name="heartbeat" type="uint16">
- <rule name="permitted-range"/>
- <rule name="no-heartbeat-min"/>
- </field>
- </control>
- <control name="open" code="0x7">
- <implement role="server" handle="MUST"/>
- <response name="open-ok"/>
- <response name="redirect"/>
- <field name="virtual-host" type="str8" required="true">
- <rule name="separation"/>
- <rule name="security"/>
- </field>
- <field name="capabilities" type="str16-array"/>
- <field name="insist" type="bit">
- <rule name="behavior"/>
- </field>
- </control>
- <control name="open-ok" code="0x8">
- <implement role="client" handle="MUST"/>
- <field name="known-hosts" type="amqp-host-array"/>
- </control>
- <control name="redirect" code="0x9">
- <rule name="usage"/>
- <implement role="client" handle="MUST"/>
- <field name="host" type="amqp-host-url" required="true"/>
- <field name="known-hosts" type="amqp-host-array"/>
- </control>
- <control name="heartbeat" code="0xa"/>
- <control name="close" code="0xb">
- <implement role="client" handle="MUST"/>
- <implement role="server" handle="MUST"/>
- <response name="close-ok"/>
- <field name="reply-code" type="close-code" required="true"/>
- <field name="reply-text" type="str8"/>
- </control>
- <control name="close-ok" code="0xc">
- <rule name="reporting"/>
- <implement role="client" handle="MUST"/>
- <implement role="server" handle="MUST"/>
- </control>
- </class>
- <class name="session" code="0x2">
- <rule name="attachment"/>
- <role name="server" implement="MUST"/>
- <role name="client" implement="MUST"/>
- <role name="sender" implement="MUST"/>
- <role name="receiver" implement="MUST"/>
- <domain name="name" type="vbin16"/>
- <domain name="detach-code" type="uint8">
- <enum>
- <choice name="normal" value="0"/>
- <choice name="session-busy" value="1"/>
- <choice name="transport-busy" value="2"/>
- <choice name="not-attached" value="3"/>
- <choice name="unknown-ids" value="4"/>
- </enum>
- </domain>
- <domain name="commands" type="sequence-set"/>
- <struct name="header" size="1" pack="1">
- <field name="sync" type="bit"/>
- </struct>
- <struct name="command-fragment" size="0" pack="0">
- <field name="command-id" type="sequence-no" required="true"/>
- <field name="byte-ranges" type="byte-ranges" required="true"/>
- </struct>
- <domain name="command-fragments" type="array"/>
- <control name="attach" code="0x1">
- <rule name="one-transport-per-session"/>
- <rule name="one-session-per-transport"/>
- <rule name="idempotence"/>
- <rule name="scoping"/>
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MAY"/>
- <response name="attached"/>
- <response name="detached"/>
- <field name="name" type="name" required="true"/>
- <field name="force" type="bit"/>
- </control>
- <control name="attached" code="0x2">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="name" type="name" required="true"/>
- </control>
- <control name="detach" code="0x3">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <response name="detached"/>
- <field name="name" type="name" required="true"/>
- </control>
- <control name="detached" code="0x4">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="name" type="name" required="true"/>
- <field name="code" type="detach-code" required="true"/>
- </control>
- <control name="request-timeout" code="0x5">
- <rule name="maximum-granted-timeout"/>
- <implement role="sender" handle="MUST"/>
- <implement role="receiver" handle="MUST"/>
- <response name="timeout"/>
- <field name="timeout" type="uint32"/>
- </control>
- <control name="timeout" code="0x6">
- <implement role="sender" handle="MUST"/>
- <implement role="receiver" handle="MUST"/>
- <field name="timeout" type="uint32"/>
- </control>
- <control name="command-point" code="0x7">
- <rule name="newly-attached-transports"/>
- <rule name="zero-offset"/>
- <rule name="nonzero-offset"/>
- <implement role="receiver" handle="MUST"/>
- <field name="command-id" type="sequence-no" required="true"/>
- <field name="command-offset" type="uint64" required="true"/>
- </control>
- <control name="expected" code="0x8">
- <rule name="include-next-command"/>
- <rule name="commands-empty-means-new-session"/>
- <rule name="no-overlaps"/>
- <rule name="minimal-fragments"/>
- <implement role="sender" handle="MUST"/>
- <field name="commands" type="commands" required="true"/>
- <field name="fragments" type="command-fragments"/>
- </control>
- <control name="confirmed" code="0x9">
- <rule name="durability"/>
- <rule name="no-overlaps"/>
- <rule name="minimal-fragments"/>
- <implement role="sender" handle="MUST"/>
- <field name="commands" type="commands">
- <rule name="exclude-known-complete"/>
- </field>
- <field name="fragments" type="command-fragments"/>
- </control>
- <control name="completed" code="0xa">
- <rule name="known-completed-reply"/>
- <rule name="delayed-reply"/>
- <rule name="merged-reply"/>
- <implement role="sender" handle="MUST"/>
- <field name="commands" type="commands">
- <rule name="completed-implies-confirmed"/>
- <rule name="exclude-known-complete"/>
- </field>
- <field name="timely-reply" type="bit"/>
- </control>
- <control name="known-completed" code="0xb">
- <rule name="stateless"/>
- <implement role="receiver" handle="MUST"/>
- <field name="commands" type="commands">
- <rule name="known-completed-implies-known-confirmed"/>
- </field>
- </control>
- <control name="flush" code="0xc">
- <implement role="receiver" handle="MUST"/>
- <field name="expected" type="bit"/>
- <field name="confirmed" type="bit"/>
- <field name="completed" type="bit"/>
- </control>
- <control name="gap" code="0xd">
- <rule name="gap-confirmation-and-completion"/>
- <rule name="aborted-commands"/>
- <rule name="completed-or-confirmed-commands"/>
- <implement role="receiver" handle="MUST"/>
- <field name="commands" type="commands"/>
- </control>
- </class>
- <class name="execution" code="0x3">
- <role name="server" implement="MUST"/>
- <role name="client" implement="MUST"/>
- <domain name="error-code" type="uint16">
- <enum>
- <choice name="unauthorized-access" value="403"/>
- <choice name="not-found" value="404"/>
- <choice name="resource-locked" value="405"/>
- <choice name="precondition-failed" value="406"/>
- <choice name="resource-deleted" value="408"/>
- <choice name="illegal-state" value="409"/>
- <choice name="command-invalid" value="503"/>
- <choice name="resource-limit-exceeded" value="506"/>
- <choice name="not-allowed" value="530"/>
- <choice name="illegal-argument" value="531"/>
- <choice name="not-implemented" value="540"/>
- <choice name="internal-error" value="541"/>
- <choice name="invalid-argument" value="542"/>
- </enum>
- </domain>
- <command name="sync" code="0x1">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- </command>
- <command name="result" code="0x2">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="command-id" type="sequence-no" required="true"/>
- <field name="value" type="struct32"/>
- </command>
- <command name="exception" code="0x3">
- <implement role="client" handle="MUST"/>
- <implement role="server" handle="MUST"/>
- <field name="error-code" type="error-code" required="true"/>
- <field name="command-id" type="sequence-no"/>
- <field name="class-code" type="uint8"/>
- <field name="command-code" type="uint8"/>
- <field name="field-index" type="uint8"/>
- <field name="description" type="str16"/>
- <field name="error-info" type="map"/>
- </command>
- </class>
- <class name="message" code="0x4">
- <rule name="persistent-message"/>
- <rule name="no-persistent-message-discard"/>
- <rule name="throttling"/>
- <rule name="non-persistent-message-overflow"/>
- <rule name="non-persistent-message-discard"/>
- <rule name="min-priority-levels"/>
- <rule name="priority-level-implementation"/>
- <rule name="priority-delivery"/>
- <role name="server" implement="MUST"/>
- <role name="client" implement="MUST"/>
- <domain name="destination" type="str8"/>
- <domain name="accept-mode" type="uint8">
- <enum>
- <choice name="explicit" value="0"/>
- <choice name="none" value="1"/>
- </enum>
- </domain>
- <domain name="acquire-mode" type="uint8">
- <enum>
- <choice name="pre-acquired" value="0"/>
- <choice name="not-acquired" value="1"/>
- </enum>
- </domain>
- <domain name="reject-code" type="uint16">
- <enum>
- <choice name="unspecified" value="0"/>
- <choice name="unroutable" value="1"/>
- <choice name="immediate" value="2"/>
- </enum>
- </domain>
- <domain name="resume-id" type="str16"/>
- <domain name="delivery-mode" type="uint8">
- <enum>
- <choice name="non-persistent" value="1"/>
- <choice name="persistent" value="2"/>
- </enum>
- </domain>
- <domain name="delivery-priority" type="uint8">
- <enum>
- <choice name="lowest" value="0"/>
- <choice name="lower" value="1"/>
- <choice name="low" value="2"/>
- <choice name="below-average" value="3"/>
- <choice name="medium" value="4"/>
- <choice name="above-average" value="5"/>
- <choice name="high" value="6"/>
- <choice name="higher" value="7"/>
- <choice name="very-high" value="8"/>
- <choice name="highest" value="9"/>
- </enum>
- </domain>
- <struct name="delivery-properties" code="0x1" size="4" pack="2">
- <field name="discard-unroutable" type="bit"/>
- <field name="immediate" type="bit"/>
- <field name="redelivered" type="bit">
- <rule name="implementation"/>
- <rule name="hinting"/>
- </field>
- <field name="priority" type="delivery-priority" required="true"/>
- <field name="delivery-mode" type="delivery-mode" required="true"/>
- <field name="ttl" type="uint64">
- <rule name="ttl-decrement"/>
- </field>
- <field name="timestamp" type="datetime"/>
- <field name="expiration" type="datetime"/>
- <field name="exchange" type="exchange.name"/>
- <field name="routing-key" type="str8"/>
- <field name="resume-id" type="resume-id"/>
- <field name="resume-ttl" type="uint64"/>
- </struct>
- <struct name="fragment-properties" code="0x2" size="4" pack="2">
- <field name="first" type="bit" default="1"/>
- <field name="last" type="bit" default="1"/>
- <field name="fragment-size" type="uint64"/>
- </struct>
- <struct name="reply-to" size="2" pack="2">
- <field name="exchange" type="exchange.name"/>
- <field name="routing-key" type="str8"/>
- </struct>
- <struct name="message-properties" code="0x3" size="4" pack="2">
- <field name="content-length" type="uint64"/>
- <field name="message-id" type="uuid">
- <rule name="unique"/>
- <rule name="immutable"/>
- </field>
- <field name="correlation-id" type="vbin16"/>
- <field name="reply-to" type="reply-to"/>
- <field name="content-type" type="str8"/>
- <field name="content-encoding" type="str8"/>
- <field name="user-id" type="vbin16">
- <rule name="authentication"/>
- </field>
- <field name="app-id" type="vbin16"/>
- <field name="application-headers" type="map"/>
- </struct>
- <domain name="flow-mode" type="uint8">
- <enum>
- <choice name="credit" value="0"/>
- <choice name="window" value="1"/>
- </enum>
- </domain>
- <domain name="credit-unit" type="uint8">
- <enum>
- <choice name="message" value="0"/>
- <choice name="byte" value="1"/>
- </enum>
- </domain>
- <command name="transfer" code="0x1">
- <rule name="transactional-publish"/>
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="destination" type="destination">
- <rule name="blank-destination"/>
- <exception name="nonexistent-exchange" error-code="not-found"/>
- </field>
- <field name="accept-mode" type="accept-mode" required="true"/>
- <field name="acquire-mode" type="acquire-mode" required="true"/>
- <segments>
- <header>
- <entry type="delivery-properties"/>
- <entry type="fragment-properties"/>
- <entry type="message-properties"/>
- </header>
- <body/>
- </segments>
- </command>
- <command name="accept" code="0x2">
- <rule name="acquisition"/>
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="transfers" type="session.commands" required="true"/>
- </command>
- <command name="reject" code="0x3">
- <rule name="alternate-exchange"/>
- <rule name="acquisition"/>
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="transfers" type="session.commands" required="true"/>
- <field name="code" type="reject-code" required="true"/>
- <field name="text" type="str8"/>
- </command>
- <command name="release" code="0x4">
- <rule name="ordering"/>
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MAY"/>
- <field name="transfers" type="session.commands" required="true"/>
- <field name="set-redelivered" type="bit"/>
- </command>
- <command name="acquire" code="0x5">
- <rule name="one-to-one"/>
- <implement role="server" handle="MUST"/>
- <field name="transfers" type="session.commands" required="true"/>
- <result>
- <struct name="acquired" code="0x4" size="4" pack="2">
- <field name="transfers" type="session.commands" required="true"/>
- </struct>
- </result>
- </command>
- <command name="resume" code="0x6">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="destination" type="destination">
- <exception name="destination-not-found" error-code="not-found"/>
- </field>
- <field name="resume-id" type="resume-id" required="true">
- <rule name="unknown-resume-id"/>
- </field>
- <result>
- <struct name="message-resume-result" code="0x5" size="4" pack="2">
- <field name="offset" type="uint64"/>
- </struct>
- </result>
- </command>
- <command name="subscribe" code="0x7">
- <rule name="simultaneous-subscriptions"/>
- <rule name="default-flow-mode"/>
- <exception name="queue-deletion" error-code="resource-deleted"/>
- <exception name="queue-not-found" error-code="not-found"/>
- <rule name="initial-credit"/>
- <implement role="server" handle="MUST"/>
- <field name="queue" type="queue.name" required="true"/>
- <field name="destination" type="destination">
- <exception name="unique-subscriber-destination" error-code="not-allowed"/>
- </field>
- <field name="accept-mode" type="accept-mode" required="true"/>
- <field name="acquire-mode" type="acquire-mode" required="true"/>
- <field name="exclusive" type="bit">
- <exception name="in-use" error-code="resource-locked"/>
- </field>
- <field name="resume-id" type="resume-id"/>
- <field name="resume-ttl" type="uint64"/>
- <field name="arguments" type="map"/>
- </command>
- <command name="cancel" code="0x8">
- <rule name="post-cancel-transfer-resolution"/>
- <implement role="server" handle="MUST"/>
- <field name="destination" type="destination" required="true">
- <exception name="subscription-not-found" error-code="not-found"/>
- </field>
- </command>
- <command name="set-flow-mode" code="0x9">
- <rule name="byte-accounting"/>
- <rule name="mode-switching"/>
- <rule name="default-flow-mode"/>
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="destination" type="destination"/>
- <field name="flow-mode" type="flow-mode" required="true"/>
- </command>
- <command name="flow" code="0xa">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="destination" type="destination"/>
- <field name="unit" type="credit-unit" required="true"/>
- <field name="value" type="uint32"/>
- </command>
- <command name="flush" code="0xb">
- <implement role="server" handle="MUST"/>
- <field name="destination" type="destination"/>
- </command>
- <command name="stop" code="0xc">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <field name="destination" type="destination"/>
- </command>
- </class>
- <class name="tx" code="0x5">
- <rule name="duplicate-tracking"/>
- <role name="server" implement="SHOULD"/>
- <command name="select" code="0x1">
- <exception name="exactly-once" error-code="illegal-state"/>
- <exception name="no-dtx" error-code="illegal-state"/>
- <exception name="explicit-accepts" error-code="not-allowed"/>
- <implement role="server" handle="MUST"/>
- </command>
- <command name="commit" code="0x2">
- <exception name="select-required" error-code="illegal-state"/>
- <implement role="server" handle="MUST"/>
- </command>
- <command name="rollback" code="0x3">
- <exception name="select-required" error-code="illegal-state"/>
- <implement role="server" handle="MUST"/>
- </command>
- </class>
- <class name="dtx" code="0x6">
- <rule name="transactionality"/>
- <role name="server" implement="MAY"/>
- <role name="client" implement="MAY"/>
- <domain name="xa-status" type="uint16">
- <enum>
- <choice name="xa-ok" value="0"/>
- <choice name="xa-rbrollback" value="1"/>
- <choice name="xa-rbtimeout" value="2"/>
- <choice name="xa-heurhaz" value="3"/>
- <choice name="xa-heurcom" value="4"/>
- <choice name="xa-heurrb" value="5"/>
- <choice name="xa-heurmix" value="6"/>
- <choice name="xa-rdonly" value="7"/>
- </enum>
- </domain>
- <struct name="xa-result" code="0x1" size="4" pack="2">
- <field name="status" type="xa-status" required="true"/>
- </struct>
- <struct name="xid" size="2" pack="2">
- <field name="format" type="uint32" required="true"/>
- <field name="global-id" type="vbin8" required="true"/>
- <field name="branch-id" type="vbin8" required="true"/>
- </struct>
- <command name="select" code="0x1">
- <implement role="server" handle="MAY"/>
- </command>
- <command name="start" code="0x2">
- <exception name="illegal-state" error-code="illegal-state"/>
- <exception name="already-known" error-code="not-allowed"/>
- <exception name="join-and-resume" error-code="not-allowed"/>
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="unknown-xid" error-code="not-allowed"/>
- </field>
- <field name="join" type="bit">
- <exception name="unsupported" error-code="not-implemented"/>
- </field>
- <field name="resume" type="bit"/>
- <result type="xa-result"/>
- </command>
- <command name="end" code="0x3">
- <exception name="illegal-state" error-code="illegal-state"/>
- <exception name="suspend-and-fail" error-code="not-allowed"/>
- <rule name="success"/>
- <rule name="session-closed"/>
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="not-associated" error-code="illegal-state"/>
- </field>
- <field name="fail" type="bit">
- <rule name="failure"/>
- </field>
- <field name="suspend" type="bit">
- <rule name="resume"/>
- </field>
- <result type="xa-result"/>
- </command>
- <command name="commit" code="0x4">
- <exception name="illegal-state" error-code="illegal-state"/>
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="unknown-xid" error-code="not-found"/>
- <exception name="not-disassociated" error-code="illegal-state"/>
- </field>
- <field name="one-phase" type="bit">
- <exception name="one-phase" error-code="illegal-state"/>
- <exception name="two-phase" error-code="illegal-state"/>
- </field>
- <result type="xa-result"/>
- </command>
- <command name="forget" code="0x5">
- <exception name="illegal-state" error-code="illegal-state"/>
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="unknown-xid" error-code="not-found"/>
- <exception name="not-disassociated" error-code="illegal-state"/>
- </field>
- </command>
- <command name="get-timeout" code="0x6">
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="unknown-xid" error-code="not-found"/>
- </field>
- <result>
- <struct name="get-timeout-result" code="0x2" size="4" pack="2">
- <field name="timeout" type="uint32" required="true"/>
- </struct>
- </result>
- </command>
- <command name="prepare" code="0x7">
- <exception name="illegal-state" error-code="illegal-state"/>
- <rule name="obligation-1"/>
- <rule name="obligation-2"/>
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="unknown-xid" error-code="not-found"/>
- <exception name="not-disassociated" error-code="illegal-state"/>
- </field>
- <result type="xa-result"/>
- </command>
- <command name="recover" code="0x8">
- <implement role="server" handle="MAY"/>
- <result>
- <struct name="recover-result" code="0x3" size="4" pack="2">
- <field name="in-doubt" type="array" required="true"/>
- </struct>
- </result>
- </command>
- <command name="rollback" code="0x9">
- <exception name="illegal-state" error-code="illegal-state"/>
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="unknown-xid" error-code="not-found"/>
- <exception name="not-disassociated" error-code="illegal-state"/>
- </field>
- <result type="xa-result"/>
- </command>
- <command name="set-timeout" code="0xa">
- <rule name="effective"/>
- <rule name="reset"/>
- <implement role="server" handle="MAY"/>
- <field name="xid" type="xid" required="true">
- <exception name="unknown-xid" error-code="not-found"/>
- </field>
- <field name="timeout" type="uint32" required="true"/>
- </command>
- </class>
- <class name="exchange" code="0x7">
- <rule name="required-types"/>
- <rule name="recommended-types"/>
- <rule name="required-instances"/>
- <rule name="default-exchange"/>
- <rule name="default-access"/>
- <rule name="extensions"/>
- <role name="server" implement="MUST"/>
- <role name="client" implement="MUST"/>
- <domain name="name" type="str8"/>
- <command name="declare" code="0x1">
- <rule name="minimum"/>
- <implement role="server" handle="MUST"/>
- <field name="exchange" type="name" required="true">
- <exception name="reserved-names" error-code="not-allowed"/>
- <exception name="exchange-name-required" error-code="invalid-argument"/>
- </field>
- <field name="type" type="str8" required="true">
- <exception name="typed" error-code="not-allowed"/>
- <exception name="exchange-type-not-found" error-code="not-found"/>
- </field>
- <field name="alternate-exchange" type="name">
- <rule name="empty-name"/>
- <exception name="pre-existing-exchange" error-code="not-allowed"/>
- <rule name="double-failure"/>
- </field>
- <field name="passive" type="bit">
- <exception name="not-found" error-code="not-found"/>
- </field>
- <field name="durable" type="bit">
- <rule name="support"/>
- <rule name="sticky"/>
- </field>
- <field name="auto-delete" type="bit">
- <rule name="sticky"/>
- </field>
- <field name="arguments" type="map">
- <exception name="unknown-argument" error-code="not-implemented"/>
- </field>
- </command>
- <command name="delete" code="0x2">
- <implement role="server" handle="MUST"/>
- <field name="exchange" type="name" required="true">
- <exception name="exists" error-code="not-found"/>
- <exception name="exchange-name-required" error-code="invalid-argument"/>
- <exception name="used-as-alternate" error-code="not-allowed"/>
- </field>
- <field name="if-unused" type="bit">
- <exception name="exchange-in-use" error-code="precondition-failed"/>
- </field>
- </command>
- <command name="query" code="0x3">
- <implement role="server" handle="MUST"/>
- <field name="name" type="str8"/>
- <result>
- <struct name="exchange-query-result" code="0x1" size="4" pack="2">
- <field name="type" type="str8"/>
- <field name="durable" type="bit"/>
- <field name="not-found" type="bit"/>
- <field name="arguments" type="map"/>
- </struct>
- </result>
- </command>
- <command name="bind" code="0x4">
- <rule name="duplicates"/>
- <rule name="durable-exchange"/>
- <rule name="binding-count"/>
- <rule name="multiple-bindings"/>
- <implement role="server" handle="MUST"/>
- <field name="queue" type="queue.name" required="true">
- <exception name="empty-queue" error-code="invalid-argument"/>
- <exception name="queue-existence" error-code="not-found"/>
- </field>
- <field name="exchange" type="name" required="true">
- <exception name="exchange-existence" error-code="not-found"/>
- <exception name="exchange-name-required" error-code="invalid-argument"/>
- </field>
- <field name="binding-key" type="str8" required="true"/>
- <field name="arguments" type="map">
- <exception name="unknown-argument" error-code="not-implemented"/>
- </field>
- </command>
- <command name="unbind" code="0x5">
- <implement role="server" handle="MUST"/>
- <field name="queue" type="queue.name" required="true">
- <exception name="non-existent-queue" error-code="not-found"/>
- </field>
- <field name="exchange" type="name" required="true">
- <exception name="non-existent-exchange" error-code="not-found"/>
- <exception name="exchange-name-required" error-code="invalid-argument"/>
- </field>
- <field name="binding-key" type="str8" required="true">
- <exception name="non-existent-binding-key" error-code="not-found"/>
- </field>
- </command>
- <command name="bound" code="0x6">
- <implement role="server" handle="MUST"/>
- <field name="exchange" type="str8"/>
- <field name="queue" type="str8" required="true"/>
- <field name="binding-key" type="str8"/>
- <field name="arguments" type="map"/>
- <result>
- <struct name="exchange-bound-result" code="0x2" size="4" pack="2">
- <field name="exchange-not-found" type="bit"/>
- <field name="queue-not-found" type="bit"/>
- <field name="queue-not-matched" type="bit"/>
- <field name="key-not-matched" type="bit"/>
- <field name="args-not-matched" type="bit"/>
- </struct>
- </result>
- </command>
- </class>
- <class name="queue" code="0x8">
- <rule name="any-content"/>
- <role name="server" implement="MUST"/>
- <role name="client" implement="MUST"/>
- <domain name="name" type="str8"/>
- <command name="declare" code="0x1">
- <rule name="default-binding"/>
- <rule name="minimum-queues"/>
- <implement role="server" handle="MUST"/>
- <field name="queue" type="name" required="true">
- <exception name="reserved-prefix" error-code="not-allowed"/>
- </field>
- <field name="alternate-exchange" type="exchange.name">
- <exception name="pre-existing-exchange" error-code="not-allowed"/>
- <exception name="unknown-exchange" error-code="not-found"/>
- </field>
- <field name="passive" type="bit">
- <exception name="passive" error-code="not-found"/>
- </field>
- <field name="durable" type="bit">
- <rule name="persistence"/>
- <rule name="types"/>
- <rule name="pre-existence"/>
- </field>
- <field name="exclusive" type="bit">
- <rule name="types"/>
- <exception name="in-use" error-code="resource-locked"/>
- </field>
- <field name="auto-delete" type="bit">
- <rule name="pre-existence"/>
- </field>
- <field name="arguments" type="map">
- <exception name="unknown-argument" error-code="not-implemented"/>
- </field>
- </command>
- <command name="delete" code="0x2">
- <implement role="server" handle="MUST"/>
- <field name="queue" type="name" required="true">
- <exception name="empty-name" error-code="invalid-argument"/>
- <exception name="queue-exists" error-code="not-found"/>
- </field>
- <field name="if-unused" type="bit">
- <exception name="if-unused-flag" error-code="precondition-failed"/>
- </field>
- <field name="if-empty" type="bit">
- <exception name="not-empty" error-code="precondition-failed"/>
- </field>
- </command>
- <command name="purge" code="0x3">
- <rule name="empty"/>
- <rule name="pending-messages"/>
- <rule name="purge-recovery"/>
- <implement role="server" handle="MUST"/>
- <field name="queue" type="name" required="true">
- <exception name="empty-name" error-code="invalid-argument"/>
- <exception name="queue-exists" error-code="not-found"/>
- </field>
- </command>
- <command name="query" code="0x4">
- <implement role="server" handle="MUST"/>
- <field name="queue" type="name" required="true"/>
- <result>
- <struct name="queue-query-result" code="0x1" size="4" pack="2">
- <field name="queue" type="name" required="true"/>
- <field name="alternate-exchange" type="exchange.name"/>
- <field name="durable" type="bit"/>
- <field name="exclusive" type="bit"/>
- <field name="auto-delete" type="bit"/>
- <field name="arguments" type="map"/>
- <field name="message-count" type="uint32" required="true"/>
- <field name="subscriber-count" type="uint32" required="true"/>
- </struct>
- </result>
- </command>
- </class>
- <class name="file" code="0x9">
- <rule name="reliable-storage"/>
- <rule name="no-discard"/>
- <rule name="priority-levels"/>
- <rule name="acknowledgement-support"/>
- <role name="server" implement="MAY"/>
- <role name="client" implement="MAY"/>
- <struct name="file-properties" code="0x1" size="4" pack="2">
- <field name="content-type" type="str8"/>
- <field name="content-encoding" type="str8"/>
- <field name="headers" type="map"/>
- <field name="priority" type="uint8"/>
- <field name="reply-to" type="str8"/>
- <field name="message-id" type="str8"/>
- <field name="filename" type="str8"/>
- <field name="timestamp" type="datetime"/>
- <field name="cluster-id" type="str8"/>
- </struct>
- <domain name="return-code" type="uint16">
- <enum>
- <choice name="content-too-large" value="311"/>
- <choice name="no-route" value="312"/>
- <choice name="no-consumers" value="313"/>
- </enum>
- </domain>
- <command name="qos" code="0x1">
- <implement role="server" handle="MUST"/>
- <response name="qos-ok"/>
- <field name="prefetch-size" type="uint32"/>
- <field name="prefetch-count" type="uint16">
- <rule name="prefetch-discretion"/>
- </field>
- <field name="global" type="bit"/>
- </command>
- <command name="qos-ok" code="0x2">
- <implement role="client" handle="MUST"/>
- </command>
- <command name="consume" code="0x3">
- <rule name="min-consumers"/>
- <implement role="server" handle="MUST"/>
- <response name="consume-ok"/>
- <field name="queue" type="queue.name">
- <exception name="queue-exists-if-empty" error-code="not-allowed"/>
- </field>
- <field name="consumer-tag" type="str8">
- <exception name="not-existing-consumer" error-code="not-allowed"/>
- <exception name="not-empty-consumer-tag" error-code="not-allowed"/>
- </field>
- <field name="no-local" type="bit"/>
- <field name="no-ack" type="bit"/>
- <field name="exclusive" type="bit">
- <exception name="in-use" error-code="resource-locked"/>
- </field>
- <field name="nowait" type="bit"/>
- <field name="arguments" type="map"/>
- </command>
- <command name="consume-ok" code="0x4">
- <implement role="client" handle="MUST"/>
- <field name="consumer-tag" type="str8"/>
- </command>
- <command name="cancel" code="0x5">
- <implement role="server" handle="MUST"/>
- <field name="consumer-tag" type="str8"/>
- </command>
- <command name="open" code="0x6">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <response name="open-ok"/>
- <field name="identifier" type="str8"/>
- <field name="content-size" type="uint64">
- <rule name="content-size"/>
- </field>
- </command>
- <command name="open-ok" code="0x7">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <response name="stage"/>
- <field name="staged-size" type="uint64">
- <rule name="behavior"/>
- <rule name="staging"/>
- </field>
- </command>
- <command name="stage" code="0x8">
- <implement role="server" handle="MUST"/>
- <implement role="client" handle="MUST"/>
- <segments>
- <header required="true">
- <entry type="file-properties"/>
- </header>
- <body/>
- </segments>
- </command>
- <command name="publish" code="0x9">
- <implement role="server" handle="MUST"/>
- <field name="exchange" type="exchange.name">
- <rule name="default"/>
- <exception name="refusal" error-code="not-implemented"/>
- </field>
- <field name="routing-key" type="str8"/>
- <field name="mandatory" type="bit">
- <rule name="implementation"/>
- </field>
- <field name="immediate" type="bit">
- <rule name="implementation"/>
- </field>
- <field name="identifier" type="str8"/>
- </command>
- <command name="return" code="0xa">
- <implement role="client" handle="MUST"/>
- <field name="reply-code" type="return-code"/>
- <field name="reply-text" type="str8"/>
- <field name="exchange" type="exchange.name"/>
- <field name="routing-key" type="str8"/>
- <segments>
- <header required="true">
- <entry type="file-properties"/>
- </header>
- <body/>
- </segments>
- </command>
- <command name="deliver" code="0xb">
- <rule name="redelivery-tracking"/>
- <implement role="client" handle="MUST"/>
- <field name="consumer-tag" type="str8"/>
- <field name="delivery-tag" type="uint64">
- <rule name="non-zero"/>
- </field>
- <field name="redelivered" type="bit"/>
- <field name="exchange" type="exchange.name"/>
- <field name="routing-key" type="str8"/>
- <field name="identifier" type="str8"/>
- </command>
- <command name="ack" code="0xc">
- <implement role="server" handle="MUST"/>
- <field name="delivery-tag" type="uint64">
- <rule name="session-local"/>
- </field>
- <field name="multiple" type="bit">
- <rule name="validation"/>
- </field>
- </command>
- <command name="reject" code="0xd">
- <rule name="server-interpretation"/>
- <rule name="not-selection"/>
- <implement role="server" handle="MUST"/>
- <field name="delivery-tag" type="uint64">
- <rule name="session-local"/>
- </field>
- <field name="requeue" type="bit">
- <rule name="requeue-strategy"/>
- </field>
- </command>
- </class>
- <class name="stream" code="0xa">
- <rule name="overflow-discard"/>
- <rule name="priority-levels"/>
- <rule name="acknowledgement-support"/>
- <role name="server" implement="MAY"/>
- <role name="client" implement="MAY"/>
- <struct name="stream-properties" code="0x1" size="4" pack="2">
- <field name="content-type" type="str8"/>
- <field name="content-encoding" type="str8"/>
- <field name="headers" type="map"/>
- <field name="priority" type="uint8"/>
- <field name="timestamp" type="datetime"/>
- </struct>
- <domain name="return-code" type="uint16">
- <enum>
- <choice name="content-too-large" value="311"/>
- <choice name="no-route" value="312"/>
- <choice name="no-consumers" value="313"/>
- </enum>
- </domain>
- <command name="qos" code="0x1">
- <implement role="server" handle="MUST"/>
- <response name="qos-ok"/>
- <field name="prefetch-size" type="uint32"/>
- <field name="prefetch-count" type="uint16"/>
- <field name="consume-rate" type="uint32">
- <rule name="ignore-prefetch"/>
- <rule name="drop-by-priority"/>
- </field>
- <field name="global" type="bit"/>
- </command>
- <command name="qos-ok" code="0x2">
- <implement role="client" handle="MUST"/>
- </command>
- <command name="consume" code="0x3">
- <rule name="min-consumers"/>
- <rule name="priority-based-delivery"/>
- <implement role="server" handle="MUST"/>
- <response name="consume-ok"/>
- <field name="queue" type="queue.name">
- <exception name="queue-exists-if-empty" error-code="not-allowed"/>
- </field>
- <field name="consumer-tag" type="str8">
- <exception name="not-existing-consumer" error-code="not-allowed"/>
- <exception name="not-empty-consumer-tag" error-code="not-allowed"/>
- </field>
- <field name="no-local" type="bit"/>
- <field name="exclusive" type="bit">
- <exception name="in-use" error-code="resource-locked"/>
- </field>
- <field name="nowait" type="bit"/>
- <field name="arguments" type="map"/>
- </command>
- <command name="consume-ok" code="0x4">
- <implement role="client" handle="MUST"/>
- <field name="consumer-tag" type="str8"/>
- </command>
- <command name="cancel" code="0x5">
- <implement role="server" handle="MUST"/>
- <field name="consumer-tag" type="str8"/>
- </command>
- <command name="publish" code="0x6">
- <implement role="server" handle="MUST"/>
- <field name="exchange" type="exchange.name">
- <rule name="default"/>
- <exception name="refusal" error-code="not-implemented"/>
- </field>
- <field name="routing-key" type="str8"/>
- <field name="mandatory" type="bit">
- <rule name="implementation"/>
- </field>
- <field name="immediate" type="bit">
- <rule name="implementation"/>
- </field>
- <segments>
- <header required="true">
- <entry type="stream-properties"/>
- </header>
- <body/>
- </segments>
- </command>
- <command name="return" code="0x7">
- <implement role="client" handle="MUST"/>
- <field name="reply-code" type="return-code"/>
- <field name="reply-text" type="str8"/>
- <field name="exchange" type="exchange.name"/>
- <field name="routing-key" type="str8"/>
- <segments>
- <header required="true">
- <entry type="stream-properties"/>
- </header>
- <body/>
- </segments>
- </command>
- <command name="deliver" code="0x8">
- <implement role="client" handle="MUST"/>
- <field name="consumer-tag" type="str8"/>
- <field name="delivery-tag" type="uint64">
- <rule name="session-local"/>
- </field>
- <field name="exchange" type="exchange.name"/>
- <field name="queue" type="queue.name" required="true"/>
- <segments>
- <header required="true">
- <entry type="stream-properties"/>
- </header>
- <body/>
- </segments>
- </command>
- </class>
-</amqp>
diff --git a/qpid/python/qpid/specs/amqp-0-10.dtd b/qpid/python/qpid/specs/amqp-0-10.dtd
deleted file mode 100644
index 2be198525a..0000000000
--- a/qpid/python/qpid/specs/amqp-0-10.dtd
+++ /dev/null
@@ -1,246 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
- Copyright Notice
- ================
- (c) Copyright Cisco Systems, Credit Suisse, Deutsche Börse Systems, Envoy Technologies, Inc.,
- Goldman Sachs, IONA Technologies PLC, iMatix Corporation sprl.,JPMorgan Chase Bank Inc. N.A,
- Novell, Rabbit Technologies Ltd., Red Hat, Inc., TWIST Process Innovations ltd, and 29West Inc
- 2006, 2007. All rights reserved.
-
- License
- =======
- JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., iMatix Corporation, IONA
- Technologies, Red Hat, Inc., TWIST Process Innovations, and 29West Inc. (collectively, the
- "Authors") each hereby grants to you a worldwide, perpetual, royalty-free, nontransferable,
- nonexclusive license to (i) copy, display, distribute and implement the Advanced Messaging Queue
- Protocol ("AMQP") Specification and (ii) the Licensed Claims that are held by the Authors, all for
- the purpose of implementing the Advanced Messaging Queue Protocol Specification. Your license and
- any rights under this Agreement will terminate immediately without notice from any Author if you
- bring any claim, suit, demand, or action related to the Advanced Messaging Queue Protocol
- Specification against any Author. Upon termination, you shall destroy all copies of the Advanced
- Messaging Queue Protocol Specification in your possession or control.
-
- As used hereunder, "Licensed Claims" means those claims of a patent or patent application,
- throughout the world, excluding design patents and design registrations, owned or controlled, or
- that can be sublicensed without fee and in compliance with the requirements of this Agreement, by
- an Author or its affiliates now or at any future time and which would necessarily be infringed by
- implementation of the Advanced Messaging Queue Protocol Specification. A claim is necessarily
- infringed hereunder only when it is not possible to avoid infringing it because there is no
- plausible non-infringing alternative for implementing the required portions of the Advanced
- Messaging Queue Protocol Specification. Notwithstanding the foregoing, Licensed Claims shall not
- include any claims other than as set forth above even if contained in the same patent as Licensed
- Claims; or that read solely on any implementations of any portion of the Advanced Messaging Queue
- Protocol Specification that are not required by the Advanced Messaging Queue Protocol
- Specification, or that, if licensed, would require a payment of royalties by the licensor to
- unaffiliated third parties. Moreover, Licensed Claims shall not include (i) any enabling
- technologies that may be necessary to make or use any Licensed Product but are not themselves
- expressly set forth in the Advanced Messaging Queue Protocol Specification (e.g., semiconductor
- manufacturing technology, compiler technology, object oriented technology, networking technology,
- operating system technology, and the like); or (ii) the implementation of other published
- standards developed elsewhere and merely referred to in the body of the Advanced Messaging Queue
- Protocol Specification, or (iii) any Licensed Product and any combinations thereof the purpose or
- function of which is not required for compliance with the Advanced Messaging Queue Protocol
- Specification. For purposes of this definition, the Advanced Messaging Queue Protocol
- Specification shall be deemed to include both architectural and interconnection requirements
- essential for interoperability and may also include supporting source code artifacts where such
- architectural, interconnection requirements and source code artifacts are expressly identified as
- being required or documentation to achieve compliance with the Advanced Messaging Queue Protocol
- Specification.
-
- As used hereunder, "Licensed Products" means only those specific portions of products (hardware,
- software or combinations thereof) that implement and are compliant with all relevant portions of
- the Advanced Messaging Queue Protocol Specification.
-
- The following disclaimers, which you hereby also acknowledge as to any use you may make of the
- Advanced Messaging Queue Protocol Specification:
-
- THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION IS PROVIDED "AS IS," AND THE AUTHORS MAKE NO
- REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS
- OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE
- IMPLEMENTATION OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION WILL NOT INFRINGE ANY THIRD
- PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
-
- THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
- DAMAGES ARISING OUT OF OR RELATING TO ANY USE, IMPLEMENTATION OR OF THE ADVANCED
- MESSAGING QUEUE PROTOCOL SPECIFICATION.
-
- The name and trademarks of the Authors may NOT be used in any manner, including advertising or
- publicity pertaining to the Advanced Messaging Queue Protocol Specification or its contents
- without specific, written prior permission. Title to copyright in the Advanced Messaging Queue
- Protocol Specification will at all times remain with the Authors.
-
- No other rights are granted by implication, estoppel or otherwise.
-
- Upon termination of your license or rights under this Agreement, you shall destroy all copies of
- the Advanced Messaging Queue Protocol Specification in your possession or control.
-
- Trademarks
- ==========
- "JPMorgan", "JPMorgan Chase", "Chase", the JPMorgan Chase logo and the Octagon Symbol are
- trademarks of JPMorgan Chase & Co.
-
- IMATIX and the iMatix logo are trademarks of iMatix Corporation sprl.
-
- IONA, IONA Technologies, and the IONA logos are trademarks of IONA Technologies PLC and/or its
- subsidiaries.
-
- LINUX is a trademark of Linus Torvalds. RED HAT and JBOSS are registered trademarks of Red Hat,
- Inc. in the US and other countries.
-
- Java, all Java-based trademarks and OpenOffice.org are trademarks of Sun Microsystems, Inc. in the
- United States, other countries, or both.
-
- Other company, product, or service names may be trademarks or service marks of others.
-
- Links to full AMQP specification:
- =================================
- http://www.envoytech.org/spec/amq/
- http://www.iona.com/opensource/amqp/
- http://www.redhat.com/solutions/specifications/amqp/
- http://www.twiststandards.org/tiki-index.php?page=AMQ
- http://www.imatix.com/amqp
--->
-
-<!ELEMENT amqp (doc|type|struct|domain|constant|class)*>
-<!ATTLIST amqp
- xmlns CDATA #IMPLIED
- major CDATA #REQUIRED
- minor CDATA #REQUIRED
- port CDATA #REQUIRED
- comment CDATA #IMPLIED
->
-
-<!ELEMENT constant (doc|rule)*>
-<!ATTLIST constant
- name CDATA #REQUIRED
- value CDATA #REQUIRED
- label CDATA #IMPLIED
->
-
-<!ELEMENT type (doc|rule)*>
-<!ATTLIST type
- name CDATA #REQUIRED
- label CDATA #IMPLIED
- code CDATA #IMPLIED
- fixed-width CDATA #IMPLIED
- variable-width CDATA #IMPLIED
->
-
-<!ELEMENT domain (doc|rule|enum)*>
-<!ATTLIST domain
- name CDATA #REQUIRED
- type CDATA #IMPLIED
- label CDATA #IMPLIED
->
-
-<!ELEMENT struct (field|doc|rule)*>
-<!ATTLIST struct
- name CDATA #REQUIRED
- label CDATA #IMPLIED
- size (0|1|2|4) #IMPLIED
- pack (0|1|2|4) #IMPLIED
- code CDATA #IMPLIED>
-
-<!ELEMENT enum (choice)*>
-
-<!ELEMENT choice (doc|rule)*>
-<!ATTLIST choice
- name CDATA #REQUIRED
- value CDATA #REQUIRED
->
-
-<!ELEMENT class (doc|role|rule|struct|domain|control|command)*>
-<!ATTLIST class
- name CDATA #REQUIRED
- code CDATA #REQUIRED
- label CDATA #IMPLIED
->
-
-<!ELEMENT role (doc|rule)*>
-<!ATTLIST role
- name CDATA #REQUIRED
- implement (MAY|SHOULD|MUST) #REQUIRED
->
-
-<!ELEMENT control (doc|implement|rule|field|response)*>
-<!ATTLIST control
- name CDATA #REQUIRED
- code CDATA #REQUIRED
- label CDATA #IMPLIED
->
-
-<!ELEMENT command ((doc|implement|rule|exception|field|response)*, result?, segments?)>
-<!ATTLIST command
- name CDATA #REQUIRED
- code CDATA #REQUIRED
- label CDATA #IMPLIED
->
-
-<!ELEMENT implement (doc|rule)*>
-<!ATTLIST implement
- role CDATA #REQUIRED
- handle (MAY|SHOULD|MUST) #REQUIRED
- send (MAY|SHOULD|MUST) #IMPLIED
->
-
-<!ELEMENT field (doc|rule|exception)*>
-<!ATTLIST field
- name CDATA #REQUIRED
- type CDATA #IMPLIED
- default CDATA #IMPLIED
- code CDATA #IMPLIED
- label CDATA #IMPLIED
- required CDATA #IMPLIED
->
-
-<!ELEMENT rule (doc*)>
-<!ATTLIST rule
- name CDATA #REQUIRED
- label CDATA #IMPLIED
->
-
-<!ELEMENT exception (doc*)>
-<!ATTLIST exception
- name CDATA #REQUIRED
- error-code CDATA #IMPLIED
- label CDATA #IMPLIED
->
-
-<!ELEMENT response (doc|rule)*>
-<!ATTLIST response
- name CDATA #IMPLIED
->
-
-<!ELEMENT result (doc|rule|struct)*>
-<!ATTLIST result
- type CDATA #IMPLIED
->
-
-<!ELEMENT segments (doc|rule|header|body)*>
-
-<!ELEMENT header (doc|rule|entry)*>
-<!ATTLIST header
- required (true|false) #IMPLIED
->
-
-<!ELEMENT entry (doc|rule)*>
-<!ATTLIST entry
- type CDATA #REQUIRED
->
-
-<!ELEMENT body (doc|rule)*>
-<!ATTLIST body
- required (true|false) #IMPLIED
->
-
-<!ELEMENT doc (#PCDATA|xref)*>
-<!ATTLIST doc
- type (grammar|scenario|picture|bnf|todo) #IMPLIED
- title CDATA #IMPLIED
->
-
-<!ELEMENT xref (#PCDATA)>
-<!ATTLIST xref
- ref CDATA #REQUIRED>
diff --git a/qpid/python/qpid/specs/amqp-0-8-qpid-stripped.xml b/qpid/python/qpid/specs/amqp-0-8-qpid-stripped.xml
deleted file mode 100644
index 6975e17aa6..0000000000
--- a/qpid/python/qpid/specs/amqp-0-8-qpid-stripped.xml
+++ /dev/null
@@ -1,784 +0,0 @@
-<?xml version="1.0"?>
-
-<!--
-(c) Copyright JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy
-Technologies Inc., iMatix Corporation, IONA\ufffd Technologies, Red
-Hat, Inc., TWIST Process Innovations, and 29West Inc. 2006.
-
-Copyright (c) 2009 AMQP Working Group.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
-derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--->
-
-<amqp major="8" minor="0" port="5672">
- <constant name="frame method" value="1"/>
- <constant name="frame header" value="2"/>
- <constant name="frame body" value="3"/>
- <constant name="frame oob method" value="4"/>
- <constant name="frame oob header" value="5"/>
- <constant name="frame oob body" value="6"/>
- <constant name="frame trace" value="7"/>
- <constant name="frame heartbeat" value="8"/>
- <constant name="frame min size" value="4096"/>
- <constant name="frame end" value="206"/>
- <constant name="reply success" value="200"/>
- <constant name="not delivered" value="310" class="soft error"/>
- <constant name="content too large" value="311" class="soft error"/>
- <constant name="connection forced" value="320" class="hard error"/>
- <constant name="invalid path" value="402" class="hard error"/>
- <constant name="access refused" value="403" class="soft error"/>
- <constant name="not found" value="404" class="soft error"/>
- <constant name="resource locked" value="405" class="soft error"/>
- <constant name="frame error" value="501" class="hard error"/>
- <constant name="syntax error" value="502" class="hard error"/>
- <constant name="command invalid" value="503" class="hard error"/>
- <constant name="channel error" value="504" class="hard error"/>
- <constant name="resource error" value="506" class="hard error"/>
- <constant name="not allowed" value="530" class="hard error"/>
- <constant name="not implemented" value="540" class="hard error"/>
- <constant name="internal error" value="541" class="hard error"/>
- <domain name="access ticket" type="short">
- <assert check="ne" value="0"/>
- </domain>
- <domain name="class id" type="short"/>
- <domain name="consumer tag" type="shortstr"/>
- <domain name="delivery tag" type="longlong"/>
- <domain name="exchange name" type="shortstr">
- <assert check="length" value="127"/>
- </domain>
- <domain name="known hosts" type="shortstr"/>
- <domain name="method id" type="short"/>
- <domain name="no ack" type="bit"/>
- <domain name="no local" type="bit"/>
- <domain name="path" type="shortstr">
- <assert check="notnull"/>
- <assert check="syntax" rule="path"/>
- <assert check="length" value="127"/>
- </domain>
- <domain name="peer properties" type="table"/>
- <domain name="queue name" type="shortstr">
- <assert check="length" value="127"/>
- </domain>
- <domain name="redelivered" type="bit"/>
- <domain name="reply code" type="short">
- <assert check="notnull"/>
- </domain>
- <domain name="reply text" type="shortstr">
- <assert check="notnull"/>
- </domain>
- <class name="connection" handler="connection" index="10">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="start" synchronous="1" index="10">
- <chassis name="client" implement="MUST"/>
- <response name="start-ok"/>
- <field name="version major" type="octet"/>
- <field name="version minor" type="octet"/>
- <field name="server properties" domain="peer properties"/>
- <field name="mechanisms" type="longstr">
- <see name="security mechanisms"/>
- <assert check="notnull"/>
- </field>
- <field name="locales" type="longstr">
- <assert check="notnull"/>
- </field>
- </method>
- <method name="start-ok" synchronous="1" index="11">
- <chassis name="server" implement="MUST"/>
- <field name="client properties" domain="peer properties"/>
- <field name="mechanism" type="shortstr">
- <assert check="notnull"/>
- </field>
- <field name="response" type="longstr">
- <assert check="notnull"/>
- </field>
- <field name="locale" type="shortstr">
- <assert check="notnull"/>
- </field>
- </method>
- <method name="secure" synchronous="1" index="20">
- <chassis name="client" implement="MUST"/>
- <response name="secure-ok"/>
- <field name="challenge" type="longstr">
- <see name="security mechanisms"/>
- </field>
- </method>
- <method name="secure-ok" synchronous="1" index="21">
- <chassis name="server" implement="MUST"/>
- <field name="response" type="longstr">
- <assert check="notnull"/>
- </field>
- </method>
- <method name="tune" synchronous="1" index="30">
- <chassis name="client" implement="MUST"/>
- <response name="tune-ok"/>
- <field name="channel max" type="short"/>
- <field name="frame max" type="long"/>
- <field name="heartbeat" type="short"/>
- </method>
- <method name="tune-ok" synchronous="1" index="31">
- <chassis name="server" implement="MUST"/>
- <field name="channel max" type="short">
- <assert check="notnull"/>
- <assert check="le" method="tune" field="channel max"/>
- </field>
- <field name="frame max" type="long"/>
- <field name="heartbeat" type="short"/>
- </method>
- <method name="open" synchronous="1" index="40">
- <chassis name="server" implement="MUST"/>
- <response name="open-ok"/>
- <response name="redirect"/>
- <field name="virtual host" domain="path">
- <assert check="regexp" value="^[a-zA-Z0-9/-_]+$"/>
- </field>
- <field name="capabilities" type="shortstr"/>
- <field name="insist" type="bit"/>
- </method>
- <method name="open-ok" synchronous="1" index="41">
- <chassis name="client" implement="MUST"/>
- <field name="known hosts" domain="known hosts"/>
- </method>
- <method name="redirect" synchronous="1" index="50">
- <chassis name="client" implement="MAY"/>
- <field name="host" type="shortstr">
- <assert check="notnull"/>
- </field>
- <field name="known hosts" domain="known hosts"/>
- </method>
- <method name="close" synchronous="1" index="60">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- <response name="close-ok"/>
- <field name="reply code" domain="reply code"/>
- <field name="reply text" domain="reply text"/>
- <field name="class id" domain="class id"/>
- <!-- Qpid difference : correct the domain -->
- <field name="method id" domain="method id"/>
- </method>
- <method name="close-ok" synchronous="1" index="61">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- </method>
- </class>
- <class name="channel" handler="channel" index="20">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="open" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="open-ok"/>
- <field name="out of band" type="shortstr">
- <assert check="null"/>
- </field>
- </method>
- <method name="open-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="flow" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <response name="flow-ok"/>
- <field name="active" type="bit"/>
- </method>
- <method name="flow-ok" index="21">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <field name="active" type="bit"/>
- </method>
- <method name="alert" index="30">
- <chassis name="client" implement="MUST"/>
- <field name="reply code" domain="reply code"/>
- <field name="reply text" domain="reply text"/>
- <field name="details" type="table"/>
- </method>
- <method name="close" synchronous="1" index="40">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- <response name="close-ok"/>
- <field name="reply code" domain="reply code"/>
- <field name="reply text" domain="reply text"/>
- <field name="class id" domain="class id"/>
- <field name="method id" domain="method id"/>
- </method>
- <method name="close-ok" synchronous="1" index="41">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- </method>
- </class>
- <class name="access" handler="connection" index="30">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="request" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="request-ok"/>
- <field name="realm" domain="path"/>
- <field name="exclusive" type="bit"/>
- <field name="passive" type="bit"/>
- <field name="active" type="bit"/>
- <field name="write" type="bit"/>
- <field name="read" type="bit"/>
- </method>
- <method name="request-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- <field name="ticket" domain="access ticket"/>
- </method>
- </class>
- <class name="exchange" handler="channel" index="40">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="declare" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="declare-ok"/>
- <field name="ticket" domain="access ticket"/>
- <field name="exchange" domain="exchange name">
- <assert check="regexp" value="^[a-zA-Z0-9-_.:]+$"/>
- </field>
- <field name="type" type="shortstr">
- <assert check="regexp" value="^[a-zA-Z0-9-_.:]+$"/>
- </field>
- <field name="passive" type="bit"/>
- <field name="durable" type="bit"/>
- <field name="auto delete" type="bit"/>
- <field name="internal" type="bit"/>
- <field name="nowait" type="bit"/>
- <field name="arguments" type="table"/>
- </method>
- <method name="declare-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="delete" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="delete-ok"/>
- <field name="ticket" domain="access ticket"/>
- <field name="exchange" domain="exchange name">
- <assert check="notnull"/>
- </field>
- <field name="if unused" type="bit"/>
- <field name="nowait" type="bit"/>
- </method>
- <method name="delete-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- </method>
- <!-- Qpid specific addition -->
- <method name="bound" synchronous="1" index="22">
- <chassis name="server" implement="SHOULD"/>
- <field name="exchange" domain="exchange name"/>
- <field name="routing key" type="shortstr"/>
- <field name="queue" domain="queue name"/>
- </method>
- <method name="bound-ok" synchronous="1" index="23">
- <field name="reply code" domain="reply code"/>
- <field name="reply text" domain="reply text"/>
- <chassis name="client" implement="SHOULD"/>
- </method>
- <!-- End Qpid specific addition -->
- </class>
- <class name="queue" handler="channel" index="50">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="declare" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="declare-ok"/>
- <field name="ticket" domain="access ticket"/>
- <field name="queue" domain="queue name">
- <assert check="regexp" value="^[a-zA-Z0-9-_.:]*$"/>
- </field>
- <field name="passive" type="bit"/>
- <field name="durable" type="bit"/>
- <field name="exclusive" type="bit"/>
- <field name="auto delete" type="bit"/>
- <field name="nowait" type="bit"/>
- <field name="arguments" type="table"/>
- </method>
- <method name="declare-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- <field name="queue" domain="queue name">
- <assert check="notnull"/>
- </field>
- <field name="message count" type="long"/>
- <field name="consumer count" type="long"/>
- </method>
- <method name="bind" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="bind-ok"/>
- <field name="ticket" domain="access ticket"/>
- <field name="queue" domain="queue name"/>
- <field name="exchange" domain="exchange name"/>
- <field name="routing key" type="shortstr"/>
- <field name="nowait" type="bit"/>
- <field name="arguments" type="table"/>
- </method>
- <method name="bind-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="purge" synchronous="1" index="30">
- <chassis name="server" implement="MUST"/>
- <response name="purge-ok"/>
- <field name="ticket" domain="access ticket"/>
- <field name="queue" domain="queue name"/>
- <field name="nowait" type="bit"/>
- </method>
- <method name="purge-ok" synchronous="1" index="31">
- <chassis name="client" implement="MUST"/>
- <field name="message count" type="long"/>
- </method>
- <method name="delete" synchronous="1" index="40">
- <chassis name="server" implement="MUST"/>
- <response name="delete-ok"/>
- <field name="ticket" domain="access ticket"/>
- <field name="queue" domain="queue name"/>
- <field name="if unused" type="bit"/>
- <field name="if empty" type="bit"/>
- <field name="nowait" type="bit"/>
- </method>
- <method name="delete-ok" synchronous="1" index="41">
- <chassis name="client" implement="MUST"/>
- <field name="message count" type="long"/>
- </method>
- </class>
- <class name="basic" handler="channel" index="60">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MAY"/>
- <field name="content type" type="shortstr"/>
- <field name="content encoding" type="shortstr"/>
- <field name="headers" type="table"/>
- <field name="delivery mode" type="octet"/>
- <field name="priority" type="octet"/>
- <field name="correlation id" type="shortstr"/>
- <field name="reply to" type="shortstr"/>
- <field name="expiration" type="shortstr"/>
- <field name="message id" type="shortstr"/>
- <field name="timestamp" type="timestamp"/>
- <field name="type" type="shortstr"/>
- <field name="user id" type="shortstr"/>
- <field name="app id" type="shortstr"/>
- <field name="cluster id" type="shortstr"/>
- <method name="qos" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="qos-ok"/>
- <field name="prefetch size" type="long"/>
- <field name="prefetch count" type="short"/>
- <field name="global" type="bit"/>
- </method>
- <method name="qos-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="consume" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="consume-ok"/>
- <field name="ticket" domain="access ticket"/>
- <field name="queue" domain="queue name"/>
- <field name="consumer tag" domain="consumer tag"/>
- <field name="no local" domain="no local"/>
- <field name="no ack" domain="no ack"/>
- <field name="exclusive" type="bit"/>
- <field name="nowait" type="bit"/>
- <!-- Qpid specific addition : interop issue extra field -->
- <field name="arguments" type="table"/>
- </method>
- <method name="consume-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- <field name="consumer tag" domain="consumer tag"/>
- </method>
- <method name="cancel" synchronous="1" index="30">
- <chassis name="server" implement="MUST"/>
- <response name="cancel-ok"/>
- <field name="consumer tag" domain="consumer tag"/>
- <field name="nowait" type="bit"/>
- </method>
- <method name="cancel-ok" synchronous="1" index="31">
- <chassis name="client" implement="MUST"/>
- <field name="consumer tag" domain="consumer tag"/>
- </method>
- <method name="publish" content="1" index="40">
- <chassis name="server" implement="MUST"/>
- <field name="ticket" domain="access ticket"/>
- <field name="exchange" domain="exchange name"/>
- <field name="routing key" type="shortstr"/>
- <field name="mandatory" type="bit"/>
- <field name="immediate" type="bit"/>
- </method>
- <method name="return" content="1" index="50">
- <chassis name="client" implement="MUST"/>
- <field name="reply code" domain="reply code"/>
- <field name="reply text" domain="reply text"/>
- <field name="exchange" domain="exchange name"/>
- <field name="routing key" type="shortstr"/>
- </method>
- <method name="deliver" content="1" index="60">
- <chassis name="client" implement="MUST"/>
- <field name="consumer tag" domain="consumer tag"/>
- <field name="delivery tag" domain="delivery tag"/>
- <field name="redelivered" domain="redelivered"/>
- <field name="exchange" domain="exchange name"/>
- <field name="routing key" type="shortstr"/>
- </method>
- <method name="get" synchronous="1" index="70">
- <response name="get-ok"/>
- <response name="get-empty"/>
- <chassis name="server" implement="MUST"/>
- <field name="ticket" domain="access ticket"/>
- <field name="queue" domain="queue name"/>
- <field name="no ack" domain="no ack"/>
- </method>
- <method name="get-ok" synchronous="1" content="1" index="71">
- <chassis name="client" implement="MAY"/>
- <field name="delivery tag" domain="delivery tag"/>
- <field name="redelivered" domain="redelivered"/>
- <field name="exchange" domain="exchange name"/>
- <field name="routing key" type="shortstr"/>
- <field name="message count" type="long"/>
- </method>
- <method name="get-empty" synchronous="1" index="72">
- <chassis name="client" implement="MAY"/>
- <field name="cluster id" type="shortstr"/>
- </method>
- <method name="ack" index="80">
- <chassis name="server" implement="MUST"/>
- <field name="delivery tag" domain="delivery tag"/>
- <field name="multiple" type="bit"/>
- </method>
- <method name="reject" index="90">
- <chassis name="server" implement="MUST"/>
- <field name="delivery tag" domain="delivery tag"/>
- <field name="requeue" type="bit"/>
- </method>
- <!-- Qpid specific modification : interop issue, added synchronous reply -->
- <method name="recover" index="100">
- <chassis name="server" implement="MUST"/>
- <field name="requeue" type="bit"/>
- <response name="recover-ok"/>
- </method>
- <method name="recover-ok" synchronous="1" index="101">
- <chassis name="client" implement="MUST"/>
- </method>
- <!-- End Qpid specific modification -->
- </class>
- <class name="file" handler="channel" index="70">
- <chassis name="server" implement="MAY"/>
- <chassis name="client" implement="MAY"/>
- <field name="content type" type="shortstr"/>
- <field name="content encoding" type="shortstr"/>
- <field name="headers" type="table"/>
- <field name="priority" type="octet"/>
- <field name="reply to" type="shortstr"/>
- <field name="message id" type="shortstr"/>
- <field name="filename" type="shortstr"/>
- <field name="timestamp" type="timestamp"/>
- <field name="cluster id" type="shortstr"/>
- <method name="qos" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="qos-ok"/>
- <field name="prefetch size" type="long"/>
- <field name="prefetch count" type="short"/>
- <field name="global" type="bit"/>
- </method>
- <method name="qos-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="consume" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="consume-ok"/>
- <field name="ticket" domain="access ticket"/>
- <field name="queue" domain="queue name"/>
- <field name="consumer tag" domain="consumer tag"/>
- <field name="no local" domain="no local"/>
- <field name="no ack" domain="no ack"/>
- <field name="exclusive" type="bit"/>
- <field name="nowait" type="bit"/>
- </method>
- <method name="consume-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- <field name="consumer tag" domain="consumer tag"/>
- </method>
- <method name="cancel" synchronous="1" index="30">
- <chassis name="server" implement="MUST"/>
- <response name="cancel-ok"/>
- <field name="consumer tag" domain="consumer tag"/>
- <field name="nowait" type="bit"/>
- </method>
- <method name="cancel-ok" synchronous="1" index="31">
- <chassis name="client" implement="MUST"/>
- <field name="consumer tag" domain="consumer tag"/>
- </method>
- <method name="open" synchronous="1" index="40">
- <response name="open-ok"/>
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <field name="identifier" type="shortstr"/>
- <field name="content size" type="longlong"/>
- </method>
- <method name="open-ok" synchronous="1" index="41">
- <response name="stage"/>
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <field name="staged size" type="longlong"/>
- </method>
- <method name="stage" content="1" index="50">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="publish" index="60">
- <chassis name="server" implement="MUST"/>
- <field name="ticket" domain="access ticket"/>
- <field name="exchange" domain="exchange name"/>
- <field name="routing key" type="shortstr"/>
- <field name="mandatory" type="bit"/>
- <field name="immediate" type="bit"/>
- <field name="identifier" type="shortstr"/>
- </method>
- <method name="return" content="1" index="70">
- <chassis name="client" implement="MUST"/>
- <field name="reply code" domain="reply code"/>
- <field name="reply text" domain="reply text"/>
- <field name="exchange" domain="exchange name"/>
- <field name="routing key" type="shortstr"/>
- </method>
- <method name="deliver" index="80">
- <chassis name="client" implement="MUST"/>
- <field name="consumer tag" domain="consumer tag"/>
- <field name="delivery tag" domain="delivery tag"/>
- <field name="redelivered" domain="redelivered"/>
- <field name="exchange" domain="exchange name"/>
- <field name="routing key" type="shortstr"/>
- <field name="identifier" type="shortstr"/>
- </method>
- <method name="ack" index="90">
- <chassis name="server" implement="MUST"/>
- <field name="delivery tag" domain="delivery tag"/>
- <field name="multiple" type="bit"/>
- </method>
- <method name="reject" index="100">
- <chassis name="server" implement="MUST"/>
- <field name="delivery tag" domain="delivery tag"/>
- <field name="requeue" type="bit"/>
- </method>
- </class>
- <class name="stream" handler="channel" index="80">
- <chassis name="server" implement="MAY"/>
- <chassis name="client" implement="MAY"/>
- <field name="content type" type="shortstr"/>
- <field name="content encoding" type="shortstr"/>
- <field name="headers" type="table"/>
- <field name="priority" type="octet"/>
- <field name="timestamp" type="timestamp"/>
- <method name="qos" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="qos-ok"/>
- <field name="prefetch size" type="long"/>
- <field name="prefetch count" type="short"/>
- <field name="consume rate" type="long"/>
- <field name="global" type="bit"/>
- </method>
- <method name="qos-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="consume" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="consume-ok"/>
- <field name="ticket" domain="access ticket"/>
- <field name="queue" domain="queue name"/>
- <field name="consumer tag" domain="consumer tag"/>
- <field name="no local" domain="no local"/>
- <field name="exclusive" type="bit"/>
- <field name="nowait" type="bit"/>
- </method>
- <method name="consume-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- <field name="consumer tag" domain="consumer tag"/>
- </method>
- <method name="cancel" synchronous="1" index="30">
- <chassis name="server" implement="MUST"/>
- <response name="cancel-ok"/>
- <field name="consumer tag" domain="consumer tag"/>
- <field name="nowait" type="bit"/>
- </method>
- <method name="cancel-ok" synchronous="1" index="31">
- <chassis name="client" implement="MUST"/>
- <field name="consumer tag" domain="consumer tag"/>
- </method>
- <method name="publish" content="1" index="40">
- <chassis name="server" implement="MUST"/>
- <field name="ticket" domain="access ticket"/>
- <field name="exchange" domain="exchange name"/>
- <field name="routing key" type="shortstr"/>
- <field name="mandatory" type="bit"/>
- <field name="immediate" type="bit"/>
- </method>
- <method name="return" content="1" index="50">
- <chassis name="client" implement="MUST"/>
- <field name="reply code" domain="reply code"/>
- <field name="reply text" domain="reply text"/>
- <field name="exchange" domain="exchange name"/>
- <field name="routing key" type="shortstr"/>
- </method>
- <method name="deliver" content="1" index="60">
- <chassis name="client" implement="MUST"/>
- <field name="consumer tag" domain="consumer tag"/>
- <field name="delivery tag" domain="delivery tag"/>
- <field name="exchange" domain="exchange name"/>
- <field name="queue" domain="queue name">
- <assert check="notnull"/>
- </field>
- </method>
- </class>
- <class name="tx" handler="channel" index="90">
- <chassis name="server" implement="SHOULD"/>
- <chassis name="client" implement="MAY"/>
- <method name="select" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="select-ok"/>
- </method>
- <method name="select-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="commit" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="commit-ok"/>
- </method>
- <method name="commit-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="rollback" synchronous="1" index="30">
- <chassis name="server" implement="MUST"/>
- <response name="rollback-ok"/>
- </method>
- <method name="rollback-ok" synchronous="1" index="31">
- <chassis name="client" implement="MUST"/>
- </method>
- </class>
- <class name="dtx" handler="channel" index="100">
- <chassis name="server" implement="MAY"/>
- <chassis name="client" implement="MAY"/>
- <method name="select" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="select-ok"/>
- </method>
- <method name="select-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="start" synchronous="1" index="20">
- <chassis name="server" implement="MAY"/>
- <response name="start-ok"/>
- <field name="dtx identifier" type="shortstr">
- <assert check="notnull"/>
- </field>
- </method>
- <method name="start-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- </method>
- </class>
- <class name="tunnel" handler="tunnel" index="110">
- <chassis name="server" implement="MAY"/>
- <chassis name="client" implement="MAY"/>
- <field name="headers" type="table"/>
- <field name="proxy name" type="shortstr"/>
- <field name="data name" type="shortstr"/>
- <field name="durable" type="octet"/>
- <field name="broadcast" type="octet"/>
- <method name="request" content="1" index="10">
- <chassis name="server" implement="MUST"/>
- <field name="meta data" type="table"/>
- </method>
- </class>
- <class name="test" handler="channel" index="120">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="SHOULD"/>
- <method name="integer" synchronous="1" index="10">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- <response name="integer-ok"/>
- <field name="integer 1" type="octet"/>
- <field name="integer 2" type="short"/>
- <field name="integer 3" type="long"/>
- <field name="integer 4" type="longlong"/>
- <field name="operation" type="octet">
- <assert check="enum">
- <value name="add"/>
- <value name="min"/>
- <value name="max"/>
- </assert>
- </field>
- </method>
- <method name="integer-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- <field name="result" type="longlong"/>
- </method>
- <method name="string" synchronous="1" index="20">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- <response name="string-ok"/>
- <field name="string 1" type="shortstr"/>
- <field name="string 2" type="longstr"/>
- <field name="operation" type="octet">
- <assert check="enum">
- <value name="add"/>
- <value name="min"/>
- <value name="max"/>
- </assert>
- </field>
- </method>
- <method name="string-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- <field name="result" type="longstr"/>
- </method>
- <method name="table" synchronous="1" index="30">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- <response name="table-ok"/>
- <field name="table" type="table"/>
- <field name="integer op" type="octet">
- <assert check="enum">
- <value name="add"/>
- <value name="min"/>
- <value name="max"/>
- </assert>
- </field>
- <field name="string op" type="octet">
- <assert check="enum">
- <value name="add"/>
- <value name="min"/>
- <value name="max"/>
- </assert>
- </field>
- </method>
- <method name="table-ok" synchronous="1" index="31">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- <field name="integer result" type="longlong"/>
- <field name="string result" type="longstr"/>
- </method>
- <method name="content" synchronous="1" content="1" index="40">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- <response name="content-ok"/>
- </method>
- <method name="content-ok" synchronous="1" content="1" index="41">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- <field name="content checksum" type="long"/>
- </method>
- </class>
-</amqp>
diff --git a/qpid/python/qpid/specs/amqp-0-9-1-stripped.xml b/qpid/python/qpid/specs/amqp-0-9-1-stripped.xml
deleted file mode 100644
index ec55c8dd7a..0000000000
--- a/qpid/python/qpid/specs/amqp-0-9-1-stripped.xml
+++ /dev/null
@@ -1,477 +0,0 @@
-<?xml version="1.0"?>
-<!--
-Copyright (c) 2009 AMQP Working Group.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
-derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--->
-<amqp major="0" minor="91" port="5672">
- <constant name="frame-method" value="1"/>
- <constant name="frame-header" value="2"/>
- <constant name="frame-body" value="3"/>
- <constant name="frame-heartbeat" value="8"/>
- <constant name="frame-min-size" value="4096"/>
- <constant name="frame-end" value="206"/>
- <constant name="reply-success" value="200"/>
- <constant name="content-too-large" value="311" class="soft-error"/>
- <constant name="no-consumers" value="313" class="soft-error"/>
- <constant name="connection-forced" value="320" class="hard-error"/>
- <constant name="invalid-path" value="402" class="hard-error"/>
- <constant name="access-refused" value="403" class="soft-error"/>
- <constant name="not-found" value="404" class="soft-error"/>
- <constant name="resource-locked" value="405" class="soft-error"/>
- <constant name="precondition-failed" value="406" class="soft-error"/>
- <constant name="frame-error" value="501" class="hard-error"/>
- <constant name="syntax-error" value="502" class="hard-error"/>
- <constant name="command-invalid" value="503" class="hard-error"/>
- <constant name="channel-error" value="504" class="hard-error"/>
- <constant name="unexpected-frame" value="505" class="hard-error"/>
- <constant name="resource-error" value="506" class="hard-error"/>
- <constant name="not-allowed" value="530" class="hard-error"/>
- <constant name="not-implemented" value="540" class="hard-error"/>
- <constant name="internal-error" value="541" class="hard-error"/>
- <domain name="class-id" type="short"/>
- <domain name="consumer-tag" type="shortstr"/>
- <domain name="delivery-tag" type="longlong"/>
- <domain name="exchange-name" type="shortstr">
- <assert check="length" value="127"/>
- <assert check="regexp" value="^[a-zA-Z0-9-_.:]*$"/>
- </domain>
- <domain name="method-id" type="short"/>
- <domain name="no-ack" type="bit"/>
- <domain name="no-local" type="bit"/>
- <domain name="nowait" type="bit"/>
- <!-- Qpid: restore these so that the generation sees the methods aas the same -->
- <domain name="known-hosts" type="shortstr"/>
- <domain name="access-ticket" type="short"/>
- <!-- end Qpid specific -->
- <domain name="path" type="shortstr">
- <assert check="notnull"/>
- <assert check="length" value="127"/>
- </domain>
- <domain name="peer-properties" type="table"/>
- <domain name="queue-name" type="shortstr">
- <assert check="length" value="127"/>
- <assert check="regexp" value="^[a-zA-Z0-9-_.:]*$"/>
- </domain>
- <domain name="redelivered" type="bit"/>
- <domain name="message-count" type="long"/>
- <domain name="reply-code" type="short">
- <assert check="notnull"/>
- </domain>
- <domain name="reply-text" type="shortstr">
- <assert check="notnull"/>
- </domain>
- <domain name="bit" type="bit"/>
- <domain name="octet" type="octet"/>
- <domain name="short" type="short"/>
- <domain name="long" type="long"/>
- <domain name="longlong" type="longlong"/>
- <domain name="shortstr" type="shortstr"/>
- <domain name="longstr" type="longstr"/>
- <domain name="timestamp" type="timestamp"/>
- <domain name="table" type="table"/>
- <class name="connection" handler="connection" index="10">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="start" synchronous="1" index="10">
- <chassis name="client" implement="MUST"/>
- <response name="start-ok"/>
- <field name="version-major" domain="octet"/>
- <field name="version-minor" domain="octet"/>
- <field name="server-properties" domain="peer-properties"/>
- <field name="mechanisms" domain="longstr">
- <assert check="notnull"/>
- </field>
- <field name="locales" domain="longstr">
- <assert check="notnull"/>
- </field>
- </method>
- <method name="start-ok" synchronous="1" index="11">
- <chassis name="server" implement="MUST"/>
- <field name="client-properties" domain="peer-properties"/>
- <field name="mechanism" domain="shortstr">
- <assert check="notnull"/>
- </field>
- <field name="response" domain="longstr">
- <assert check="notnull"/>
- </field>
- <field name="locale" domain="shortstr">
- <assert check="notnull"/>
- </field>
- </method>
- <method name="secure" synchronous="1" index="20">
- <chassis name="client" implement="MUST"/>
- <response name="secure-ok"/>
- <field name="challenge" domain="longstr"/>
- </method>
- <method name="secure-ok" synchronous="1" index="21">
- <chassis name="server" implement="MUST"/>
- <field name="response" domain="longstr">
- <assert check="notnull"/>
- </field>
- </method>
- <method name="tune" synchronous="1" index="30">
- <chassis name="client" implement="MUST"/>
- <response name="tune-ok"/>
- <field name="channel-max" domain="short"/>
- <field name="frame-max" domain="long"/>
- <field name="heartbeat" domain="short"/>
- </method>
- <method name="tune-ok" synchronous="1" index="31">
- <chassis name="server" implement="MUST"/>
- <field name="channel-max" domain="short">
- <assert check="notnull"/>
- <assert check="le" method="tune" field="channel-max"/>
- </field>
- <field name="frame-max" domain="long"/>
- <field name="heartbeat" domain="short"/>
- </method>
- <method name="open" synchronous="1" index="40">
- <chassis name="server" implement="MUST"/>
- <response name="open-ok"/>
- <field name="virtual-host" domain="path"/>
- <field name="capabilities" type="shortstr" reserved="1"/>
- <field name="insist" type="bit" reserved="1"/>
- </method>
- <method name="open-ok" synchronous="1" index="41">
- <chassis name="client" implement="MUST"/>
- <field name="known-hosts" domain="known-hosts" reserved="1"/>
- </method>
- <method name="close" synchronous="1" index="50">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- <response name="close-ok"/>
- <field name="reply-code" domain="reply-code"/>
- <field name="reply-text" domain="reply-text"/>
- <field name="class-id" domain="class-id"/>
- <field name="method-id" domain="method-id"/>
- </method>
- <method name="close-ok" synchronous="1" index="51">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- </method>
- </class>
- <class name="channel" handler="channel" index="20">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="open" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="open-ok"/>
- <field name="out-of-band" type="shortstr" reserved="1"/>
- </method>
- <method name="open-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- <field name="channel-id" type="longstr" reserved="1"/>
- </method>
- <method name="flow" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <response name="flow-ok"/>
- <field name="active" domain="bit"/>
- </method>
- <method name="flow-ok" index="21">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <field name="active" domain="bit"/>
- </method>
- <method name="close" synchronous="1" index="40">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- <response name="close-ok"/>
- <field name="reply-code" domain="reply-code"/>
- <field name="reply-text" domain="reply-text"/>
- <field name="class-id" domain="class-id"/>
- <field name="method-id" domain="method-id"/>
- </method>
- <method name="close-ok" synchronous="1" index="41">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- </method>
- </class>
- <class name="exchange" handler="channel" index="40">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="declare" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="declare-ok"/>
- <field name="ticket" domain="access-ticket" reserved="1"/>
- <field name="exchange" domain="exchange-name">
- <assert check="notnull"/>
- </field>
- <field name="type" domain="shortstr"/>
- <field name="passive" domain="bit"/>
- <field name="durable" domain="bit"/>
- <field name="auto-delete" type="bit" reserved="1"/>
- <field name="internal" type="bit" reserved="1"/>
- <field name="nowait" domain="bit"/>
- <field name="arguments" domain="table"/>
- </method>
- <method name="declare-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="delete" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="delete-ok"/>
- <field name="ticket" domain="access-ticket" reserved="1"/>
- <field name="exchange" domain="exchange-name">
- <assert check="notnull"/>
- </field>
- <field name="if-unused" domain="bit"/>
- <field name="nowait" domain="bit"/>
- </method>
- <method name="delete-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- </method>
- <!-- Qpid : Added Exchange.bound and Exchange.bound-ok -->
- <method name="bound" synchronous="1" index="22">
- <chassis name="server" implement="SHOULD"/>
- <response name="bound-ok"/>
- <field name="exchange" domain="exchange-name"/>
- <field name = "routing-key" type = "shortstr"/>
- <field name = "queue" domain = "queue name"/>
- </method>
- <method name="bound-ok" synchronous="1" index="23">
- <field name="reply-code" domain="reply-code"/>
- <field name="reply-text" domain="reply-text"/>
- <chassis name="client" implement="SHOULD"/>
- </method>
- <!-- End Qpid addition -->
- </class>
- <class name="queue" handler="channel" index="50">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="declare" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="declare-ok"/>
- <field name="ticket" domain="access-ticket" reserved="1"/>
- <field name="queue" domain="queue-name"/>
- <field name="passive" domain="bit"/>
- <field name="durable" domain="bit"/>
- <field name="exclusive" domain="bit"/>
- <field name="auto-delete" domain="bit"/>
- <field name="nowait" domain="bit"/>
- <field name="arguments" domain="table"/>
- </method>
- <method name="declare-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- <field name="queue" domain="queue-name">
- <assert check="notnull"/>
- </field>
- <field name="message-count" domain="long"/>
- <field name="consumer-count" domain="long"/>
- </method>
- <method name="bind" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="bind-ok"/>
- <field name="ticket" domain="access-ticket" reserved="1"/>
- <field name="queue" domain="queue-name"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- <field name="nowait" domain="bit"/>
- <field name="arguments" domain="table"/>
- </method>
- <method name="bind-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="unbind" synchronous="1" index="50">
- <chassis name="server" implement="MUST"/>
- <response name="unbind-ok"/>
- <field name="ticket" domain="access-ticket" reserved="1"/>
- <field name="queue" domain="queue-name"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- <field name="arguments" domain="table"/>
- </method>
- <method name="unbind-ok" synchronous="1" index="51">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="purge" synchronous="1" index="30">
- <chassis name="server" implement="MUST"/>
- <response name="purge-ok"/>
- <field name="ticket" domain="access-ticket" reserved="1"/>
- <field name="queue" domain="queue-name"/>
- <field name="nowait" domain="bit"/>
- </method>
- <method name="purge-ok" synchronous="1" index="31">
- <chassis name="client" implement="MUST"/>
- <field name="message-count" domain="long"/>
- </method>
- <method name="delete" synchronous="1" index="40">
- <chassis name="server" implement="MUST"/>
- <response name="delete-ok"/>
- <field name="ticket" domain="access-ticket" reserved="1"/>
- <field name="queue" domain="queue-name"/>
- <field name="if-unused" domain="bit"/>
- <field name="if-empty" domain="bit"/>
- <field name="nowait" domain="bit"/>
- </method>
- <method name="delete-ok" synchronous="1" index="41">
- <chassis name="client" implement="MUST"/>
- <field name="message-count" domain="long"/>
- </method>
- </class>
- <class name="basic" handler="channel" index="60">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MAY"/>
- <field name="content-type" domain="shortstr"/>
- <field name="content-encoding" domain="shortstr"/>
- <field name="headers" domain="table"/>
- <field name="delivery-mode" domain="octet"/>
- <field name="priority" domain="octet"/>
- <field name="correlation-id" domain="shortstr"/>
- <field name="reply-to" domain="shortstr"/>
- <field name="expiration" domain="shortstr"/>
- <field name="message-id" domain="shortstr"/>
- <field name="timestamp" domain="timestamp"/>
- <field name="type" domain="shortstr"/>
- <field name="user-id" domain="shortstr"/>
- <field name="app-id" domain="shortstr"/>
- <field name="reserved" domain="shortstr"/>
- <method name="qos" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="qos-ok"/>
- <field name="prefetch-size" domain="long"/>
- <field name="prefetch-count" domain="short"/>
- <field name="global" domain="bit"/>
- </method>
- <method name="qos-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="consume" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="consume-ok"/>
- <field name="ticket" domain="access-ticket" reserved="1"/>
- <field name="queue" domain="queue-name"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- <field name="no-local" domain="no-local"/>
- <field name="no-ack" domain="no-ack"/>
- <field name="exclusive" domain="bit"/>
- <field name="nowait" domain="bit"/>
- <field name="arguments" domain="table"/>
- </method>
- <method name="consume-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- </method>
- <method name="cancel" synchronous="1" index="30">
- <chassis name="server" implement="MUST"/>
- <response name="cancel-ok"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- <field name="nowait" domain="bit"/>
- </method>
- <method name="cancel-ok" synchronous="1" index="31">
- <chassis name="client" implement="MUST"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- </method>
- <method name="publish" content="1" index="40">
- <chassis name="server" implement="MUST"/>
- <field name="ticket" domain="access-ticket" reserved="1"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- <field name="mandatory" domain="bit"/>
- <field name="immediate" domain="bit"/>
- </method>
- <method name="return" content="1" index="50">
- <chassis name="client" implement="MUST"/>
- <field name="reply-code" domain="reply-code"/>
- <field name="reply-text" domain="reply-text"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- </method>
- <method name="deliver" content="1" index="60">
- <chassis name="client" implement="MUST"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- <field name="delivery-tag" domain="delivery-tag"/>
- <field name="redelivered" domain="redelivered"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- </method>
- <method name="get" synchronous="1" index="70">
- <response name="get-ok"/>
- <response name="get-empty"/>
- <chassis name="server" implement="MUST"/>
- <field name="ticket" domain="access-ticket" reserved="1"/>
- <field name="queue" domain="queue-name"/>
- <field name="no-ack" domain="no-ack"/>
- </method>
- <method name="get-ok" synchronous="1" content="1" index="71">
- <chassis name="client" implement="MAY"/>
- <field name="delivery-tag" domain="delivery-tag"/>
- <field name="redelivered" domain="redelivered"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- <field name="message-count" domain="long"/>
- </method>
- <method name="get-empty" synchronous="1" index="72">
- <chassis name="client" implement="MAY"/>
- <field name="cluster-id" type="shortstr" reserved="1"/>
- </method>
- <method name="ack" index="80">
- <chassis name="server" implement="MUST"/>
- <field name="delivery-tag" domain="delivery-tag"/>
- <field name="multiple" domain="bit"/>
- </method>
- <method name="reject" index="90">
- <chassis name="server" implement="MUST"/>
- <field name="delivery-tag" domain="delivery-tag"/>
- <field name="requeue" domain="bit"/>
- </method>
- <method name="recover" index="100" deprecated="1">
- <chassis name="server" implement="MAY"/>
- <field name="requeue" domain="bit"/>
- </method>
- <method name="recover-sync" index="110">
- <chassis name="server" implement="MUST"/>
- <field name="requeue" domain="bit"/>
- </method>
- <method name="recover-sync-ok" synchronous="1" index="111">
- <chassis name="client" implement="MUST"/>
- </method>
- </class>
- <class name="tx" handler="channel" index="90">
- <chassis name="server" implement="SHOULD"/>
- <chassis name="client" implement="MAY"/>
- <method name="select" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="select-ok"/>
- </method>
- <method name="select-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="commit" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="commit-ok"/>
- </method>
- <method name="commit-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="rollback" synchronous="1" index="30">
- <chassis name="server" implement="MUST"/>
- <response name="rollback-ok"/>
- </method>
- <method name="rollback-ok" synchronous="1" index="31">
- <chassis name="client" implement="MUST"/>
- </method>
- </class>
-</amqp>
diff --git a/qpid/python/qpid/specs/amqp-0-9-qpid-stripped.xml b/qpid/python/qpid/specs/amqp-0-9-qpid-stripped.xml
deleted file mode 100644
index e0075870de..0000000000
--- a/qpid/python/qpid/specs/amqp-0-9-qpid-stripped.xml
+++ /dev/null
@@ -1,876 +0,0 @@
-<?xml version="1.0"?>
-
-<!--
-(c) Copyright JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy
-Technologies Inc., iMatix Corporation, IONA\ufffd Technologies, Red
-Hat, Inc., TWIST Process Innovations, and 29West Inc. 2006.
-
-Copyright (c) 2009 AMQP Working Group.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
-derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--->
-
-<amqp major="0" minor="9" port="5672">
- <constant name="frame-method" value="1"/>
- <constant name="frame-header" value="2"/>
- <constant name="frame-body" value="3"/>
- <constant name="frame-oob-method" value="4"/>
- <constant name="frame-oob-header" value="5"/>
- <constant name="frame-oob-body" value="6"/>
- <constant name="frame-trace" value="7"/>
- <constant name="frame-heartbeat" value="8"/>
- <constant name="frame-min-size" value="4096"/>
- <constant name="frame-end" value="206"/>
- <constant name="reply-success" value="200"/>
- <constant name="not-delivered" value="310" class="soft-error"/>
- <constant name="content-too-large" value="311" class="soft-error"/>
- <constant name="no-route" value="312" class="soft-error"/>
- <constant name="no-consumers" value="313" class="soft-error"/>
- <constant name="connection-forced" value="320" class="hard-error"/>
- <constant name="invalid-path" value="402" class="hard-error"/>
- <constant name="access-refused" value="403" class="soft-error"/>
- <constant name="not-found" value="404" class="soft-error"/>
- <constant name="resource-locked" value="405" class="soft-error"/>
- <constant name="precondition-failed" value="406" class="soft-error"/>
- <constant name="frame-error" value="501" class="hard-error"/>
- <constant name="syntax-error" value="502" class="hard-error"/>
- <constant name="command-invalid" value="503" class="hard-error"/>
- <constant name="channel-error" value="504" class="hard-error"/>
- <constant name="resource-error" value="506" class="hard-error"/>
- <constant name="not-allowed" value="530" class="hard-error"/>
- <constant name="not-implemented" value="540" class="hard-error"/>
- <constant name="internal-error" value="541" class="hard-error"/>
- <domain name="access-ticket" type="short">
- <assert check="ne" value="0"/>
- </domain>
- <domain name="class-id" type="short"/>
- <domain name="consumer-tag" type="shortstr"/>
- <domain name="delivery-tag" type="longlong"/>
- <domain name="exchange-name" type="shortstr">
- <assert check="length" value="127"/>
- </domain>
- <domain name="known-hosts" type="shortstr"/>
- <domain name="method-id" type="short"/>
- <domain name="no-ack" type="bit"/>
- <domain name="no-local" type="bit"/>
- <domain name="path" type="shortstr">
- <assert check="notnull"/>
- <assert check="syntax" rule="path"/>
- <assert check="length" value="127"/>
- </domain>
- <domain name="peer-properties" type="table"/>
- <domain name="queue-name" type="shortstr">
- <assert check="length" value="127"/>
- </domain>
- <domain name="redelivered" type="bit"/>
- <domain name="reply-code" type="short">
- <assert check="notnull"/>
- </domain>
- <domain name="reply-text" type="shortstr">
- <assert check="notnull"/>
- </domain>
- <domain name="channel-id" type="longstr"/>
- <domain name="duration" type="longlong"/>
- <domain name="offset" type="longlong"/>
- <domain name="reference" type="longstr"/>
- <domain name="destination" type="shortstr"/>
- <domain name="reject-code" type="short"/>
- <domain name="reject-text" type="shortstr"/>
- <domain name="security-token" type="longstr"/>
- <domain name="bit" type="bit"/>
- <domain name="octet" type="octet"/>
- <domain name="short" type="short"/>
- <domain name="long" type="long"/>
- <domain name="longlong" type="longlong"/>
- <domain name="shortstr" type="shortstr"/>
- <domain name="longstr" type="longstr"/>
- <domain name="timestamp" type="timestamp"/>
- <domain name="table" type="table"/>
- <class name="connection" handler="connection" index="10">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="start" synchronous="1" index="10">
- <chassis name="client" implement="MUST"/>
- <response name="start-ok"/>
- <field name="version-major" domain="octet"/>
- <field name="version-minor" domain="octet"/>
- <field name="server-properties" domain="peer-properties"/>
- <field name="mechanisms" domain="longstr">
- <assert check="notnull"/>
- </field>
- <field name="locales" domain="longstr">
- <assert check="notnull"/>
- </field>
- </method>
- <method name="start-ok" synchronous="1" index="11">
- <chassis name="server" implement="MUST"/>
- <field name="client-properties" domain="peer-properties"/>
- <field name="mechanism" domain="shortstr">
- <assert check="notnull"/>
- </field>
- <field name="response" domain="longstr">
- <assert check="notnull"/>
- </field>
- <field name="locale" domain="shortstr">
- <assert check="notnull"/>
- </field>
- </method>
- <method name="secure" synchronous="1" index="20">
- <chassis name="client" implement="MUST"/>
- <response name="secure-ok"/>
- <field name="challenge" domain="longstr"/>
- </method>
- <method name="secure-ok" synchronous="1" index="21">
- <chassis name="server" implement="MUST"/>
- <field name="response" domain="longstr">
- <assert check="notnull"/>
- </field>
- </method>
- <method name="tune" synchronous="1" index="30">
- <chassis name="client" implement="MUST"/>
- <response name="tune-ok"/>
- <field name="channel-max" domain="short"/>
- <field name="frame-max" domain="long"/>
- <field name="heartbeat" domain="short"/>
- </method>
- <method name="tune-ok" synchronous="1" index="31">
- <chassis name="server" implement="MUST"/>
- <field name="channel-max" domain="short">
- <assert check="notnull"/>
- <assert check="le" method="tune" field="channel-max"/>
- </field>
- <field name="frame-max" domain="long"/>
- <field name="heartbeat" domain="short"/>
- </method>
- <method name="open" synchronous="1" index="40">
- <chassis name="server" implement="MUST"/>
- <response name="open-ok"/>
- <response name="redirect"/>
- <field name="virtual-host" domain="path">
- <assert check="regexp" value="^[a-zA-Z0-9/-_]+$"/>
- </field>
- <field name="capabilities" domain="shortstr"/>
- <field name="insist" domain="bit"/>
- </method>
- <method name="open-ok" synchronous="1" index="41">
- <chassis name="client" implement="MUST"/>
- <field name="known-hosts" domain="known-hosts"/>
- </method>
- <method name="redirect" synchronous="1" index="42">
- <chassis name="client" implement="MUST"/>
- <field name="host" domain="shortstr">
- <assert check="notnull"/>
- </field>
- <field name="known-hosts" domain="known-hosts"/>
- </method>
- <method name="close" synchronous="1" index="50">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- <response name="close-ok"/>
- <field name="reply-code" domain="reply-code"/>
- <field name="reply-text" domain="reply-text"/>
- <field name="class-id" domain="class-id"/>
- <field name="method-id" domain="method-id"/>
- </method>
- <method name="close-ok" synchronous="1" index="51">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- </method>
- </class>
- <class name="channel" handler="channel" index="20">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="open" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="open-ok"/>
- <field name="out-of-band" domain="shortstr">
- <assert check="null"/>
- </field>
- </method>
- <method name="open-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- <field name="channel-id" domain="channel-id"/>
- </method>
- <method name="flow" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <response name="flow-ok"/>
- <field name="active" domain="bit"/>
- </method>
- <method name="flow-ok" index="21">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <field name="active" domain="bit"/>
- </method>
- <method name="close" synchronous="1" index="40">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- <response name="close-ok"/>
- <field name="reply-code" domain="reply-code"/>
- <field name="reply-text" domain="reply-text"/>
- <field name="class-id" domain="class-id"/>
- <field name="method-id" domain="method-id"/>
- </method>
- <method name="close-ok" synchronous="1" index="41">
- <chassis name="client" implement="MUST"/>
- <chassis name="server" implement="MUST"/>
- </method>
- <method name="resume" index="50">
- <response name="ok"/>
- <chassis name="server" implement="MAY"/>
- <field name="channel-id" domain="channel-id"/>
- </method>
- <method name="ping" index="60">
- <response name="ok"/>
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="pong" index="70">
- <response name="ok"/>
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="ok" index="80">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- </method>
- </class>
- <class name="access" handler="connection" index="30">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="request" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="request-ok"/>
- <field name="realm" domain="shortstr"/>
- <field name="exclusive" domain="bit"/>
- <field name="passive" domain="bit"/>
- <field name="active" domain="bit"/>
- <field name="write" domain="bit"/>
- <field name="read" domain="bit"/>
- </method>
- <method name="request-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- <field name="ticket" domain="access-ticket"/>
- </method>
- </class>
- <class name="exchange" handler="channel" index="40">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="declare" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="declare-ok"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="exchange" domain="exchange-name">
- <assert check="regexp" value="^[a-zA-Z0-9-_.:]+$"/>
- </field>
- <field name="type" domain="shortstr">
- <assert check="regexp" value="^[a-zA-Z0-9-_.:]+$"/>
- </field>
- <field name="passive" domain="bit"/>
- <field name="durable" domain="bit"/>
- <field name="auto-delete" domain="bit"/>
- <field name="internal" domain="bit"/>
- <field name="nowait" domain="bit"/>
- <field name="arguments" domain="table"/>
- </method>
- <method name="declare-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="delete" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="delete-ok"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="exchange" domain="exchange-name">
- <assert check="notnull"/>
- </field>
- <field name="if-unused" domain="bit"/>
- <field name="nowait" domain="bit"/>
- </method>
- <method name="delete-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- </method>
- <!-- Qpid specific addition -->
- <method name="bound" synchronous="1" index="22">
- <chassis name="server" implement="SHOULD"/>
- <response name="bound-ok"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" type="shortstr"/>
- <field name="queue" domain="queue name"/>
- </method>
- <method name="bound-ok" synchronous="1" index="23">
- <field name="reply-code" domain="reply-code"/>
- <field name="reply-text" domain="reply-text"/>
- <chassis name="client" implement="SHOULD"/>
- </method>
- <!-- End Qpid specific addition -->
- </class>
- <class name="queue" handler="channel" index="50">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="declare" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="declare-ok"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="queue" domain="queue-name">
- <assert check="regexp" value="^[a-zA-Z0-9-_.:]*$"/>
- </field>
- <field name="passive" domain="bit"/>
- <field name="durable" domain="bit"/>
- <field name="exclusive" domain="bit"/>
- <field name="auto-delete" domain="bit"/>
- <field name="nowait" domain="bit"/>
- <!-- Qpid diff - this field is known as filter in the original 0-9,
- however since the name does not go on the wire, there is no
- interop implication -->
- <field name="arguments" domain="table"/>
- </method>
- <method name="declare-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- <field name="queue" domain="queue-name">
- <assert check="notnull"/>
- </field>
- <field name="message-count" domain="long"/>
- <field name="consumer-count" domain="long"/>
- </method>
- <method name="bind" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="bind-ok"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="queue" domain="queue-name"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- <field name="nowait" domain="bit"/>
- <field name="arguments" domain="table"/>
- </method>
- <method name="bind-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="unbind" synchronous="1" index="50">
- <chassis name="server" implement="MUST"/>
- <response name="unbind-ok"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="queue" domain="queue-name"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- <field name="arguments" domain="table"/>
- </method>
- <method name="unbind-ok" synchronous="1" index="51">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="purge" synchronous="1" index="30">
- <chassis name="server" implement="MUST"/>
- <response name="purge-ok"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="queue" domain="queue-name"/>
- <field name="nowait" domain="bit"/>
- </method>
- <method name="purge-ok" synchronous="1" index="31">
- <chassis name="client" implement="MUST"/>
- <field name="message-count" domain="long"/>
- </method>
- <method name="delete" synchronous="1" index="40">
- <chassis name="server" implement="MUST"/>
- <response name="delete-ok"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="queue" domain="queue-name"/>
- <field name="if-unused" domain="bit"/>
- <field name="if-empty" domain="bit"/>
- <field name="nowait" domain="bit"/>
- </method>
- <method name="delete-ok" synchronous="1" index="41">
- <chassis name="client" implement="MUST"/>
- <field name="message-count" domain="long"/>
- </method>
- </class>
- <class name="basic" handler="channel" index="60">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MAY"/>
- <field name="content-type" domain="shortstr"/>
- <field name="content-encoding" domain="shortstr"/>
- <field name="headers" domain="table"/>
- <field name="delivery-mode" domain="octet"/>
- <field name="priority" domain="octet"/>
- <field name="correlation-id" domain="shortstr"/>
- <field name="reply-to" domain="shortstr"/>
- <field name="expiration" domain="shortstr"/>
- <field name="message-id" domain="shortstr"/>
- <field name="timestamp" domain="timestamp"/>
- <field name="type" domain="shortstr"/>
- <field name="user-id" domain="shortstr"/>
- <field name="app-id" domain="shortstr"/>
- <field name="cluster-id" domain="shortstr"/>
- <method name="qos" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="qos-ok"/>
- <field name="prefetch-size" domain="long"/>
- <field name="prefetch-count" domain="short"/>
- <field name="global" domain="bit"/>
- </method>
- <method name="qos-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="consume" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="consume-ok"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="queue" domain="queue-name"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- <field name="no-local" domain="no-local"/>
- <field name="no-ack" domain="no-ack"/>
- <field name="exclusive" domain="bit"/>
- <field name="nowait" domain="bit"/>
- <field name="arguments" domain="table"/>
- </method>
- <method name="consume-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- </method>
- <method name="cancel" synchronous="1" index="30">
- <chassis name="server" implement="MUST"/>
- <response name="cancel-ok"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- <field name="nowait" domain="bit"/>
- </method>
- <method name="cancel-ok" synchronous="1" index="31">
- <chassis name="client" implement="MUST"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- </method>
- <method name="publish" content="1" index="40">
- <chassis name="server" implement="MUST"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- <field name="mandatory" domain="bit"/>
- <field name="immediate" domain="bit"/>
- </method>
- <method name="return" content="1" index="50">
- <chassis name="client" implement="MUST"/>
- <field name="reply-code" domain="reply-code"/>
- <field name="reply-text" domain="reply-text"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- </method>
- <method name="deliver" content="1" index="60">
- <chassis name="client" implement="MUST"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- <field name="delivery-tag" domain="delivery-tag"/>
- <field name="redelivered" domain="redelivered"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- </method>
- <method name="get" synchronous="1" index="70">
- <response name="get-ok"/>
- <response name="get-empty"/>
- <chassis name="server" implement="MUST"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="queue" domain="queue-name"/>
- <field name="no-ack" domain="no-ack"/>
- </method>
- <method name="get-ok" synchronous="1" content="1" index="71">
- <chassis name="client" implement="MAY"/>
- <field name="delivery-tag" domain="delivery-tag"/>
- <field name="redelivered" domain="redelivered"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- <field name="message-count" domain="long"/>
- </method>
- <method name="get-empty" synchronous="1" index="72">
- <chassis name="client" implement="MAY"/>
- <field name="cluster-id" domain="shortstr"/>
- </method>
- <method name="ack" index="80">
- <chassis name="server" implement="MUST"/>
- <field name="delivery-tag" domain="delivery-tag"/>
- <field name="multiple" domain="bit"/>
- </method>
- <method name="reject" index="90">
- <chassis name="server" implement="MUST"/>
- <field name="delivery-tag" domain="delivery-tag"/>
- <field name="requeue" domain="bit"/>
- </method>
- <method name="recover" index="100">
- <chassis name="server" implement="MUST"/>
- <field name="requeue" domain="bit"/>
- </method>
- <!-- Qpid specific addition -->
- <method name="recover-sync" index="102">
- <chassis name="server" implement="MUST"/>
- <field name="requeue" type="bit"/>
- <response name="recover-sync-ok"/>
- </method>
- <method name="recover-sync-ok" synchronous="1" index="101">
- <chassis name="client" implement="MUST"/>
- </method>
- <!-- End Qpid specific addition -->
- </class>
- <class name="file" handler="channel" index="70">
- <chassis name="server" implement="MAY"/>
- <chassis name="client" implement="MAY"/>
- <field name="content-type" domain="shortstr"/>
- <field name="content-encoding" domain="shortstr"/>
- <field name="headers" domain="table"/>
- <field name="priority" domain="octet"/>
- <field name="reply-to" domain="shortstr"/>
- <field name="message-id" domain="shortstr"/>
- <field name="filename" domain="shortstr"/>
- <field name="timestamp" domain="timestamp"/>
- <field name="cluster-id" domain="shortstr"/>
- <method name="qos" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="qos-ok"/>
- <field name="prefetch-size" domain="long"/>
- <field name="prefetch-count" domain="short"/>
- <field name="global" domain="bit"/>
- </method>
- <method name="qos-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="consume" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="consume-ok"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="queue" domain="queue-name"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- <field name="no-local" domain="no-local"/>
- <field name="no-ack" domain="no-ack"/>
- <field name="exclusive" domain="bit"/>
- <field name="nowait" domain="bit"/>
- <field name="filter" domain="table"/>
- </method>
- <method name="consume-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- </method>
- <method name="cancel" synchronous="1" index="30">
- <response name="cancel-ok"/>
- <chassis name="server" implement="MUST"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- <field name="nowait" domain="bit"/>
- </method>
- <method name="cancel-ok" synchronous="1" index="31">
- <chassis name="client" implement="MUST"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- </method>
- <method name="open" synchronous="1" index="40">
- <response name="open-ok"/>
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <field name="identifier" domain="shortstr"/>
- <field name="content-size" domain="longlong"/>
- </method>
- <method name="open-ok" synchronous="1" index="41">
- <response name="stage"/>
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <field name="staged-size" domain="longlong"/>
- </method>
- <method name="stage" content="1" index="50">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="publish" index="60">
- <chassis name="server" implement="MUST"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- <field name="mandatory" domain="bit"/>
- <field name="immediate" domain="bit"/>
- <field name="identifier" domain="shortstr"/>
- </method>
- <method name="return" content="1" index="70">
- <chassis name="client" implement="MUST"/>
- <field name="reply-code" domain="reply-code"/>
- <field name="reply-text" domain="reply-text"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- </method>
- <method name="deliver" index="80">
- <chassis name="client" implement="MUST"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- <field name="delivery-tag" domain="delivery-tag"/>
- <field name="redelivered" domain="redelivered"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- <field name="identifier" domain="shortstr"/>
- </method>
- <method name="ack" index="90">
- <chassis name="server" implement="MUST"/>
- <field name="delivery-tag" domain="delivery-tag"/>
- <field name="multiple" domain="bit"/>
- </method>
- <method name="reject" index="100">
- <chassis name="server" implement="MUST"/>
- <field name="delivery-tag" domain="delivery-tag"/>
- <field name="requeue" domain="bit"/>
- </method>
- </class>
- <class name="stream" handler="channel" index="80">
- <chassis name="server" implement="MAY"/>
- <chassis name="client" implement="MAY"/>
- <field name="content-type" domain="shortstr"/>
- <field name="content-encoding" domain="shortstr"/>
- <field name="headers" domain="table"/>
- <field name="priority" domain="octet"/>
- <field name="timestamp" domain="timestamp"/>
- <method name="qos" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="qos-ok"/>
- <field name="prefetch-size" domain="long"/>
- <field name="prefetch-count" domain="short"/>
- <field name="consume-rate" domain="long"/>
- <field name="global" domain="bit"/>
- </method>
- <method name="qos-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="consume" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="consume-ok"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="queue" domain="queue-name"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- <field name="no-local" domain="no-local"/>
- <field name="exclusive" domain="bit"/>
- <field name="nowait" domain="bit"/>
- <field name="filter" domain="table"/>
- </method>
- <method name="consume-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- </method>
- <method name="cancel" synchronous="1" index="30">
- <chassis name="server" implement="MUST"/>
- <response name="cancel-ok"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- <field name="nowait" domain="bit"/>
- </method>
- <method name="cancel-ok" synchronous="1" index="31">
- <chassis name="client" implement="MUST"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- </method>
- <method name="publish" content="1" index="40">
- <chassis name="server" implement="MUST"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- <field name="mandatory" domain="bit"/>
- <field name="immediate" domain="bit"/>
- </method>
- <method name="return" content="1" index="50">
- <chassis name="client" implement="MUST"/>
- <field name="reply-code" domain="reply-code"/>
- <field name="reply-text" domain="reply-text"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- </method>
- <method name="deliver" content="1" index="60">
- <chassis name="client" implement="MUST"/>
- <field name="consumer-tag" domain="consumer-tag"/>
- <field name="delivery-tag" domain="delivery-tag"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="queue" domain="queue-name">
- <assert check="notnull"/>
- </field>
- </method>
- </class>
- <class name="tx" handler="channel" index="90">
- <chassis name="server" implement="SHOULD"/>
- <chassis name="client" implement="MAY"/>
- <method name="select" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="select-ok"/>
- </method>
- <method name="select-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="commit" synchronous="1" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="commit-ok"/>
- </method>
- <method name="commit-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="rollback" synchronous="1" index="30">
- <chassis name="server" implement="MUST"/>
- <response name="rollback-ok"/>
- </method>
- <method name="rollback-ok" synchronous="1" index="31">
- <chassis name="client" implement="MUST"/>
- </method>
- </class>
- <class name="dtx" handler="channel" index="100">
- <chassis name="server" implement="MAY"/>
- <chassis name="client" implement="MAY"/>
- <method name="select" synchronous="1" index="10">
- <chassis name="server" implement="MUST"/>
- <response name="select-ok"/>
- </method>
- <method name="select-ok" synchronous="1" index="11">
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="start" synchronous="1" index="20">
- <chassis name="server" implement="MAY"/>
- <response name="start-ok"/>
- <field name="dtx-identifier" domain="shortstr">
- <assert check="notnull"/>
- </field>
- </method>
- <method name="start-ok" synchronous="1" index="21">
- <chassis name="client" implement="MUST"/>
- </method>
- </class>
- <class name="tunnel" handler="tunnel" index="110">
- <chassis name="server" implement="MAY"/>
- <chassis name="client" implement="MAY"/>
- <field name="headers" domain="table"/>
- <field name="proxy-name" domain="shortstr"/>
- <field name="data-name" domain="shortstr"/>
- <field name="durable" domain="octet"/>
- <field name="broadcast" domain="octet"/>
- <method name="request" content="1" index="10">
- <chassis name="server" implement="MUST"/>
- <field name="meta-data" domain="table"/>
- </method>
- </class>
- <class name="message" handler="channel" index="120">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <method name="transfer" index="10">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <response name="ok"/>
- <response name="reject"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="destination" domain="destination"/>
- <field name="redelivered" domain="redelivered"/>
- <field name="immediate" domain="bit"/>
- <field name="ttl" domain="duration"/>
- <field name="priority" domain="octet"/>
- <field name="timestamp" domain="timestamp"/>
- <field name="delivery-mode" domain="octet"/>
- <field name="expiration" domain="timestamp"/>
- <field name="exchange" domain="exchange-name"/>
- <field name="routing-key" domain="shortstr"/>
- <field name="message-id" domain="shortstr"/>
- <field name="correlation-id" domain="shortstr"/>
- <field name="reply-to" domain="shortstr"/>
- <field name="content-type" domain="shortstr"/>
- <field name="content-encoding" domain="shortstr"/>
- <field name="user-id" domain="shortstr"/>
- <field name="app-id" domain="shortstr"/>
- <field name="transaction-id" domain="shortstr"/>
- <field name="security-token" domain="security-token"/>
- <field name="application-headers" domain="table"/>
- <field name="body" domain="content"/>
- </method>
- <method name="consume" index="20">
- <chassis name="server" implement="MUST"/>
- <response name="ok"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="queue" domain="queue-name"/>
- <field name="destination" domain="destination"/>
- <field name="no-local" domain="no-local"/>
- <field name="no-ack" domain="no-ack"/>
- <field name="exclusive" domain="bit"/>
- <field name="filter" domain="table"/>
- </method>
- <method name="cancel" index="30">
- <chassis name="server" implement="MUST"/>
- <response name="ok"/>
- <field name="destination" domain="destination"/>
- </method>
- <method name="get" index="40">
- <response name="ok"/>
- <response name="empty"/>
- <chassis name="server" implement="MUST"/>
- <field name="ticket" domain="access-ticket"/>
- <field name="queue" domain="queue-name"/>
- <field name="destination" domain="destination"/>
- <field name="no-ack" domain="no-ack"/>
- </method>
- <method name="recover" index="50">
- <chassis name="server" implement="MUST"/>
- <response name="ok"/>
- <field name="requeue" domain="bit"/>
- </method>
- <method name="open" index="60">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <response name="ok"/>
- <field name="reference" domain="reference"/>
- </method>
- <method name="close" index="70">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <response name="ok"/>
- <field name="reference" domain="reference"/>
- </method>
- <method name="append" index="80">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <response name="ok"/>
- <field name="reference" domain="reference"/>
- <field name="bytes" domain="longstr"/>
- </method>
- <method name="checkpoint" index="90">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <response name="ok"/>
- <field name="reference" domain="reference"/>
- <field name="identifier" domain="shortstr"/>
- </method>
- <method name="resume" index="100">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <response name="offset"/>
- <field name="reference" domain="reference"/>
- <field name="identifier" domain="shortstr"/>
- </method>
- <method name="qos" index="110">
- <chassis name="server" implement="MUST"/>
- <response name="ok"/>
- <field name="prefetch-size" domain="long"/>
- <field name="prefetch-count" domain="short"/>
- <field name="global" domain="bit"/>
- </method>
- <method name="ok" index="500">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="empty" index="510">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- </method>
- <method name="reject" index="520">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <field name="code" domain="reject-code"/>
- <field name="text" domain="reject-text"/>
- </method>
- <method name="offset" index="530">
- <chassis name="server" implement="MUST"/>
- <chassis name="client" implement="MUST"/>
- <field name="value" domain="offset"/>
- </method>
- </class>
-</amqp>
diff --git a/qpid/python/qpid/specs_config.py b/qpid/python/qpid/specs_config.py
deleted file mode 100644
index d991e8b084..0000000000
--- a/qpid/python/qpid/specs_config.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# 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 os
-
-AMQP_SPEC_DIR=os.path.join(os.path.dirname(os.path.abspath(__file__)), "specs")
-amqp_spec = os.path.join(AMQP_SPEC_DIR, "amqp-0-10-qpid-errata-stripped.xml")
-amqp_spec_0_8 = os.path.join(AMQP_SPEC_DIR, "amqp-0-8-qpid-stripped.xml")
-amqp_spec_0_9 = os.path.join(AMQP_SPEC_DIR, "amqp-0-9-qpid-stripped.xml")
-amqp_spec_0_9_1 = os.path.join(AMQP_SPEC_DIR, "amqp-0-9-1-stripped.xml")
diff --git a/qpid/python/qpid/testlib.py b/qpid/python/qpid/testlib.py
deleted file mode 100644
index 256aa7b5e6..0000000000
--- a/qpid/python/qpid/testlib.py
+++ /dev/null
@@ -1,241 +0,0 @@
-#
-# 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.
-#
-
-#
-# Support library for qpid python tests.
-#
-
-import string
-import random
-
-import unittest, traceback, socket
-import qpid.client, qmf.console
-import Queue
-from qpid.content import Content
-from qpid.message import Message
-from qpid.harness import Skipped
-from qpid.exceptions import VersionError
-
-import qpid.messaging
-from qpidtoollibs import BrokerAgent
-
-class TestBase(unittest.TestCase):
- """Base class for Qpid test cases.
-
- self.client is automatically connected with channel 1 open before
- the test methods are run.
-
- Deletes queues and exchanges after. Tests call
- self.queue_declare(channel, ...) and self.exchange_declare(chanel,
- ...) which are wrappers for the Channel functions that note
- resources to clean up later.
- """
-
- def configure(self, config):
- self.config = config
-
- def setUp(self):
- self.queues = []
- self.exchanges = []
- self.client = self.connect()
- self.channel = self.client.channel(1)
- self.version = (self.client.spec.major, self.client.spec.minor)
- if self.version == (8, 0) or self.version == (0, 9):
- self.channel.channel_open()
- else:
- self.channel.session_open()
-
- def tearDown(self):
- try:
- for ch, q in self.queues:
- ch.queue_delete(queue=q)
- for ch, ex in self.exchanges:
- ch.exchange_delete(exchange=ex)
- except:
- print "Error on tearDown:"
- print traceback.print_exc()
-
- self.client.close()
-
- def connect(self, host=None, port=None, user=None, password=None, tune_params=None, client_properties=None, channel_options=None):
- """Create a new connction, return the Client object"""
- host = host or self.config.broker.host
- port = port or self.config.broker.port or 5672
- user = user or self.config.broker.user or "guest"
- password = password or self.config.broker.password or "guest"
- client = qpid.client.Client(host, port)
- try:
- client.start(username = user, password=password, tune_params=tune_params, client_properties=client_properties, channel_options=channel_options)
- except qpid.client.Closed, e:
- if isinstance(e.args[0], VersionError):
- raise Skipped(e.args[0])
- else:
- raise e
- except socket.error, e:
- raise Skipped(e)
- return client
-
- def queue_declare(self, channel=None, *args, **keys):
- channel = channel or self.channel
- reply = channel.queue_declare(*args, **keys)
- self.queues.append((channel, keys["queue"]))
- return reply
-
- def exchange_declare(self, channel=None, ticket=0, exchange='',
- type='', passive=False, durable=False,
- auto_delete=False,
- arguments={}):
- channel = channel or self.channel
- reply = channel.exchange_declare(ticket=ticket, exchange=exchange, type=type, passive=passive,durable=durable, auto_delete=auto_delete, arguments=arguments)
- self.exchanges.append((channel,exchange))
- return reply
-
- def uniqueString(self):
- """Generate a unique string, unique for this TestBase instance"""
- if not "uniqueCounter" in dir(self): self.uniqueCounter = 1;
- return "Test Message " + str(self.uniqueCounter)
-
- def randomLongString(self, length=65535):
- body = ''.join(random.choice(string.ascii_uppercase) for _ in range(length))
- return body
-
- def consume(self, queueName, no_ack=True):
- """Consume from named queue returns the Queue object."""
-
- reply = self.channel.basic_consume(queue=queueName, no_ack=no_ack)
- return self.client.queue(reply.consumer_tag)
-
- def subscribe(self, channel=None, **keys):
- channel = channel or self.channel
- consumer_tag = keys["destination"]
- channel.message_subscribe(**keys)
- channel.message_flow(destination=consumer_tag, unit=0, value=0xFFFFFFFFL)
- channel.message_flow(destination=consumer_tag, unit=1, value=0xFFFFFFFFL)
-
- def assertEmpty(self, queue):
- """Assert that the queue is empty"""
- try:
- queue.get(timeout=1)
- self.fail("Queue is not empty.")
- except Queue.Empty: None # Ignore
-
- def assertPublishGet(self, queue, exchange="", routing_key="", properties=None):
- """
- Publish to exchange and assert queue.get() returns the same message.
- """
- body = self.uniqueString()
- self.channel.basic_publish(
- exchange=exchange,
- content=Content(body, properties=properties),
- routing_key=routing_key)
- msg = queue.get(timeout=1)
- self.assertEqual(body, msg.content.body)
- if (properties):
- self.assertEqual(properties, msg.content.properties)
-
- def assertPublishConsume(self, queue="", exchange="", routing_key="", properties=None):
- """
- Publish a message and consume it, assert it comes back intact.
- Return the Queue object used to consume.
- """
- self.assertPublishGet(self.consume(queue), exchange, routing_key, properties)
-
- def assertChannelException(self, expectedCode, message):
- if self.version == (8, 0) or self.version == (0, 9):
- if not isinstance(message, Message): self.fail("expected channel_close method, got %s" % (message))
- self.assertEqual("channel", message.method.klass.name)
- self.assertEqual("close", message.method.name)
- else:
- if not isinstance(message, Message): self.fail("expected session_closed method, got %s" % (message))
- self.assertEqual("session", message.method.klass.name)
- self.assertEqual("closed", message.method.name)
- self.assertEqual(expectedCode, message.reply_code)
-
-
- def assertConnectionException(self, expectedCode, message):
- if not isinstance(message, Message): self.fail("expected connection_close method, got %s" % (message))
- self.assertEqual("connection", message.method.klass.name)
- self.assertEqual("close", message.method.name)
- self.assertEqual(expectedCode, message.reply_code)
-
-#0-10 support
-from qpid.connection import Connection
-from qpid.util import connect, ssl, URL
-
-class TestBase010(unittest.TestCase):
- """
- Base class for Qpid test cases. using the final 0-10 spec
- """
-
- def configure(self, config):
- self.config = config
- self.broker = config.broker
- self.defines = self.config.defines
-
- def setUp(self):
- self.conn = self.connect()
- self.session = self.conn.session("test-session", timeout=10)
- self.qmf = None
- self.test_queue_name = self.id()
-
- def startQmf(self, handler=None):
- self.qmf = qmf.console.Session(handler)
- self.qmf_broker = self.qmf.addBroker(str(self.broker))
-
- def startBrokerAccess(self):
- """
- New-style management access to the broker. Can be used in lieu of startQmf.
- """
- if 'broker_conn' not in self.__dict__:
- self.broker_conn = qpid.messaging.Connection(str(self.broker))
- self.broker_conn.open()
- self.broker_access = BrokerAgent(self.broker_conn)
-
- def connect(self, host=None, port=None):
- url = self.broker
- if url.scheme == URL.AMQPS:
- default_port = 5671
- else:
- default_port = 5672
- try:
- sock = connect(host or url.host, port or url.port or default_port)
- except socket.error, e:
- raise Skipped(e)
- if url.scheme == URL.AMQPS:
- sock = ssl(sock)
- conn = Connection(sock, username=url.user or "guest",
- password=url.password or "guest")
- try:
- conn.start(timeout=10)
- except VersionError, e:
- raise Skipped(e)
- return conn
-
- def tearDown(self):
- if not self.session.error(): self.session.close(timeout=10)
- self.conn.close(timeout=10)
- if self.qmf:
- self.qmf.delBroker(self.qmf_broker)
-
- def subscribe(self, session=None, **keys):
- session = session or self.session
- consumer_tag = keys["destination"]
- session.message_subscribe(**keys)
- session.message_flow(destination=consumer_tag, unit=0, value=0xFFFFFFFFL)
- session.message_flow(destination=consumer_tag, unit=1, value=0xFFFFFFFFL)
diff --git a/qpid/python/qpid/tests/__init__.py b/qpid/python/qpid/tests/__init__.py
deleted file mode 100644
index 85ab013b5a..0000000000
--- a/qpid/python/qpid/tests/__init__.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#
-# 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.
-#
-
-class Test:
-
- def __init__(self, name):
- self.name = name
-
- def configure(self, config):
- self.config = config
-
-# API Tests
-import qpid.tests.framing
-import qpid.tests.mimetype
-import qpid.tests.messaging
-
-# Legacy Tests
-import qpid.tests.codec
-import qpid.tests.queue
-import qpid.tests.datatypes
-import qpid.tests.connection
-import qpid.tests.spec010
-import qpid.tests.codec010
-import qpid.tests.util
-import qpid.tests.saslmech.finder
-
-class TestTestsXXX(Test):
-
- def testFoo(self):
- print "this test has output"
-
- def testBar(self):
- print "this test "*8
- print "has"*10
- print "a"*75
- print "lot of"*10
- print "output"*10
-
- def testQux(self):
- import sys
- sys.stdout.write("this test has output with no newline")
-
- def testQuxFail(self):
- import sys
- sys.stdout.write("this test has output with no newline")
- fdsa
diff --git a/qpid/python/qpid/tests/codec.py b/qpid/python/qpid/tests/codec.py
deleted file mode 100644
index 8017f794fe..0000000000
--- a/qpid/python/qpid/tests/codec.py
+++ /dev/null
@@ -1,729 +0,0 @@
-#!/usr/bin/env 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 unittest
-from qpid.codec import Codec
-from qpid.spec08 import load
-from cStringIO import StringIO
-from qpid.reference import ReferenceId
-
-__doc__ = """
-
- This is a unit test script for qpid/codec.py
-
- It can be run standalone or as part of the existing test framework.
-
- To run standalone:
- -------------------
-
- Place in the qpid/python/tests/ directory and type...
-
- python codec.py
-
- A brief output will be printed on screen. The verbose output will be placed inn a file called
- codec_unit_test_output.txt. [TODO: make this filename configurable]
-
- To run as part of the existing test framework:
- -----------------------------------------------
-
- python run-tests tests.codec
-
- Change History:
- -----------------
- Jimmy John 05/19/2007 Initial draft
- Jimmy John 05/22/2007 Implemented comments by Rafael Schloming
-
-
-"""
-
-from qpid.specs_config import amqp_spec_0_8
-SPEC = load(amqp_spec_0_8)
-
-# --------------------------------------
-# --------------------------------------
-class BaseDataTypes(unittest.TestCase):
-
-
- """
- Base class containing common functions
- """
-
- # ---------------
- def setUp(self):
- """
- standard setUp for unitetest (refer unittest documentation for details)
- """
- self.codec = Codec(StringIO(), SPEC)
-
- # ------------------
- def tearDown(self):
- """
- standard tearDown for unitetest (refer unittest documentation for details)
- """
- self.codec.stream.flush()
- self.codec.stream.close()
-
- # ----------------------------------------
- def callFunc(self, functionName, *args):
- """
- helper function - given a function name and arguments, calls the function with the args and
- returns the contents of the stream
- """
- getattr(self.codec, functionName)(args[0])
- return self.codec.stream.getvalue()
-
- # ----------------------------------------
- def readFunc(self, functionName, *args):
- """
- helper function - creates a input stream and then calls the function with arguments as have been
- supplied
- """
- self.codec.stream = StringIO(args[0])
- return getattr(self.codec, functionName)()
-
-
-# ----------------------------------------
-# ----------------------------------------
-class IntegerTestCase(BaseDataTypes):
-
- """
- Handles octet, short, long, long long
-
- """
-
- # -------------------------
- def __init__(self, *args):
- """
- sets constants for use in tests
- """
-
- BaseDataTypes.__init__(self, *args)
- self.const_integer = 2
- self.const_integer_octet_encoded = '\x02'
- self.const_integer_short_encoded = '\x00\x02'
- self.const_integer_long_encoded = '\x00\x00\x00\x02'
- self.const_integer_long_long_encoded = '\x00\x00\x00\x00\x00\x00\x00\x02'
-
- # -------------------------- #
- # Unsigned Octect - 8 bits #
- # -------------------------- #
-
- # --------------------------
- def test_unsigned_octet(self):
- """
- ubyte format requires 0<=number<=255
- """
- self.failUnlessEqual(self.callFunc('encode_octet', self.const_integer), self.const_integer_octet_encoded, 'octect encoding FAILED...')
-
- # -------------------------------------------
- def test_octet_out_of_upper_range(self):
- """
- testing for input above acceptable range
- """
- self.failUnlessRaises(Exception, self.codec.encode_octet, 256)
-
- # -------------------------------------------
- def test_uoctet_out_of_lower_range(self):
- """
- testing for input below acceptable range
- """
- self.failUnlessRaises(Exception, self.codec.encode_octet, -1)
-
- # ---------------------------------
- def test_uoctet_with_fraction(self):
- """
- the fractional part should be ignored...
- """
- self.failUnlessEqual(self.callFunc('encode_octet', 2.5), self.const_integer_octet_encoded, 'octect encoding FAILED with fractions...')
-
- # ------------------------------------
- def test_unsigned_octet_decode(self):
- """
- octet decoding
- """
- self.failUnlessEqual(self.readFunc('decode_octet', self.const_integer_octet_encoded), self.const_integer, 'octect decoding FAILED...')
-
- # ----------------------------------- #
- # Unsigned Short Integers - 16 bits #
- # ----------------------------------- #
-
- # -----------------------
- def test_ushort_int(self):
- """
- testing unsigned short integer
- """
- self.failUnlessEqual(self.callFunc('encode_short', self.const_integer), self.const_integer_short_encoded, 'short encoding FAILED...')
-
- # -------------------------------------------
- def test_ushort_int_out_of_upper_range(self):
- """
- testing for input above acceptable range
- """
- self.failUnlessRaises(Exception, self.codec.encode_short, 65536)
-
- # -------------------------------------------
- def test_ushort_int_out_of_lower_range(self):
- """
- testing for input below acceptable range
- """
- self.failUnlessRaises(Exception, self.codec.encode_short, -1)
-
- # ---------------------------------
- def test_ushort_int_with_fraction(self):
- """
- the fractional part should be ignored...
- """
- self.failUnlessEqual(self.callFunc('encode_short', 2.5), self.const_integer_short_encoded, 'short encoding FAILED with fractions...')
-
- # ------------------------------------
- def test_ushort_int_decode(self):
- """
- unsigned short decoding
- """
- self.failUnlessEqual(self.readFunc('decode_short', self.const_integer_short_encoded), self.const_integer, 'unsigned short decoding FAILED...')
-
-
- # ---------------------------------- #
- # Unsigned Long Integers - 32 bits #
- # ---------------------------------- #
-
- # -----------------------
- def test_ulong_int(self):
- """
- testing unsigned long iteger
- """
- self.failUnlessEqual(self.callFunc('encode_long', self.const_integer), self.const_integer_long_encoded, 'long encoding FAILED...')
-
- # -------------------------------------------
- def test_ulong_int_out_of_upper_range(self):
- """
- testing for input above acceptable range
- """
- self.failUnlessRaises(Exception, self.codec.encode_long, 4294967296)
-
- # -------------------------------------------
- def test_ulong_int_out_of_lower_range(self):
- """
- testing for input below acceptable range
- """
- self.failUnlessRaises(Exception, self.codec.encode_long, -1)
-
- # ---------------------------------
- def test_ulong_int_with_fraction(self):
- """
- the fractional part should be ignored...
- """
- self.failUnlessEqual(self.callFunc('encode_long', 2.5), self.const_integer_long_encoded, 'long encoding FAILED with fractions...')
-
- # -------------------------------
- def test_ulong_int_decode(self):
- """
- unsigned long decoding
- """
- self.failUnlessEqual(self.readFunc('decode_long', self.const_integer_long_encoded), self.const_integer, 'unsigned long decoding FAILED...')
-
-
- # --------------------------------------- #
- # Unsigned Long Long Integers - 64 bits #
- # --------------------------------------- #
-
- # -----------------------
- def test_ulong_long_int(self):
- """
- testing unsinged long long integer
- """
- self.failUnlessEqual(self.callFunc('encode_longlong', self.const_integer), self.const_integer_long_long_encoded, 'long long encoding FAILED...')
-
- # -------------------------------------------
- def test_ulong_long_int_out_of_upper_range(self):
- """
- testing for input above acceptable range
- """
- self.failUnlessRaises(Exception, self.codec.encode_longlong, 18446744073709551616)
-
- # -------------------------------------------
- def test_ulong_long_int_out_of_lower_range(self):
- """
- testing for input below acceptable range
- """
- self.failUnlessRaises(Exception, self.codec.encode_longlong, -1)
-
- # ---------------------------------
- def test_ulong_long_int_with_fraction(self):
- """
- the fractional part should be ignored...
- """
- self.failUnlessEqual(self.callFunc('encode_longlong', 2.5), self.const_integer_long_long_encoded, 'long long encoding FAILED with fractions...')
-
- # ------------------------------------
- def test_ulong_long_int_decode(self):
- """
- unsigned long long decoding
- """
- self.failUnlessEqual(self.readFunc('decode_longlong', self.const_integer_long_long_encoded), self.const_integer, 'unsigned long long decoding FAILED...')
-
-# -----------------------------------
-# -----------------------------------
-class BitTestCase(BaseDataTypes):
-
- """
- Handles bits
- """
-
- # ----------------------------------------------
- def callFunc(self, functionName, *args):
- """
- helper function
- """
- for ele in args:
- getattr(self.codec, functionName)(ele)
-
- self.codec.flush()
- return self.codec.stream.getvalue()
-
- # -------------------
- def test_bit1(self):
- """
- sends in 11
- """
- self.failUnlessEqual(self.callFunc('encode_bit', 1, 1), '\x03', '11 bit encoding FAILED...')
-
- # -------------------
- def test_bit2(self):
- """
- sends in 10011
- """
- self.failUnlessEqual(self.callFunc('encode_bit', 1, 1, 0, 0, 1), '\x13', '10011 bit encoding FAILED...')
-
- # -------------------
- def test_bit3(self):
- """
- sends in 1110100111 [10 bits(right to left), should be compressed into two octets]
- """
- self.failUnlessEqual(self.callFunc('encode_bit', 1,1,1,0,0,1,0,1,1,1), '\xa7\x03', '1110100111(right to left) bit encoding FAILED...')
-
- # ------------------------------------
- def test_bit_decode_1(self):
- """
- decode bit 1
- """
- self.failUnlessEqual(self.readFunc('decode_bit', '\x01'), 1, 'decode bit 1 FAILED...')
-
- # ------------------------------------
- def test_bit_decode_0(self):
- """
- decode bit 0
- """
- self.failUnlessEqual(self.readFunc('decode_bit', '\x00'), 0, 'decode bit 0 FAILED...')
-
-# -----------------------------------
-# -----------------------------------
-class StringTestCase(BaseDataTypes):
-
- """
- Handles short strings, long strings
- """
-
- # ------------------------------------------------------------- #
- # Short Strings - 8 bit length followed by zero or more octets #
- # ------------------------------------------------------------- #
-
- # ---------------------------------------
- def test_short_string_zero_length(self):
- """
- 0 length short string
- """
- self.failUnlessEqual(self.callFunc('encode_shortstr', ''), '\x00', '0 length short string encoding FAILED...')
-
- # -------------------------------------------
- def test_short_string_positive_length(self):
- """
- positive length short string
- """
- self.failUnlessEqual(self.callFunc('encode_shortstr', 'hello world'), '\x0bhello world', 'positive length short string encoding FAILED...')
-
- # -------------------------------------------
- def test_short_string_out_of_upper_range(self):
- """
- string length > 255
- """
- self.failUnlessRaises(Exception, self.codec.encode_shortstr, 'x'*256)
-
- # ------------------------------------
- def test_short_string_decode(self):
- """
- short string decode
- """
- self.failUnlessEqual(self.readFunc('decode_shortstr', '\x0bhello world'), 'hello world', 'short string decode FAILED...')
-
-
- # ------------------------------------------------------------- #
- # Long Strings - 32 bit length followed by zero or more octets #
- # ------------------------------------------------------------- #
-
- # ---------------------------------------
- def test_long_string_zero_length(self):
- """
- 0 length long string
- """
- self.failUnlessEqual(self.callFunc('encode_longstr', ''), '\x00\x00\x00\x00', '0 length long string encoding FAILED...')
-
- # -------------------------------------------
- def test_long_string_positive_length(self):
- """
- positive length long string
- """
- self.failUnlessEqual(self.callFunc('encode_longstr', 'hello world'), '\x00\x00\x00\x0bhello world', 'positive length long string encoding FAILED...')
-
- # ------------------------------------
- def test_long_string_decode(self):
- """
- long string decode
- """
- self.failUnlessEqual(self.readFunc('decode_longstr', '\x00\x00\x00\x0bhello world'), 'hello world', 'long string decode FAILED...')
-
-
-# --------------------------------------
-# --------------------------------------
-class TimestampTestCase(BaseDataTypes):
-
- """
- No need of any test cases here as timestamps are implemented as long long which is tested above
- """
- pass
-
-# ---------------------------------------
-# ---------------------------------------
-class FieldTableTestCase(BaseDataTypes):
-
- """
- Handles Field Tables
-
- Only S/I type messages seem to be implemented currently
- """
-
- # -------------------------
- def __init__(self, *args):
- """
- sets constants for use in tests
- """
-
- BaseDataTypes.__init__(self, *args)
- self.const_field_table_dummy_dict = {'$key1':'value1','$key2':'value2'}
- self.const_field_table_dummy_dict_encoded = '\x00\x00\x00\x22\x05$key2S\x00\x00\x00\x06value2\x05$key1S\x00\x00\x00\x06value1'
-
- # -------------------------------------------
- def test_field_table_name_value_pair(self):
- """
- valid name value pair
- """
- self.failUnlessEqual(self.callFunc('encode_table', {'$key1':'value1'}), '\x00\x00\x00\x11\x05$key1S\x00\x00\x00\x06value1', 'valid name value pair encoding FAILED...')
-
- # ---------------------------------------------------
- def test_field_table_multiple_name_value_pair(self):
- """
- multiple name value pair
- """
- self.failUnlessEqual(self.callFunc('encode_table', self.const_field_table_dummy_dict), self.const_field_table_dummy_dict_encoded, 'multiple name value pair encoding FAILED...')
-
- # ------------------------------------
- def test_field_table_decode(self):
- """
- field table decode
- """
- self.failUnlessEqual(self.readFunc('decode_table', self.const_field_table_dummy_dict_encoded), self.const_field_table_dummy_dict, 'field table decode FAILED...')
-
-
-# ------------------------------------
-# ------------------------------------
-class ContentTestCase(BaseDataTypes):
-
- """
- Handles Content data types
- """
-
- # -----------------------------
- def test_content_inline(self):
- """
- inline content
- """
- self.failUnlessEqual(self.callFunc('encode_content', 'hello inline message'), '\x00\x00\x00\x00\x14hello inline message', 'inline content encoding FAILED...')
-
- # --------------------------------
- def test_content_reference(self):
- """
- reference content
- """
- self.failUnlessEqual(self.callFunc('encode_content', ReferenceId('dummyId')), '\x01\x00\x00\x00\x07dummyId', 'reference content encoding FAILED...')
-
- # ------------------------------------
- def test_content_inline_decode(self):
- """
- inline content decode
- """
- self.failUnlessEqual(self.readFunc('decode_content', '\x00\x00\x00\x00\x14hello inline message'), 'hello inline message', 'inline content decode FAILED...')
-
- # ------------------------------------
- def test_content_reference_decode(self):
- """
- reference content decode
- """
- self.failUnlessEqual(self.readFunc('decode_content', '\x01\x00\x00\x00\x07dummyId').id, 'dummyId', 'reference content decode FAILED...')
-
-# -----------------------------------
-# -----------------------------------
-class BooleanTestCase(BaseDataTypes):
-
- # -------------------
- def test_true_encode(self):
- self.failUnlessEqual(self.callFunc('encode_boolean', True), '\x01', 'True encoding FAILED...')
-
- # -------------------
- def test_true_decode(self):
- self.failUnlessEqual(self.readFunc('decode_boolean', '\x01'), True, 'True decoding FAILED...')
- self.failUnlessEqual(self.readFunc('decode_boolean', '\x02'), True, 'True decoding FAILED...')
- self.failUnlessEqual(self.readFunc('decode_boolean', '\xFF'), True, 'True decoding FAILED...')
-
- # -------------------
- def test_false_encode(self):
- self.failUnlessEqual(self.callFunc('encode_boolean', False), '\x00', 'False encoding FAILED...')
-
- # -------------------
- def test_false_decode(self):
- self.failUnlessEqual(self.readFunc('decode_boolean', '\x00'), False, 'False decoding FAILED...')
-
-# -----------------------------------
-# -----------------------------------
-class ResolveTestCase(BaseDataTypes):
-
- # -------------------
- # Test resolving the value 1, which should implicitly be a python int
- def test_resolve_int_1(self):
- value = 1
- expected = "signed_int"
- resolved = self.codec.resolve(value.__class__, value)
- self.failUnlessEqual(resolved, expected, "resolve FAILED...expected %s got %s" % (expected, resolved))
- # -------------------
- # Test resolving the value -1, which should implicitly be a python int
- def test_resolve_int_negative_1(self):
- value = -1
- expected = "signed_int"
- resolved = self.codec.resolve(value.__class__, value)
- self.failUnlessEqual(resolved, expected, "resolve FAILED...expected %s got %s" % (expected, resolved))
- # -------------------
- # Test resolving the min signed 32bit integer value, -2^31
- def test_resolve_int_min(self):
- value = -2147483648 #-2^31
- expected = "signed_int"
- resolved = self.codec.resolve(value.__class__, value)
- self.failUnlessEqual(resolved, expected, "resolve FAILED...expected %s got %s" % (expected, resolved))
- # -------------------
- # Test resolving the max signed 32bit integer value, 2^31 -1
- def test_resolve_int_max(self):
- value = 2147483647 #2^31 -1
- expected = "signed_int"
- resolved = self.codec.resolve(value.__class__, value)
- self.failUnlessEqual(resolved, expected, "resolve FAILED...expected %s got %s" % (expected, resolved))
- # -------------------
- # Test resolving above the max signed 32bit integer value of 2^31 -1
- # Should be a python long, but should be classed as a signed 64bit long on the wire either way
- def test_resolve_int_above_signed_32bit_max(self):
- value = 2147483648 #2^31, i.e 1 above the 32bit signed max
- expected = "signed_long"
- resolved = self.codec.resolve(value.__class__, value)
- self.failUnlessEqual(resolved, expected, "resolve FAILED...expected %s got %s" % (expected, resolved))
- # -------------------
- # Test resolving above the max signed 32bit integer value of 2^31 -1
- # As above except use an explicitly cast python long
- def test_resolve_long_above_signed_32bit_max(self):
- value = 2147483648L #2^31, i.e 1 above the 32bit signed max
- expected = "signed_long"
- resolved = self.codec.resolve(value.__class__, value)
- self.failUnlessEqual(resolved, expected, "resolve FAILED...expected %s got %s" % (expected, resolved))
- # -------------------
- # Test resolving an explicitly cast python long of value 1, i.e less than the max signed 32bit integer value
- # Should be encoded as a 32bit signed int on the wire
- def test_resolve_long_1(self):
- value = 1L
- expected = "signed_int"
- resolved = self.codec.resolve(value.__class__, value)
- self.failUnlessEqual(resolved, expected, "resolve FAILED...expected %s got %s" % (expected, resolved))
- # -------------------
- # Test resolving the max signed 64bit integer value of 2^63 -1
- # Should be a python long, but should be classed as a signed 64bit long on the wire either way
- def test_resolve_64bit_signed_max(self):
- value = 9223372036854775807 #2^63 -1
- expected = "signed_long"
- resolved = self.codec.resolve(value.__class__, value)
- self.failUnlessEqual(resolved, expected, "resolve FAILED...expected %s got %s" % (expected, resolved))
- # -------------------
- # Test resolving the min signed 64bit integer value of -2^63
- # Should be a python long, but should be classed as a signed 64bit long on the wire either way
- def test_resolve_64bit_signed_min(self):
- value = -9223372036854775808 # -2^63
- expected = "signed_long"
- resolved = self.codec.resolve(value.__class__, value)
- self.failUnlessEqual(resolved, expected, "resolve FAILED...expected %s got %s" % (expected, resolved))
- # -------------------
- # Test resolving a value of 2^63, i.e more than the max a signed 64bit integer value can hold.
- # Should throw an exception indicating the value can't be encoded.
- def test_resolve_above_64bit_signed_max(self):
- value = 9223372036854775808L #2^63
- self.failUnlessRaises(Exception, self.codec.resolve, value.__class__, value)
- # -------------------
- # Test resolving a value of -2^63 -1, i.e less than the min a signed 64bit integer value can hold.
- # Should throw an exception indicating the value can't be encoded.
- def test_resolve_below_64bit_signed_min(self):
- value = 9223372036854775808L # -2^63 -1
- self.failUnlessRaises(Exception, self.codec.resolve, value.__class__, value)
- # -------------------
- # Test resolving a float. Should indicate use of double as python uses 64bit floats
- def test_resolve_float(self):
- value = 1.1
- expected = "double"
- resolved = self.codec.resolve(value.__class__, value)
- self.failUnlessEqual(resolved, expected, "resolve FAILED...expected %s got %s" % (expected, resolved))
- # -------------------
- # Test resolving a string. Should indicate use of long string encoding
- def test_resolve_string(self):
- value = "myString"
- expected = "longstr"
- resolved = self.codec.resolve(value.__class__, value)
- self.failUnlessEqual(resolved, expected, "resolve FAILED...expected %s got %s" % (expected, resolved))
- # -------------------
- # Test resolving None. Should indicate use of a void encoding.
- def test_resolve_None(self):
- value = None
- expected = "void"
- resolved = self.codec.resolve(value.__class__, value)
- self.failUnlessEqual(resolved, expected, "resolve FAILED...expected %s got %s" % (expected, resolved))
-
-# ------------------------ #
-# Pre - existing test code #
-# ------------------------ #
-
-# ---------------------
-def test(type, value):
- """
- old test function cut/copy/paste from qpid/codec.py
- """
- if isinstance(value, (list, tuple)):
- values = value
- else:
- values = [value]
- stream = StringIO()
- codec = Codec(stream, SPEC)
- for v in values:
- codec.encode(type, v)
- codec.flush()
- enc = stream.getvalue()
- stream.reset()
- dup = []
- for i in xrange(len(values)):
- dup.append(codec.decode(type))
- if values != dup:
- raise AssertionError("%r --> %r --> %r" % (values, enc, dup))
-
-# -----------------------
-def dotest(type, value):
- """
- old test function cut/copy/paste from qpid/codec.py
- """
- args = (type, value)
- test(*args)
-
-# -------------
-def oldtests():
- """
- old test function cut/copy/paste from qpid/codec.py
- """
- for value in ("1", "0", "110", "011", "11001", "10101", "10011"):
- for i in range(10):
- dotest("bit", map(lambda x: x == "1", value*i))
-
- for value in ({}, {"asdf": "fdsa", "fdsa": 1, "three": 3}, {"one": 1}):
- dotest("table", value)
-
- for type in ("octet", "short", "long", "longlong"):
- for value in range(0, 256):
- dotest(type, value)
-
- for type in ("shortstr", "longstr"):
- for value in ("", "a", "asdf"):
- dotest(type, value)
-
-# -----------------------------------------
-class oldTests(unittest.TestCase):
-
- """
- class to handle pre-existing test cases
- """
-
- # ---------------------------
- def test_oldtestcases(self):
- """
- call the old tests
- """
- return oldtests()
-
-# ---------------------------
-# ---------------------------
-if __name__ == '__main__':
-
- codec_test_suite = unittest.TestSuite()
-
- #adding all the test suites...
- codec_test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(IntegerTestCase))
- codec_test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(BitTestCase))
- codec_test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(StringTestCase))
- codec_test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TimestampTestCase))
- codec_test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(FieldTableTestCase))
- codec_test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(ContentTestCase))
-
- #loading pre-existing test case from qpid/codec.py
- codec_test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(oldTests))
-
- run_output_stream = StringIO()
- test_runner = unittest.TextTestRunner(run_output_stream, '', '')
- test_result = test_runner.run(codec_test_suite)
-
- print '\n%d test run...' % (test_result.testsRun)
-
- if test_result.wasSuccessful():
- print '\nAll tests successful\n'
-
- if test_result.failures:
- print '\n----------'
- print '%d FAILURES:' % (len(test_result.failures))
- print '----------\n'
- for failure in test_result.failures:
- print str(failure[0]) + ' ... FAIL'
-
- if test_result.errors:
- print '\n---------'
- print '%d ERRORS:' % (len(test_result.errors))
- print '---------\n'
-
- for error in test_result.errors:
- print str(error[0]) + ' ... ERROR'
-
- f = open('codec_unit_test_output.txt', 'w')
- f.write(str(run_output_stream.getvalue()))
- f.close()
diff --git a/qpid/python/qpid/tests/codec010.py b/qpid/python/qpid/tests/codec010.py
deleted file mode 100644
index 787ebc146f..0000000000
--- a/qpid/python/qpid/tests/codec010.py
+++ /dev/null
@@ -1,133 +0,0 @@
-#
-# 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 time
-
-from unittest import TestCase
-from qpid.codec010 import StringCodec
-from qpid.datatypes import timestamp, uuid4
-from qpid.ops import PRIMITIVE
-
-class CodecTest(TestCase):
-
- def check(self, type, value, compare=True):
- t = PRIMITIVE[type]
- sc = StringCodec()
- sc.write_primitive(t, value)
- decoded = sc.read_primitive(t)
- if compare:
- assert decoded == value, "%s, %s" % (decoded, value)
- return decoded
-
- def testMapString(self):
- self.check("map", {"string": "this is a test"})
-
- def testMapUnicode(self):
- self.check("map", {"unicode": u"this is a unicode test"})
-
- def testMapBinary(self):
- self.check("map", {"binary": "\x7f\xb4R^\xe5\xf0:\x89\x96E1\xf6\xfe\xb9\x1b\xf5"})
-
- def testMapBuffer(self):
- s = "\x7f\xb4R^\xe5\xf0:\x89\x96E1\xf6\xfe\xb9\x1b\xf5"
- dec = self.check("map", {"buffer": buffer(s)}, False)
- assert dec["buffer"] == s
-
- def testMapInt(self):
- self.check("map", {"int": 3})
-
- def testMapLong(self):
- self.check("map", {"long": 2**32})
- self.check("map", {"long": 1 << 34})
- self.check("map", {"long": -(1 << 34)})
-
- def testMapTimestamp(self):
- decoded = self.check("map", {"timestamp": timestamp(0)})
- assert isinstance(decoded["timestamp"], timestamp)
-
- def testMapDatetime(self):
- decoded = self.check("map", {"datetime": timestamp(0).datetime()}, compare=False)
- assert isinstance(decoded["datetime"], timestamp)
- assert decoded["datetime"] == 0.0
-
- def testMapNone(self):
- self.check("map", {"none": None})
-
- def testMapNested(self):
- self.check("map", {"map": {"string": "nested test"}})
-
- def testMapList(self):
- self.check("map", {"list": [1, "two", 3.0, -4]})
-
- def testMapUUID(self):
- self.check("map", {"uuid": uuid4()})
-
- def testMapAll(self):
- decoded = self.check("map", {"string": "this is a test",
- "unicode": u"this is a unicode test",
- "binary": "\x7f\xb4R^\xe5\xf0:\x89\x96E1\xf6\xfe\xb9\x1b\xf5",
- "int": 3,
- "long": 2**32,
- "timestamp": timestamp(0),
- "none": None,
- "map": {"string": "nested map"},
- "list": [1, "two", 3.0, -4],
- "uuid": uuid4()})
- assert isinstance(decoded["timestamp"], timestamp)
-
- def testMapEmpty(self):
- self.check("map", {})
-
- def testMapNone(self):
- self.check("map", None)
-
- def testList(self):
- self.check("list", [1, "two", 3.0, -4])
-
- def testListEmpty(self):
- self.check("list", [])
-
- def testListNone(self):
- self.check("list", None)
-
- def testArrayInt(self):
- self.check("array", [1, 2, 3, 4])
-
- def testArrayString(self):
- self.check("array", ["one", "two", "three", "four"])
-
- def testArrayEmpty(self):
- self.check("array", [])
-
- def testArrayNone(self):
- self.check("array", None)
-
- def testInt16(self):
- self.check("int16", 3)
- self.check("int16", -3)
-
- def testInt64(self):
- self.check("int64", 3)
- self.check("int64", -3)
- self.check("int64", 1<<34)
- self.check("int64", -(1<<34))
-
- def testDatetime(self):
- self.check("datetime", timestamp(0))
- self.check("datetime", timestamp(long(time.time())))
diff --git a/qpid/python/qpid/tests/connection.py b/qpid/python/qpid/tests/connection.py
deleted file mode 100644
index 6847285f69..0000000000
--- a/qpid/python/qpid/tests/connection.py
+++ /dev/null
@@ -1,227 +0,0 @@
-#
-# 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 time
-from threading import *
-from unittest import TestCase
-from qpid.util import connect, listen
-from qpid.connection import *
-from qpid.datatypes import Message
-from qpid.delegates import Server
-from qpid.queue import Queue
-from qpid.session import Delegate
-from qpid.ops import QueueQueryResult
-
-PORT = 1234
-
-class TestServer:
-
- def __init__(self, queue):
- self.queue = queue
-
- def connection(self, connection):
- return Server(connection, delegate=self.session)
-
- def session(self, session):
- session.auto_sync = False
- return TestSession(session, self.queue)
-
-class TestSession(Delegate):
-
- def __init__(self, session, queue):
- self.session = session
- self.queue = queue
-
- def execution_sync(self, es):
- pass
-
- def queue_query(self, qq):
- return QueueQueryResult(qq.queue)
-
- def message_transfer(self, cmd):
- if cmd.destination == "echo":
- m = Message(cmd.payload)
- m.headers = cmd.headers
- self.session.message_transfer(cmd.destination, cmd.accept_mode,
- cmd.acquire_mode, m)
- elif cmd.destination == "abort":
- self.session.channel.connection.sock.close()
- elif cmd.destination == "heartbeat":
- self.session.channel.connection_heartbeat()
- else:
- self.queue.put(cmd)
-
-class ConnectionTest(TestCase):
-
- def setUp(self):
- self.queue = Queue()
- self.running = True
- started = Event()
-
- def run():
- ts = TestServer(self.queue)
- for s in listen("0.0.0.0", PORT, lambda: self.running, lambda: started.set()):
- conn = Connection(s, delegate=ts.connection)
- try:
- conn.start(5)
- except Closed:
- pass
-
- self.server = Thread(target=run)
- self.server.setDaemon(True)
- self.server.start()
-
- started.wait(3)
- assert started.isSet()
-
- def tearDown(self):
- self.running = False
- connect("127.0.0.1", PORT).close()
- self.server.join(3)
-
- def connect(self, **kwargs):
- return Connection(connect("127.0.0.1", PORT), **kwargs)
-
- def test(self):
- c = self.connect()
- c.start(10)
-
- ssn1 = c.session("test1", timeout=10)
- ssn2 = c.session("test2", timeout=10)
-
- assert ssn1 == c.sessions["test1"]
- assert ssn2 == c.sessions["test2"]
- assert ssn1.channel != None
- assert ssn2.channel != None
- assert ssn1 in c.attached.values()
- assert ssn2 in c.attached.values()
-
- ssn1.close(5)
-
- assert ssn1.channel == None
- assert ssn1 not in c.attached.values()
- assert ssn2 in c.sessions.values()
-
- ssn2.close(5)
-
- assert ssn2.channel == None
- assert ssn2 not in c.attached.values()
- assert ssn2 not in c.sessions.values()
-
- ssn = c.session("session", timeout=10)
-
- assert ssn.channel != None
- assert ssn in c.sessions.values()
-
- destinations = ("one", "two", "three")
-
- for d in destinations:
- ssn.message_transfer(d)
-
- for d in destinations:
- cmd = self.queue.get(10)
- assert cmd.destination == d
- assert cmd.headers == None
- assert cmd.payload == None
-
- msg = Message("this is a test")
- ssn.message_transfer("four", message=msg)
- cmd = self.queue.get(10)
- assert cmd.destination == "four"
- assert cmd.headers == None
- assert cmd.payload == msg.body
-
- qq = ssn.queue_query("asdf")
- assert qq.queue == "asdf"
- c.close(5)
-
- def testCloseGet(self):
- c = self.connect()
- c.start(10)
- ssn = c.session("test", timeout=10)
- echos = ssn.incoming("echo")
-
- for i in range(10):
- ssn.message_transfer("echo", message=Message("test%d" % i))
-
- ssn.auto_sync=False
- ssn.message_transfer("abort")
-
- for i in range(10):
- m = echos.get(timeout=10)
- assert m.body == "test%d" % i
-
- try:
- m = echos.get(timeout=10)
- assert False
- except Closed, e:
- pass
-
- def testCloseListen(self):
- c = self.connect()
- c.start(10)
- ssn = c.session("test", timeout=10)
- echos = ssn.incoming("echo")
-
- messages = []
- exceptions = []
- condition = Condition()
- def listener(m): messages.append(m)
- def exc_listener(e):
- condition.acquire()
- exceptions.append(e)
- condition.notify()
- condition.release()
-
- echos.listen(listener, exc_listener)
-
- for i in range(10):
- ssn.message_transfer("echo", message=Message("test%d" % i))
-
- ssn.auto_sync=False
- ssn.message_transfer("abort")
-
- condition.acquire()
- start = time.time()
- elapsed = 0
- while not exceptions and elapsed < 10:
- condition.wait(10 - elapsed)
- elapsed = time.time() - start
- condition.release()
-
- for i in range(10):
- m = messages.pop(0)
- assert m.body == "test%d" % i
-
- assert len(exceptions) == 1
-
- def testSync(self):
- c = self.connect()
- c.start(10)
- s = c.session("test")
- s.auto_sync = False
- s.message_transfer("echo", message=Message("test"))
- s.sync(10)
-
- def testHeartbeat(self):
- c = self.connect(heartbeat=10)
- c.start(10)
- s = c.session("test")
- s.channel.connection_heartbeat()
- s.message_transfer("heartbeat")
diff --git a/qpid/python/qpid/tests/datatypes.py b/qpid/python/qpid/tests/datatypes.py
deleted file mode 100644
index 00e649d6cf..0000000000
--- a/qpid/python/qpid/tests/datatypes.py
+++ /dev/null
@@ -1,296 +0,0 @@
-#
-# 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.
-#
-
-from unittest import TestCase
-from qpid.datatypes import *
-from qpid.ops import DeliveryProperties, FragmentProperties, MessageProperties
-
-class SerialTest(TestCase):
-
- def test(self):
- for s in (serial(0), serial(0x8FFFFFFFL), serial(0xFFFFFFFFL)):
- assert s + 1 > s
- assert s - 1 < s
- assert s < s + 1
- assert s > s - 1
-
- assert serial(0xFFFFFFFFL) + 1 == serial(0)
-
- assert min(serial(0xFFFFFFFFL), serial(0x0)) == serial(0xFFFFFFFFL)
- assert max(serial(0xFFFFFFFFL), serial(0x0)) == serial(0x0)
-
- def testIncr(self):
- s = serial(0)
- s += 1
- assert s == serial(1)
-
- def testIn(self):
- l = [serial(1), serial(2), serial(3), serial(4)]
- assert serial(1) in l
- assert serial(0xFFFFFFFFL + 2) in l
- assert 4 in l
-
- def testNone(self):
- assert serial(0) != None
-
- def testHash(self):
- d = {}
- d[serial(0)] = "zero"
- assert d[0] == "zero"
-
- def testAdd(self):
- assert serial(2) + 2 == serial(4)
- assert serial(2) + 2 == 4
-
- def testSub(self):
- delta = serial(4) - serial(2)
- assert isinstance(delta, int) or isinstance(delta, long)
- assert delta == 2
-
- delta = serial(4) - 2
- assert isinstance(delta, Serial)
- assert delta == serial(2)
-
-class RangedSetTest(TestCase):
-
- def check(self, ranges):
- posts = []
- for range in ranges:
- posts.append(range.lower)
- posts.append(range.upper)
-
- sorted = posts[:]
- sorted.sort()
-
- assert posts == sorted
-
- idx = 1
- while idx + 1 < len(posts):
- assert posts[idx] + 1 != posts[idx+1]
- idx += 2
-
- def test(self):
- rs = RangedSet()
-
- self.check(rs.ranges)
-
- rs.add(1)
-
- assert 1 in rs
- assert 2 not in rs
- assert 0 not in rs
- self.check(rs.ranges)
-
- rs.add(2)
-
- assert 0 not in rs
- assert 1 in rs
- assert 2 in rs
- assert 3 not in rs
- self.check(rs.ranges)
-
- rs.add(0)
-
- assert -1 not in rs
- assert 0 in rs
- assert 1 in rs
- assert 2 in rs
- assert 3 not in rs
- self.check(rs.ranges)
-
- rs.add(37)
-
- assert -1 not in rs
- assert 0 in rs
- assert 1 in rs
- assert 2 in rs
- assert 3 not in rs
- assert 36 not in rs
- assert 37 in rs
- assert 38 not in rs
- self.check(rs.ranges)
-
- rs.add(-1)
- self.check(rs.ranges)
-
- rs.add(-3)
- self.check(rs.ranges)
-
- rs.add(1, 20)
- assert 21 not in rs
- assert 20 in rs
- self.check(rs.ranges)
-
- def testAddSelf(self):
- a = RangedSet()
- a.add(0, 8)
- self.check(a.ranges)
- a.add(0, 8)
- self.check(a.ranges)
- assert len(a.ranges) == 1
- range = a.ranges[0]
- assert range.lower == 0
- assert range.upper == 8
-
- def testEmpty(self):
- s = RangedSet()
- assert s.empty()
- s.add(0, -1)
- assert s.empty()
- s.add(0, 0)
- assert not s.empty()
-
- def testMinMax(self):
- s = RangedSet()
- assert s.max() is None
- assert s.min() is None
- s.add(0, 10)
- assert s.max() == 10
- assert s.min() == 0
- s.add(0, 5)
- assert s.max() == 10
- assert s.min() == 0
- s.add(0, 11)
- assert s.max() == 11
- assert s.min() == 0
- s.add(15, 20)
- assert s.max() == 20
- assert s.min() == 0
- s.add(-10, -5)
- assert s.max() == 20
- assert s.min() == -10
-
-class RangeTest(TestCase):
-
- def testIntersect1(self):
- a = Range(0, 10)
- b = Range(9, 20)
- i1 = a.intersect(b)
- i2 = b.intersect(a)
- assert i1.upper == 10
- assert i2.upper == 10
- assert i1.lower == 9
- assert i2.lower == 9
-
- def testIntersect2(self):
- a = Range(0, 10)
- b = Range(11, 20)
- assert a.intersect(b) == None
- assert b.intersect(a) == None
-
- def testIntersect3(self):
- a = Range(0, 10)
- b = Range(3, 5)
- i1 = a.intersect(b)
- i2 = b.intersect(a)
- assert i1.upper == 5
- assert i2.upper == 5
- assert i1.lower == 3
- assert i2.lower == 3
-
-class UUIDTest(TestCase):
-
- def test(self):
- # this test is kind of lame, but it does excercise the basic
- # functionality of the class
- u = uuid4()
- for i in xrange(1024):
- assert u != uuid4()
-
-class MessageTest(TestCase):
-
- def setUp(self):
- self.mp = MessageProperties()
- self.dp = DeliveryProperties()
- self.fp = FragmentProperties()
-
- def testHas(self):
- m = Message(self.mp, self.dp, self.fp, "body")
- assert m.has("message_properties")
- assert m.has("delivery_properties")
- assert m.has("fragment_properties")
-
- def testGet(self):
- m = Message(self.mp, self.dp, self.fp, "body")
- assert m.get("message_properties") == self.mp
- assert m.get("delivery_properties") == self.dp
- assert m.get("fragment_properties") == self.fp
-
- def testSet(self):
- m = Message(self.mp, self.dp, "body")
- assert m.get("fragment_properties") is None
- m.set(self.fp)
- assert m.get("fragment_properties") == self.fp
-
- def testSetOnEmpty(self):
- m = Message("body")
- assert m.get("delivery_properties") is None
- m.set(self.dp)
- assert m.get("delivery_properties") == self.dp
-
- def testSetReplace(self):
- m = Message(self.mp, self.dp, self.fp, "body")
- dp = DeliveryProperties()
- assert m.get("delivery_properties") == self.dp
- assert m.get("delivery_properties") != dp
- m.set(dp)
- assert m.get("delivery_properties") != self.dp
- assert m.get("delivery_properties") == dp
-
- def testClear(self):
- m = Message(self.mp, self.dp, self.fp, "body")
- assert m.get("message_properties") == self.mp
- assert m.get("delivery_properties") == self.dp
- assert m.get("fragment_properties") == self.fp
- m.clear("fragment_properties")
- assert m.get("fragment_properties") is None
- assert m.get("message_properties") == self.mp
- assert m.get("delivery_properties") == self.dp
-
-class TimestampTest(TestCase):
-
- def check(self, expected, *values):
- for v in values:
- assert isinstance(v, timestamp)
- assert v == expected
- assert v == timestamp(expected)
-
- def testAdd(self):
- self.check(4.0,
- timestamp(2.0) + 2.0,
- 2.0 + timestamp(2.0))
-
- def testSub(self):
- self.check(2.0,
- timestamp(4.0) - 2.0,
- 4.0 - timestamp(2.0))
-
- def testNeg(self):
- self.check(-4.0, -timestamp(4.0))
-
- def testPos(self):
- self.check(+4.0, +timestamp(4.0))
-
- def testAbs(self):
- self.check(4.0, abs(timestamp(-4.0)))
-
- def testConversion(self):
- dt = timestamp(0).datetime()
- t = timestamp(dt)
- assert t == 0
diff --git a/qpid/python/qpid/tests/framing.py b/qpid/python/qpid/tests/framing.py
deleted file mode 100644
index 0b33df8b9a..0000000000
--- a/qpid/python/qpid/tests/framing.py
+++ /dev/null
@@ -1,289 +0,0 @@
-#
-# 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.
-#
-
-# setup, usage, teardown, errors(sync), errors(async), stress, soak,
-# boundary-conditions, config
-
-from qpid.tests import Test
-from qpid.framing import *
-
-class Base(Test):
-
- def cmp_frames(self, frm1, frm2):
- assert frm1.flags == frm2.flags, "expected: %r, got %r" % (frm1, frm2)
- assert frm1.type == frm2.type, "expected: %r, got %r" % (frm1, frm2)
- assert frm1.track == frm2.track, "expected: %r, got %r" % (frm1, frm2)
- assert frm1.channel == frm2.channel, "expected: %r, got %r" % (frm1, frm2)
- assert frm1.payload == frm2.payload, "expected: %r, got %r" % (frm1, frm2)
-
- def cmp_segments(self, seg1, seg2):
- assert seg1.first == seg2.first, "expected: %r, got %r" % (seg1, seg2)
- assert seg1.last == seg2.last, "expected: %r, got %r" % (seg1, seg2)
- assert seg1.type == seg2.type, "expected: %r, got %r" % (seg1, seg2)
- assert seg1.track == seg2.track, "expected: %r, got %r" % (seg1, seg2)
- assert seg1.channel == seg2.channel, "expected: %r, got %r" % (seg1, seg2)
- assert seg1.payload == seg2.payload, "expected: %r, got %r" % (seg1, seg2)
-
- def cmp_list(self, l1, l2):
- if l1 is None:
- assert l2 is None
- return
-
- assert len(l1) == len(l2)
- for v1, v2 in zip(l1, l2):
- if isinstance(v1, Compound):
- self.cmp_ops(v1, v2)
- else:
- assert v1 == v2
-
- def cmp_ops(self, op1, op2):
- if op1 is None:
- assert op2 is None
- return
-
- assert op1.__class__ == op2.__class__
- cls = op1.__class__
- assert op1.NAME == op2.NAME
- assert op1.CODE == op2.CODE
- assert op1.FIELDS == op2.FIELDS
- for f in cls.FIELDS:
- v1 = getattr(op1, f.name)
- v2 = getattr(op2, f.name)
- if COMPOUND.has_key(f.type) or f.type == "struct32":
- self.cmp_ops(v1, v2)
- elif f.type in ("list", "array"):
- self.cmp_list(v1, v2)
- else:
- assert v1 == v2, "expected: %r, got %r" % (v1, v2)
-
- if issubclass(cls, Command) or issubclass(cls, Control):
- assert op1.channel == op2.channel
-
- if issubclass(cls, Command):
- assert op1.sync == op2.sync, "expected: %r, got %r" % (op1.sync, op2.sync)
- assert (op1.headers is None and op2.headers is None) or \
- (op1.headers is not None and op2.headers is not None)
- if op1.headers is not None:
- assert len(op1.headers) == len(op2.headers)
- for h1, h2 in zip(op1.headers, op2.headers):
- self.cmp_ops(h1, h2)
-
-class FrameTest(Base):
-
- def enc_dec(self, frames, encoded=None):
- enc = FrameEncoder()
- dec = FrameDecoder()
-
- enc.write(*frames)
- bytes = enc.read()
- if encoded is not None:
- assert bytes == encoded, "expected %r, got %r" % (encoded, bytes)
- dec.write(bytes)
- dframes = dec.read()
-
- assert len(frames) == len(dframes)
- for f, df, in zip(frames, dframes):
- self.cmp_frames(f, df)
-
- def testEmpty(self):
- self.enc_dec([Frame(0, 0, 0, 0, "")],
- "\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00")
-
- def testSingle(self):
- self.enc_dec([Frame(0, 0, 0, 1, "payload")],
- "\x00\x00\x00\x13\x00\x00\x00\x01\x00\x00\x00\x00payload")
-
- def testMaxChannel(self):
- self.enc_dec([Frame(0, 0, 0, 65535, "max-channel")],
- "\x00\x00\x00\x17\x00\x00\xff\xff\x00\x00\x00\x00max-channel")
-
- def testMaxType(self):
- self.enc_dec([Frame(0, 255, 0, 0, "max-type")],
- "\x00\xff\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00max-type")
-
- def testMaxTrack(self):
- self.enc_dec([Frame(0, 0, 15, 0, "max-track")],
- "\x00\x00\x00\x15\x00\x0f\x00\x00\x00\x00\x00\x00max-track")
-
- def testSequence(self):
- self.enc_dec([Frame(0, 0, 0, 0, "zero"),
- Frame(0, 0, 0, 1, "one"),
- Frame(0, 0, 1, 0, "two"),
- Frame(0, 0, 1, 1, "three"),
- Frame(0, 1, 0, 0, "four"),
- Frame(0, 1, 0, 1, "five"),
- Frame(0, 1, 1, 0, "six"),
- Frame(0, 1, 1, 1, "seven"),
- Frame(1, 0, 0, 0, "eight"),
- Frame(1, 0, 0, 1, "nine"),
- Frame(1, 0, 1, 0, "ten"),
- Frame(1, 0, 1, 1, "eleven"),
- Frame(1, 1, 0, 0, "twelve"),
- Frame(1, 1, 0, 1, "thirteen"),
- Frame(1, 1, 1, 0, "fourteen"),
- Frame(1, 1, 1, 1, "fifteen")])
-
-class SegmentTest(Base):
-
- def enc_dec(self, segments, frames=None, interleave=None, max_payload=Frame.MAX_PAYLOAD):
- enc = SegmentEncoder(max_payload)
- dec = SegmentDecoder()
-
- enc.write(*segments)
- frms = enc.read()
- if frames is not None:
- assert len(frames) == len(frms), "expected %s, got %s" % (frames, frms)
- for f1, f2 in zip(frames, frms):
- self.cmp_frames(f1, f2)
- if interleave is not None:
- ilvd = []
- for f in frms:
- ilvd.append(f)
- if interleave:
- ilvd.append(interleave.pop(0))
- ilvd.extend(interleave)
- dec.write(*ilvd)
- else:
- dec.write(*frms)
- segs = dec.read()
- assert len(segments) == len(segs)
- for s1, s2 in zip(segments, segs):
- self.cmp_segments(s1, s2)
-
- def testEmpty(self):
- self.enc_dec([Segment(True, True, 0, 0, 0, "")],
- [Frame(FIRST_FRM | LAST_FRM | FIRST_SEG | LAST_SEG, 0, 0, 0,
- "")])
-
- def testSingle(self):
- self.enc_dec([Segment(True, True, 0, 0, 0, "payload")],
- [Frame(FIRST_FRM | LAST_FRM | FIRST_SEG | LAST_SEG, 0, 0, 0,
- "payload")])
-
- def testMaxChannel(self):
- self.enc_dec([Segment(False, False, 0, 0, 65535, "max-channel")],
- [Frame(FIRST_FRM | LAST_FRM, 0, 0, 65535, "max-channel")])
-
- def testMaxType(self):
- self.enc_dec([Segment(False, False, 255, 0, 0, "max-type")],
- [Frame(FIRST_FRM | LAST_FRM, 255, 0, 0, "max-type")])
-
- def testMaxTrack(self):
- self.enc_dec([Segment(False, False, 0, 15, 0, "max-track")],
- [Frame(FIRST_FRM | LAST_FRM, 0, 15, 0, "max-track")])
-
- def testSequence(self):
- self.enc_dec([Segment(True, False, 0, 0, 0, "one"),
- Segment(False, False, 0, 0, 0, "two"),
- Segment(False, True, 0, 0, 0, "three")],
- [Frame(FIRST_FRM | LAST_FRM | FIRST_SEG, 0, 0, 0, "one"),
- Frame(FIRST_FRM | LAST_FRM, 0, 0, 0, "two"),
- Frame(FIRST_FRM | LAST_FRM | LAST_SEG, 0, 0, 0, "three")])
-
- def testInterleaveChannel(self):
- frames = [Frame(0, 0, 0, 0, chr(ord("a") + i)) for i in range(7)]
- frames[0].flags |= FIRST_FRM
- frames[-1].flags |= LAST_FRM
-
- ilvd = [Frame(0, 0, 0, 1, chr(ord("a") + i)) for i in range(7)]
-
- self.enc_dec([Segment(False, False, 0, 0, 0, "abcdefg")], frames, ilvd, max_payload=1)
-
- def testInterleaveTrack(self):
- frames = [Frame(0, 0, 0, 0, "%c%c" % (ord("a") + i, ord("a") + i + 1))
- for i in range(0, 8, 2)]
- frames[0].flags |= FIRST_FRM
- frames[-1].flags |= LAST_FRM
-
- ilvd = [Frame(0, 0, 1, 0, "%c%c" % (ord("a") + i, ord("a") + i + 1))
- for i in range(0, 8, 2)]
-
- self.enc_dec([Segment(False, False, 0, 0, 0, "abcdefgh")], frames, ilvd, max_payload=2)
-
-from qpid.ops import *
-
-class OpTest(Base):
-
- def enc_dec(self, ops):
- enc = OpEncoder()
- dec = OpDecoder()
- enc.write(*ops)
- segs = enc.read()
- dec.write(*segs)
- dops = dec.read()
- assert len(ops) == len(dops)
- for op1, op2 in zip(ops, dops):
- self.cmp_ops(op1, op2)
-
- def testEmtpyMT(self):
- self.enc_dec([MessageTransfer()])
-
- def testEmptyMTSync(self):
- self.enc_dec([MessageTransfer(sync=True)])
-
- def testMT(self):
- self.enc_dec([MessageTransfer(destination="asdf")])
-
- def testSyncMT(self):
- self.enc_dec([MessageTransfer(destination="asdf", sync=True)])
-
- def testEmptyPayloadMT(self):
- self.enc_dec([MessageTransfer(payload="")])
-
- def testPayloadMT(self):
- self.enc_dec([MessageTransfer(payload="test payload")])
-
- def testHeadersEmptyPayloadMT(self):
- self.enc_dec([MessageTransfer(headers=[DeliveryProperties()])])
-
- def testHeadersPayloadMT(self):
- self.enc_dec([MessageTransfer(headers=[DeliveryProperties()], payload="test payload")])
-
- def testMultiHeadersEmptyPayloadMT(self):
- self.enc_dec([MessageTransfer(headers=[DeliveryProperties(), MessageProperties()])])
-
- def testMultiHeadersPayloadMT(self):
- self.enc_dec([MessageTransfer(headers=[MessageProperties(), DeliveryProperties()], payload="test payload")])
-
- def testContentTypeHeadersPayloadMT(self):
- self.enc_dec([MessageTransfer(headers=[MessageProperties(content_type="text/plain")], payload="test payload")])
-
- def testMulti(self):
- self.enc_dec([MessageTransfer(),
- MessageTransfer(sync=True),
- MessageTransfer(destination="one"),
- MessageTransfer(destination="two", sync=True),
- MessageTransfer(destination="three", payload="test payload")])
-
- def testControl(self):
- self.enc_dec([SessionAttach(name="asdf")])
-
- def testMixed(self):
- self.enc_dec([SessionAttach(name="fdsa"), MessageTransfer(destination="test")])
-
- def testChannel(self):
- self.enc_dec([SessionAttach(name="asdf", channel=3), MessageTransfer(destination="test", channel=1)])
-
- def testCompound(self):
- self.enc_dec([MessageTransfer(headers=[MessageProperties(reply_to=ReplyTo(exchange="exch", routing_key="rk"))])])
-
- def testListCompound(self):
- self.enc_dec([ExecutionResult(value=RecoverResult(in_doubt=[Xid(global_id="one"),
- Xid(global_id="two"),
- Xid(global_id="three")]))])
diff --git a/qpid/python/qpid/tests/messaging/__init__.py b/qpid/python/qpid/tests/messaging/__init__.py
deleted file mode 100644
index be7000f9c9..0000000000
--- a/qpid/python/qpid/tests/messaging/__init__.py
+++ /dev/null
@@ -1,236 +0,0 @@
-#
-# 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 time
-from math import ceil
-from qpid.harness import Skipped
-from qpid.tests.messaging.implementation import *
-from qpid.tests import Test
-from qpid.util import URL
-
-class Base(Test):
-
- def setup_connection(self):
- return None
-
- def setup_session(self):
- return None
-
- def setup_sender(self):
- return None
-
- def setup_receiver(self):
- return None
-
- def setup(self):
- self.test_id = uuid4()
- if self.is_swigged_qpid_messaging():
- self.broker = CompatURL(self.config.broker)
- else:
- self.broker = self.config.broker
-
- try:
- self.conn = self.setup_connection()
- except ConnectError, e:
- raise Skipped(e)
- self.ssn = self.setup_session()
- self.snd = self.setup_sender()
- if self.snd is not None:
- self.snd.durable = self.durable()
- self.rcv = self.setup_receiver()
-
- def teardown(self):
- if self.conn is not None and self.conn.attached():
- self.teardown_connection(self.conn)
- self.conn = None
-
- def teardown_connection(self, conn):
- conn.close(timeout=self.timeout())
-
- def content(self, base, count = None):
- if count is None:
- return "%s[%s]" % (base, self.test_id)
- else:
- return "%s[%s, %s]" % (base, count, self.test_id)
-
- def message(self, base, count = None, **kwargs):
- return Message(content=self.content(base, count), **kwargs)
-
- def ping(self, ssn):
- PING_Q = 'ping-queue; {create: always, delete: always}'
- # send a message
- sender = ssn.sender(PING_Q, durable=self.durable())
- content = self.content("ping")
- sender.send(content)
- receiver = ssn.receiver(PING_Q)
- msg = receiver.fetch(0)
- ssn.acknowledge()
- assert msg.content == content, "expected %r, got %r" % (content, msg.content)
-
- def drain(self, rcv, limit=None, timeout=0, expected=None, redelivered=False):
- messages = []
- try:
- while limit is None or len(messages) < limit:
- messages.append(rcv.fetch(timeout=timeout))
- except Empty:
- pass
- if expected is not None:
- self.assertEchos(expected, messages, redelivered)
- return messages
-
- def diff(self, m1, m2, excluded_properties=()):
- result = {}
- for attr in ("id", "subject", "user_id", "reply_to",
- "correlation_id", "durable", "priority", "ttl",
- "redelivered", "content_type", "content"):
- a1 = getattr(m1, attr)
- a2 = getattr(m2, attr)
- if a1 != a2:
- result[attr] = (a1, a2)
- p1 = dict(m1.properties)
- p2 = dict(m2.properties)
- for ep in excluded_properties:
- p1.pop(ep, None)
- p2.pop(ep, None)
- if p1 != p2:
- result["properties"] = (p1, p2)
- return result
-
- def assertEcho(self, msg, echo, redelivered=False):
- if not isinstance(msg, Message) or not isinstance(echo, Message):
- if isinstance(msg, Message):
- msg = msg.content
- if isinstance(echo, Message):
- echo = echo.content
- assert msg == echo, "expected %s, got %s" % (msg, echo)
- else:
- delta = self.diff(msg, echo, ("x-amqp-0-10.routing-key","qpid.subject"))
- mttl, ettl = delta.pop("ttl", (0, 0))
- if redelivered:
- assert echo.redelivered, \
- "expected %s to be redelivered: %s" % (msg, echo)
- if delta.has_key("redelivered"):
- del delta["redelivered"]
- assert mttl is not None and ettl is not None, "%s, %s" % (mttl, ettl)
- assert mttl >= ettl, "%s, %s" % (mttl, ettl)
- assert not delta, "expected %s, got %s, delta %s" % (msg, echo, delta)
-
- def assertEchos(self, msgs, echoes, redelivered=False):
- assert len(msgs) == len(echoes), "%s, %s" % (msgs, echoes)
- for m, e in zip(msgs, echoes):
- self.assertEcho(m, e, redelivered)
-
- def assertEmpty(self, rcv):
- contents = self.drain(rcv)
- assert len(contents) == 0, "%s is supposed to be empty: %s" % (rcv, contents)
-
- def assertAvailable(self, rcv, expected=None, lower=None, upper=None):
- if expected is not None:
- if lower is not None or upper is not None:
- raise ValueError("cannot specify lower or upper when specifying expected")
- lower = expected
- upper = expected
- else:
- if lower is None:
- lower = int(ceil(rcv.threshold*rcv.capacity))
- if upper is None:
- upper = rcv.capacity
-
- p = rcv.available()
- if upper == lower:
- assert p == lower, "expected %s, got %s" % (lower, p)
- else:
- assert lower <= p <= upper, "expected %s to be in range [%s, %s]" % (p, lower, upper)
-
- def sleep(self):
- time.sleep(self.delay())
-
- def delay(self):
- return float(self.config.defines.get("delay", "2"))
-
- def timeout(self):
- return float(self.config.defines.get("timeout", "60"))
-
- def get_bool(self, name):
- return self.config.defines.get(name, "false").lower() in ("true", "yes", "1")
-
- def durable(self):
- return self.get_bool("durable")
-
- def reconnect(self):
- return self.get_bool("reconnect")
-
-
- def transport(self):
- if self.broker.scheme == self.broker.AMQPS:
- return "ssl"
- else:
- return "tcp"
-
- def connection_options(self):
- protocol_version = self.config.defines.get("protocol_version")
- if protocol_version:
- return {"reconnect": self.reconnect(),
- "transport": self.transport(),
- "protocol":protocol_version}
- else:
- return {"reconnect": self.reconnect(),
- "transport": self.transport()}
-
- def is_swigged_qpid_messaging(self):
- return Connection.__module__ == 'qpid_messaging'
-
-class VersionTest (Base):
- def create_connection(self, version="amqp1.0", force=False):
- opts = self.connection_options()
- if force or not 'protocol' in opts:
- opts['protocol'] = version;
- return Connection.establish(self.broker, **opts)
-
- def setup_connection(self):
- return self.create_connection()
-
- def setup_session(self):
- return self.conn.session()
-
-class CompatURL(URL):
- """The formation of the URL for the C++ client is different to that of the pure Python client in that
- the C++ client expects <scheme>:<user>/<pass>.. whereas the pure Python's URL class expects
- <scheme>://<user>:<pass>.."""
- def __init__(self, *args, **kwargs):
- URL.__init__(self, *args, **kwargs)
-
- def __str__(self):
- s = ""
- if self.scheme:
- s += "%s:" % self.scheme
- if self.user:
- s += self.user
- if self.password:
- s += "/%s" % self.password
- s += "@"
- if ':' not in self.host:
- s += self.host
- else:
- s += "[%s]" % self.host
- if self.port:
- s += ":%s" % self.port
- return s
-
-import address, endpoints, message
diff --git a/qpid/python/qpid/tests/messaging/address.py b/qpid/python/qpid/tests/messaging/address.py
deleted file mode 100644
index aa9562a717..0000000000
--- a/qpid/python/qpid/tests/messaging/address.py
+++ /dev/null
@@ -1,321 +0,0 @@
-#
-# 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.
-#
-
-
-from qpid.tests import Test
-from qpid.messaging.address import lex, parse, ParseError, EOF, ID, NUMBER, \
- SYM, WSPACE, LEXER
-from qpid.lexer import Token
-from qpid.harness import Skipped
-from qpid.tests.parser import ParserBase
-
-def indent(st):
- return " " + st.replace("\n", "\n ")
-
-def pprint_address(name, subject, options):
- return "NAME: %s\nSUBJECT: %s\nOPTIONS: %s" % \
- (pprint(name), pprint(subject), pprint(options))
-
-def pprint(o):
- if isinstance(o, dict):
- return pprint_map(o)
- elif isinstance(o, list):
- return pprint_list(o)
- elif isinstance(o, basestring):
- return pprint_string(o)
- else:
- return repr(o)
-
-def pprint_map(m):
- items = ["%s: %s" % (pprint(k), pprint(v)) for k, v in m.items()]
- items.sort()
- return pprint_items("{", items, "}")
-
-def pprint_list(l):
- return pprint_items("[", [pprint(x) for x in l], "]")
-
-def pprint_items(start, items, end):
- if items:
- return "%s\n%s\n%s" % (start, ",\n".join([indent(i) for i in items]), end)
- else:
- return "%s%s" % (start, end)
-
-def pprint_string(s):
- result = "'"
- for c in s:
- if c == "'":
- result += "\\'"
- elif c == "\n":
- result += "\\n"
- elif ord(c) >= 0x80:
- result += "\\u%04x" % ord(c)
- else:
- result += c
- result += "'"
- return result
-
-class AddressTests(ParserBase, Test):
-
- EXCLUDE = (WSPACE, EOF)
-
- def fields(self, line, n):
- result = line.split(":", n - 1)
- result.extend([None]*(n - len(result)))
- return result
-
- def call(self, parser, mode, input):
- try:
- from subprocess import Popen, PIPE, STDOUT
- po = Popen([parser, mode], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
- except ImportError, e:
- raise Skipped("%s" % e)
- except OSError, e:
- raise Skipped("%s: %s" % (e, parser))
- out, _ = po.communicate(input=input)
- return out
-
- def parser(self):
- return self.config.defines.get("address.parser")
-
- def do_lex(self, st):
- parser = self.parser()
- if parser:
- out = self.call(parser, "lex", st)
- lines = out.split("\n")
- toks = []
- for line in lines:
- if line.strip():
- name, position, value = self.fields(line, 3)
- toks.append(Token(LEXER.type(name), value, position, st))
- return toks
- else:
- return lex(st)
-
- def do_parse(self, st):
- return parse(st)
-
- def valid(self, addr, name=None, subject=None, options=None):
- parser = self.parser()
- if parser:
- got = self.call(parser, "parse", addr)
- expected = "%s\n" % pprint_address(name, subject, options)
- assert expected == got, "expected\n<EXP>%s</EXP>\ngot\n<GOT>%s</GOT>" % (expected, got)
- else:
- ParserBase.valid(self, addr, (name, subject, options))
-
- def invalid(self, addr, error=None):
- parser = self.parser()
- if parser:
- got = self.call(parser, "parse", addr)
- expected = "ERROR: %s\n" % error
- assert expected == got, "expected %r, got %r" % (expected, got)
- else:
- ParserBase.invalid(self, addr, error)
-
- def testDashInId1(self):
- self.lex("foo-bar", ID)
-
- def testDashInId2(self):
- self.lex("foo-3", ID)
-
- def testDashAlone1(self):
- self.lex("foo - bar", ID, SYM, ID)
-
- def testDashAlone2(self):
- self.lex("foo - 3", ID, SYM, NUMBER)
-
- def testLeadingDash(self):
- self.lex("-foo", SYM, ID)
-
- def testTrailingDash(self):
- self.lex("foo-", ID, SYM)
-
- def testNegativeNum(self):
- self.lex("-3", NUMBER)
-
- def testIdNum(self):
- self.lex("id1", ID)
-
- def testIdSpaceNum(self):
- self.lex("id 1", ID, NUMBER)
-
- def testHash(self):
- self.valid("foo/bar.#", "foo", "bar.#")
-
- def testStar(self):
- self.valid("foo/bar.*", "foo", "bar.*")
-
- def testColon(self):
- self.valid("foo.bar/baz.qux:moo:arf", "foo.bar", "baz.qux:moo:arf")
-
- def testOptions(self):
- self.valid("foo.bar/baz.qux:moo:arf; {key: value}",
- "foo.bar", "baz.qux:moo:arf", {"key": "value"})
-
- def testOptionsTrailingComma(self):
- self.valid("name/subject; {key: value,}", "name", "subject",
- {"key": "value"})
-
- def testOptionsNone(self):
- self.valid("name/subject; {key: None}", "name", "subject",
- {"key": None})
-
- def testSemiSubject(self):
- self.valid("foo.bar/'baz.qux;moo:arf'; {key: value}",
- "foo.bar", "baz.qux;moo:arf", {"key": "value"})
-
- def testCommaSubject(self):
- self.valid("foo.bar/baz.qux.{moo,arf}", "foo.bar", "baz.qux.{moo,arf}")
-
- def testCommaSubjectOptions(self):
- self.valid("foo.bar/baz.qux.{moo,arf}; {key: value}", "foo.bar",
- "baz.qux.{moo,arf}", {"key": "value"})
-
- def testUnbalanced(self):
- self.valid("foo.bar/baz.qux.{moo,arf; {key: value}", "foo.bar",
- "baz.qux.{moo,arf", {"key": "value"})
-
- def testSlashQuote(self):
- self.valid("foo.bar\\/baz.qux.{moo,arf; {key: value}",
- "foo.bar/baz.qux.{moo,arf",
- None, {"key": "value"})
-
- def testSlashHexEsc1(self):
- self.valid("foo.bar\\x00baz.qux.{moo,arf; {key: value}",
- "foo.bar\x00baz.qux.{moo,arf",
- None, {"key": "value"})
-
- def testSlashHexEsc2(self):
- self.valid("foo.bar\\xffbaz.qux.{moo,arf; {key: value}",
- "foo.bar\xffbaz.qux.{moo,arf",
- None, {"key": "value"})
-
- def testSlashHexEsc3(self):
- self.valid("foo.bar\\xFFbaz.qux.{moo,arf; {key: value}",
- "foo.bar\xFFbaz.qux.{moo,arf",
- None, {"key": "value"})
-
- def testSlashUnicode1(self):
- self.valid("foo.bar\\u1234baz.qux.{moo,arf; {key: value}",
- u"foo.bar\u1234baz.qux.{moo,arf", None, {"key": "value"})
-
- def testSlashUnicode2(self):
- self.valid("foo.bar\\u0000baz.qux.{moo,arf; {key: value}",
- u"foo.bar\u0000baz.qux.{moo,arf", None, {"key": "value"})
-
- def testSlashUnicode3(self):
- self.valid("foo.bar\\uffffbaz.qux.{moo,arf; {key: value}",
- u"foo.bar\uffffbaz.qux.{moo,arf", None, {"key": "value"})
-
- def testSlashUnicode4(self):
- self.valid("foo.bar\\uFFFFbaz.qux.{moo,arf; {key: value}",
- u"foo.bar\uFFFFbaz.qux.{moo,arf", None, {"key": "value"})
-
- def testNoName(self):
- self.invalid("; {key: value}",
- "unexpected token SEMI(;) line:1,0:; {key: value}")
-
- def testEmpty(self):
- self.invalid("", "unexpected token EOF line:1,0:")
-
- def testNoNameSlash(self):
- self.invalid("/asdf; {key: value}",
- "unexpected token SLASH(/) line:1,0:/asdf; {key: value}")
-
- def testBadOptions1(self):
- self.invalid("name/subject; {",
- "expecting (NUMBER, STRING, ID, LBRACE, LBRACK, RBRACE), "
- "got EOF line:1,15:name/subject; {")
-
- def testBadOptions2(self):
- self.invalid("name/subject; { 3",
- "expecting COLON, got EOF "
- "line:1,17:name/subject; { 3")
-
- def testBadOptions3(self):
- self.invalid("name/subject; { key:",
- "expecting (NUMBER, STRING, ID, LBRACE, LBRACK), got EOF "
- "line:1,20:name/subject; { key:")
-
- def testBadOptions4(self):
- self.invalid("name/subject; { key: value",
- "expecting (COMMA, RBRACE), got EOF "
- "line:1,26:name/subject; { key: value")
-
- def testBadOptions5(self):
- self.invalid("name/subject; { key: value asdf",
- "expecting (COMMA, RBRACE), got ID(asdf) "
- "line:1,27:name/subject; { key: value asdf")
-
- def testBadOptions6(self):
- self.invalid("name/subject; { key: value,",
- "expecting (NUMBER, STRING, ID, LBRACE, LBRACK, RBRACE), got EOF "
- "line:1,27:name/subject; { key: value,")
-
- def testBadOptions7(self):
- self.invalid("name/subject; { key: value } asdf",
- "expecting EOF, got ID(asdf) "
- "line:1,29:name/subject; { key: value } asdf")
-
- def testList1(self):
- self.valid("name/subject; { key: [] }", "name", "subject", {"key": []})
-
- def testList2(self):
- self.valid("name/subject; { key: ['one'] }", "name", "subject", {"key": ['one']})
-
- def testList3(self):
- self.valid("name/subject; { key: [1, 2, 3] }", "name", "subject",
- {"key": [1, 2, 3]})
-
- def testList4(self):
- self.valid("name/subject; { key: [1, [2, 3], 4] }", "name", "subject",
- {"key": [1, [2, 3], 4]})
-
- def testBadList1(self):
- self.invalid("name/subject; { key: [ }", "expecting (NUMBER, STRING, ID, LBRACE, LBRACK), "
- "got RBRACE(}) line:1,23:name/subject; { key: [ }")
-
- def testBadList2(self):
- self.invalid("name/subject; { key: [ 1 }", "expecting (COMMA, RBRACK), "
- "got RBRACE(}) line:1,25:name/subject; { key: [ 1 }")
-
- def testBadList3(self):
- self.invalid("name/subject; { key: [ 1 2 }", "expecting (COMMA, RBRACK), "
- "got NUMBER(2) line:1,25:name/subject; { key: [ 1 2 }")
-
- def testBadList4(self):
- self.invalid("name/subject; { key: [ 1 2 ] }", "expecting (COMMA, RBRACK), "
- "got NUMBER(2) line:1,25:name/subject; { key: [ 1 2 ] }")
-
- def testMap1(self):
- self.valid("name/subject; { 'key': value }",
- "name", "subject", {"key": "value"})
-
- def testMap2(self):
- self.valid("name/subject; { 1: value }", "name", "subject", {1: "value"})
-
- def testMap3(self):
- self.valid('name/subject; { "foo.bar": value }',
- "name", "subject", {"foo.bar": "value"})
-
- def testBoolean(self):
- self.valid("name/subject; { true1: True, true2: true, "
- "false1: False, false2: false }",
- "name", "subject", {"true1": True, "true2": True,
- "false1": False, "false2": False})
diff --git a/qpid/python/qpid/tests/messaging/endpoints.py b/qpid/python/qpid/tests/messaging/endpoints.py
deleted file mode 100644
index ce2b4181a2..0000000000
--- a/qpid/python/qpid/tests/messaging/endpoints.py
+++ /dev/null
@@ -1,1476 +0,0 @@
-#
-# 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.
-#
-
-# setup, usage, teardown, errors(sync), errors(async), stress, soak,
-# boundary-conditions, config
-
-import errno, os, socket, sys, time
-from qpid import compat
-from qpid.compat import set
-from qpid.messaging import *
-from qpid.messaging.transports import TRANSPORTS
-from qpid.tests.messaging import Base
-from threading import Thread
-
-class SetupTests(Base):
-
- def testEstablish(self):
- self.conn = Connection.establish(self.broker, **self.connection_options())
- self.ping(self.conn.session())
-
- def testOpen(self):
- self.conn = Connection(self.broker, **self.connection_options())
- self.conn.open()
- self.ping(self.conn.session())
-
- def testOpenReconnectURLs(self):
- options = self.connection_options()
- options["reconnect_urls"] = [self.broker, self.broker]
- self.conn = Connection(self.broker, **options)
- self.conn.open()
- self.ping(self.conn.session())
-
- def testTcpNodelay(self):
- self.conn = Connection.establish(self.broker, tcp_nodelay=True)
- assert self.conn._driver._transport.socket.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY)
-
- def testConnectError(self):
- try:
- # Specifying port 0 yields a bad address on Windows; port 4 is unassigned
- self.conn = Connection.establish("localhost:4")
- assert False, "connect succeeded"
- except ConnectError, e:
- assert "refused" in str(e)
-
- def testGetError(self):
- self.conn = Connection("localhost:0")
- try:
- self.conn.open()
- assert False, "connect succeeded"
- except ConnectError, e:
- assert self.conn.get_error() == e
-
- def use_fds(self):
- fds = []
- try:
- while True:
- fds.append(os.open(getattr(os, "devnull", "/dev/null"), os.O_RDONLY))
- except OSError, e:
- if e.errno != errno.EMFILE:
- raise e
- else:
- return fds
-
- def testOpenCloseResourceLeaks(self):
- fds = self.use_fds()
- try:
- for i in range(32):
- if fds: os.close(fds.pop())
- for i in xrange(64):
- conn = Connection.establish(self.broker, **self.connection_options())
- conn.close()
- finally:
- while fds:
- os.close(fds.pop())
-
- def testOpenFailResourceLeaks(self):
- fds = self.use_fds()
- try:
- for i in range(32):
- if fds: os.close(fds.pop())
- for i in xrange(64):
- conn = Connection("localhost:0", **self.connection_options())
- # XXX: we need to force a waiter to be created for this test
- # to work
- conn._lock.acquire()
- conn._wait(lambda: False, timeout=0.001)
- conn._lock.release()
- try:
- conn.open()
- except ConnectError, e:
- pass
- finally:
- while fds:
- os.close(fds.pop())
-
- def testReconnect(self):
- options = self.connection_options()
- real = TRANSPORTS["tcp"]
-
- class flaky:
-
- def __init__(self, conn, host, port):
- self.real = real(conn, host, port)
- self.sent_count = 0
- self.recv_count = 0
-
- def fileno(self):
- return self.real.fileno()
-
- def reading(self, reading):
- return self.real.reading(reading)
-
- def writing(self, writing):
- return self.real.writing(writing)
-
- def send(self, bytes):
- if self.sent_count > 2048:
- raise socket.error("fake error")
- n = self.real.send(bytes)
- self.sent_count += n
- return n
-
- def recv(self, n):
- if self.recv_count > 2048:
- return ""
- bytes = self.real.recv(n)
- self.recv_count += len(bytes)
- return bytes
-
- def close(self):
- self.real.close()
-
- TRANSPORTS["flaky"] = flaky
-
- options["reconnect"] = True
- options["reconnect_interval"] = 0
- options["reconnect_limit"] = 100
- options["reconnect_log"] = False
- options["transport"] = "flaky"
-
- self.conn = Connection.establish(self.broker, **options)
- ssn = self.conn.session()
- snd = ssn.sender("test-reconnect-queue; {create: always, delete: always}")
- rcv = ssn.receiver(snd.target)
-
- msgs = [self.message("testReconnect", i) for i in range(20)]
- for m in msgs:
- snd.send(m)
-
- content = set()
- drained = []
- duplicates = []
- try:
- while True:
- m = rcv.fetch(timeout=0)
- if m.content not in content:
- content.add(m.content)
- drained.append(m)
- else:
- duplicates.append(m)
- ssn.acknowledge(m)
- except Empty:
- pass
- # XXX: apparently we don't always get duplicates, should figure out why
- #assert duplicates, "no duplicates"
- assert len(drained) == len(msgs)
- for m, d in zip(msgs, drained):
- # XXX: we should figure out how to provide proper end to end
- # redelivered
- self.assertEcho(m, d, d.redelivered)
-
-class ConnectionTests(Base):
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def testCheckClosed(self):
- assert not self.conn.check_closed()
-
- def testSessionAnon(self):
- ssn1 = self.conn.session()
- ssn2 = self.conn.session()
- self.ping(ssn1)
- self.ping(ssn2)
- assert ssn1 is not ssn2
-
- def testSessionNamed(self):
- ssn1 = self.conn.session("one")
- ssn2 = self.conn.session("two")
- self.ping(ssn1)
- self.ping(ssn2)
- assert ssn1 is not ssn2
- assert ssn1 is self.conn.session("one")
- assert ssn2 is self.conn.session("two")
-
- def testDetach(self):
- ssn = self.conn.session()
- self.ping(ssn)
- self.conn.detach()
- try:
- self.ping(ssn)
- assert False, "ping succeeded"
- except Detached:
- # this is the expected failure when pinging on a detached
- # connection
- pass
- self.conn.attach()
- self.ping(ssn)
-
- def testClose(self):
- self.conn.close()
- assert not self.conn.attached()
-
- def testSimultaneousClose(self):
- ssns = [self.conn.session() for i in range(3)]
- for s in ssns:
- for i in range(3):
- s.receiver("amq.topic")
- s.sender("amq.topic")
-
- def closer(errors):
- try:
- self.conn.close()
- except:
- _, e, _ = sys.exc_info()
- errors.append(compat.format_exc(e))
-
- t1_errors = []
- t2_errors = []
- t1 = Thread(target=lambda: closer(t1_errors))
- t2 = Thread(target=lambda: closer(t2_errors))
- t1.start()
- t2.start()
- t1.join(self.delay())
- t2.join(self.delay())
-
- assert not t1_errors, t1_errors[0]
- assert not t2_errors, t2_errors[0]
-
-class hangable:
-
- def __init__(self, conn, host, port):
- self.tcp = TRANSPORTS["tcp"](conn, host, port)
- self.hung = False
-
- def hang(self):
- self.hung = True
-
- def fileno(self):
- return self.tcp.fileno()
-
- def reading(self, reading):
- if self.hung:
- return True
- else:
- return self.tcp.reading(reading)
-
- def writing(self, writing):
- if self.hung:
- return False
- else:
- return self.tcp.writing(writing)
-
- def send(self, bytes):
- if self.hung:
- return 0
- else:
- return self.tcp.send(bytes)
-
- def recv(self, n):
- if self.hung:
- return ""
- else:
- return self.tcp.recv(n)
-
- def close(self):
- self.tcp.close()
-
-TRANSPORTS["hangable"] = hangable
-
-class TimeoutTests(Base):
-
- def setup_connection(self):
- options = self.connection_options()
- options["transport"] = "hangable"
- return Connection.establish(self.broker, **options)
-
- def setup_session(self):
- return self.conn.session()
-
- def setup_sender(self):
- return self.ssn.sender("amq.topic")
-
- def setup_receiver(self):
- return self.ssn.receiver("amq.topic; {link: {reliability: unreliable}}")
-
- def teardown_connection(self, conn):
- try:
- conn.detach(timeout=0)
- except Timeout:
- pass
-
- def hang(self):
- self.conn._driver._transport.hang()
-
- def timeoutTest(self, method):
- self.hang()
- try:
- method(timeout=self.delay())
- assert False, "did not time out"
- except Timeout:
- pass
-
- def testSenderSync(self):
- self.snd.send(self.content("testSenderSync"), sync=False)
- self.timeoutTest(self.snd.sync)
-
- def testSenderClose(self):
- self.snd.send(self.content("testSenderClose"), sync=False)
- self.timeoutTest(self.snd.close)
-
- def testReceiverClose(self):
- self.timeoutTest(self.rcv.close)
-
- def testSessionSync(self):
- self.snd.send(self.content("testSessionSync"), sync=False)
- self.timeoutTest(self.ssn.sync)
-
- def testSessionClose(self):
- self.timeoutTest(self.ssn.close)
-
- def testConnectionDetach(self):
- self.timeoutTest(self.conn.detach)
-
- def testConnectionClose(self):
- self.timeoutTest(self.conn.close)
-
- def testConnectionOpen(self):
- options = self.connection_options()
- options["reconnect"] = True
- options["reconnect_timeout"] = self.delay()
- try:
- bad_conn = Connection.establish("badhostname", **options)
- assert False, "did not time out"
- except Timeout:
- pass
-
-ACK_QC = 'test-ack-queue; {create: always}'
-ACK_QD = 'test-ack-queue; {delete: always}'
-
-class SessionTests(Base):
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self):
- return self.conn.session()
-
- def testSender(self):
- snd = self.ssn.sender('test-snd-queue; {create: sender, delete: receiver}',
- durable=self.durable())
- snd2 = self.ssn.sender(snd.target, durable=self.durable())
- assert snd is not snd2
- snd2.close()
-
- content = self.content("testSender")
- snd.send(content)
- rcv = self.ssn.receiver(snd.target)
- msg = rcv.fetch(0)
- assert msg.content == content
- self.ssn.acknowledge(msg)
-
- def testReceiver(self):
- rcv = self.ssn.receiver('test-rcv-queue; {create: always}')
- rcv2 = self.ssn.receiver(rcv.source)
- assert rcv is not rcv2
- rcv2.close()
-
- content = self.content("testReceiver")
- snd = self.ssn.sender(rcv.source, durable=self.durable())
- snd.send(content)
- msg = rcv.fetch(0)
- assert msg.content == content
- self.ssn.acknowledge(msg)
- snd2 = self.ssn.receiver('test-rcv-queue; {delete: always}')
-
- def testDetachedReceiver(self):
- self.conn.detach()
- rcv = self.ssn.receiver("test-dis-rcv-queue; {create: always, delete: always}")
- m = self.content("testDetachedReceiver")
- self.conn.attach()
- snd = self.ssn.sender("test-dis-rcv-queue")
- snd.send(m)
- self.drain(rcv, expected=[m])
-
- def testNextReceiver(self):
- ADDR = 'test-next-rcv-queue; {create: always, delete: always}'
- rcv1 = self.ssn.receiver(ADDR, capacity=UNLIMITED)
- rcv2 = self.ssn.receiver(ADDR, capacity=UNLIMITED)
- rcv3 = self.ssn.receiver(ADDR, capacity=UNLIMITED)
-
- snd = self.ssn.sender(ADDR)
-
- msgs = []
- for i in range(10):
- content = self.content("testNextReceiver", i)
- snd.send(content)
- msgs.append(content)
-
- fetched = []
- try:
- while True:
- rcv = self.ssn.next_receiver(timeout=self.delay())
- assert rcv in (rcv1, rcv2, rcv3)
- assert rcv.available() > 0
- fetched.append(rcv.fetch().content)
- except Empty:
- pass
- assert msgs == fetched, "expecting %s, got %s" % (msgs, fetched)
- self.ssn.acknowledge()
- #we set the capacity to 0 to prevent the deletion of the queue -
- #triggered the deletion policy when the first receiver is closed -
- #resulting in session exceptions being issued for the remaining
- #active subscriptions:
- for r in [rcv1, rcv2, rcv3]:
- r.capacity = 0
-
- # XXX, we need a convenient way to assert that required queues are
- # empty on setup, and possibly also to drain queues on teardown
- def ackTest(self, acker, ack_capacity=None):
- # send a bunch of messages
- snd = self.ssn.sender(ACK_QC, durable=self.durable())
- contents = [self.content("ackTest", i) for i in range(15)]
- for c in contents:
- snd.send(c)
-
- # drain the queue, verify the messages are there and then close
- # without acking
- rcv = self.ssn.receiver(ACK_QC)
- self.drain(rcv, expected=contents)
- self.ssn.close()
-
- # drain the queue again, verify that they are all the messages
- # were requeued, and ack this time before closing
- self.ssn = self.conn.session()
- if ack_capacity is not None:
- self.ssn.ack_capacity = ack_capacity
- rcv = self.ssn.receiver(ACK_QC)
- self.drain(rcv, expected=contents)
- acker(self.ssn)
- self.ssn.close()
-
- # drain the queue a final time and verify that the messages were
- # dequeued
- self.ssn = self.conn.session()
- rcv = self.ssn.receiver(ACK_QD)
- self.assertEmpty(rcv)
-
- def testAcknowledge(self):
- self.ackTest(lambda ssn: ssn.acknowledge())
-
- def testAcknowledgeAsync(self):
- self.ackTest(lambda ssn: ssn.acknowledge(sync=False))
-
- def testAcknowledgeAsyncAckCap0(self):
- try:
- try:
- self.ackTest(lambda ssn: ssn.acknowledge(sync=False), 0)
- assert False, "acknowledge shouldn't succeed with ack_capacity of zero"
- except InsufficientCapacity:
- pass
- finally:
- self.ssn.ack_capacity = UNLIMITED
- self.drain(self.ssn.receiver(ACK_QD))
- self.ssn.acknowledge()
-
- def testAcknowledgeAsyncAckCap1(self):
- self.ackTest(lambda ssn: ssn.acknowledge(sync=False), 1)
-
- def testAcknowledgeAsyncAckCap5(self):
- self.ackTest(lambda ssn: ssn.acknowledge(sync=False), 5)
-
- def testAcknowledgeAsyncAckCapUNLIMITED(self):
- self.ackTest(lambda ssn: ssn.acknowledge(sync=False), UNLIMITED)
-
- def testRelease(self):
- msgs = [self.message("testRelease", i) for i in range(3)]
- snd = self.ssn.sender("test-release-queue; {create: always, delete: always}")
- for m in msgs:
- snd.send(m)
- rcv = self.ssn.receiver(snd.target)
- echos = self.drain(rcv, expected=msgs)
- self.ssn.acknowledge(echos[0])
- self.ssn.acknowledge(echos[1], Disposition(RELEASED, set_redelivered=True))
- self.ssn.acknowledge(echos[2], Disposition(RELEASED))
- self.drain(rcv, limit=1, expected=msgs[1:2], redelivered=True)
- self.drain(rcv, expected=msgs[2:3])
- self.ssn.acknowledge()
-
- def testReject(self):
- msgs = [self.message("testReject", i) for i in range(3)]
- snd = self.ssn.sender("""
- test-reject-queue; {
- create: always,
- delete: always,
- node: {
- x-declare: {
- alternate-exchange: 'amq.topic'
- }
- }
- }
-""")
- for m in msgs:
- snd.send(m)
- rcv = self.ssn.receiver(snd.target)
- rej = self.ssn.receiver("amq.topic")
- echos = self.drain(rcv, expected=msgs)
- self.ssn.acknowledge(echos[0])
- self.ssn.acknowledge(echos[1], Disposition(REJECTED))
- self.ssn.acknowledge(echos[2],
- Disposition(REJECTED, code=0, text="test-reject"))
- self.drain(rej, expected=msgs[1:])
- self.ssn.acknowledge()
-
- def send(self, ssn, target, base, count=1):
- snd = ssn.sender(target, durable=self.durable())
- messages = []
- for i in range(count):
- c = self.message(base, i)
- snd.send(c)
- messages.append(c)
- snd.close()
- return messages
-
- def txTest(self, commit):
- TX_Q = 'test-tx-queue; {create: sender, delete: receiver}'
- TX_Q_COPY = 'test-tx-queue-copy; {create: always, delete: always}'
- txssn = self.conn.session(transactional=True)
- messages = self.send(self.ssn, TX_Q, "txTest", 3)
- txrcv = txssn.receiver(TX_Q)
- txsnd = txssn.sender(TX_Q_COPY, durable=self.durable())
- rcv = self.ssn.receiver(txrcv.source)
- copy_rcv = self.ssn.receiver(txsnd.target)
- self.assertEmpty(copy_rcv)
- for i in range(3):
- m = txrcv.fetch(0)
- txsnd.send(m)
- self.assertEmpty(copy_rcv)
- txssn.acknowledge()
- if commit:
- txssn.commit()
- self.assertEmpty(rcv)
- self.drain(copy_rcv, expected=messages)
- else:
- txssn.rollback()
- self.drain(rcv, expected=messages, redelivered=True)
- self.assertEmpty(copy_rcv)
- self.ssn.acknowledge()
-
- def testCommit(self):
- self.txTest(True)
-
- def testRollback(self):
- self.txTest(False)
-
- def txTestSend(self, commit):
- TX_SEND_Q = 'test-tx-send-queue; {create: sender, delete: receiver}'
- txssn = self.conn.session(transactional=True)
- messages = self.send(txssn, TX_SEND_Q, "txTestSend", 3)
- rcv = self.ssn.receiver(TX_SEND_Q)
- self.assertEmpty(rcv)
-
- if commit:
- txssn.commit()
- self.drain(rcv, expected=messages)
- self.ssn.acknowledge()
- else:
- txssn.rollback()
- self.assertEmpty(rcv)
- txssn.commit()
- self.assertEmpty(rcv)
-
- def testCommitSend(self):
- self.txTestSend(True)
-
- def testRollbackSend(self):
- self.txTestSend(False)
-
- def txTestAck(self, commit):
- TX_ACK_QC = 'test-tx-ack-queue; {create: always}'
- TX_ACK_QD = 'test-tx-ack-queue; {delete: always}'
- txssn = self.conn.session(transactional=True)
- txrcv = txssn.receiver(TX_ACK_QC)
- self.assertEmpty(txrcv)
- messages = self.send(self.ssn, TX_ACK_QC, "txTestAck", 3)
- self.drain(txrcv, expected=messages)
-
- if commit:
- txssn.acknowledge()
- else:
- txssn.rollback()
- self.drain(txrcv, expected=messages, redelivered=True)
- txssn.acknowledge()
- txssn.rollback()
- self.drain(txrcv, expected=messages, redelivered=True)
- txssn.commit() # commit without ack
- self.assertEmpty(txrcv)
-
- txssn.close()
-
- txssn = self.conn.session(transactional=True)
- txrcv = txssn.receiver(TX_ACK_QC)
- self.drain(txrcv, expected=messages, redelivered=True)
- txssn.acknowledge()
- txssn.commit()
- rcv = self.ssn.receiver(TX_ACK_QD)
- self.assertEmpty(rcv)
- txssn.close()
- self.assertEmpty(rcv)
-
- def testCommitAck(self):
- self.txTestAck(True)
-
- def testRollbackAck(self):
- self.txTestAck(False)
-
- def testDoubleCommit(self):
- ssn = self.conn.session(transactional=True)
- snd = ssn.sender("amq.direct/doubleCommit")
- rcv = ssn.receiver("amq.direct/doubleCommit")
- msgs = [self.message("testDoubleCommit", i, subject="doubleCommit") for i in range(3)]
- for m in msgs:
- snd.send(m)
- ssn.commit()
- self.drain(rcv, expected=msgs)
- ssn.acknowledge()
- ssn.commit()
-
- def testClose(self):
- self.ssn.close()
- try:
- self.ping(self.ssn)
- assert False, "ping succeeded"
- except Detached:
- pass
-
- def testRxCallback(self):
- """Verify that the callback is invoked when a message is received.
- """
- ADDR = 'test-rx_callback-queue; {create: always, delete: receiver}'
- class CallbackHandler:
- def __init__(self):
- self.handler_called = False
- def __call__(self, ssn):
- self.handler_called = True
- self.ssn = ssn
- cb = CallbackHandler()
- self.ssn.set_message_received_notify_handler(cb)
- rcv = self.ssn.receiver(ADDR)
- rcv.capacity = UNLIMITED
- snd = self.ssn.sender(ADDR)
- assert not cb.handler_called
- snd.send("Ping")
- deadline = time.time() + self.timeout()
- while time.time() < deadline:
- if cb.handler_called:
- break;
- assert cb.handler_called
- assert cb.ssn == self.ssn
- snd.close()
- rcv.close()
-
-
-RECEIVER_Q = 'test-receiver-queue; {create: always, delete: always}'
-
-class ReceiverTests(Base):
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self):
- return self.conn.session()
-
- def setup_sender(self):
- return self.ssn.sender(RECEIVER_Q)
-
- def setup_receiver(self):
- return self.ssn.receiver(RECEIVER_Q)
-
- def send(self, base, count = None, sync=True):
- content = self.content(base, count)
- self.snd.send(content, sync=sync)
- return content
-
- def testFetch(self):
- try:
- msg = self.rcv.fetch(0)
- assert False, "unexpected message: %s" % msg
- except Empty:
- pass
- try:
- start = time.time()
- msg = self.rcv.fetch(self.delay())
- assert False, "unexpected message: %s" % msg
- except Empty:
- elapsed = time.time() - start
- assert elapsed >= self.delay()
-
- one = self.send("testFetch", 1)
- two = self.send("testFetch", 2)
- three = self.send("testFetch", 3)
- msg = self.rcv.fetch(0)
- assert msg.content == one
- msg = self.rcv.fetch(self.delay())
- assert msg.content == two
- msg = self.rcv.fetch()
- assert msg.content == three
- self.ssn.acknowledge()
-
- def fetchFromClosedTest(self, entry):
- entry.close()
- try:
- msg = self.rcv.fetch(0)
- assert False, "unexpected result: %s" % msg
- except Empty, e:
- assert False, "unexpected exception: %s" % e
- except LinkClosed, e:
- pass
-
- def testFetchFromClosedReceiver(self):
- self.fetchFromClosedTest(self.rcv)
-
- def testFetchFromClosedSession(self):
- self.fetchFromClosedTest(self.ssn)
-
- def testFetchFromClosedConnection(self):
- self.fetchFromClosedTest(self.conn)
-
- def fetchFromConcurrentCloseTest(self, entry):
- def closer():
- self.sleep()
- entry.close()
- t = Thread(target=closer)
- t.start()
- try:
- msg = self.rcv.fetch()
- assert False, "unexpected result: %s" % msg
- except Empty, e:
- assert False, "unexpected exception: %s" % e
- except LinkClosed, e:
- pass
- t.join()
-
- def testFetchFromConcurrentCloseReceiver(self):
- self.fetchFromConcurrentCloseTest(self.rcv)
-
- def testFetchFromConcurrentCloseSession(self):
- self.fetchFromConcurrentCloseTest(self.ssn)
-
- def testFetchFromConcurrentCloseConnection(self):
- self.fetchFromConcurrentCloseTest(self.conn)
-
- def testCapacityIncrease(self):
- content = self.send("testCapacityIncrease")
- self.sleep()
- assert self.rcv.available() == 0
- self.rcv.capacity = UNLIMITED
- self.sleep()
- assert self.rcv.available() == 1
- msg = self.rcv.fetch(0)
- assert msg.content == content
- assert self.rcv.available() == 0
- self.ssn.acknowledge()
-
- def testCapacityDecrease(self):
- self.rcv.capacity = UNLIMITED
- one = self.send("testCapacityDecrease", 1)
- self.sleep()
- assert self.rcv.available() == 1
- msg = self.rcv.fetch(0)
- assert msg.content == one
-
- self.rcv.capacity = 0
-
- two = self.send("testCapacityDecrease", 2)
- self.sleep()
- assert self.rcv.available() == 0
- msg = self.rcv.fetch(0)
- assert msg.content == two
-
- self.ssn.acknowledge()
-
- def capacityTest(self, capacity, threshold=None):
- if threshold is not None:
- self.rcv.threshold = threshold
- self.rcv.capacity = capacity
- self.assertAvailable(self.rcv, 0)
-
- for i in range(2*capacity):
- self.send("capacityTest(%s, %s)" % (capacity, threshold), i, sync=False)
- self.snd.sync()
- self.sleep()
- self.assertAvailable(self.rcv)
-
- first = capacity/2
- second = capacity - first
- self.drain(self.rcv, limit = first)
- self.sleep()
- self.assertAvailable(self.rcv)
- self.drain(self.rcv, limit = second)
- self.sleep()
- self.assertAvailable(self.rcv)
-
- drained = self.drain(self.rcv)
- assert len(drained) == capacity, "%s, %s" % (len(drained), drained)
- self.assertAvailable(self.rcv, 0)
-
- self.ssn.acknowledge()
-
- def testCapacity5(self):
- self.capacityTest(5)
-
- def testCapacity5Threshold1(self):
- self.capacityTest(5, 1)
-
- def testCapacity10(self):
- self.capacityTest(10)
-
- def testCapacity10Threshold1(self):
- self.capacityTest(10, 1)
-
- def testCapacity100(self):
- self.capacityTest(100)
-
- def testCapacity100Threshold1(self):
- self.capacityTest(100, 1)
-
- def testCapacityUNLIMITED(self):
- self.rcv.capacity = UNLIMITED
- self.assertAvailable(self.rcv, 0)
-
- for i in range(10):
- self.send("testCapacityUNLIMITED", i)
- self.sleep()
- self.assertAvailable(self.rcv, 10)
-
- self.drain(self.rcv)
- self.assertAvailable(self.rcv, 0)
-
- self.ssn.acknowledge()
-
- def testAvailable(self):
- self.rcv.capacity = UNLIMITED
- assert self.rcv.available() == 0
-
- for i in range(3):
- self.send("testAvailable", i)
- self.sleep()
- assert self.rcv.available() == 3
-
- for i in range(3, 10):
- self.send("testAvailable", i)
- self.sleep()
- assert self.rcv.available() == 10
-
- self.drain(self.rcv, limit=3)
- assert self.rcv.available() == 7
-
- self.drain(self.rcv)
- assert self.rcv.available() == 0
-
- self.ssn.acknowledge()
-
- def testDoubleClose(self):
- m1 = self.content("testDoubleClose", 1)
- m2 = self.content("testDoubleClose", 2)
-
- snd = self.ssn.sender("""test-double-close; {
- create: always,
- delete: sender,
- node: {
- type: topic
- }
-}
-""")
- r1 = self.ssn.receiver(snd.target)
- r2 = self.ssn.receiver(snd.target)
- snd.send(m1)
- self.drain(r1, expected=[m1])
- self.drain(r2, expected=[m1])
- r1.close()
- snd.send(m2)
- self.drain(r2, expected=[m2])
- r2.close()
-
- # XXX: need testClose
-
- def testMode(self):
- msgs = [self.content("testMode", 1),
- self.content("testMode", 2),
- self.content("testMode", 3)]
-
- for m in msgs:
- self.snd.send(m)
-
- rb = self.ssn.receiver('test-receiver-queue; {mode: browse}')
- rc = self.ssn.receiver('test-receiver-queue; {mode: consume}')
- self.drain(rb, expected=msgs)
- self.drain(rc, expected=msgs)
- rb2 = self.ssn.receiver(rb.source)
- self.assertEmpty(rb2)
- self.drain(self.rcv, expected=[])
-
- def testUnsettled(self):
- # just tests the code path and not the value
- rcv = self.ssn.receiver('test-receiver-unsettled-queue; {create: always, delete: always}')
- rcv.unsettled()
-
- def unreliabilityTest(self, mode="unreliable"):
- msgs = [self.message("testUnreliable", i) for i in range(3)]
- snd = self.ssn.sender("test-unreliability-queue; {create: sender, delete: receiver}")
- rcv = self.ssn.receiver(snd.target)
- for m in msgs:
- snd.send(m)
-
- # close without ack on reliable receiver, messages should be requeued
- ssn = self.conn.session()
- rrcv = ssn.receiver("test-unreliability-queue")
- self.drain(rrcv, expected=msgs)
- ssn.close()
-
- # close without ack on unreliable receiver, messages should not be requeued
- ssn = self.conn.session()
- urcv = ssn.receiver("test-unreliability-queue; {link: {reliability: %s}}" % mode)
- self.drain(urcv, expected=msgs, redelivered=True)
- ssn.close()
-
- self.assertEmpty(rcv)
-
- def testUnreliable(self):
- self.unreliabilityTest(mode="unreliable")
-
- def testAtMostOnce(self):
- self.unreliabilityTest(mode="at-most-once")
-
-class AddressTests(Base):
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self):
- return self.conn.session()
-
- def badOption(self, options, error):
- try:
- self.ssn.sender("test-bad-options-snd; %s" % options)
- assert False
- except InvalidOption, e:
- assert "error in options: %s" % error == str(e), e
-
- try:
- self.ssn.receiver("test-bad-options-rcv; %s" % options)
- assert False
- except InvalidOption, e:
- assert "error in options: %s" % error == str(e), e
-
- def testIllegalKey(self):
- self.badOption("{create: always, node: "
- "{this-property-does-not-exist: 3}}",
- "node: this-property-does-not-exist: "
- "illegal key")
-
- def testWrongValue(self):
- self.badOption("{create: asdf}", "create: asdf not in "
- "('always', 'sender', 'receiver', 'never')")
-
- def testWrongType1(self):
- self.badOption("{node: asdf}",
- "node: asdf is not a map")
-
- def testWrongType2(self):
- self.badOption("{node: {durable: []}}",
- "node: durable: [] is not a bool")
-
- def testCreateQueue(self):
- snd = self.ssn.sender("test-create-queue; {create: always, delete: always, "
- "node: {type: queue, durable: False, "
- "x-declare: {auto_delete: true}}}")
- content = self.content("testCreateQueue")
- snd.send(content)
- rcv = self.ssn.receiver("test-create-queue")
- self.drain(rcv, expected=[content])
-
- def createExchangeTest(self, props=""):
- addr = """test-create-exchange; {
- create: always,
- delete: always,
- node: {
- type: topic,
- durable: False,
- x-declare: {auto_delete: true, %s}
- }
- }""" % props
- snd = self.ssn.sender(addr)
- snd.send("ping")
- rcv1 = self.ssn.receiver("test-create-exchange/first")
- rcv2 = self.ssn.receiver("test-create-exchange/first")
- rcv3 = self.ssn.receiver("test-create-exchange/second")
- for r in (rcv1, rcv2, rcv3):
- try:
- r.fetch(0)
- assert False
- except Empty:
- pass
- msg1 = Message(self.content("testCreateExchange", 1), subject="first")
- msg2 = Message(self.content("testCreateExchange", 2), subject="second")
- snd.send(msg1)
- snd.send(msg2)
- self.drain(rcv1, expected=[msg1.content])
- self.drain(rcv2, expected=[msg1.content])
- self.drain(rcv3, expected=[msg2.content])
-
- def testCreateExchange(self):
- self.createExchangeTest()
-
- def testCreateExchangeDirect(self):
- self.createExchangeTest("type: direct")
-
- def testCreateExchangeTopic(self):
- self.createExchangeTest("type: topic")
-
- def testDeleteBySender(self):
- snd = self.ssn.sender("test-delete; {create: always}")
- snd.send("ping")
- snd.close()
- snd = self.ssn.sender("test-delete; {delete: always}")
- snd.send("ping")
- snd.close()
- try:
- self.ssn.sender("test-delete")
- except NotFound, e:
- assert "no such queue" in str(e)
-
- def testDeleteByReceiver(self):
- rcv = self.ssn.receiver("test-delete; {create: always, delete: always}")
- try:
- rcv.fetch(0)
- except Empty:
- pass
- rcv.close()
-
- try:
- self.ssn.receiver("test-delete")
- assert False
- except NotFound, e:
- assert "no such queue" in str(e)
-
- def testDeleteSpecial(self):
- snd = self.ssn.sender("amq.topic; {delete: always}")
- snd.send("asdf")
- try:
- snd.close()
- assert False, "successfully deleted amq.topic"
- except SessionError, e:
- assert e.code == 530
- # XXX: need to figure out close after error
- self.conn._remove_session(self.ssn)
-
- def testNodeBindingsQueue(self):
- snd = self.ssn.sender("""
-test-node-bindings-queue; {
- create: always,
- delete: always,
- node: {
- x-bindings: [{exchange: "amq.topic", key: "a.#"},
- {exchange: "amq.direct", key: "b"},
- {exchange: "amq.topic", key: "c.*"}]
- }
-}
-""")
- snd.send("one")
- snd_a = self.ssn.sender("amq.topic/a.foo")
- snd_b = self.ssn.sender("amq.direct/b")
- snd_c = self.ssn.sender("amq.topic/c.bar")
- snd_a.send("two")
- snd_b.send("three")
- snd_c.send("four")
- rcv = self.ssn.receiver("test-node-bindings-queue")
- self.drain(rcv, expected=["one", "two", "three", "four"])
-
- def testNodeBindingsTopic(self):
- rcv = self.ssn.receiver("test-node-bindings-topic-queue; {create: always, delete: always}")
- rcv_a = self.ssn.receiver("test-node-bindings-topic-queue-a; {create: always, delete: always}")
- rcv_b = self.ssn.receiver("test-node-bindings-topic-queue-b; {create: always, delete: always}")
- rcv_c = self.ssn.receiver("test-node-bindings-topic-queue-c; {create: always, delete: always}")
- snd = self.ssn.sender("""
-test-node-bindings-topic; {
- create: always,
- delete: always,
- node: {
- type: topic,
- x-bindings: [{queue: test-node-bindings-topic-queue, key: "#"},
- {queue: test-node-bindings-topic-queue-a, key: "a.#"},
- {queue: test-node-bindings-topic-queue-b, key: "b"},
- {queue: test-node-bindings-topic-queue-c, key: "c.*"}]
- }
-}
-""")
- m1 = Message("one")
- m2 = Message(subject="a.foo", content="two")
- m3 = Message(subject="b", content="three")
- m4 = Message(subject="c.bar", content="four")
- snd.send(m1)
- snd.send(m2)
- snd.send(m3)
- snd.send(m4)
- self.drain(rcv, expected=[m1, m2, m3, m4])
- self.drain(rcv_a, expected=[m2])
- self.drain(rcv_b, expected=[m3])
- self.drain(rcv_c, expected=[m4])
-
- def testLinkBindings(self):
- m_a = self.message("testLinkBindings", 1, subject="a")
- m_b = self.message("testLinkBindings", 2, subject="b")
-
- self.ssn.sender("test-link-bindings-queue; {create: always, delete: always}")
- snd = self.ssn.sender("amq.topic")
-
- snd.send(m_a)
- snd.send(m_b)
- snd.close()
-
- rcv = self.ssn.receiver("test-link-bindings-queue")
- self.assertEmpty(rcv)
-
- snd = self.ssn.sender("""
-amq.topic; {
- link: {
- x-bindings: [{queue: test-link-bindings-queue, key: a}]
- }
-}
-""")
-
- snd.send(m_a)
- snd.send(m_b)
-
- self.drain(rcv, expected=[m_a])
- rcv.close()
-
- rcv = self.ssn.receiver("""
-test-link-bindings-queue; {
- link: {
- x-bindings: [{exchange: "amq.topic", key: b}]
- }
-}
-""")
-
- snd.send(m_a)
- snd.send(m_b)
-
- self.drain(rcv, expected=[m_a, m_b])
-
- def testSubjectOverride(self):
- snd = self.ssn.sender("amq.topic/a")
- rcv_a = self.ssn.receiver("amq.topic/a")
- rcv_b = self.ssn.receiver("amq.topic/b")
- m1 = self.content("testSubjectOverride", 1)
- m2 = self.content("testSubjectOverride", 2)
- snd.send(m1)
- snd.send(Message(subject="b", content=m2))
- self.drain(rcv_a, expected=[m1])
- self.drain(rcv_b, expected=[m2])
-
- def testSubjectDefault(self):
- m1 = self.content("testSubjectDefault", 1)
- m2 = self.content("testSubjectDefault", 2)
- snd = self.ssn.sender("amq.topic/a")
- rcv = self.ssn.receiver("amq.topic")
- snd.send(m1)
- snd.send(Message(subject="b", content=m2))
- e1 = rcv.fetch(timeout=0)
- e2 = rcv.fetch(timeout=0)
- assert e1.subject == "a", "subject: %s" % e1.subject
- assert e2.subject == "b", "subject: %s" % e2.subject
- self.assertEmpty(rcv)
-
- def doReliabilityTest(self, reliability, messages, expected):
- snd = self.ssn.sender("amq.topic")
- rcv = self.ssn.receiver("amq.topic; {link: {reliability: %s}}" % reliability)
- for m in messages:
- snd.send(m)
- self.conn.detach()
- self.conn.attach()
- self.drain(rcv, expected=expected)
-
- def testReliabilityUnreliable(self):
- msgs = [self.message("testReliabilityUnreliable", i) for i in range(3)]
- self.doReliabilityTest("unreliable", msgs, [])
-
- def testReliabilityAtLeastOnce(self):
- msgs = [self.message("testReliabilityAtLeastOnce", i) for i in range(3)]
- self.doReliabilityTest("at-least-once", msgs, msgs)
-
- def testLinkName(self):
- msgs = [self.message("testLinkName", i) for i in range(3)]
- snd = self.ssn.sender("amq.topic")
- trcv = self.ssn.receiver("amq.topic; {link: {name: test-link-name}}")
- qrcv = self.ssn.receiver("test-link-name")
- for m in msgs:
- snd.send(m)
- self.drain(qrcv, expected=msgs)
-
- def testAssert1(self):
- try:
- snd = self.ssn.sender("amq.topic; {assert: always, node: {type: queue}}")
- assert 0, "assertion failed to trigger"
- except AssertionFailed, e:
- pass
- except NotFound, e: # queue named amp.topic not found
- pass
-
- def testAssert2(self):
- snd = self.ssn.sender("amq.topic; {assert: always}")
-
-NOSUCH_Q = "this-queue-should-not-exist"
-UNPARSEABLE_ADDR = "name/subject; {bad options"
-UNLEXABLE_ADDR = "\0x0\0x1\0x2\0x3"
-
-class AddressErrorTests(Base):
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self):
- return self.conn.session()
-
- def senderErrorTest(self, addr, exc, check=lambda e: True):
- try:
- self.ssn.sender(addr, durable=self.durable())
- assert False, "sender creation succeeded"
- except exc, e:
- assert check(e), "unexpected error: %s" % compat.format_exc(e)
-
- def receiverErrorTest(self, addr, exc, check=lambda e: True):
- try:
- self.ssn.receiver(addr)
- assert False, "receiver creation succeeded"
- except exc, e:
- assert check(e), "unexpected error: %s" % compat.format_exc(e)
-
- def testNoneTarget(self):
- self.senderErrorTest(None, MalformedAddress)
-
- def testNoneSource(self):
- self.receiverErrorTest(None, MalformedAddress)
-
- def testNoTarget(self):
- self.senderErrorTest(NOSUCH_Q, NotFound, lambda e: NOSUCH_Q in str(e))
-
- def testNoSource(self):
- self.receiverErrorTest(NOSUCH_Q, NotFound, lambda e: NOSUCH_Q in str(e))
-
- def testUnparseableTarget(self):
- self.senderErrorTest(UNPARSEABLE_ADDR, MalformedAddress,
- lambda e: "expecting COLON" in str(e))
-
- def testUnparseableSource(self):
- self.receiverErrorTest(UNPARSEABLE_ADDR, MalformedAddress,
- lambda e: "expecting COLON" in str(e))
-
- def testUnlexableTarget(self):
- self.senderErrorTest(UNLEXABLE_ADDR, MalformedAddress,
- lambda e: "unrecognized characters" in str(e))
-
- def testUnlexableSource(self):
- self.receiverErrorTest(UNLEXABLE_ADDR, MalformedAddress,
- lambda e: "unrecognized characters" in str(e))
-
- def testInvalidMode(self):
- self.receiverErrorTest('name; {mode: "this-is-a-bad-receiver-mode"}',
- InvalidOption,
- lambda e: "not in ('browse', 'consume')" in str(e))
-
-SENDER_Q = 'test-sender-q; {create: always, delete: always}'
-
-class SenderTests(Base):
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self):
- return self.conn.session()
-
- def setup_sender(self):
- return self.ssn.sender(SENDER_Q)
-
- def setup_receiver(self):
- return self.ssn.receiver(SENDER_Q)
-
- def checkContent(self, content):
- self.snd.send(content)
- msg = self.rcv.fetch(0)
- assert msg.content == content
-
- out = Message(content)
- self.snd.send(out)
- echo = self.rcv.fetch(0)
- assert out.content == echo.content
- assert echo.content == msg.content
- self.ssn.acknowledge()
-
- def testSendString(self):
- self.checkContent(self.content("testSendString"))
-
- def testSendList(self):
- self.checkContent(["testSendList", 1, 3.14, self.test_id])
-
- def testSendMap(self):
- self.checkContent({"testSendMap": self.test_id, "pie": "blueberry", "pi": 3.14})
-
- def asyncTest(self, capacity):
- self.snd.capacity = capacity
- msgs = [self.content("asyncTest", i) for i in range(15)]
- for m in msgs:
- self.snd.send(m, sync=False)
- self.drain(self.rcv, timeout=self.delay(), expected=msgs)
- self.ssn.acknowledge()
-
- def testSendAsyncCapacity0(self):
- try:
- self.asyncTest(0)
- assert False, "send shouldn't succeed with zero capacity"
- except InsufficientCapacity:
- # this is expected
- pass
-
- def testSendAsyncCapacity1(self):
- self.asyncTest(1)
-
- def testSendAsyncCapacity5(self):
- self.asyncTest(5)
-
- def testSendAsyncCapacityUNLIMITED(self):
- self.asyncTest(UNLIMITED)
-
- def testCapacityTimeout(self):
- self.snd.capacity = 1
- msgs = []
- caught = False
- while len(msgs) < 100:
- m = self.content("testCapacity", len(msgs))
- try:
- self.snd.send(m, sync=False, timeout=0)
- msgs.append(m)
- except InsufficientCapacity:
- caught = True
- break
- self.snd.sync()
- self.drain(self.rcv, expected=msgs)
- self.ssn.acknowledge()
- assert caught, "did not exceed capacity"
-
- def testEINTR(self):
- m1 = self.content("testEINTR", 0)
- m2 = self.content("testEINTR", 1)
-
- self.snd.send(m1, timeout=self.timeout())
- try:
- os.setuid(500)
- assert False, "setuid should fail"
- except:
- pass
- self.snd.send(m2, timeout=self.timeout())
-
-
-class ErrorCallbackTests(Base):
-
- class Callback:
- def __init__(self, name):
- self.name = name
- self.obj = None
- self.exc = None
-
- def __call__(self, obj, exc):
- self.obj = obj
- self.exc = exc
-
- def testConnectErrorCallback(self):
- cb = ErrorCallbackTests.Callback("connection")
- self.conn = Connection("localhost:4")
- self.conn.set_async_exception_notify_handler(cb)
- try:
- self.conn.open()
- assert False, "connect succeeded"
- except Exception:
- assert self.conn == cb.obj, cb.obj
- assert cb.name == "connection"
- assert cb.exc is not None
-
- def testSessionErrorCallback(self):
- ccb = ErrorCallbackTests.Callback("connection")
- self.conn = Connection.establish(self.broker, **self.connection_options())
- self.conn.set_async_exception_notify_handler(ccb)
- scb = ErrorCallbackTests.Callback("session")
- self.ssn = self.conn.session(transactional=True)
- self.ssn.set_async_exception_notify_handler(scb)
- self.conn.detach()
- try:
- self.ping(self.ssn)
- assert False, "session succeeded"
- except Exception:
- assert self.ssn == scb.obj, scb.obj
- assert scb.name == "session"
- assert scb.exc is not None
- # connection callback should be empty
- assert ccb.obj == None, ccb.obj
-
- def testSenderErrorCallback(self):
- ccb = ErrorCallbackTests.Callback("connection")
- conn = Connection(self.broker, **self.connection_options())
- conn.set_async_exception_notify_handler(ccb)
- scb = ErrorCallbackTests.Callback("session")
- ssn = conn.session()
- ssn.set_async_exception_notify_handler(scb)
- snd = ssn.sender(NOSUCH_Q)
- sndcb = ErrorCallbackTests.Callback("sender")
- snd.set_async_exception_notify_handler(sndcb)
- conn.open()
- try:
- snd.send(self.message("HI"))
- assert False, "send worked"
- except Exception:
- assert snd == sndcb.obj, sndcb.obj
- assert sndcb.name == "sender"
- assert sndcb.exc is not None
- # connection and session callbacks are empty
- assert ccb.obj == None, ccb.obj
- assert scb.obj == None, scb.obj
-
- def testReceiverErrorCallback(self):
- ccb = ErrorCallbackTests.Callback("connection")
- self.conn = Connection(self.broker, **self.connection_options())
- self.conn.set_async_exception_notify_handler(ccb)
- scb = ErrorCallbackTests.Callback("session")
- self.ssn = self.conn.session()
- self.ssn.set_async_exception_notify_handler(scb)
- self.recv = self.ssn.receiver(NOSUCH_Q)
- rcb = ErrorCallbackTests.Callback("receiver")
- self.recv.set_async_exception_notify_handler(rcb)
- self.conn.open()
- try:
- self.recv.fetch()
- assert False, "fetch worked"
- except Exception:
- assert self.recv == rcb.obj, rcb.obj
- assert rcb.name == "receiver"
- assert rcb.exc is not None
- # connection and session callbacks are empty
- assert ccb.obj == None, ccb.obj
- assert scb.obj == None, scb.obj
diff --git a/qpid/python/qpid/tests/messaging/implementation.py b/qpid/python/qpid/tests/messaging/implementation.py
deleted file mode 100644
index fce60c6f38..0000000000
--- a/qpid/python/qpid/tests/messaging/implementation.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# 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 os
-if 'QPID_USE_SWIG_CLIENT' in os.environ and os.environ['QPID_USE_SWIG_CLIENT']:
- try:
- from qpid_messaging import *
- from qpid.datatypes import uuid4
- except ImportError, e:
- print "Swigged client not found. Falling back to pure bindings, %s\n" % e
- from qpid.messaging import *
-else:
- from qpid.messaging import *
diff --git a/qpid/python/qpid/tests/messaging/message.py b/qpid/python/qpid/tests/messaging/message.py
deleted file mode 100644
index bfdd2c79e5..0000000000
--- a/qpid/python/qpid/tests/messaging/message.py
+++ /dev/null
@@ -1,187 +0,0 @@
-#
-# 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.
-#
-
-from qpid.tests.messaging.implementation import *
-from qpid.messaging.address import parse
-from qpid.tests.messaging import Base
-
-class MessageTests(Base):
-
- def testCreateString(self):
- m = Message("string")
- assert m.content == "string"
- assert m.content_type is None
-
- def testCreateUnicode(self):
- m = Message(u"unicode")
- assert m.content == u"unicode"
- assert m.content_type == "text/plain"
-
- def testCreateMap(self):
- m = Message({})
- assert m.content == {}
- assert m.content_type == "amqp/map"
-
- def testCreateList(self):
- m = Message([])
- assert m.content == []
- assert m.content_type == "amqp/list"
-
- def testContentTypeOverride(self):
- m = Message()
- m.content_type = "text/html; charset=utf8"
- m.content = u"<html/>"
- assert m.content_type == "text/html; charset=utf8"
-
-ECHO_Q = 'test-message-echo-queue; {create: always, delete: always}'
-
-class MessageEchoTests(Base):
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self):
- return self.conn.session()
-
- def setup_sender(self):
- return self.ssn.sender(ECHO_Q)
-
- def setup_receiver(self):
- return self.ssn.receiver(ECHO_Q)
-
- def check(self, msg):
- self.snd.send(msg)
- echo = self.rcv.fetch(0)
- self.assertEcho(msg, echo)
- self.ssn.acknowledge(echo)
-
- def testStringContent(self):
- self.check(Message("string"))
-
- def testUnicodeContent(self):
- self.check(Message(u"unicode"))
-
-
- TEST_MAP = {"key1": "string",
- "key2": u"unicode",
- "key3": 3,
- "key4": -3,
- "key5": 3.14,
- "key6": -3.14,
- "key7": ["one", 2, 3.14],
- "key8": [],
- "key9": {"sub-key0": 3},
- "key10": True,
- "key11": False,
- "x-amqp-0-10.app-id": "test-app-id",
- "x-amqp-0-10.content-encoding": "test-content-encoding"}
-
- def testMapContent(self):
- self.check(Message(MessageEchoTests.TEST_MAP))
-
- def testListContent(self):
- self.check(Message([]))
- self.check(Message([1, 2, 3]))
- self.check(Message(["one", 2, 3.14, {"four": 4}]))
-
- def testProperties(self):
- msg = Message()
- msg.subject = "subject"
- msg.correlation_id = str(self.test_id)
- msg.durable = True
- msg.priority = 7
- msg.ttl = 60
- msg.properties = MessageEchoTests.TEST_MAP
- msg.reply_to = "reply-address"
- self.check(msg)
-
- def testApplicationProperties(self):
- msg = Message()
- msg.properties["a"] = u"A"
- msg.properties["b"] = 1
- msg.properties["c"] = ["x", 2]
- msg.properties["d"] = "D"
- #make sure deleting works as expected
- msg.properties["foo"] = "bar"
- del msg.properties["foo"]
- self.check(msg)
-
- def testContentTypeUnknown(self):
- msg = Message(content_type = "this-content-type-does-not-exist")
- self.check(msg)
-
- def testTextPlain(self):
- self.check(Message(content_type="text/plain", content="asdf"))
-
- def testTextPlainEmpty(self):
- self.check(Message(content_type="text/plain"))
-
- def check_rt(self, addr, expected=None):
- if expected is None:
- expected = addr
- msg = Message(reply_to=addr)
- self.snd.send(msg)
- echo = self.rcv.fetch(0)
- #reparse addresses and check individual parts as this avoids
- #failing due to differenecs in whitespace when running over
- #swigged client:
- (actual_name, actual_subject, actual_options) = parse(echo.reply_to)
- (expected_name, expected_subject, expected_options) = parse(expected)
- assert actual_name == expected_name, (actual_name, expected_name)
- assert actual_subject == expected_subject, (actual_subject, expected_subject)
- assert actual_options == expected_options, (actual_options, expected_options)
- self.ssn.acknowledge(echo)
-
- def testReplyTo(self):
- self.check_rt("name")
-
- def testReplyToQueue(self):
- self.check_rt("name; {node: {type: queue}}", "name")
-
- def testReplyToQueueSubject(self):
- self.check_rt("name/subject; {node: {type: queue}}", "name")
-
- def testReplyToTopic(self):
- self.check_rt("name; {node: {type: topic}}")
-
- def testReplyToTopicSubject(self):
- self.check_rt("name/subject; {node: {type: topic}}")
-
- def testBooleanEncoding(self):
- msg = Message({"true": True, "false": False})
- self.snd.send(msg)
- echo = self.rcv.fetch(0)
- self.assertEcho(msg, echo)
- t = echo.content["true"]
- f = echo.content["false"]
- assert isinstance(t, bool), t
- assert isinstance(f, bool), f
-
- def testExceptionRaisedMismatchedContentType(self):
- msg = Message(content_type="amqp/map", content="asdf")
- try:
- self.snd.send(msg)
- self.rcv.fetch(0)
- assert False, "Exception not raised on mismatched content/content_type"
- except Exception, e:
- pass
-
- def testRecoverAfterException(self):
- self.testExceptionRaisedMismatchedContentType()
- self.testTextPlain()
diff --git a/qpid/python/qpid/tests/mimetype.py b/qpid/python/qpid/tests/mimetype.py
deleted file mode 100644
index 22760316f0..0000000000
--- a/qpid/python/qpid/tests/mimetype.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# 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.
-#
-
-from qpid.tests import Test
-from qpid.mimetype import lex, parse, ParseError, EOF, WSPACE
-from parser import ParserBase
-
-class MimeTypeTests(ParserBase, Test):
-
- EXCLUDE = (WSPACE, EOF)
-
- def do_lex(self, st):
- return lex(st)
-
- def do_parse(self, st):
- return parse(st)
-
- def valid(self, addr, type=None, subtype=None, parameters=None):
- ParserBase.valid(self, addr, (type, subtype, parameters))
-
- def testTypeOnly(self):
- self.invalid("type", "expecting SLASH, got EOF line:1,4:type")
-
- def testTypeSubtype(self):
- self.valid("type/subtype", "type", "subtype", [])
-
- def testTypeSubtypeParam(self):
- self.valid("type/subtype ; name=value",
- "type", "subtype", [("name", "value")])
-
- def testTypeSubtypeParamComment(self):
- self.valid("type/subtype ; name(This is a comment.)=value",
- "type", "subtype", [("name", "value")])
-
- def testMultipleParams(self):
- self.valid("type/subtype ; name1=value1 ; name2=value2",
- "type", "subtype", [("name1", "value1"), ("name2", "value2")])
-
- def testCaseInsensitivity(self):
- self.valid("Type/Subtype", "type", "subtype", [])
diff --git a/qpid/python/qpid/tests/parser.py b/qpid/python/qpid/tests/parser.py
deleted file mode 100644
index a4865cc9fe..0000000000
--- a/qpid/python/qpid/tests/parser.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# 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.
-#
-
-from qpid.parser import ParseError
-
-class ParserBase:
-
- def lex(self, addr, *types):
- toks = [t.type for t in self.do_lex(addr) if t.type not in self.EXCLUDE]
- assert list(types) == toks, "expected %s, got %s" % (types, toks)
-
- def valid(self, addr, expected):
- got = self.do_parse(addr)
- assert expected == got, "expected %s, got %s" % (expected, got)
-
- def invalid(self, addr, error=None):
- try:
- p = self.do_parse(addr)
- assert False, "invalid address parsed: %s" % p
- except ParseError, e:
- assert error == str(e), "expected %r, got %r" % (error, str(e))
diff --git a/qpid/python/qpid/tests/queue.py b/qpid/python/qpid/tests/queue.py
deleted file mode 100644
index e12354eb43..0000000000
--- a/qpid/python/qpid/tests/queue.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# Do not delete - marks this directory as a python package.
-
-#
-# 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 threading, time
-from unittest import TestCase
-from qpid.queue import Queue, Empty, Closed
-
-
-class QueueTest (TestCase):
-
- # The qpid queue class just provides sime simple extensions to
- # python's standard queue data structure, so we don't need to test
- # all the queue functionality.
-
- def test_listen(self):
- values = []
- heard = threading.Event()
- def listener(x):
- values.append(x)
- heard.set()
-
- q = Queue(0)
- q.listen(listener)
- heard.clear()
- q.put(1)
- heard.wait()
- assert values[-1] == 1
- heard.clear()
- q.put(2)
- heard.wait()
- assert values[-1] == 2
-
- q.listen(None)
- q.put(3)
- assert q.get(3) == 3
- q.listen(listener)
-
- heard.clear()
- q.put(4)
- heard.wait()
- assert values[-1] == 4
-
- def test_close(self):
- q = Queue(0)
- q.put(1); q.put(2); q.put(3); q.close()
- assert q.get() == 1
- assert q.get() == 2
- assert q.get() == 3
- for i in range(10):
- try:
- q.get()
- raise AssertionError("expected Closed")
- except Closed:
- pass
diff --git a/qpid/python/qpid/tests/saslmech/__init__.py b/qpid/python/qpid/tests/saslmech/__init__.py
deleted file mode 100644
index d8a500d9d8..0000000000
--- a/qpid/python/qpid/tests/saslmech/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# 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.
-#
-
diff --git a/qpid/python/qpid/tests/saslmech/finder.py b/qpid/python/qpid/tests/saslmech/finder.py
deleted file mode 100644
index 3ad5e727ba..0000000000
--- a/qpid/python/qpid/tests/saslmech/finder.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-# 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.
-#
-
-from unittest import TestCase
-from qpid.saslmech.finder import get_sasl_mechanism
-from my_sasl import MY_SASL
-from my_sasl2 import MY_SASL2
-
-class SaslFinderTests (TestCase):
- """Tests the ability to chose the a sasl mechanism from those available to be loaded"""
-
- def test_known_mechansim(self):
-
- supportedMechs = ["MY-SASL"]
-
- mech = get_sasl_mechanism(supportedMechs, "myuser", "mypass", namespace="qpid.tests.saslmech")
-
- self.assertTrue(isinstance(mech, MY_SASL), "Mechanism %s is of unexpected type" % mech)
- self.assertEquals("MY-SASL", mech.mechanismName())
- self.assertTrue(mech.sasl_options is None)
-
- def test_unknown_mechansim(self):
-
- supportedMechs = ["not_a_mech"]
-
- mech = get_sasl_mechanism(supportedMechs, "myuser", "mypass", namespace="qpid.tests.saslmech")
-
- self.assertTrue(mech == None, "Mechanism instance should be none")
-
- def test_sasl_mechanism_with_higher_priority_prefered(self):
-
- supportedMechs = ["MY-SASL", "MY-SASL2"]
-
- mech = get_sasl_mechanism(supportedMechs, "myuser", "mypass", namespace="qpid.tests.saslmech")
-
- self.assertTrue(isinstance(mech, MY_SASL), "Mechanism %s is of unexpected type" % mech)
-
- def test_sasl_mechanism_fallback_without_credentials(self):
-
- # MY-SASL requires username/password, MY-SASL2 does not
- supportedMechs = ["MY-SASL", "MY-SASL2"]
-
- mech = get_sasl_mechanism(supportedMechs, None, None, namespace="qpid.tests.saslmech")
-
- self.assertTrue(isinstance(mech, MY_SASL2), "Mechanism %s is of unexpected type" % mech)
-
- def test_sasl_mechansim_options(self):
-
- supportedMechs = ["MY-SASL"]
-
- sasl_options = {'hello': 'world'}
- mech = get_sasl_mechanism(supportedMechs, "myuser", "mypass", namespace="qpid.tests.saslmech", sasl_options=sasl_options)
-
- self.assertTrue(isinstance(mech, MY_SASL), "Mechanism %s is of unexpected type" % mech)
- self.assertEquals(sasl_options, mech.sasl_options)
diff --git a/qpid/python/qpid/tests/saslmech/my_sasl.py b/qpid/python/qpid/tests/saslmech/my_sasl.py
deleted file mode 100644
index c15fe4451c..0000000000
--- a/qpid/python/qpid/tests/saslmech/my_sasl.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# 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.
-#
-
-from qpid.saslmech.sasl import Sasl
-
-class MY_SASL(Sasl): pass
diff --git a/qpid/python/qpid/tests/saslmech/my_sasl2.py b/qpid/python/qpid/tests/saslmech/my_sasl2.py
deleted file mode 100644
index e0b3dfa56f..0000000000
--- a/qpid/python/qpid/tests/saslmech/my_sasl2.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# 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.
-#
-
-from qpid.saslmech.sasl import Sasl
-
-class MY_SASL2(Sasl):
-
- def priority(self):
- return 0
-
- def prerequisitesOk(self):
- return True
diff --git a/qpid/python/qpid/tests/spec010.py b/qpid/python/qpid/tests/spec010.py
deleted file mode 100644
index ac04e1ee02..0000000000
--- a/qpid/python/qpid/tests/spec010.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#
-# 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 os, tempfile, shutil, stat
-from unittest import TestCase
-from qpid.codec010 import Codec, StringCodec
-from qpid.ops import *
-
-class SpecTest(TestCase):
-
- def testSessionHeader(self):
- sc = StringCodec()
- sc.write_compound(Header(sync=True))
- assert sc.encoded == "\x01\x01"
-
- sc = StringCodec()
- sc.write_compound(Header(sync=False))
- assert sc.encoded == "\x01\x00"
-
- def encdec(self, value):
- sc = StringCodec()
- sc.write_compound(value)
- decoded = sc.read_compound(value.__class__)
- return decoded
-
- def testMessageProperties(self):
- props = MessageProperties(content_length=3735928559L,
- reply_to=ReplyTo(exchange="the exchange name",
- routing_key="the routing key"))
- dec = self.encdec(props)
- assert props.content_length == dec.content_length
- assert props.reply_to.exchange == dec.reply_to.exchange
- assert props.reply_to.routing_key == dec.reply_to.routing_key
-
- def testMessageSubscribe(self):
- cmd = MessageSubscribe(exclusive=True, destination="this is a test")
- dec = self.encdec(cmd)
- assert cmd.exclusive == dec.exclusive
- assert cmd.destination == dec.destination
-
- def testXid(self):
- sc = StringCodec()
- xid = Xid(format=0, global_id="gid", branch_id="bid")
- sc.write_compound(xid)
- assert sc.encoded == '\x00\x00\x00\x10\x06\x04\x07\x00\x00\x00\x00\x00\x03gid\x03bid'
- dec = sc.read_compound(Xid)
- assert xid.__dict__ == dec.__dict__
-
-# def testLoadReadOnly(self):
-# spec = "amqp.0-10-qpid-errata.xml"
-# f = testrunner.get_spec_file(spec)
-# dest = tempfile.mkdtemp()
-# shutil.copy(f, dest)
-# shutil.copy(os.path.join(os.path.dirname(f), "amqp.0-10.dtd"), dest)
-# os.chmod(dest, stat.S_IRUSR | stat.S_IXUSR)
-# fname = os.path.join(dest, spec)
-# load(fname)
-# assert not os.path.exists("%s.pcl" % fname)
diff --git a/qpid/python/qpid/tests/util.py b/qpid/python/qpid/tests/util.py
deleted file mode 100644
index 4e901218c2..0000000000
--- a/qpid/python/qpid/tests/util.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# 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.
-#
-from unittest import TestCase
-from qpid.util import get_client_properties_with_defaults
-
-class UtilTest (TestCase):
-
- def test_default_client_properties_08091(self):
- client_properties = get_client_properties_with_defaults(version_property_key="version")
- self.assertTrue("product" in client_properties)
- self.assertTrue("version" in client_properties)
- self.assertTrue("platform" in client_properties)
-
- def test_default_client_properties_010(self):
- client_properties = get_client_properties_with_defaults(version_property_key="qpid.client_version")
- self.assertTrue("product" in client_properties)
- self.assertTrue("qpid.client_version" in client_properties)
- self.assertTrue("platform" in client_properties)
-
- def test_client_properties_with_provided_value(self):
- client_properties = get_client_properties_with_defaults(provided_client_properties={"mykey":"myvalue"})
- self.assertTrue("product" in client_properties)
- self.assertTrue("mykey" in client_properties)
- self.assertEqual("myvalue", client_properties["mykey"])
-
- def test_client_properties_with_provided_value_that_overrides_default(self):
- client_properties = get_client_properties_with_defaults(provided_client_properties={"product":"myproduct"})
- self.assertEqual("myproduct", client_properties["product"])
-
- def test_client_properties_with_no_provided_values(self):
- client_properties = get_client_properties_with_defaults(provided_client_properties=None)
- self.assertTrue("product" in client_properties)
-
- client_properties = get_client_properties_with_defaults()
- self.assertTrue("product" in client_properties)
-
diff --git a/qpid/python/qpid/util.py b/qpid/python/qpid/util.py
deleted file mode 100644
index b17f13e6e6..0000000000
--- a/qpid/python/qpid/util.py
+++ /dev/null
@@ -1,208 +0,0 @@
-#
-# 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 os, socket, time, textwrap, re, sys
-
-try:
- from ssl import wrap_socket as ssl
-except ImportError:
- from socket import ssl as wrap_socket
- class ssl:
- def __init__(self, sock, keyfile=None, certfile=None, trustfile=None):
- # Bug (QPID-4337): this is the "old" version of python SSL.
- # The private key is required. If a certificate is given, but no
- # keyfile, assume the key is contained in the certificate
- if certfile and not keyfile:
- keyfile = certfile
- self.sock = sock
- self.ssl = wrap_socket(sock, keyfile=keyfile, certfile=certfile)
-
- def recv(self, n):
- return self.ssl.read(n)
-
- def send(self, s):
- return self.ssl.write(s)
-
- def close(self):
- self.sock.close()
-
-def get_client_properties_with_defaults(provided_client_properties={}, version_property_key="qpid.client_version"):
- ppid = 0
- version = "unidentified"
- try:
- ppid = os.getppid()
- except:
- pass
-
- try:
- import pkg_resources
- pkg = pkg_resources.require("qpid-python")
- if pkg and pkg[0] and pkg[0].version:
- version = pkg[0].version
- except:
- pass
-
- client_properties = {"product": "qpid python client",
- version_property_key : version,
- "platform": os.name,
- "qpid.client_process": os.path.basename(sys.argv and sys.argv[0] or ''),
- "qpid.client_pid": os.getpid(),
- "qpid.client_ppid": ppid}
-
- if provided_client_properties:
- client_properties.update(provided_client_properties)
- return client_properties
-
-def connect(host, port):
- for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
- af, socktype, proto, canonname, sa = res
- sock = socket.socket(af, socktype, proto)
- try:
- sock.connect(sa)
- break
- except socket.error, msg:
- sock.close()
- else:
- # If we got here then we couldn't connect (yet)
- raise
- return sock
-
-def listen(host, port, predicate = lambda: True, bound = lambda: None):
- sock = socket.socket()
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- sock.bind((host, port))
- sock.listen(5)
- bound()
- while predicate():
- s, a = sock.accept()
- yield s
-
-def mtime(filename):
- return os.stat(filename).st_mtime
-
-def wait(condition, predicate, timeout=None):
- condition.acquire()
- try:
- passed = 0
- start = time.time()
- while not predicate():
- if timeout is None:
- # using the timed wait prevents keyboard interrupts from being
- # blocked while waiting
- condition.wait(3)
- elif passed < timeout:
- condition.wait(timeout - passed)
- else:
- return False
- passed = time.time() - start
- return True
- finally:
- condition.release()
-
-def notify(condition, action=lambda: None):
- condition.acquire()
- try:
- action()
- condition.notifyAll()
- finally:
- condition.release()
-
-def fill(text, indent, heading = None):
- sub = indent * " "
- if heading:
- if not text:
- return (indent - 2) * " " + heading
- init = (indent - 2) * " " + heading + " -- "
- else:
- init = sub
- w = textwrap.TextWrapper(initial_indent = init, subsequent_indent = sub)
- return w.fill(" ".join(text.split()))
-
-class URL:
-
- RE = re.compile(r"""
- # [ <scheme>:// ] [ <user> [ / <password> ] @] ( <host4> | \[ <host6> \] ) [ :<port> ]
- ^ (?: ([^:/@]+)://)? (?: ([^:/@]+) (?: / ([^:/@]+) )? @)? (?: ([^@:/\[]+) | \[ ([a-f0-9:.]+) \] ) (?: :([0-9]+))?$
-""", re.X | re.I)
-
- AMQPS = "amqps"
- AMQP = "amqp"
-
- def __init__(self, s=None, **kwargs):
- if s is None:
- self.scheme = kwargs.get('scheme', None)
- self.user = kwargs.get('user', None)
- self.password = kwargs.get('password', None)
- self.host = kwargs.get('host', None)
- self.port = kwargs.get('port', None)
- if self.host is None:
- raise ValueError('Host required for url')
- elif isinstance(s, URL):
- self.scheme = s.scheme
- self.user = s.user
- self.password = s.password
- self.host = s.host
- self.port = s.port
- else:
- match = URL.RE.match(s)
- if match is None:
- raise ValueError(s)
- self.scheme, self.user, self.password, host4, host6, port = match.groups()
- self.host = host4 or host6
- if port is None:
- self.port = None
- else:
- self.port = int(port)
-
- def __repr__(self):
- return "URL(%r)" % str(self)
-
- def __str__(self):
- s = ""
- if self.scheme:
- s += "%s://" % self.scheme
- if self.user:
- s += self.user
- if self.password:
- s += "/%s" % self.password
- s += "@"
- if ':' not in self.host:
- s += self.host
- else:
- s += "[%s]" % self.host
- if self.port:
- s += ":%s" % self.port
- return s
-
- def __eq__(self, url):
- if isinstance(url, basestring):
- url = URL(url)
- return \
- self.scheme==url.scheme and \
- self.user==url.user and self.password==url.password and \
- self.host==url.host and self.port==url.port
-
- def __ne__(self, url):
- return not self.__eq__(url)
-
-def default(value, default):
- if value is None:
- return default
- else:
- return value
diff --git a/qpid/python/qpid/validator.py b/qpid/python/qpid/validator.py
deleted file mode 100644
index d234642b3e..0000000000
--- a/qpid/python/qpid/validator.py
+++ /dev/null
@@ -1,107 +0,0 @@
-#
-# 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.
-#
-
-class Context:
-
- def __init__(self):
- self.containers = []
-
- def push(self, o):
- self.containers.append(o)
-
- def pop(self):
- return self.containers.pop()
-
-class Values:
-
- def __init__(self, *values):
- self.values = values
-
- def validate(self, o, ctx):
- if not o in self.values:
- return "%s not in %s" % (o, self.values)
-
- def __str__(self):
- return self.value
-
-class Types:
-
- def __init__(self, *types):
- self.types = types
-
- def validate(self, o, ctx):
- for t in self.types:
- if isinstance(o, t):
- return
- if len(self.types) == 1:
- return "%s is not a %s" % (o, self.types[0].__name__)
- else:
- return "%s is not one of: %s" % (o, ", ".join([t.__name__ for t in self.types]))
-
-class List:
-
- def __init__(self, condition):
- self.condition = condition
-
- def validate(self, o, ctx):
- if not isinstance(o, list):
- return "%s is not a list" % o
-
- ctx.push(o)
- for v in o:
- err = self.condition.validate(v, ctx)
- if err: return err
-
-class Map:
-
- def __init__(self, map, restricted=True):
- self.map = map
- self.restricted = restricted
-
- def validate(self, o, ctx):
- errors = []
-
- if not hasattr(o, "get"):
- return "%s is not a map" % o
-
- ctx.push(o)
- for k, t in self.map.items():
- v = o.get(k)
- if v is not None:
- err = t.validate(v, ctx)
- if err: errors.append("%s: %s" % (k, err))
- if self.restricted:
- for k in o:
- if not k in self.map:
- errors.append("%s: illegal key" % k)
- ctx.pop()
-
- if errors:
- return ", ".join(errors)
-
-class And:
-
- def __init__(self, *conditions):
- self.conditions = conditions
-
- def validate(self, o, ctx):
- for c in self.conditions:
- err = c.validate(o, ctx)
- if err:
- return err
diff --git a/qpid/python/qpid_tests/__init__.py b/qpid/python/qpid_tests/__init__.py
deleted file mode 100644
index 0459ace65c..0000000000
--- a/qpid/python/qpid_tests/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Do not delete - marks this directory as a python package.
-
-#
-# 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 broker_1_0, broker_0_10, broker_0_9, broker_0_8
diff --git a/qpid/python/qpid_tests/broker_0_10/__init__.py b/qpid/python/qpid_tests/broker_0_10/__init__.py
deleted file mode 100644
index 312dc22645..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/__init__.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Do not delete - marks this directory as a python package.
-
-#
-# 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.
-#
-
-from alternate_exchange import *
-from broker import *
-from dtx import *
-from example import *
-from exchange import *
-from management import *
-from message import *
-from query import *
-from queue import *
-from tx import *
-from lvq import *
-from priority import *
-from threshold import *
-from extensions import *
-from msg_groups import *
-from new_api import *
-from stats import *
-from qmf_events import *
diff --git a/qpid/python/qpid_tests/broker_0_10/alternate_exchange.py b/qpid/python/qpid_tests/broker_0_10/alternate_exchange.py
deleted file mode 100644
index 2e2d5de13a..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/alternate_exchange.py
+++ /dev/null
@@ -1,351 +0,0 @@
-#
-# 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 traceback
-from qpid.queue import Empty
-from qpid.datatypes import Message, RangedSet
-from qpid.testlib import TestBase010
-from qpid.session import SessionException
-
-class AlternateExchangeTests(TestBase010):
- """
- Tests for the new mechanism for message returns introduced in 0-10
- and available in 0-9 for preview
- """
-
- def test_unroutable(self):
- """
- Test that unroutable messages are delivered to the alternate-exchange if specified
- """
- session = self.session
- #create an exchange with an alternate defined
- session.exchange_declare(exchange="secondary", type="fanout")
- session.exchange_declare(exchange="primary", type="direct", alternate_exchange="secondary")
-
- #declare, bind (to the alternate exchange) and consume from a queue for 'returned' messages
- session.queue_declare(queue="returns", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="returns", exchange="secondary")
- session.message_subscribe(destination="a", queue="returns")
- session.message_flow(destination="a", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="a", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- returned = session.incoming("a")
-
- #declare, bind (to the primary exchange) and consume from a queue for 'processed' messages
- session.queue_declare(queue="processed", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="processed", exchange="primary", binding_key="my-key")
- session.message_subscribe(destination="b", queue="processed")
- session.message_flow(destination="b", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="b", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- processed = session.incoming("b")
-
- #publish to the primary exchange
- #...one message that makes it to the 'processed' queue:
- dp=self.session.delivery_properties(routing_key="my-key")
- session.message_transfer(destination="primary", message=Message(dp, "Good"))
- #...and one that does not:
- dp=self.session.delivery_properties(routing_key="unused-key")
- session.message_transfer(destination="primary", message=Message(dp, "Bad"))
-
- #delete the exchanges
- session.exchange_delete(exchange="primary")
- session.exchange_delete(exchange="secondary")
-
- #verify behaviour
- self.assertEqual("Good", processed.get(timeout=1).body)
- self.assertEqual("Bad", returned.get(timeout=1).body)
- self.assertEmpty(processed)
- self.assertEmpty(returned)
-
- def test_queue_delete(self):
- """
- Test that messages in a queue being deleted are delivered to the alternate-exchange if specified
- """
- session = self.session
- #set up a 'dead letter queue':
- dlq = self.setup_dlq()
-
- #create a queue using the dlq as its alternate exchange:
- session.queue_declare(queue="delete-me", alternate_exchange="dlq")
- #send it some messages:
- dp=self.session.delivery_properties(routing_key="delete-me")
- session.message_transfer(message=Message(dp, "One"))
- session.message_transfer(message=Message(dp, "Two"))
- session.message_transfer(message=Message(dp, "Three"))
- #delete it:
- session.queue_delete(queue="delete-me")
- #delete the dlq exchange:
- session.exchange_delete(exchange="dlq")
-
- #check the messages were delivered to the dlq:
- self.assertEqual("One", dlq.get(timeout=1).body)
- self.assertEqual("Two", dlq.get(timeout=1).body)
- self.assertEqual("Three", dlq.get(timeout=1).body)
- self.assertEmpty(dlq)
-
- def test_delete_while_used_by_queue(self):
- """
- Ensure an exchange still in use as an alternate-exchange for a
- queue can't be deleted
- """
- session = self.session
- session.exchange_declare(exchange="alternate", type="fanout")
-
- session2 = self.conn.session("alternate", 2)
- session2.queue_declare(queue="q", alternate_exchange="alternate")
- try:
- session2.exchange_delete(exchange="alternate")
- self.fail("Expected deletion of in-use alternate-exchange to fail")
- except SessionException, e:
- session = self.session
- session.queue_delete(queue="q")
- session.exchange_delete(exchange="alternate")
- self.assertEquals(530, e.args[0].error_code)
-
-
- def test_delete_while_used_by_exchange(self):
- """
- Ensure an exchange still in use as an alternate-exchange for
- another exchange can't be deleted
- """
- session = self.session
- session.exchange_declare(exchange="alternate", type="fanout")
-
- session = self.conn.session("alternate", 2)
- session.exchange_declare(exchange="e", type="fanout", alternate_exchange="alternate")
- try:
- session.exchange_delete(exchange="alternate")
- self.fail("Expected deletion of in-use alternate-exchange to fail")
- except SessionException, e:
- session = self.session
- session.exchange_delete(exchange="e")
- session.exchange_delete(exchange="alternate")
- self.assertEquals(530, e.args[0].error_code)
-
-
- def test_modify_existing_exchange_alternate(self):
- """
- Ensure that attempting to modify an exhange to change
- the alternate throws an exception
- """
- session = self.session
- session.exchange_declare(exchange="alt1", type="direct")
- session.exchange_declare(exchange="alt2", type="direct")
- session.exchange_declare(exchange="onealternate", type="fanout", alternate_exchange="alt1")
- try:
- # attempt to change the alternate on an already existing exchange
- session.exchange_declare(exchange="onealternate", type="fanout", alternate_exchange="alt2")
- self.fail("Expected changing an alternate on an existing exchange to fail")
- except SessionException, e:
- self.assertEquals(530, e.args[0].error_code)
- session = self.conn.session("alternate", 2)
- session.exchange_delete(exchange="onealternate")
- session.exchange_delete(exchange="alt2")
- session.exchange_delete(exchange="alt1")
-
-
- def test_add_alternate_to_exchange(self):
- """
- Ensure that attempting to modify an exhange by adding
- an alternate throws an exception
- """
- session = self.session
- session.exchange_declare(exchange="alt1", type="direct")
- session.exchange_declare(exchange="noalternate", type="fanout")
- try:
- # attempt to add an alternate on an already existing exchange
- session.exchange_declare(exchange="noalternate", type="fanout", alternate_exchange="alt1")
- self.fail("Expected adding an alternate on an existing exchange to fail")
- except SessionException, e:
- self.assertEquals(530, e.args[0].error_code)
- session = self.conn.session("alternate", 2)
- session.exchange_delete(exchange="noalternate")
- session.exchange_delete(exchange="alt1")
-
-
- def test_del_alternate_to_exchange(self):
- """
- Ensure that attempting to modify an exhange by declaring
- it again without an alternate does nothing
- """
- session = self.session
- session.exchange_declare(exchange="alt1", type="direct")
- session.exchange_declare(exchange="onealternate", type="fanout", alternate_exchange="alt1")
- # attempt to re-declare without an alternate - silently ignore
- session.exchange_declare(exchange="onealternate", type="fanout" )
- session.exchange_delete(exchange="onealternate")
- session.exchange_delete(exchange="alt1")
-
- def test_queue_autodelete(self):
- """
- Test that messages in a queue being auto-deleted are delivered
- to the alternate-exchange if specified, including messages
- that are acquired but not accepted
- """
- session = self.session
- #set up a 'dead letter queue':
- session.exchange_declare(exchange="dlq", type="fanout")
- session.queue_declare(queue="deleted", exclusive=True, auto_delete=True)
- session.exchange_bind(exchange="dlq", queue="deleted")
- session.message_subscribe(destination="dlq", queue="deleted")
- session.message_flow(destination="dlq", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="dlq", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- dlq = session.incoming("dlq")
-
- #on a separate session, create an auto-deleted queue using the
- #dlq as its alternate exchange (handling of auto-delete is
- #different for exclusive and non-exclusive queues, so test
- #both modes):
- for mode in [True, False]:
- session2 = self.conn.session("another-session")
- session2.queue_declare(queue="my-queue", alternate_exchange="dlq", exclusive=mode, auto_delete=True)
- #send it some messages:
- dp=session2.delivery_properties(routing_key="my-queue")
- session2.message_transfer(message=Message(dp, "One"))
- session2.message_transfer(message=Message(dp, "Two"))
- session2.message_transfer(message=Message(dp, "Three"))
- session2.message_subscribe(destination="incoming", queue="my-queue")
- session2.message_flow(destination="incoming", unit=session.credit_unit.message, value=1)
- session2.message_flow(destination="incoming", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- self.assertEqual("One", session2.incoming("incoming").get(timeout=1).body)
- session2.close()
-
- #check the messages were delivered to the dlq:
- self.assertEqual("One", dlq.get(timeout=1).body)
- self.assertEqual("Two", dlq.get(timeout=1).body)
- self.assertEqual("Three", dlq.get(timeout=1).body)
- self.assertEmpty(dlq)
-
- def test_queue_delete_loop(self):
- """
- Test that if a queue is bound to its own alternate exchange,
- then on deletion there is no infinite looping
- """
- session = self.session
- dlq = self.setup_dlq()
-
- #create a queue using the dlq as its alternate exchange:
- session.queue_declare(queue="delete-me", alternate_exchange="dlq")
- #bind that queue to the dlq as well:
- session.exchange_bind(exchange="dlq", queue="delete-me")
- #send it some messages:
- dp=self.session.delivery_properties(routing_key="delete-me")
- for m in ["One", "Two", "Three"]:
- session.message_transfer(message=Message(dp, m))
- #delete it:
- session.queue_delete(queue="delete-me")
- #cleanup:
- session.exchange_delete(exchange="dlq")
-
- #check the messages were delivered to the dlq:
- for m in ["One", "Two", "Three"]:
- self.assertEqual(m, dlq.get(timeout=1).body)
- self.assertEmpty(dlq)
-
- def test_queue_delete_no_match(self):
- """
- Test that on queue deletion, if the queues own alternate
- exchange cannot find a match for the message, the
- alternate-exchange of that exchange will be tried. Note:
- though the spec rules out going to the alternate-exchanges
- alternate exchange when sending to an exchange, it does not
- cover this case.
- """
- session = self.session
- dlq = self.setup_dlq()
-
- #setu up an 'intermediary' exchange
- session.exchange_declare(exchange="my-exchange", type="direct", alternate_exchange="dlq")
-
- #create a queue using the intermediary as its alternate exchange:
- session.queue_declare(queue="delete-me", alternate_exchange="my-exchange")
- #bind that queue to the dlq as well:
- session.exchange_bind(exchange="dlq", queue="delete-me")
- #send it some messages:
- dp=self.session.delivery_properties(routing_key="delete-me")
- for m in ["One", "Two", "Three"]:
- session.message_transfer(message=Message(dp, m))
-
- #delete it:
- session.queue_delete(queue="delete-me")
- #cleanup:
- session.exchange_delete(exchange="my-exchange")
- session.exchange_delete(exchange="dlq")
-
- #check the messages were delivered to the dlq:
- for m in ["One", "Two", "Three"]:
- self.assertEqual(m, dlq.get(timeout=1).body)
- self.assertEmpty(dlq)
-
- def test_reject_no_match(self):
- """
- Test that on rejecting a message, if the queues own alternate
- exchange cannot find a match for the message, the
- alternate-exchange of that exchange will be tried. Note:
- though the spec rules out going to the alternate-exchanges
- alternate exchange when sending to an exchange, it does not
- cover this case.
- """
- session = self.session
- dlq = self.setup_dlq()
-
- #setu up an 'intermediary' exchange
- session.exchange_declare(exchange="my-exchange", type="direct", alternate_exchange="dlq")
-
- #create a queue using the intermediary as its alternate exchange:
- session.queue_declare(queue="delivery-queue", alternate_exchange="my-exchange", auto_delete=True)
- #send it some messages:
- dp=self.session.delivery_properties(routing_key="delivery-queue")
- for m in ["One", "Two", "Three"]:
- session.message_transfer(message=Message(dp, m))
-
- #get and reject those messages:
- session.message_subscribe(destination="a", queue="delivery-queue")
- session.message_flow(destination="a", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="a", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- incoming = session.incoming("a")
- for m in ["One", "Two", "Three"]:
- msg = incoming.get(timeout=1)
- self.assertEqual(m, msg.body)
- session.message_reject(RangedSet(msg.id))
- session.message_cancel(destination="a")
-
- #check the messages were delivered to the dlq:
- for m in ["One", "Two", "Three"]:
- self.assertEqual(m, dlq.get(timeout=1).body)
- self.assertEmpty(dlq)
- #cleanup:
- session.exchange_delete(exchange="my-exchange")
- session.exchange_delete(exchange="dlq")
-
- def setup_dlq(self):
- session = self.session
- #set up 'dead-letter' handling:
- session.exchange_declare(exchange="dlq", type="fanout")
- session.queue_declare(queue="deleted", exclusive=True, auto_delete=True)
- session.exchange_bind(exchange="dlq", queue="deleted")
- session.message_subscribe(destination="dlq", queue="deleted")
- session.message_flow(destination="dlq", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="dlq", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- dlq = session.incoming("dlq")
- return dlq
-
- def assertEmpty(self, queue):
- try:
- msg = queue.get(timeout=1)
- self.fail("Queue not empty: " + str(msg))
- except Empty: None
diff --git a/qpid/python/qpid_tests/broker_0_10/broker.py b/qpid/python/qpid_tests/broker_0_10/broker.py
deleted file mode 100644
index 81d723e322..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/broker.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#
-# 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.
-#
-from qpid.client import Closed
-from qpid.queue import Empty
-from qpid.testlib import TestBase010
-from qpid.datatypes import Message, RangedSet
-
-class BrokerTests(TestBase010):
- """Tests for basic Broker functionality"""
-
- def test_ack_and_no_ack(self):
- """
- First, this test tries to receive a message with a no-ack
- consumer. Second, this test tries to explicitly receive and
- acknowledge a message with an acknowledging consumer.
- """
- session = self.session
- session.queue_declare(queue = "myqueue", exclusive=True, auto_delete=True)
-
- # No ack consumer
- ctag = "tag1"
- session.message_subscribe(queue = "myqueue", destination = ctag)
- session.message_flow(destination=ctag, unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination=ctag, unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- body = "test no-ack"
- session.message_transfer(message=Message(session.delivery_properties(routing_key="myqueue"), body))
- msg = session.incoming(ctag).get(timeout = 5)
- self.assert_(msg.body == body)
-
- # Acknowledging consumer
- session.queue_declare(queue = "otherqueue", exclusive=True, auto_delete=True)
- ctag = "tag2"
- session.message_subscribe(queue = "otherqueue", destination = ctag, accept_mode = 1)
- session.message_flow(destination=ctag, unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination=ctag, unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- body = "test ack"
- session.message_transfer(message=Message(session.delivery_properties(routing_key="otherqueue"), body))
- msg = session.incoming(ctag).get(timeout = 5)
- session.message_accept(RangedSet(msg.id))
- self.assert_(msg.body == body)
-
- def test_simple_delivery_immediate(self):
- """
- Test simple message delivery where consume is issued before publish
- """
- session = self.session
- session.queue_declare(queue="test-queue", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="test-queue", exchange="amq.fanout")
- consumer_tag = "tag1"
- session.message_subscribe(queue="test-queue", destination=consumer_tag)
- session.message_flow(unit = session.credit_unit.message, value = 0xFFFFFFFFL, destination = consumer_tag)
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = consumer_tag)
- queue = session.incoming(consumer_tag)
-
- body = "Immediate Delivery"
- session.message_transfer("amq.fanout", None, None, Message(body))
- msg = queue.get(timeout=5)
- self.assert_(msg.body == body)
-
- def test_simple_delivery_queued(self):
- """
- Test basic message delivery where publish is issued before consume
- (i.e. requires queueing of the message)
- """
- session = self.session
- session.queue_declare(queue="test-queue", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="test-queue", exchange="amq.fanout")
- body = "Queued Delivery"
- session.message_transfer("amq.fanout", None, None, Message(body))
-
- consumer_tag = "tag1"
- session.message_subscribe(queue="test-queue", destination=consumer_tag)
- session.message_flow(unit = session.credit_unit.message, value = 0xFFFFFFFFL, destination = consumer_tag)
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = consumer_tag)
- queue = session.incoming(consumer_tag)
- msg = queue.get(timeout=5)
- self.assert_(msg.body == body)
diff --git a/qpid/python/qpid_tests/broker_0_10/dtx.py b/qpid/python/qpid_tests/broker_0_10/dtx.py
deleted file mode 100644
index a9619bcdb8..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/dtx.py
+++ /dev/null
@@ -1,790 +0,0 @@
-#
-# 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.
-#
-from qpid.client import Client, Closed
-from qpid.queue import Empty
-from qpid.datatypes import Message, RangedSet
-from qpid.session import SessionException
-from qpid.testlib import TestBase010
-from qpid.compat import set
-from struct import pack, unpack
-from time import sleep
-
-class DtxTests(TestBase010):
- """
- Tests for the amqp dtx related classes.
-
- Tests of the form test_simple_xxx test the basic transactional
- behaviour. The approach here is to 'swap' a message from one queue
- to another by consuming and re-publishing in the same
- transaction. That transaction is then completed in different ways
- and the appropriate result verified.
-
- The other tests enforce more specific rules and behaviour on a
- per-method or per-field basis.
- """
-
- XA_RBROLLBACK = 1
- XA_RBTIMEOUT = 2
- XA_OK = 0
- tx_counter = 0
-
- def reset_channel(self):
- self.session.close()
- self.session = self.conn.session("dtx-session", 1)
-
- def test_simple_commit(self):
- """
- Test basic one-phase commit behaviour.
- """
- guard = self.keepQueuesAlive(["queue-a", "queue-b"])
- session = self.session
- tx = self.xid("my-xid")
- self.txswap(tx, "commit")
-
- #neither queue should have any messages accessible
- self.assertMessageCount(0, "queue-a")
- self.assertMessageCount(0, "queue-b")
-
- #commit
- self.assertEqual(self.XA_OK, session.dtx_commit(xid=tx, one_phase=True).status)
-
- #should close and reopen session to ensure no unacked messages are held
- self.reset_channel()
-
- #check result
- self.assertMessageCount(0, "queue-a")
- self.assertMessageCount(1, "queue-b")
- self.assertMessageId("commit", "queue-b")
-
- def test_simple_prepare_commit(self):
- """
- Test basic two-phase commit behaviour.
- """
- guard = self.keepQueuesAlive(["queue-a", "queue-b"])
- session = self.session
- tx = self.xid("my-xid")
- self.txswap(tx, "prepare-commit")
-
- #prepare
- self.assertEqual(self.XA_OK, session.dtx_prepare(xid=tx).status)
-
- #neither queue should have any messages accessible
- self.assertMessageCount(0, "queue-a")
- self.assertMessageCount(0, "queue-b")
-
- #commit
- self.assertEqual(self.XA_OK, session.dtx_commit(xid=tx, one_phase=False).status)
-
- self.reset_channel()
-
- #check result
- self.assertMessageCount(0, "queue-a")
- self.assertMessageCount(1, "queue-b")
- self.assertMessageId("prepare-commit", "queue-b")
-
-
- def test_simple_rollback(self):
- """
- Test basic rollback behaviour.
- """
- guard = self.keepQueuesAlive(["queue-a", "queue-b"])
- session = self.session
- tx = self.xid("my-xid")
- self.txswap(tx, "rollback")
-
- #neither queue should have any messages accessible
- self.assertMessageCount(0, "queue-a")
- self.assertMessageCount(0, "queue-b")
-
- #rollback
- self.assertEqual(self.XA_OK, session.dtx_rollback(xid=tx).status)
-
- self.reset_channel()
-
- #check result
- self.assertMessageCount(1, "queue-a")
- self.assertMessageCount(0, "queue-b")
- self.assertMessageId("rollback", "queue-a")
-
- def test_simple_prepare_rollback(self):
- """
- Test basic rollback behaviour after the transaction has been prepared.
- """
- guard = self.keepQueuesAlive(["queue-a", "queue-b"])
- session = self.session
- tx = self.xid("my-xid")
- self.txswap(tx, "prepare-rollback")
-
- #prepare
- self.assertEqual(self.XA_OK, session.dtx_prepare(xid=tx).status)
-
- #neither queue should have any messages accessible
- self.assertMessageCount(0, "queue-a")
- self.assertMessageCount(0, "queue-b")
-
- #rollback
- self.assertEqual(self.XA_OK, session.dtx_rollback(xid=tx).status)
-
- self.reset_channel()
-
- #check result
- self.assertMessageCount(1, "queue-a")
- self.assertMessageCount(0, "queue-b")
- self.assertMessageId("prepare-rollback", "queue-a")
-
- def test_select_required(self):
- """
- check that an error is flagged if select is not issued before
- start or end
- """
- session = self.session
- tx = self.xid("dummy")
- try:
- session.dtx_start(xid=tx)
-
- #if we get here we have failed, but need to do some cleanup:
- session.dtx_end(xid=tx)
- session.dtx_rollback(xid=tx)
- self.fail("Session not selected for use with dtx, expected exception!")
- except SessionException, e:
- self.assertEquals(503, e.args[0].error_code)
-
- def test_start_already_known(self):
- """
- Verify that an attempt to start an association with a
- transaction that is already known is not allowed (unless the
- join flag is set).
- """
- #create two sessions on different connection & select them for use with dtx:
- session1 = self.session
- session1.dtx_select()
-
- other = self.connect()
- session2 = other.session("other", 0)
- session2.dtx_select()
-
- #create a xid
- tx = self.xid("dummy")
- #start work on one session under that xid:
- session1.dtx_start(xid=tx)
- #then start on the other without the join set
- failed = False
- try:
- session2.dtx_start(xid=tx)
- except SessionException, e:
- failed = True
- error = e
-
- #cleanup:
- if not failed:
- session2.dtx_end(xid=tx)
- other.close()
- session1.dtx_end(xid=tx)
- session1.dtx_rollback(xid=tx)
-
- #verification:
- if failed: self.assertEquals(530, error.args[0].error_code)
- else: self.fail("Xid already known, expected exception!")
-
- def test_forget_xid_on_completion(self):
- """
- Verify that a xid is 'forgotten' - and can therefore be used
- again - once it is completed.
- """
- #do some transactional work & complete the transaction
- self.test_simple_commit()
- # session has been reset, so reselect for use with dtx
- self.session.dtx_select()
-
- #start association for the same xid as the previously completed txn
- tx = self.xid("my-xid")
- self.session.dtx_start(xid=tx)
- self.session.dtx_end(xid=tx)
- self.session.dtx_rollback(xid=tx)
-
- def test_start_join_and_resume(self):
- """
- Ensure the correct error is signalled when both the join and
- resume flags are set on starting an association between a
- session and a transcation.
- """
- session = self.session
- session.dtx_select()
- tx = self.xid("dummy")
- try:
- session.dtx_start(xid=tx, join=True, resume=True)
- #failed, but need some cleanup:
- session.dtx_end(xid=tx)
- session.dtx_rollback(xid=tx)
- self.fail("Join and resume both set, expected exception!")
- except SessionException, e:
- self.assertEquals(503, e.args[0].error_code)
-
- def test_start_join(self):
- """
- Verify 'join' behaviour, where a session is associated with a
- transaction that is already associated with another session.
- """
- guard = self.keepQueuesAlive(["one", "two"])
- #create two sessions & select them for use with dtx:
- session1 = self.session
- session1.dtx_select()
-
- session2 = self.conn.session("second", 2)
- session2.dtx_select()
-
- #setup
- session1.queue_declare(queue="one", auto_delete=True)
- session1.queue_declare(queue="two", auto_delete=True)
- session1.message_transfer(self.createMessage(session1, "one", "a", "DtxMessage"))
- session1.message_transfer(self.createMessage(session1, "two", "b", "DtxMessage"))
-
- #create a xid
- tx = self.xid("dummy")
- #start work on one session under that xid:
- session1.dtx_start(xid=tx)
- #then start on the other with the join flag set
- session2.dtx_start(xid=tx, join=True)
-
- #do work through each session
- self.swap(session1, "one", "two")#swap 'a' from 'one' to 'two'
- self.swap(session2, "two", "one")#swap 'b' from 'two' to 'one'
-
- #mark end on both sessions
- session1.dtx_end(xid=tx)
- session2.dtx_end(xid=tx)
-
- #commit and check
- session1.dtx_commit(xid=tx, one_phase=True)
- self.assertMessageCount(1, "one")
- self.assertMessageCount(1, "two")
- self.assertMessageId("a", "two")
- self.assertMessageId("b", "one")
-
-
- def test_suspend_resume(self):
- """
- Test suspension and resumption of an association
- """
- session = self.session
- session.dtx_select()
-
- #setup
- session.queue_declare(queue="one", exclusive=True, auto_delete=True)
- session.queue_declare(queue="two", exclusive=True, auto_delete=True)
- session.message_transfer(self.createMessage(session, "one", "a", "DtxMessage"))
- session.message_transfer(self.createMessage(session, "two", "b", "DtxMessage"))
-
- tx = self.xid("dummy")
-
- session.dtx_start(xid=tx)
- self.swap(session, "one", "two")#swap 'a' from 'one' to 'two'
- session.dtx_end(xid=tx, suspend=True)
-
- session.dtx_start(xid=tx, resume=True)
- self.swap(session, "two", "one")#swap 'b' from 'two' to 'one'
- session.dtx_end(xid=tx)
-
- #commit and check
- session.dtx_commit(xid=tx, one_phase=True)
- self.assertMessageCount(1, "one")
- self.assertMessageCount(1, "two")
- self.assertMessageId("a", "two")
- self.assertMessageId("b", "one")
-
- def test_suspend_start_end_resume(self):
- """
- Test suspension and resumption of an association with work
- done on another transaction when the first transaction is
- suspended
- """
- session = self.session
- session.dtx_select()
-
- #setup
- session.queue_declare(queue="one", exclusive=True, auto_delete=True)
- session.queue_declare(queue="two", exclusive=True, auto_delete=True)
- session.message_transfer(self.createMessage(session, "one", "a", "DtxMessage"))
- session.message_transfer(self.createMessage(session, "two", "b", "DtxMessage"))
-
- tx = self.xid("dummy")
-
- session.dtx_start(xid=tx)
- self.swap(session, "one", "two")#swap 'a' from 'one' to 'two'
- session.dtx_end(xid=tx, suspend=True)
-
- session.dtx_start(xid=tx, resume=True)
- self.swap(session, "two", "one")#swap 'b' from 'two' to 'one'
- session.dtx_end(xid=tx)
-
- #commit and check
- session.dtx_commit(xid=tx, one_phase=True)
- self.assertMessageCount(1, "one")
- self.assertMessageCount(1, "two")
- self.assertMessageId("a", "two")
- self.assertMessageId("b", "one")
-
- def test_end_suspend_and_fail(self):
- """
- Verify that the correct error is signalled if the suspend and
- fail flag are both set when disassociating a transaction from
- the session
- """
- session = self.session
- session.dtx_select()
- tx = self.xid("suspend_and_fail")
- session.dtx_start(xid=tx)
- try:
- session.dtx_end(xid=tx, suspend=True, fail=True)
- self.fail("Suspend and fail both set, expected exception!")
- except SessionException, e:
- self.assertEquals(503, e.args[0].error_code)
-
- #cleanup
- other = self.connect()
- session = other.session("cleanup", 1)
- session.dtx_rollback(xid=tx)
- session.close()
- other.close()
-
-
- def test_end_unknown_xid(self):
- """
- Verifies that the correct exception is thrown when an attempt
- is made to end the association for a xid not previously
- associated with the session
- """
- session = self.session
- session.dtx_select()
- tx = self.xid("unknown-xid")
- try:
- session.dtx_end(xid=tx)
- self.fail("Attempted to end association with unknown xid, expected exception!")
- except SessionException, e:
- self.assertEquals(409, e.args[0].error_code)
-
- def test_end(self):
- """
- Verify that the association is terminated by end and subsequent
- operations are non-transactional
- """
- guard = self.keepQueuesAlive(["tx-queue"])
- session = self.conn.session("alternate", 1)
-
- #publish a message under a transaction
- session.dtx_select()
- tx = self.xid("dummy")
- session.dtx_start(xid=tx)
- session.message_transfer(self.createMessage(session, "tx-queue", "one", "DtxMessage"))
- session.dtx_end(xid=tx)
-
- #now that association with txn is ended, publish another message
- session.message_transfer(self.createMessage(session, "tx-queue", "two", "DtxMessage"))
-
- #check the second message is available, but not the first
- self.assertMessageCount(1, "tx-queue")
- self.subscribe(session, queue="tx-queue", destination="results")
- msg = session.incoming("results").get(timeout=1)
- self.assertEqual("two", self.getMessageProperty(msg, 'correlation_id'))
- session.message_cancel(destination="results")
- #ack the message then close the session
- session.message_accept(RangedSet(msg.id))
- session.close()
-
- session = self.session
- #commit the transaction and check that the first message (and
- #only the first message) is then delivered
- session.dtx_commit(xid=tx, one_phase=True)
- self.assertMessageCount(1, "tx-queue")
- self.assertMessageId("one", "tx-queue")
-
- def test_invalid_commit_one_phase_true(self):
- """
- Test that a commit with one_phase = True is rejected if the
- transaction in question has already been prepared.
- """
- other = self.connect()
- tester = other.session("tester", 1)
- tester.queue_declare(queue="dummy", exclusive=True, auto_delete=True)
- tester.dtx_select()
- tx = self.xid("dummy")
- tester.dtx_start(xid=tx)
- tester.message_transfer(self.createMessage(tester, "dummy", "dummy", "whatever"))
- tester.dtx_end(xid=tx)
- tester.dtx_prepare(xid=tx)
- failed = False
- try:
- tester.dtx_commit(xid=tx, one_phase=True)
- except SessionException, e:
- failed = True
- error = e
-
- if failed:
- self.session.dtx_rollback(xid=tx)
- self.assertEquals(409, error.args[0].error_code)
- else:
- tester.close()
- other.close()
- self.fail("Invalid use of one_phase=True, expected exception!")
-
- def test_invalid_commit_one_phase_false(self):
- """
- Test that a commit with one_phase = False is rejected if the
- transaction in question has not yet been prepared.
- """
- other = self.connect()
- tester = other.session("tester", 1)
- tester.queue_declare(queue="dummy", exclusive=True, auto_delete=True)
- tester.dtx_select()
- tx = self.xid("dummy")
- tester.dtx_start(xid=tx)
- tester.message_transfer(self.createMessage(tester, "dummy", "dummy", "whatever"))
- tester.dtx_end(xid=tx)
- failed = False
- try:
- tester.dtx_commit(xid=tx, one_phase=False)
- except SessionException, e:
- failed = True
- error = e
-
- if failed:
- self.session.dtx_rollback(xid=tx)
- self.assertEquals(409, error.args[0].error_code)
- else:
- tester.close()
- other.close()
- self.fail("Invalid use of one_phase=False, expected exception!")
-
- def test_invalid_commit_not_ended(self):
- """
- Test that a commit fails if the xid is still associated with a session.
- """
- other = self.connect()
- tester = other.session("tester", 1)
- self.session.queue_declare(queue="dummy", exclusive=True, auto_delete=True)
- self.session.dtx_select()
- tx = self.xid("dummy")
- self.session.dtx_start(xid=tx)
- self.session.message_transfer(self.createMessage(tester, "dummy", "dummy", "whatever"))
-
- failed = False
- try:
- tester.dtx_commit(xid=tx, one_phase=False)
- except SessionException, e:
- failed = True
- error = e
-
- if failed:
- self.session.dtx_end(xid=tx)
- self.session.dtx_rollback(xid=tx)
- self.assertEquals(409, error.args[0].error_code)
- else:
- tester.close()
- other.close()
- self.fail("Commit should fail as xid is still associated!")
-
- def test_invalid_rollback_not_ended(self):
- """
- Test that a rollback fails if the xid is still associated with a session.
- """
- other = self.connect()
- tester = other.session("tester", 1)
- self.session.queue_declare(queue="dummy", exclusive=True, auto_delete=True)
- self.session.dtx_select()
- tx = self.xid("dummy")
- self.session.dtx_start(xid=tx)
- self.session.message_transfer(self.createMessage(tester, "dummy", "dummy", "whatever"))
-
- failed = False
- try:
- tester.dtx_rollback(xid=tx)
- except SessionException, e:
- failed = True
- error = e
-
- if failed:
- self.session.dtx_end(xid=tx)
- self.session.dtx_rollback(xid=tx)
- self.assertEquals(409, error.args[0].error_code)
- else:
- tester.close()
- other.close()
- self.fail("Rollback should fail as xid is still associated!")
-
-
- def test_invalid_prepare_not_ended(self):
- """
- Test that a prepare fails if the xid is still associated with a session.
- """
- other = self.connect()
- tester = other.session("tester", 1)
- self.session.queue_declare(queue="dummy", exclusive=True, auto_delete=True)
- self.session.dtx_select()
- tx = self.xid("dummy")
- self.session.dtx_start(xid=tx)
- self.session.message_transfer(self.createMessage(tester, "dummy", "dummy", "whatever"))
-
- failed = False
- try:
- tester.dtx_prepare(xid=tx)
- except SessionException, e:
- failed = True
- error = e
-
- if failed:
- self.session.dtx_end(xid=tx)
- self.session.dtx_rollback(xid=tx)
- self.assertEquals(409, error.args[0].error_code)
- else:
- tester.close()
- other.close()
- self.fail("Rollback should fail as xid is still associated!")
-
- def test_implicit_end(self):
- """
- Test that an association is implicitly ended when the session
- is closed (whether by exception or explicit client request)
- and the transaction in question is marked as rollback only.
- """
- session1 = self.session
- session2 = self.conn.session("other", 2)
-
- #setup:
- session2.queue_declare(queue="dummy", exclusive=True, auto_delete=True)
- session2.message_transfer(self.createMessage(session2, "dummy", "a", "whatever"))
- tx = self.xid("dummy")
-
- session2.dtx_select()
- session2.dtx_start(xid=tx)
- session2.message_subscribe(queue="dummy", destination="dummy")
- session2.message_flow(destination="dummy", unit=session2.credit_unit.message, value=1)
- session2.message_flow(destination="dummy", unit=session2.credit_unit.byte, value=0xFFFFFFFFL)
- msg = session2.incoming("dummy").get(timeout=1)
- session2.message_accept(RangedSet(msg.id))
- session2.message_cancel(destination="dummy")
- session2.message_transfer(self.createMessage(session2, "dummy", "b", "whatever"))
- session2.close()
-
- self.assertEqual(self.XA_RBROLLBACK, session1.dtx_prepare(xid=tx).status)
- session1.dtx_rollback(xid=tx)
-
- def test_get_timeout(self):
- """
- Check that get-timeout returns the correct value, (and that a
- transaction with a timeout can complete normally)
- """
- session = self.session
- tx = self.xid("dummy")
-
- session.dtx_select()
- session.dtx_start(xid=tx)
- # below test checks for default value of dtx-default-timeout broker option
- self.assertEqual(60, session.dtx_get_timeout(xid=tx).timeout)
- session.dtx_set_timeout(xid=tx, timeout=200)
- self.assertEqual(200, session.dtx_get_timeout(xid=tx).timeout)
- self.assertEqual(self.XA_OK, session.dtx_end(xid=tx).status)
- self.assertEqual(self.XA_OK, session.dtx_rollback(xid=tx).status)
-
- def test_set_timeout(self):
- """
- Test the timeout of a transaction results in the expected
- behaviour
- """
-
- guard = self.keepQueuesAlive(["queue-a", "queue-b"])
- #open new session to allow self.session to be used in checking the queue
- session = self.conn.session("worker", 1)
- #setup:
- tx = self.xid("dummy")
- session.queue_declare(queue="queue-a", auto_delete=True)
- session.queue_declare(queue="queue-b", auto_delete=True)
- session.message_transfer(self.createMessage(session, "queue-a", "timeout", "DtxMessage"))
-
- session.dtx_select()
- session.dtx_start(xid=tx)
- self.swap(session, "queue-a", "queue-b")
- session.dtx_set_timeout(xid=tx, timeout=2)
- sleep(3)
- #check that the work has been rolled back already
- self.assertMessageCount(1, "queue-a")
- self.assertMessageCount(0, "queue-b")
- self.assertMessageId("timeout", "queue-a")
- #check the correct codes are returned when we try to complete the txn
- self.assertEqual(self.XA_RBTIMEOUT, session.dtx_end(xid=tx).status)
- self.assertEqual(self.XA_RBTIMEOUT, session.dtx_rollback(xid=tx).status)
-
- def test_set_timeout_too_high(self):
- """
- Test the timeout can't be more than --dtx-max-timeout
- broker option
- """
- session = self.session
- tx = self.xid("dummy")
-
- session.dtx_select()
- session.dtx_start(xid=tx)
- try:
- session.dtx_set_timeout(xid=tx, timeout=3601)
- except SessionException, e:
- self.assertEquals(542, e.args[0].error_code)
-
-
-
- def test_recover(self):
- """
- Test basic recover behaviour
- """
- session = self.session
-
- session.dtx_select()
- session.queue_declare(queue="dummy", exclusive=True, auto_delete=True)
-
- prepared = []
- for i in range(1, 10):
- tx = self.xid("tx%s" % (i))
- session.dtx_start(xid=tx)
- session.message_transfer(self.createMessage(session, "dummy", "message%s" % (i), "message%s" % (i)))
- session.dtx_end(xid=tx)
- if i in [2, 5, 6, 8]:
- session.dtx_prepare(xid=tx)
- prepared.append(tx)
- else:
- session.dtx_rollback(xid=tx)
-
- xids = session.dtx_recover().in_doubt
-
- #rollback the prepared transactions returned by recover
- for x in xids:
- session.dtx_rollback(xid=x)
-
- #validate against the expected list of prepared transactions
- actual = set([x.global_id for x in xids]) #TODO: come up with nicer way to test these
- expected = set([x.global_id for x in prepared])
- intersection = actual.intersection(expected)
-
- if intersection != expected:
- missing = expected.difference(actual)
- extra = actual.difference(expected)
- self.fail("Recovered xids not as expected. missing: %s; extra: %s" % (missing, extra))
-
- def test_bad_resume(self):
- """
- Test that a resume on a session not selected for use with dtx fails
- """
- session = self.session
- try:
- session.dtx_start(resume=True)
- except SessionException, e:
- self.assertEquals(503, e.args[0].error_code)
-
- def test_prepare_unknown(self):
- session = self.session
- try:
- session.dtx_prepare(xid=self.xid("unknown"))
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
- def test_commit_unknown(self):
- session = self.session
- try:
- session.dtx_commit(xid=self.xid("unknown"))
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
- def test_rollback_unknown(self):
- session = self.session
- try:
- session.dtx_rollback(xid=self.xid("unknown"))
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
- def test_get_timeout_unknown(self):
- session = self.session
- try:
- session.dtx_get_timeout(xid=self.xid("unknown"))
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
- def xid(self, txid):
- DtxTests.tx_counter += 1
- branchqual = "v%s" % DtxTests.tx_counter
- return self.session.xid(format=0, global_id=txid, branch_id=branchqual)
-
- def txswap(self, tx, id):
- session = self.session
- #declare two queues:
- session.queue_declare(queue="queue-a", auto_delete=True)
- session.queue_declare(queue="queue-b", auto_delete=True)
-
- #put message with specified id on one queue:
- dp=session.delivery_properties(routing_key="queue-a")
- mp=session.message_properties(correlation_id=id)
- session.message_transfer(message=Message(dp, mp, "DtxMessage"))
-
- #start the transaction:
- session.dtx_select()
- self.assertEqual(self.XA_OK, self.session.dtx_start(xid=tx).status)
-
- #'swap' the message from one queue to the other, under that transaction:
- self.swap(self.session, "queue-a", "queue-b")
-
- #mark the end of the transactional work:
- self.assertEqual(self.XA_OK, self.session.dtx_end(xid=tx).status)
-
- def swap(self, session, src, dest):
- #consume from src:
- session.message_subscribe(destination="temp-swap", queue=src)
- session.message_flow(destination="temp-swap", unit=session.credit_unit.message, value=1)
- session.message_flow(destination="temp-swap", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- msg = session.incoming("temp-swap").get(timeout=1)
- session.message_cancel(destination="temp-swap")
- session.message_accept(RangedSet(msg.id))
- #todo: also complete at this point?
-
- #re-publish to dest:
- dp=session.delivery_properties(routing_key=dest)
- mp=session.message_properties(correlation_id=self.getMessageProperty(msg, 'correlation_id'))
- session.message_transfer(message=Message(dp, mp, msg.body))
-
- def assertMessageCount(self, expected, queue):
- self.assertEqual(expected, self.session.queue_query(queue=queue).message_count)
-
- def assertMessageId(self, expected, queue):
- self.session.message_subscribe(queue=queue, destination="results")
- self.session.message_flow(destination="results", unit=self.session.credit_unit.message, value=1)
- self.session.message_flow(destination="results", unit=self.session.credit_unit.byte, value=0xFFFFFFFFL)
- self.assertEqual(expected, self.getMessageProperty(self.session.incoming("results").get(timeout=1), 'correlation_id'))
- self.session.message_cancel(destination="results")
-
- def getMessageProperty(self, msg, prop):
- for h in msg.headers:
- if hasattr(h, prop): return getattr(h, prop)
- return None
-
- def keepQueuesAlive(self, names):
- session = self.conn.session("nasty", 99)
- for n in names:
- session.queue_declare(queue=n, auto_delete=True)
- session.message_subscribe(destination=n, queue=n)
- return session
-
- def createMessage(self, session, key, id, body):
- dp=session.delivery_properties(routing_key=key)
- mp=session.message_properties(correlation_id=id)
- session.message_transfer(message=Message(dp, mp, body))
diff --git a/qpid/python/qpid_tests/broker_0_10/example.py b/qpid/python/qpid_tests/broker_0_10/example.py
deleted file mode 100644
index e36907d501..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/example.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# 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.
-#
-
-from qpid.datatypes import Message, RangedSet
-from qpid.testlib import TestBase010
-
-class ExampleTest (TestBase010):
- """
- An example Qpid test, illustrating the unittest framework and the
- python Qpid client. The test class must inherit TestBase. The
- test code uses the Qpid client to interact with a qpid broker and
- verify it behaves as expected.
- """
-
- def test_example(self):
- """
- An example test. Note that test functions must start with 'test_'
- to be recognized by the test framework.
- """
-
- # By inheriting TestBase, self.client is automatically connected
- # and self.session is automatically opened as session(1)
- # Other session methods mimic the protocol.
- session = self.session
-
- # Now we can send regular commands. If you want to see what the method
- # arguments mean or what other commands are available, you can use the
- # python builtin help() method. For example:
- #help(chan)
- #help(chan.exchange_declare)
-
- # If you want browse the available protocol methods without being
- # connected to a live server you can use the amqp-doc utility:
- #
- # Usage amqp-doc [<options>] <spec> [<pattern_1> ... <pattern_n>]
- #
- # Options:
- # -e, --regexp use regex instead of glob when matching
-
- # Now that we know what commands are available we can use them to
- # interact with the server.
-
- # Here we use ordinal arguments.
- session.exchange_declare("test", "direct")
-
- # Here we use keyword arguments.
- session.queue_declare(queue="test-queue", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="test-queue", exchange="test", binding_key="key")
-
- # Call Session.subscribe to register as a consumer.
- # All the protocol methods return a message object. The message object
- # has fields corresponding to the reply method fields, plus a content
- # field that is filled if the reply includes content. In this case the
- # interesting field is the consumer_tag.
- session.message_subscribe(queue="test-queue", destination="consumer_tag")
- session.message_flow(destination="consumer_tag", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="consumer_tag", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
-
- # We can use the session.incoming(...) method to access the messages
- # delivered for our consumer_tag.
- queue = session.incoming("consumer_tag")
-
- # Now lets publish a message and see if our consumer gets it. To do
- # this we need to import the Message class.
- delivery_properties = session.delivery_properties(routing_key="key")
- sent = Message(delivery_properties, "Hello World!")
- session.message_transfer(destination="test", message=sent)
-
- # Now we'll wait for the message to arrive. We can use the timeout
- # argument in case the server hangs. By default queue.get() will wait
- # until a message arrives or the connection to the server dies.
- msg = queue.get(timeout=10)
-
- # And check that we got the right response with assertEqual
- self.assertEqual(sent.body, msg.body)
-
- # Now acknowledge the message.
- session.message_accept(RangedSet(msg.id))
-
diff --git a/qpid/python/qpid_tests/broker_0_10/exchange.py b/qpid/python/qpid_tests/broker_0_10/exchange.py
deleted file mode 100644
index 916f9d8b85..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/exchange.py
+++ /dev/null
@@ -1,558 +0,0 @@
-#
-# 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.
-#
-
-"""
-Tests for exchange behaviour.
-
-Test classes ending in 'RuleTests' are derived from rules in amqp.xml.
-"""
-
-import Queue, logging, traceback
-from qpid.testlib import TestBase010
-from qpid.datatypes import Message
-from qpid.client import Closed
-from qpid.session import SessionException
-
-
-class TestHelper(TestBase010):
- def setUp(self):
- TestBase010.setUp(self)
- self.queues = []
- self.exchanges = []
- self.subscriptions = []
-
- def tearDown(self):
- try:
- for s in self.subscriptions:
- self.session.message_cancel(destination=s)
- for ssn, q in self.queues:
- ssn.queue_delete(queue=q)
- for ssn, ex in self.exchanges:
- ssn.exchange_delete(exchange=ex)
- except:
- print "Error on tearDown:"
- print traceback.print_exc()
- TestBase010.tearDown(self)
-
- def createMessage(self, key="", body=""):
- return Message(self.session.delivery_properties(routing_key=key), body)
-
- def getApplicationHeaders(self, msg):
- for h in msg.headers:
- if hasattr(h, 'application_headers'): return getattr(h, 'application_headers')
- return None
-
- def assertPublishGet(self, queue, exchange="", routing_key="", properties=None):
- """
- Publish to exchange and assert queue.get() returns the same message.
- """
- body = self.uniqueString()
- dp=self.session.delivery_properties(routing_key=routing_key)
- mp=self.session.message_properties(application_headers=properties)
- self.session.message_transfer(destination=exchange, message=Message(dp, mp, body))
- msg = queue.get(timeout=1)
- self.assertEqual(body, msg.body)
- if (properties):
- self.assertEqual(properties, self.getApplicationHeaders(msg))
-
- def assertPublishConsume(self, queue="", exchange="", routing_key="", properties=None):
- """
- Publish a message and consume it, assert it comes back intact.
- Return the Queue object used to consume.
- """
- self.assertPublishGet(self.consume(queue), exchange, routing_key, properties)
-
- def assertEmpty(self, queue):
- """Assert that the queue is empty"""
- try:
- queue.get(timeout=1)
- self.fail("Queue is not empty.")
- except Queue.Empty: None # Ignore
-
- def queue_declare(self, session=None, *args, **keys):
- session = session or self.session
- reply = session.queue_declare(*args, **keys)
- self.queues.append((session, keys["queue"]))
- return reply
-
- def exchange_declare(self, session=None, ticket=0, exchange='',
- type='', passive=False, durable=False,
- auto_delete=False,
- arguments={}):
- session = session or self.session
- reply = session.exchange_declare(exchange=exchange, type=type, passive=passive, durable=durable, auto_delete=auto_delete, arguments=arguments)
- if exchange and not exchange.startswith("amq."):
- self.exchanges.append((session,exchange))
- return reply
-
- def uniqueString(self):
- """Generate a unique string, unique for this TestBase instance"""
- if not "uniqueCounter" in dir(self): self.uniqueCounter = 1;
- return "Test Message " + str(self.uniqueCounter)
-
- def consume(self, queueName):
- """Consume from named queue returns the Queue object."""
- if not "uniqueTag" in dir(self): self.uniqueTag = 1
- else: self.uniqueTag += 1
- consumer_tag = "tag" + str(self.uniqueTag)
- self.session.message_subscribe(queue=queueName, destination=consumer_tag)
- self.session.message_flow(destination=consumer_tag, unit=self.session.credit_unit.message, value=0xFFFFFFFFL)
- self.session.message_flow(destination=consumer_tag, unit=self.session.credit_unit.byte, value=0xFFFFFFFFL)
- self.subscriptions.append(consumer_tag)
- return self.session.incoming(consumer_tag)
-
-
-class StandardExchangeVerifier:
- """Verifies standard exchange behavior.
-
- Used as base class for classes that test standard exchanges."""
-
- def verifyDirectExchange(self, ex, unbind=False):
- """Verify that ex behaves like a direct exchange."""
- self.queue_declare(queue="q")
- self.session.exchange_bind(queue="q", exchange=ex, binding_key="k")
- try:
- self.assertPublishConsume(exchange=ex, queue="q", routing_key="k")
- try:
- self.assertPublishConsume(exchange=ex, queue="q", routing_key="kk")
- self.fail("Expected Empty exception")
- except Queue.Empty: None # Expected
- finally:
- if unbind:
- self.session.exchange_unbind(queue="q", exchange=ex, binding_key="k")
-
- def verifyFanOutExchange(self, ex, unbind=False):
- """Verify that ex behaves like a fanout exchange."""
- self.queue_declare(queue="q")
- self.session.exchange_bind(queue="q", exchange=ex)
- self.queue_declare(queue="p")
- self.session.exchange_bind(queue="p", exchange=ex)
- try:
- for qname in ["q", "p"]: self.assertPublishGet(self.consume(qname), ex)
- finally:
- if unbind:
- self.session.exchange_unbind(queue="q", exchange=ex, binding_key="")
- self.session.exchange_unbind(queue="p", exchange=ex, binding_key="")
-
-
- def verifyTopicExchange(self, ex, unbind=False):
- """Verify that ex behaves like a topic exchange"""
- self.queue_declare(queue="a")
- self.session.exchange_bind(queue="a", exchange=ex, binding_key="a.#.b.*")
- try:
- q = self.consume("a")
- self.assertPublishGet(q, ex, "a.b.x")
- self.assertPublishGet(q, ex, "a.x.b.x")
- self.assertPublishGet(q, ex, "a.x.x.b.x")
- # Shouldn't match
- self.session.message_transfer(destination=ex, message=self.createMessage("a.b"))
- self.session.message_transfer(destination=ex, message=self.createMessage("a.b.x.y"))
- self.session.message_transfer(destination=ex, message=self.createMessage("x.a.b.x"))
- self.session.message_transfer(destination=ex, message=self.createMessage("a.b"))
- self.assert_(q.empty())
- finally:
- if unbind:
- self.session.exchange_unbind(queue="a", exchange=ex, binding_key="a.#.b.*")
-
- def verifyHeadersExchange(self, ex, unbind=False):
- """Verify that ex is a headers exchange"""
- self.queue_declare(queue="q")
- self.session.exchange_bind(queue="q", exchange=ex, arguments={ "x-match":"all", "name":"fred" , "age":3} )
- try:
- q = self.consume("q")
- headers = {"name":"fred", "age":3}
- self.assertPublishGet(q, exchange=ex, properties=headers)
- self.session.message_transfer(destination=ex) # No headers, won't deliver
- self.assertEmpty(q);
- finally:
- if unbind:
- self.session.exchange_unbind(queue="q", exchange=ex, binding_key="")
-
-
-class RecommendedTypesRuleTests(TestHelper, StandardExchangeVerifier):
- """
- The server SHOULD implement these standard exchange types: topic, headers.
-
- Client attempts to declare an exchange with each of these standard types.
- """
-
- def testDirect(self):
- """Declare and test a direct exchange"""
- self.exchange_declare(0, exchange="d", type="direct")
- self.verifyDirectExchange("d")
-
- def testFanout(self):
- """Declare and test a fanout exchange"""
- self.exchange_declare(0, exchange="f", type="fanout")
- self.verifyFanOutExchange("f")
-
- def testTopic(self):
- """Declare and test a topic exchange"""
- self.exchange_declare(0, exchange="t", type="topic")
- self.verifyTopicExchange("t")
-
- def testHeaders(self):
- """Declare and test a headers exchange"""
- self.exchange_declare(0, exchange="h", type="headers")
- self.verifyHeadersExchange("h")
-
-
-class RequiredInstancesRuleTests(TestHelper, StandardExchangeVerifier):
- """
- The server MUST, in each virtual host, pre-declare an exchange instance
- for each standard exchange type that it implements, where the name of the
- exchange instance is amq. followed by the exchange type name.
-
- Client creates a temporary queue and attempts to bind to each required
- exchange instance (amq.fanout, amq.direct, and amq.topic, amq.match if
- those types are defined).
- """
- def testAmqDirect(self): self.verifyDirectExchange("amq.direct")
-
- def testAmqFanOut(self): self.verifyFanOutExchange("amq.fanout")
-
- def testAmqTopic(self): self.verifyTopicExchange("amq.topic")
-
- def testAmqMatch(self): self.verifyHeadersExchange("amq.match")
-
-class DefaultExchangeRuleTests(TestHelper, StandardExchangeVerifier):
- """
- The server MUST predeclare a direct exchange to act as the default exchange
- for content Publish methods and for default queue bindings.
-
- Client checks that the default exchange is active by specifying a queue
- binding with no exchange name, and publishing a message with a suitable
- routing key but without specifying the exchange name, then ensuring that
- the message arrives in the queue correctly.
- """
- def testDefaultExchange(self):
- # Test automatic binding by queue name.
- self.queue_declare(queue="d")
- self.assertPublishConsume(queue="d", routing_key="d")
-
-
-# TODO aconway 2006-09-27: Fill in empty tests:
-
-class DefaultAccessRuleTests(TestHelper):
- """
- The server MUST NOT allow clients to access the default exchange except
- by specifying an empty exchange name in the Queue.Bind and content Publish
- methods.
- """
-
-class ExtensionsRuleTests(TestHelper):
- """
- The server MAY implement other exchange types as wanted.
- """
-
-
-class DeclareMethodMinimumRuleTests(TestHelper):
- """
- The server SHOULD support a minimum of 16 exchanges per virtual host and
- ideally, impose no limit except as defined by available resources.
-
- The client creates as many exchanges as it can until the server reports
- an error; the number of exchanges successfuly created must be at least
- sixteen.
- """
-
-
-class DeclareMethodTicketFieldValidityRuleTests(TestHelper):
- """
- The client MUST provide a valid access ticket giving "active" access to
- the realm in which the exchange exists or will be created, or "passive"
- access if the if-exists flag is set.
-
- Client creates access ticket with wrong access rights and attempts to use
- in this method.
- """
-
-
-class DeclareMethodExchangeFieldReservedRuleTests(TestHelper):
- """
- Exchange names starting with "amq." are reserved for predeclared and
- standardised exchanges. The client MUST NOT attempt to create an exchange
- starting with "amq.".
-
- Similarly, exchanges starting with "qpid." are reserved for Qpid
- implementation-specific system exchanges (such as the management exchange).
- The client must not attempt to create an exchange starting with the string
- "qpid.".
- """
- def template(self, reservedString, exchangeType):
- try:
- self.session.exchange_declare(exchange=reservedString, type=exchangeType)
- self.fail("Expected not allowed error (530) for exchanges starting with \"" + reservedString + "\".")
- except SessionException, e:
- self.assertEquals(e.args[0].error_code, 530)
- # connection closed, reopen it
- self.tearDown()
- self.setUp()
- try:
- self.session.exchange_declare(exchange=reservedString + "abc123", type=exchangeType)
- self.fail("Expected not allowed error (530) for exchanges starting with \"" + reservedString + "\".")
- except SessionException, e:
- self.assertEquals(e.args[0].error_code, 530)
- # connection closed, reopen it
- self.tearDown()
- self.setUp()
- # The following should be legal:
- self.session.exchange_declare(exchange=reservedString[:-1], type=exchangeType)
- self.session.exchange_delete(exchange=reservedString[:-1])
- self.session.exchange_declare(exchange=reservedString[1:], type=exchangeType)
- self.session.exchange_delete(exchange=reservedString[1:])
- self.session.exchange_declare(exchange="." + reservedString, type=exchangeType)
- self.session.exchange_delete(exchange="." + reservedString)
- self.session.exchange_declare(exchange="abc." + reservedString, type=exchangeType)
- self.session.exchange_delete(exchange="abc." + reservedString)
- self.session.exchange_declare(exchange="abc." + reservedString + "def", type=exchangeType)
- self.session.exchange_delete(exchange="abc." + reservedString + "def")
-
- def test_amq(self):
- self.template("amq.", "direct")
- self.template("amq.", "topic")
- self.template("amq.", "fanout")
-
- def test_qpid(self):
- self.template("qpid.", "direct")
- self.template("qpid.", "topic")
- self.template("qpid.", "fanout")
-
-
-class DeclareMethodTypeFieldTypedRuleTests(TestHelper):
- """
- Exchanges cannot be redeclared with different types. The client MUST not
- attempt to redeclare an existing exchange with a different type than used
- in the original Exchange.Declare method.
-
-
- """
-
-
-class DeclareMethodTypeFieldSupportRuleTests(TestHelper):
- """
- The client MUST NOT attempt to create an exchange with a type that the
- server does not support.
-
-
- """
-
-
-class DeclareMethodPassiveFieldNotFoundRuleTests(TestHelper):
- """
- If set, and the exchange does not already exist, the server MUST raise a
- channel exception with reply code 404 (not found).
- """
- def test(self):
- try:
- self.session.exchange_declare(exchange="humpty_dumpty", passive=True)
- self.fail("Expected 404 for passive declaration of unknown exchange.")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
-
-class DeclareMethodDurableFieldSupportRuleTests(TestHelper):
- """
- The server MUST support both durable and transient exchanges.
-
-
- """
-
-
-class DeclareMethodDurableFieldStickyRuleTests(TestHelper):
- """
- The server MUST ignore the durable field if the exchange already exists.
-
-
- """
-
-
-class DeclareMethodAutoDeleteFieldStickyRuleTests(TestHelper):
- """
- The server MUST ignore the auto-delete field if the exchange already
- exists.
-
-
- """
-
-
-class DeleteMethodTicketFieldValidityRuleTests(TestHelper):
- """
- The client MUST provide a valid access ticket giving "active" access
- rights to the exchange's access realm.
-
- Client creates access ticket with wrong access rights and attempts to use
- in this method.
- """
-
-
-class DeleteMethodExchangeFieldExistsRuleTests(TestHelper):
- """
- The client MUST NOT attempt to delete an exchange that does not exist.
- """
-
-
-class HeadersExchangeTests(TestHelper):
- """
- Tests for headers exchange functionality.
- """
- def setUp(self):
- TestHelper.setUp(self)
- self.queue_declare(queue="q")
- self.q = self.consume("q")
-
- def myAssertPublishGet(self, headers):
- self.assertPublishGet(self.q, exchange="amq.match", properties=headers)
-
- def myBasicPublish(self, headers):
- mp=self.session.message_properties(application_headers=headers)
- self.session.message_transfer(destination="amq.match", message=Message(mp, "foobar"))
-
- def testMatchAll(self):
- self.session.exchange_bind(queue="q", exchange="amq.match", arguments={ 'x-match':'all', "name":"fred", "age":3})
- self.myAssertPublishGet({"name":"fred", "age":3})
- self.myAssertPublishGet({"name":"fred", "age":3, "extra":"ignoreme"})
-
- # None of these should match
- self.myBasicPublish({})
- self.myBasicPublish({"name":"barney"})
- self.myBasicPublish({"name":10})
- self.myBasicPublish({"name":"fred", "age":2})
- self.assertEmpty(self.q)
-
- def testMatchAny(self):
- self.session.exchange_bind(queue="q", exchange="amq.match", arguments={ 'x-match':'any', "name":"fred", "age":3})
- self.myAssertPublishGet({"name":"fred"})
- self.myAssertPublishGet({"name":"fred", "ignoreme":10})
- self.myAssertPublishGet({"ignoreme":10, "age":3})
-
- # Wont match
- self.myBasicPublish({})
- self.myBasicPublish({"irrelevant":0})
- self.assertEmpty(self.q)
-
- def testMatchVoidValue(self):
- self.session.exchange_bind(queue="q", exchange="amq.match", arguments={ 'x-match':'any', "name":None})
- self.myAssertPublishGet({"name":"fred"})
- self.myAssertPublishGet({"name":"bob"})
-
- # Wont match
- self.myBasicPublish({})
- self.myBasicPublish({"irrelevant":0})
- self.assertEmpty(self.q)
-
- def testMultipleBindings(self):
- self.session.exchange_bind(queue="q", exchange="amq.match", binding_key="SomeKey", arguments={ 'x-match':'any', "name":"fred"})
- self.session.exchange_bind(queue="q", exchange="amq.match", binding_key="AnotherKey", arguments={ 'x-match':'all', "age":3})
- self.myAssertPublishGet({"name":"fred", "age":3})
- self.assertEmpty(self.q)
-
-
-class MiscellaneousErrorsTests(TestHelper):
- """
- Test some miscellaneous error conditions
- """
- def testTypeNotKnown(self):
- try:
- self.session.exchange_declare(exchange="test_type_not_known_exchange", type="invalid_type")
- self.fail("Expected 404 for declaration of unknown exchange type.")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
- def testDifferentDeclaredType(self):
- self.exchange_declare(exchange="test_different_declared_type_exchange", type="direct")
- try:
- session = self.conn.session("alternate", 2)
- session.exchange_declare(exchange="test_different_declared_type_exchange", type="topic")
- self.fail("Expected 530 for redeclaration of exchange with different type.")
- except SessionException, e:
- self.assertEquals(530, e.args[0].error_code)
-
- def testReservedExchangeRedeclaredSameType(self):
- self.exchange_declare(exchange="amq.direct", type="direct", passive=True)
-
- def testReservedExchangeRedeclaredDifferentType(self):
- try:
- self.exchange_declare(exchange="amq.direct", type="topic")
- self.fail("Expected 530 for redeclaration of exchange with different type.")
- except SessionException, e:
- self.assertEquals(530, e.args[0].error_code)
-
- def testDefaultAccessBind(self):
- try:
- self.session.queue_declare(queue="my-queue", auto_delete=True, exclusive=True)
- self.session.exchange_bind(exchange="", queue="my-queue", binding_key="another-key")
- self.fail("Expected 542 (invalid-argument) code for bind to default exchange.")
- except SessionException, e:
- self.assertEquals(542, e.args[0].error_code)
-
- def testDefaultAccessUnbind(self):
- try:
- self.session.queue_declare(queue="my-queue", auto_delete=True, exclusive=True)
- self.session.exchange_unbind(exchange="", queue="my-queue", binding_key="my-queue")
- self.fail("Expected 542 (invalid-argument) code for unbind from default exchange.")
- except SessionException, e:
- self.assertEquals(542, e.args[0].error_code)
-
- def testDefaultAccessDelete(self):
- try:
- self.session.exchange_delete(exchange="")
- self.fail("Expected 542 (invalid-argument) code for delete of default exchange.")
- except SessionException, e:
- self.assertEquals(542, e.args[0].error_code)
-
-class ExchangeTests(TestHelper):
- def testHeadersBindNoMatchArg(self):
- self.session.queue_declare(queue="q", exclusive=True, auto_delete=True)
- try:
- self.session.exchange_bind(queue="q", exchange="amq.match", arguments={"name":"fred" , "age":3} )
- self.fail("Expected failure for missing x-match arg.")
- except SessionException, e:
- self.assertEquals(541, e.args[0].error_code)
-
-class AutodeleteTests(TestHelper, StandardExchangeVerifier):
- def checkNotExists(self, e):
- try:
- s = self.conn.session("verifier")
- s.exchange_declare(exchange=e, passive=True)
- s.exchange_delete(exchange=e)
- self.fail("Expected failure for passive declare of %s" % e)
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
-
- def testAutodeleteFanout(self):
- self.session.exchange_declare(exchange="e", type="fanout", auto_delete=True)
- self.verifyFanOutExchange("e", unbind=True)
- self.checkNotExists("e");
-
- def testAutodeleteDirect(self):
- self.session.exchange_declare(exchange="e", type="direct", auto_delete=True)
- self.verifyDirectExchange("e", unbind=True)
- self.checkNotExists("e");
-
- def testAutodeleteTopic(self):
- self.session.exchange_declare(exchange="e", type="topic", auto_delete=True)
- self.verifyTopicExchange("e", unbind=True)
- self.checkNotExists("e");
-
- def testAutodeleteHeaders(self):
- self.session.exchange_declare(exchange="e", type="headers", auto_delete=True)
- self.verifyHeadersExchange("e", unbind=True)
- self.checkNotExists("e");
diff --git a/qpid/python/qpid_tests/broker_0_10/extensions.py b/qpid/python/qpid_tests/broker_0_10/extensions.py
deleted file mode 100644
index 50c0aa3dd1..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/extensions.py
+++ /dev/null
@@ -1,87 +0,0 @@
-#
-# 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.
-#
-from qpid.client import Client, Closed
-from qpid.queue import Empty
-from qpid.content import Content
-from qpid.testlib import TestBase010
-from qpid.session import SessionException
-from qpid.datatypes import uuid4
-from time import sleep
-
-class ExtensionTests(TestBase010):
- """Tests for various extensions to AMQP 0-10"""
-
- def test_timed_autodelete(self):
- session = self.session
- session2 = self.conn.session("another-session")
- name=str(uuid4())
- session2.queue_declare(queue=name, exclusive=True, auto_delete=True, arguments={"qpid.auto_delete_timeout":3})
- session2.close()
- result = session.queue_query(queue=name)
- self.assertEqual(name, result.queue)
- sleep(5)
- result = session.queue_query(queue=name)
- self.assert_(not result.queue)
-
- def valid_policy_args(self, args, name="test-queue"):
- try:
- self.session.queue_declare(queue=name, arguments=args)
- self.session.queue_delete(queue=name) # cleanup
- except SessionException, e:
- self.fail("declare with valid policy args failed: %s" % (args))
- self.session = self.conn.session("replacement", 2)
-
- def invalid_policy_args(self, args, name="test-queue"):
- # go through invalid declare attempts twice to make sure that
- # the queue doesn't actually get created first time around
- # even if exception is thrown
- for i in range(1, 3):
- try:
- self.session.queue_declare(queue=name, arguments=args)
- self.session.queue_delete(queue=name) # cleanup
- self.fail("declare with invalid policy args suceeded: %s (iteration %d)" % (args, i))
- except SessionException, e:
- self.session = self.conn.session(str(uuid4()))
-
- def test_policy_max_size_as_valid_string(self):
- self.valid_policy_args({"qpid.max_size":"3"})
-
- def test_policy_max_count_as_valid_string(self):
- self.valid_policy_args({"qpid.max_count":"3"})
-
- def test_policy_max_count_and_size_as_valid_strings(self):
- self.valid_policy_args({"qpid.max_count":"3","qpid.max_size":"0"})
-
- def test_policy_negative_count(self):
- self.invalid_policy_args({"qpid.max_count":-1})
-
- def test_policy_negative_size(self):
- self.invalid_policy_args({"qpid.max_size":-1})
-
- def test_policy_size_as_invalid_string(self):
- self.invalid_policy_args({"qpid.max_size":"foo"})
-
- def test_policy_count_as_invalid_string(self):
- self.invalid_policy_args({"qpid.max_count":"foo"})
-
- def test_policy_size_as_float(self):
- self.invalid_policy_args({"qpid.max_size":3.14159})
-
- def test_policy_count_as_float(self):
- self.invalid_policy_args({"qpid.max_count":"2222222.22222"})
diff --git a/qpid/python/qpid_tests/broker_0_10/lvq.py b/qpid/python/qpid_tests/broker_0_10/lvq.py
deleted file mode 100644
index 07a8906fe7..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/lvq.py
+++ /dev/null
@@ -1,122 +0,0 @@
-#
-# 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.
-#
-
-from qpid.tests.messaging.implementation import *
-from qpid.tests.messaging import Base
-import math
-import random
-
-class LVQTests (Base):
- """
- Test last value queue behaviour
- """
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self):
- return self.conn.session()
-
- def test_simple(self):
- snd = self.ssn.sender("lvq; {create: sender, delete: sender, node: {x-declare:{arguments:{'qpid.last_value_queue_key':lvq-key}}}}",
- durable=self.durable())
- snd.send(create_message("a", "a-1"))
- snd.send(create_message("b", "b-1"))
- snd.send(create_message("a", "a-2"))
- snd.send(create_message("a", "a-3"))
- snd.send(create_message("c", "c-1"))
- snd.send(create_message("c", "c-2"))
-
- rcv = self.ssn.receiver("lvq; {mode: browse}")
- assert fetch_all(rcv) == ["b-1", "a-3", "c-2"]
-
- snd.send(create_message("b", "b-2"))
- assert fetch_all(rcv) == ["b-2"]
-
- snd.send(create_message("c", "c-3"))
- snd.send(create_message("d", "d-1"))
- assert fetch_all(rcv) == ["c-3", "d-1"]
-
- snd.send(create_message("b", "b-3"))
- assert fetch_all(rcv) == ["b-3"]
-
- rcv.close()
- rcv = self.ssn.receiver("lvq; {mode: browse}")
- assert (fetch_all(rcv) == ["a-3", "c-3", "d-1", "b-3"])
-
- def check_ring_lvq(self, ring_size, keys, message_count):
- address = "lvq; {create: sender, delete: sender, node: {x-declare:{arguments:{'qpid.last_value_queue_key':lvq-key,'qpid.policy_type':'ring','qpid.max_count':%i}}}}" % ring_size
- snd = self.ssn.sender(address, durable=self.durable())
- counters = {}
- for k in keys:
- counters[k] = 0
- messages = []
- for i in range(message_count):
- k = random.choice(keys)
- counters[k] += 1
- messages.append(create_message(k, "%s-%i" % (k, counters[k])))
- # make sure we have sent at least one message for every key
- for k, v in counters.iteritems():
- if v == 0:
- counters[k] += 1
- messages.append(create_message(k, "%s-%i" % (k, counters[k])))
-
- for m in messages:
- snd.send(m)
-
- rcv = self.ssn.receiver("lvq; {mode: browse}")
- retrieved = fetch_all_as_tuples(rcv)
- print [v for k, v in retrieved]
-
- for k, v in retrieved:
- assert v == "%s-%i" % (k, counters[k])
- assert len(retrieved) <= ring_size
-
- def test_ring_lvq1(self):
- self.check_ring_lvq(25, ["a","b","c","d"], 50)
-
- def test_ring_lvq2(self):
- self.check_ring_lvq(5, ["a","b","c","d","e","f","g"], 50)
-
- def test_ring_lvq3(self):
- self.check_ring_lvq(49, ["a"], 50)
-
-def create_message(key, content):
- msg = Message(content=content, properties={"lvq-key":key})
- return msg
-
-def fetch_all(rcv):
- content = []
- while True:
- try:
- content.append(rcv.fetch(0).content)
- except Empty:
- break
- return content
-
-def fetch_all_as_tuples(rcv):
- content = []
- while True:
- try:
- m = rcv.fetch(0)
- k = m.properties["lvq-key"]
- content.append((k, m.content))
- except Empty:
- break
- return content
diff --git a/qpid/python/qpid_tests/broker_0_10/management.py b/qpid/python/qpid_tests/broker_0_10/management.py
deleted file mode 100644
index 751839291b..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/management.py
+++ /dev/null
@@ -1,726 +0,0 @@
-#
-# 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.
-#
-
-from qpid.datatypes import Message, RangedSet
-from qpid.testlib import TestBase010
-from qpid.management import managementChannel, managementClient
-from threading import Condition
-from time import sleep
-import qmf.console
-import qpid.messaging
-from qpidtoollibs import BrokerAgent
-
-class ManagementTest (TestBase010):
-
- def setup_access(self):
- if 'broker_agent' not in self.__dict__:
- self.conn2 = qpid.messaging.Connection(self.broker)
- self.conn2.open()
- self.broker_agent = BrokerAgent(self.conn2)
- return self.broker_agent
-
- """
- Tests for the management hooks
- """
-
- def test_broker_connectivity_oldAPI (self):
- """
- Call the "echo" method on the broker to verify it is alive and talking.
- """
- session = self.session
-
- mc = managementClient ()
- mch = mc.addChannel (session)
-
- mc.syncWaitForStable (mch)
- brokers = mc.syncGetObjects (mch, "broker")
- self.assertEqual (len (brokers), 1)
- broker = brokers[0]
- args = {}
- body = "Echo Message Body"
- args["body"] = body
-
- for seq in range (1, 5):
- args["sequence"] = seq
- res = mc.syncCallMethod (mch, broker.id, broker.classKey, "echo", args)
- self.assertEqual (res.status, 0)
- self.assertEqual (res.statusText, "OK")
- self.assertEqual (res.sequence, seq)
- self.assertEqual (res.body, body)
- mc.removeChannel (mch)
-
- def test_methods_sync (self):
- """
- Call the "echo" method on the broker to verify it is alive and talking.
- """
- session = self.session
- self.startQmf()
-
- brokers = self.qmf.getObjects(_class="broker")
- self.assertEqual(len(brokers), 1)
- broker = brokers[0]
-
- body = "Echo Message Body"
- for seq in range(1, 20):
- res = broker.echo(seq, body)
- self.assertEqual(res.status, 0)
- self.assertEqual(res.text, "OK")
- self.assertEqual(res.sequence, seq)
- self.assertEqual(res.body, body)
-
- def test_get_objects(self):
- self.startQmf()
-
- # get the package list, verify that the qpid broker package is there
- packages = self.qmf.getPackages()
- assert 'org.apache.qpid.broker' in packages
-
- # get the schema class keys for the broker, verify the broker table and link-down event
- keys = self.qmf.getClasses('org.apache.qpid.broker')
- broker = None
- linkDown = None
- for key in keys:
- if key.getClassName() == "broker": broker = key
- if key.getClassName() == "brokerLinkDown" : linkDown = key
- assert broker
- assert linkDown
-
- brokerObjs = self.qmf.getObjects(_class="broker")
- assert len(brokerObjs) == 1
- brokerObjs = self.qmf.getObjects(_key=broker)
- assert len(brokerObjs) == 1
-
- def test_self_session_id (self):
- self.startQmf()
- sessionId = self.qmf_broker.getSessionId()
- brokerSessions = self.qmf.getObjects(_class="session")
-
- found = False
- for bs in brokerSessions:
- if bs.name.endswith(sessionId):
- found = True
- self.assertEqual (found, True)
-
- def test_standard_exchanges (self):
- self.startQmf()
-
- exchanges = self.qmf.getObjects(_class="exchange")
- exchange = self.findExchange (exchanges, "")
- self.assertEqual (exchange.type, "direct")
- exchange = self.findExchange (exchanges, "amq.direct")
- self.assertEqual (exchange.type, "direct")
- exchange = self.findExchange (exchanges, "amq.topic")
- self.assertEqual (exchange.type, "topic")
- exchange = self.findExchange (exchanges, "amq.fanout")
- self.assertEqual (exchange.type, "fanout")
- exchange = self.findExchange (exchanges, "amq.match")
- self.assertEqual (exchange.type, "headers")
- exchange = self.findExchange (exchanges, "qpid.management")
- self.assertEqual (exchange.type, "topic")
-
- def findExchange (self, exchanges, name):
- for exchange in exchanges:
- if exchange.name == name:
- return exchange
- return None
-
- def test_move_queued_messages_empty(self):
- """
- Test that moving messages from an empty queue does not cause an error.
- """
- self.startQmf()
- session = self.session
- "Set up source queue"
- session.queue_declare(queue="src-queue-empty", exclusive=True, auto_delete=True)
-
- "Set up destination queue"
- session.queue_declare(queue="dest-queue-empty", exclusive=True, auto_delete=True)
-
- queues = self.qmf.getObjects(_class="queue")
-
- "Move all messages from src-queue-empty to dest-queue-empty"
- result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("src-queue-empty", "dest-queue-empty", 0, {})
- self.assertEqual (result.status, 0)
-
- sq = self.qmf.getObjects(_class="queue", name="src-queue-empty")[0]
- dq = self.qmf.getObjects(_class="queue", name="dest-queue-empty")[0]
-
- self.assertEqual (sq.msgDepth,0)
- self.assertEqual (dq.msgDepth,0)
-
- def test_move_queued_messages(self):
- """
- Test ability to move messages from the head of one queue to another.
- Need to test moveing all and N messages.
- """
- self.startQmf()
- session = self.session
- "Set up source queue"
- session.queue_declare(queue="src-queue", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="src-queue", exchange="amq.direct", binding_key="routing_key")
-
- twenty = range(1,21)
- props = session.delivery_properties(routing_key="routing_key")
- for count in twenty:
- body = "Move Message %d" % count
- src_msg = Message(props, body)
- session.message_transfer(destination="amq.direct", message=src_msg)
-
- "Set up destination queue"
- session.queue_declare(queue="dest-queue", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="dest-queue", exchange="amq.direct")
-
- queues = self.qmf.getObjects(_class="queue")
-
- "Move 10 messages from src-queue to dest-queue"
- result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("src-queue", "dest-queue", 10, {})
- self.assertEqual (result.status, 0)
-
- sq = self.qmf.getObjects(_class="queue", name="src-queue")[0]
- dq = self.qmf.getObjects(_class="queue", name="dest-queue")[0]
-
- self.assertEqual (sq.msgDepth,10)
- self.assertEqual (dq.msgDepth,10)
-
- "Move all remaining messages to destination"
- result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("src-queue", "dest-queue", 0, {})
- self.assertEqual (result.status,0)
-
- sq = self.qmf.getObjects(_class="queue", name="src-queue")[0]
- dq = self.qmf.getObjects(_class="queue", name="dest-queue")[0]
-
- self.assertEqual (sq.msgDepth,0)
- self.assertEqual (dq.msgDepth,20)
-
- "Use a bad source queue name"
- result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("bad-src-queue", "dest-queue", 0, {})
- self.assertEqual (result.status,4)
-
- "Use a bad destination queue name"
- result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("src-queue", "bad-dest-queue", 0, {})
- self.assertEqual (result.status,4)
-
- " Use a large qty (40) to move from dest-queue back to "
- " src-queue- should move all "
- result = self.qmf.getObjects(_class="broker")[0].queueMoveMessages("dest-queue", "src-queue", 40, {})
- self.assertEqual (result.status,0)
-
- sq = self.qmf.getObjects(_class="queue", name="src-queue")[0]
- dq = self.qmf.getObjects(_class="queue", name="dest-queue")[0]
-
- self.assertEqual (sq.msgDepth,20)
- self.assertEqual (dq.msgDepth,0)
-
- "Consume the messages of the queue and check they are all there in order"
- session.message_subscribe(queue="src-queue", destination="tag")
- session.message_flow(destination="tag", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="tag", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- queue = session.incoming("tag")
- for count in twenty:
- consumed_msg = queue.get(timeout=1)
- body = "Move Message %d" % count
- self.assertEqual(body, consumed_msg.body)
-
- def test_purge_queue(self):
- """
- Test ability to purge messages from the head of a queue.
- Need to test moveing all, 1 (top message) and N messages.
- """
- self.startQmf()
- session = self.session
- "Set up purge queue"
- session.queue_declare(queue="purge-queue", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="purge-queue", exchange="amq.direct", binding_key="routing_key")
-
- twenty = range(1,21)
- props = session.delivery_properties(routing_key="routing_key")
- for count in twenty:
- body = "Purge Message %d" % count
- msg = Message(props, body)
- session.message_transfer(destination="amq.direct", message=msg)
-
- pq = self.qmf.getObjects(_class="queue", name="purge-queue")[0]
-
- "Purge top message from purge-queue"
- result = pq.purge(1, {})
- self.assertEqual (result.status, 0)
- pq = self.qmf.getObjects(_class="queue", name="purge-queue")[0]
- self.assertEqual (pq.msgDepth,19)
-
- "Purge top 9 messages from purge-queue"
- result = pq.purge(9, {})
- self.assertEqual (result.status, 0)
- pq = self.qmf.getObjects(_class="queue", name="purge-queue")[0]
- self.assertEqual (pq.msgDepth,10)
-
- "Purge all messages from purge-queue"
- result = pq.purge(0, {})
- self.assertEqual (result.status, 0)
- pq = self.qmf.getObjects(_class="queue", name="purge-queue")[0]
- self.assertEqual (pq.msgDepth,0)
-
- def test_reroute_priority_queue(self):
- self.startQmf()
- session = self.session
-
- #setup test queue supporting multiple priority levels
- session.queue_declare(queue="test-queue", exclusive=True, auto_delete=True, arguments={'x-qpid-priorities':10})
-
- #send some messages of varying priority to that queue:
- for i in range(0, 5):
- deliveryProps = session.delivery_properties(routing_key="test-queue", priority=i+5)
- session.message_transfer(message=Message(deliveryProps, "Message %d" % (i+1)))
-
-
- #declare and bind a queue to amq.fanout through which rerouted
- #messages can be verified:
- session.queue_declare(queue="rerouted", exclusive=True, auto_delete=True, arguments={'x-qpid-priorities':10})
- session.exchange_bind(queue="rerouted", exchange="amq.fanout")
-
- #reroute messages from test queue to amq.fanout (and hence to
- #rerouted queue):
- pq = self.qmf.getObjects(_class="queue", name="test-queue")[0]
- result = pq.reroute(0, False, "amq.fanout", {})
- self.assertEqual(result.status, 0)
-
- #verify messages are all rerouted:
- self.subscribe(destination="incoming", queue="rerouted")
- incoming = session.incoming("incoming")
- for i in range(0, 5):
- msg = incoming.get(timeout=1)
- self.assertEqual("Message %d" % (5-i), msg.body)
-
-
- def test_reroute_queue(self):
- """
- Test ability to reroute messages from the head of a queue.
- Need to test moving all, 1 (top message) and N messages.
- """
- self.startQmf()
- session = self.session
- "Set up test queue"
- session.exchange_declare(exchange="alt.direct1", type="direct")
- session.queue_declare(queue="alt-queue1", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="alt-queue1", exchange="alt.direct1", binding_key="routing_key")
- session.exchange_declare(exchange="alt.direct2", type="direct")
- session.queue_declare(queue="alt-queue2", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="alt-queue2", exchange="alt.direct2", binding_key="routing_key")
- session.queue_declare(queue="reroute-queue", exclusive=True, auto_delete=True, alternate_exchange="alt.direct1")
- session.exchange_bind(queue="reroute-queue", exchange="amq.direct", binding_key="routing_key")
-
- twenty = range(1,21)
- props = session.delivery_properties(routing_key="routing_key")
- mp = session.message_properties(application_headers={'x-qpid.trace' : 'A,B,C'})
- for count in twenty:
- body = "Reroute Message %d" % count
- msg = Message(props, mp, body)
- session.message_transfer(destination="amq.direct", message=msg)
-
- pq = self.qmf.getObjects(_class="queue", name="reroute-queue")[0]
-
- "Reroute top message from reroute-queue to alternate exchange"
- result = pq.reroute(1, True, "", {})
- self.assertEqual(result.status, 0)
- pq.update()
- aq = self.qmf.getObjects(_class="queue", name="alt-queue1")[0]
- self.assertEqual(pq.msgDepth,19)
- self.assertEqual(aq.msgDepth,1)
-
- "Verify that the trace was cleared on the rerouted message"
- url = "%s://%s:%d" % (self.broker.scheme or "amqp", self.broker.host, self.broker.port)
- conn = qpid.messaging.Connection(url)
- conn.open()
- sess = conn.session()
- rx = sess.receiver("alt-queue1;{mode:browse}")
- rm = rx.fetch(1)
- self.assertEqual(rm.properties['x-qpid.trace'], '')
- conn.close()
-
- "Reroute top 9 messages from reroute-queue to alt.direct2"
- result = pq.reroute(9, False, "alt.direct2", {})
- self.assertEqual(result.status, 0)
- pq.update()
- aq = self.qmf.getObjects(_class="queue", name="alt-queue2")[0]
- self.assertEqual(pq.msgDepth,10)
- self.assertEqual(aq.msgDepth,9)
-
- "Reroute using a non-existent exchange"
- result = pq.reroute(0, False, "amq.nosuchexchange", {})
- self.assertEqual(result.status, 4)
-
- "Reroute all messages from reroute-queue"
- result = pq.reroute(0, False, "alt.direct2", {})
- self.assertEqual(result.status, 0)
- pq.update()
- aq = self.qmf.getObjects(_class="queue", name="alt-queue2")[0]
- self.assertEqual(pq.msgDepth,0)
- self.assertEqual(aq.msgDepth,19)
-
- "Make more messages"
- twenty = range(1,21)
- props = session.delivery_properties(routing_key="routing_key")
- for count in twenty:
- body = "Reroute Message %d" % count
- msg = Message(props, body)
- session.message_transfer(destination="amq.direct", message=msg)
-
- "Reroute onto the same queue"
- result = pq.reroute(0, False, "amq.direct", {})
- self.assertEqual(result.status, 0)
- pq.update()
- self.assertEqual(pq.msgDepth,20)
-
- def test_reroute_alternate_exchange(self):
- """
- Test that when rerouting, the alternate-exchange is considered if relevant
- """
- self.startQmf()
- session = self.session
- # 1. Create 2 exchanges A and B (fanout) where B is the
- # alternate exchange for A
- session.exchange_declare(exchange="B", type="fanout")
- session.exchange_declare(exchange="A", type="fanout", alternate_exchange="B")
-
- # 2. Bind queue X to B
- session.queue_declare(queue="X", exclusive=True, auto_delete=True)
- session.exchange_bind(queue="X", exchange="B")
-
- # 3. Send 1 message to queue Y
- session.queue_declare(queue="Y", exclusive=True, auto_delete=True)
- props = session.delivery_properties(routing_key="Y")
- session.message_transfer(message=Message(props, "reroute me!"))
-
- # 4. Call reroute on queue Y and specify that messages should
- # be sent to exchange A
- y = self.qmf.getObjects(_class="queue", name="Y")[0]
- result = y.reroute(1, False, "A", {})
- self.assertEqual(result.status, 0)
-
- # 5. verify that the message is rerouted through B (as A has
- # no matching bindings) to X
- self.subscribe(destination="x", queue="X")
- self.assertEqual("reroute me!", session.incoming("x").get(timeout=1).body)
-
- # Cleanup
- for e in ["A", "B"]: session.exchange_delete(exchange=e)
-
- def test_reroute_invalid_alt_exchange(self):
- """
- Test that an error is returned for an attempt to reroute to
- alternate exchange on a queue for which no such exchange has
- been defined.
- """
- self.startQmf()
- session = self.session
- # create queue with no alt-exchange, and send a message to it
- session.queue_declare(queue="q", exclusive=True, auto_delete=True)
- props = session.delivery_properties(routing_key="q")
- session.message_transfer(message=Message(props, "don't reroute me!"))
-
- # attempt to reroute the message to alt-exchange
- q = self.qmf.getObjects(_class="queue", name="q")[0]
- result = q.reroute(1, True, "", {})
- # verify the attempt fails...
- self.assertEqual(result.status, 4) #invalid parameter
-
- # ...and message is still on the queue
- self.subscribe(destination="d", queue="q")
- self.assertEqual("don't reroute me!", session.incoming("d").get(timeout=1).body)
-
-
- def test_methods_async (self):
- """
- """
- class Handler (qmf.console.Console):
- def __init__(self):
- self.cv = Condition()
- self.xmtList = {}
- self.rcvList = {}
-
- def methodResponse(self, broker, seq, response):
- self.cv.acquire()
- try:
- self.rcvList[seq] = response
- finally:
- self.cv.release()
-
- def request(self, broker, count):
- self.count = count
- for idx in range(count):
- self.cv.acquire()
- try:
- seq = broker.echo(idx, "Echo Message", _async = True)
- self.xmtList[seq] = idx
- finally:
- self.cv.release()
-
- def check(self):
- if self.count != len(self.xmtList):
- return "fail (attempted send=%d, actual sent=%d)" % (self.count, len(self.xmtList))
- lost = 0
- mismatched = 0
- for seq in self.xmtList:
- value = self.xmtList[seq]
- if seq in self.rcvList:
- result = self.rcvList.pop(seq)
- if result.sequence != value:
- mismatched += 1
- else:
- lost += 1
- spurious = len(self.rcvList)
- if lost == 0 and mismatched == 0 and spurious == 0:
- return "pass"
- else:
- return "fail (lost=%d, mismatch=%d, spurious=%d)" % (lost, mismatched, spurious)
-
- handler = Handler()
- self.startQmf(handler)
- brokers = self.qmf.getObjects(_class="broker")
- self.assertEqual(len(brokers), 1)
- broker = brokers[0]
- handler.request(broker, 20)
- sleep(1)
- self.assertEqual(handler.check(), "pass")
-
- def test_connection_close(self):
- """
- Test management method for closing connection
- """
- self.startQmf()
- conn = self.connect()
- session = conn.session("my-named-session")
-
- #using qmf find named session and close the corresponding connection:
- qmf_ssn_object = [s for s in self.qmf.getObjects(_class="session") if s.name.endswith("my-named-session")][0]
- qmf_ssn_object._connectionRef_.close()
-
- #check that connection is closed
- try:
- conn.session("another-session")
- self.fail("Expected failure from closed connection")
- except: None
-
- #make sure that the named session has been closed and the name can be re-used
- conn = self.connect()
- session = conn.session("my-named-session")
- session.queue_declare(queue="whatever", exclusive=True, auto_delete=True)
-
- def test_immediate_method(self):
- url = "%s://%s:%d" % (self.broker.scheme or "amqp", self.broker.host or "localhost", self.broker.port or 5672)
- conn = qpid.messaging.Connection(url)
- conn.open()
- sess = conn.session()
- replyTo = "qmf.default.direct/reply_immediate_method_test;{node:{type:topic}}"
- agent_sender = sess.sender("qmf.default.direct/broker")
- agent_receiver = sess.receiver(replyTo)
- queue_create = sess.sender("test-queue-imm-method;{create:always,delete:always,node:{type:queue,durable:False,x-declare:{auto-delete:True}}}")
-
- method_request = {'_method_name':'reroute','_object_id':{'_object_name':'org.apache.qpid.broker:queue:test-queue-imm-method'}}
- method_request['_arguments'] = {'request':0, 'useAltExchange':False, 'exchange':'amq.fanout'}
-
- reroute_call = qpid.messaging.Message(method_request)
- reroute_call.properties['qmf.opcode'] = '_method_request'
- reroute_call.properties['x-amqp-0-10.app-id'] = 'qmf2'
- reroute_call.reply_to = replyTo
-
- agent_sender.send(reroute_call)
- result = agent_receiver.fetch(3)
- self.assertEqual(result.properties['qmf.opcode'], '_method_response')
-
- conn.close()
-
- def test_binding_count_on_queue(self):
- self.startQmf()
- conn = self.connect()
- session = self.session
-
- QUEUE = "binding_test_queue"
- EX_DIR = "binding_test_exchange_direct"
- EX_FAN = "binding_test_exchange_fanout"
- EX_TOPIC = "binding_test_exchange_topic"
- EX_HDR = "binding_test_exchange_headers"
-
- #
- # Create a test queue
- #
- session.queue_declare(queue=QUEUE, exclusive=True, auto_delete=True)
- queue = self.qmf.getObjects(_class="queue", name=QUEUE)[0]
- if not queue:
- self.fail("Queue not found")
- self.assertEqual(queue.bindingCount, 1, "wrong initial binding count")
-
- #
- # Create an exchange of each supported type
- #
- session.exchange_declare(exchange=EX_DIR, type="direct")
- session.exchange_declare(exchange=EX_FAN, type="fanout")
- session.exchange_declare(exchange=EX_TOPIC, type="topic")
- session.exchange_declare(exchange=EX_HDR, type="headers")
-
- #
- # Bind each exchange to the test queue
- #
- match = {}
- match['x-match'] = "all"
- match['key'] = "value"
- session.exchange_bind(exchange=EX_DIR, queue=QUEUE, binding_key="key1")
- session.exchange_bind(exchange=EX_DIR, queue=QUEUE, binding_key="key2")
- session.exchange_bind(exchange=EX_FAN, queue=QUEUE)
- session.exchange_bind(exchange=EX_TOPIC, queue=QUEUE, binding_key="key1.#")
- session.exchange_bind(exchange=EX_TOPIC, queue=QUEUE, binding_key="key2.#")
- session.exchange_bind(exchange=EX_HDR, queue=QUEUE, binding_key="key1", arguments=match)
- match['key2'] = "value2"
- session.exchange_bind(exchange=EX_HDR, queue=QUEUE, binding_key="key2", arguments=match)
-
- #
- # Verify that the queue's binding count accounts for the new bindings
- #
- queue.update()
- self.assertEqual(queue.bindingCount, 8,
- "added bindings not accounted for (expected 8, got %d)" % queue.bindingCount)
-
- #
- # Remove some of the bindings
- #
- session.exchange_unbind(exchange=EX_DIR, queue=QUEUE, binding_key="key2")
- session.exchange_unbind(exchange=EX_TOPIC, queue=QUEUE, binding_key="key2.#")
- session.exchange_unbind(exchange=EX_HDR, queue=QUEUE, binding_key="key2")
-
- #
- # Verify that the queue's binding count accounts for the deleted bindings
- #
- queue.update()
- self.assertEqual(queue.bindingCount, 5,
- "deleted bindings not accounted for (expected 5, got %d)" % queue.bindingCount)
- #
- # Delete the exchanges
- #
- session.exchange_delete(exchange=EX_DIR)
- session.exchange_delete(exchange=EX_FAN)
- session.exchange_delete(exchange=EX_TOPIC)
- session.exchange_delete(exchange=EX_HDR)
-
- #
- # Verify that the queue's binding count accounts for the lost bindings
- #
- queue.update()
- self.assertEqual(queue.bindingCount, 1,
- "deleted bindings not accounted for (expected 1, got %d)" % queue.bindingCount)
-
- def test_connection_stats(self):
- """
- Test message in/out stats for connection
- """
- agent = self.setup_access()
- conn = self.connect()
- session = conn.session("stats-session")
-
- #using qmf find named session and the corresponding connection:
- conn_qmf = None
- sessions = agent.getAllSessions()
- for s in sessions:
- if s.name.endswith("stats-session"):
- conn_qmf = agent.getConnection(s.connectionRef)
-
- assert(conn_qmf)
-
- #send a message to a queue
- session.queue_declare(queue="stats-q", exclusive=True, auto_delete=True)
- session.message_transfer(message=Message(session.delivery_properties(routing_key="stats-q"), "abc"))
-
- #check the 'msgs sent from' stat for this connection
- conn_qmf.update()
- self.assertEqual(conn_qmf.msgsFromClient, 1)
-
- #receive message from queue
- session.message_subscribe(destination="d", queue="stats-q")
- incoming = session.incoming("d")
- incoming.start()
- self.assertEqual("abc", incoming.get(timeout=1).body)
-
- #check the 'msgs sent to' stat for this connection
- conn_qmf.update()
- self.assertEqual(conn_qmf.msgsToClient, 1)
-
- def test_timestamp_config(self):
- """
- Test message timestamping control.
- """
- self.startQmf()
- conn = self.connect()
- session = conn.session("timestamp-session")
-
- #verify that receive message timestamping is OFF by default
- broker = self.qmf.getObjects(_class="broker")[0]
- rc = broker.getTimestampConfig()
- self.assertEqual(rc.status, 0)
- self.assertEqual(rc.text, "OK")
-
- #try to enable it
- rc = broker.setTimestampConfig(True)
- self.assertEqual(rc.status, 0)
- self.assertEqual(rc.text, "OK")
-
- rc = broker.getTimestampConfig()
- self.assertEqual(rc.status, 0)
- self.assertEqual(rc.text, "OK")
- self.assertEqual(rc.receive, True)
-
- # setup a connection & session to the broker
- url = "%s://%s:%d" % (self.broker.scheme or "amqp", self.broker.host or "localhost", self.broker.port or 5672)
- conn = qpid.messaging.Connection(url)
- conn.open()
- sess = conn.session()
-
- #send a message to a queue
- sender = sess.sender("ts-q; {create:sender, delete:receiver}")
- sender.send( qpid.messaging.Message(content="abc") )
-
- #receive message from queue, and verify timestamp is present
- receiver = sess.receiver("ts-q")
- try:
- msg = receiver.fetch(timeout=1)
- except Empty:
- assert(False)
- self.assertEqual("abc", msg.content)
- self.assertEqual(True, "x-amqp-0-10.timestamp" in msg.properties)
- assert(msg.properties["x-amqp-0-10.timestamp"])
-
- #try to disable it
- rc = broker.setTimestampConfig(False)
- self.assertEqual(rc.status, 0)
- self.assertEqual(rc.text, "OK")
-
- rc = broker.getTimestampConfig()
- self.assertEqual(rc.status, 0)
- self.assertEqual(rc.text, "OK")
- self.assertEqual(rc.receive, False)
-
- #send another message to the queue
- sender.send( qpid.messaging.Message(content="def") )
-
- #receive message from queue, and verify timestamp is NOT PRESENT
- receiver = sess.receiver("ts-q")
- try:
- msg = receiver.fetch(timeout=1)
- except Empty:
- assert(False)
- self.assertEqual("def", msg.content)
- self.assertEqual(False, "x-amqp-0-10.timestamp" in msg.properties)
-
diff --git a/qpid/python/qpid_tests/broker_0_10/message.py b/qpid/python/qpid_tests/broker_0_10/message.py
deleted file mode 100644
index 481416824d..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/message.py
+++ /dev/null
@@ -1,1117 +0,0 @@
-#
-# 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.
-#
-from qpid.client import Client, Closed
-from qpid.queue import Empty
-from qpid.testlib import TestBase010
-from qpid.datatypes import Message, RangedSet
-from qpid.session import SessionException
-
-from qpid.content import Content
-from time import sleep
-
-class MessageTests(TestBase010):
- """Tests for 'methods' on the amqp message 'class'"""
-
- def test_no_local(self):
- """
- NOTE: this is a test of a QPID specific feature
-
- Test that the qpid specific no_local arg is honoured.
- """
- session = self.session
- #setup, declare two queues one of which excludes delivery of locally sent messages
- session.queue_declare(queue="test-queue-1a", exclusive=True, auto_delete=True)
- session.queue_declare(queue="test-queue-1b", exclusive=True, auto_delete=True, arguments={'no-local':'true'})
- #establish two consumers
- self.subscribe(destination="local_included", queue="test-queue-1a")
- self.subscribe(destination="local_excluded", queue="test-queue-1b")
-
- #send a message
- session.message_transfer(message=Message(session.delivery_properties(routing_key="test-queue-1a"), "deliver-me"))
- session.message_transfer(message=Message(session.delivery_properties(routing_key="test-queue-1b"), "dont-deliver-me"))
-
- #send a message from another session on the same connection to each queue
- session2 = self.conn.session("my-local-session")
- session2.message_transfer(message=Message(session2.delivery_properties(routing_key="test-queue-1a"), "deliver-me-as-well"))
- session2.message_transfer(message=Message(session2.delivery_properties(routing_key="test-queue-1b"), "dont-deliver-me-either"))
-
- #send a message from a session on another connection to each queue
- for q in ["test-queue-1a", "test-queue-1b"]:
- session.exchange_bind(queue=q, exchange="amq.fanout", binding_key="my-key")
- other = self.connect()
- session3 = other.session("my-other-session")
- session3.message_transfer(destination="amq.fanout", message=Message("i-am-not-local"))
- other.close()
-
- #check the queues of the two consumers
- excluded = session.incoming("local_excluded")
- included = session.incoming("local_included")
- for b in ["deliver-me", "deliver-me-as-well", "i-am-not-local"]:
- msg = included.get(timeout=1)
- self.assertEqual(b, msg.body)
- msg = excluded.get(timeout=1)
- self.assertEqual("i-am-not-local", msg.body)
- try:
- excluded.get(timeout=1)
- self.fail("Received locally published message though no_local=true")
- except Empty: None
-
- def test_no_local_awkward(self):
-
- """
- NOTE: this is a test of a QPID specific feature
-
- Check that messages which will be excluded through no-local
- processing will not block subsequent deliveries
- """
-
- session = self.session
- #setup:
- session.queue_declare(queue="test-queue", exclusive=True, auto_delete=True, arguments={'no-local':'true'})
- #establish consumer which excludes delivery of locally sent messages
- self.subscribe(destination="local_excluded", queue="test-queue")
-
- #send a 'local' message
- session.message_transfer(message=Message(session.delivery_properties(routing_key="test-queue"), "local"))
-
- #send a non local message
- other = self.connect()
- session2 = other.session("my-session", 1)
- session2.message_transfer(message=Message(session2.delivery_properties(routing_key="test-queue"), "foreign"))
- session2.close()
- other.close()
-
- #check that the second message only is delivered
- excluded = session.incoming("local_excluded")
- msg = excluded.get(timeout=1)
- self.assertEqual("foreign", msg.body)
- try:
- excluded.get(timeout=1)
- self.fail("Received extra message")
- except Empty: None
- #check queue is empty
- self.assertEqual(0, session.queue_query(queue="test-queue").message_count)
-
- def test_no_local_exclusive_subscribe(self):
- """
- NOTE: this is a test of a QPID specific feature
-
- Test that the no_local processing works on queues not declared
- as exclusive, but with an exclusive subscription
- """
- session = self.session
-
- #setup, declare two queues one of which excludes delivery of
- #locally sent messages but is not declared as exclusive
- session.queue_declare(queue="test-queue-1a", exclusive=True, auto_delete=True)
- session.queue_declare(queue="test-queue-1b", auto_delete=True, arguments={'no-local':'true'})
- #establish two consumers
- self.subscribe(destination="local_included", queue="test-queue-1a")
- self.subscribe(destination="local_excluded", queue="test-queue-1b", exclusive=True)
-
- #send a message from the same session to each queue
- session.message_transfer(message=Message(session.delivery_properties(routing_key="test-queue-1a"), "deliver-me"))
- session.message_transfer(message=Message(session.delivery_properties(routing_key="test-queue-1b"), "dont-deliver-me"))
-
- #send a message from another session on the same connection to each queue
- session2 = self.conn.session("my-session")
- session2.message_transfer(message=Message(session2.delivery_properties(routing_key="test-queue-1a"), "deliver-me-as-well"))
- session2.message_transfer(message=Message(session2.delivery_properties(routing_key="test-queue-1b"), "dont-deliver-me-either"))
-
- #send a message from a session on another connection to each queue
- for q in ["test-queue-1a", "test-queue-1b"]:
- session.exchange_bind(queue=q, exchange="amq.fanout", binding_key="my-key")
- other = self.connect()
- session3 = other.session("my-other-session")
- session3.message_transfer(destination="amq.fanout", message=Message("i-am-not-local"))
- other.close()
-
- #check the queues of the two consumers
- excluded = session.incoming("local_excluded")
- included = session.incoming("local_included")
- for b in ["deliver-me", "deliver-me-as-well", "i-am-not-local"]:
- msg = included.get(timeout=1)
- self.assertEqual(b, msg.body)
- msg = excluded.get(timeout=1)
- self.assertEqual("i-am-not-local", msg.body)
- try:
- excluded.get(timeout=1)
- self.fail("Received locally published message though no_local=true")
- except Empty: None
-
-
- def test_consume_exclusive(self):
- """
- Test an exclusive consumer prevents other consumer being created
- """
- session = self.session
- session.queue_declare(queue="test-queue-2", exclusive=True, auto_delete=True)
- session.message_subscribe(destination="first", queue="test-queue-2", exclusive=True)
- try:
- session.message_subscribe(destination="second", queue="test-queue-2")
- self.fail("Expected consume request to fail due to previous exclusive consumer")
- except SessionException, e:
- self.assertEquals(405, e.args[0].error_code)
-
- def test_consume_exclusive2(self):
- """
- Check that an exclusive consumer cannot be created if a consumer already exists:
- """
- session = self.session
- session.queue_declare(queue="test-queue-2", exclusive=True, auto_delete=True)
- session.message_subscribe(destination="first", queue="test-queue-2")
- try:
- session.message_subscribe(destination="second", queue="test-queue-2", exclusive=True)
- self.fail("Expected exclusive consume request to fail due to previous consumer")
- except SessionException, e:
- self.assertEquals(405, e.args[0].error_code)
-
- def test_consume_queue_not_found(self):
- """
- Test error conditions associated with the queue field of the consume method:
- """
- session = self.session
- try:
- #queue specified but doesn't exist:
- session.message_subscribe(queue="invalid-queue", destination="a")
- self.fail("Expected failure when consuming from non-existent queue")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
- def test_consume_queue_not_specified(self):
- session = self.session
- try:
- #queue not specified and none previously declared for channel:
- session.message_subscribe(destination="a")
- self.fail("Expected failure when consuming from unspecified queue")
- except SessionException, e:
- self.assertEquals(531, e.args[0].error_code)
-
- def test_consume_unique_consumers(self):
- """
- Ensure unique consumer tags are enforced
- """
- session = self.session
- #setup, declare a queue:
- session.queue_declare(queue="test-queue-3", exclusive=True, auto_delete=True)
-
- #check that attempts to use duplicate tags are detected and prevented:
- session.message_subscribe(destination="first", queue="test-queue-3")
- try:
- session.message_subscribe(destination="first", queue="test-queue-3")
- self.fail("Expected consume request to fail due to non-unique tag")
- except SessionException, e:
- self.assertEquals(530, e.args[0].error_code)
-
- def test_cancel(self):
- """
- Test compliance of the basic.cancel method
- """
- session = self.session
- #setup, declare a queue:
- session.queue_declare(queue="test-queue-4", exclusive=True, auto_delete=True)
- session.message_transfer(message=Message(session.delivery_properties(routing_key="test-queue-4"), "One"))
-
- session.message_subscribe(destination="my-consumer", queue="test-queue-4")
- myqueue = session.incoming("my-consumer")
- session.message_flow(destination="my-consumer", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="my-consumer", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
-
- #should flush here
-
- #cancel should stop messages being delivered
- session.message_cancel(destination="my-consumer")
- session.message_transfer(message=Message(session.delivery_properties(routing_key="test-queue-4"), "Two"))
- msg = myqueue.get(timeout=1)
- self.assertEqual("One", msg.body)
- try:
- msg = myqueue.get(timeout=1)
- self.fail("Got message after cancellation: " + msg)
- except Empty: None
-
- #cancellation of non-existant consumers should be result in 404s
- try:
- session.message_cancel(destination="my-consumer")
- self.fail("Expected 404 for recancellation of subscription.")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
- session = self.conn.session("alternate-session", timeout=10)
- try:
- session.message_cancel(destination="this-never-existed")
- self.fail("Expected 404 for cancellation of unknown subscription.")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
-
- def test_ack(self):
- """
- Test basic ack/recover behaviour using a combination of implicit and
- explicit accept subscriptions.
- """
- self.startQmf()
- session1 = self.conn.session("alternate-session", timeout=10)
- session1.queue_declare(queue="test-ack-queue", auto_delete=True)
-
- delivery_properties = session1.delivery_properties(routing_key="test-ack-queue")
- for i in ["One", "Two", "Three", "Four", "Five"]:
- session1.message_transfer(message=Message(delivery_properties, i))
-
- # verify enqueued message count, use both QMF and session query to verify consistency
- self.assertEqual(5, session1.queue_query(queue="test-ack-queue").message_count)
- queueObj = self.qmf.getObjects(_class="queue", name="test-ack-queue")[0]
- self.assertEquals(queueObj.msgDepth, 5)
- self.assertEquals(queueObj.msgTotalEnqueues, 5)
- self.assertEquals(queueObj.msgTotalDequeues, 0)
-
- # subscribe with implied acquire, explicit accept:
- session1.message_subscribe(queue = "test-ack-queue", destination = "consumer")
- session1.message_flow(destination="consumer", unit=session1.credit_unit.message, value=0xFFFFFFFFL)
- session1.message_flow(destination="consumer", unit=session1.credit_unit.byte, value=0xFFFFFFFFL)
- queue = session1.incoming("consumer")
-
- msg1 = queue.get(timeout=1)
- msg2 = queue.get(timeout=1)
- msg3 = queue.get(timeout=1)
- msg4 = queue.get(timeout=1)
- msg5 = queue.get(timeout=1)
-
- self.assertEqual("One", msg1.body)
- self.assertEqual("Two", msg2.body)
- self.assertEqual("Three", msg3.body)
- self.assertEqual("Four", msg4.body)
- self.assertEqual("Five", msg5.body)
-
- # messages should not be on the queue:
- self.assertEqual(0, session1.queue_query(queue="test-ack-queue").message_count)
- # QMF shows the dequeues as not having happened yet, since they are have
- # not been accepted
- queueObj.update()
- self.assertEquals(queueObj.msgDepth, 5)
- self.assertEquals(queueObj.msgTotalEnqueues, 5)
- self.assertEquals(queueObj.msgTotalDequeues, 0)
-
- session1.message_accept(RangedSet(msg1.id, msg2.id, msg4.id))#One, Two and Four
-
- # QMF should now reflect the accepted messages as being dequeued
- self.assertEqual(0, session1.queue_query(queue="test-ack-queue").message_count)
- queueObj.update()
- self.assertEquals(queueObj.msgDepth, 2)
- self.assertEquals(queueObj.msgTotalEnqueues, 5)
- self.assertEquals(queueObj.msgTotalDequeues, 3)
-
- #subscribe from second session here to ensure queue is not auto-deleted
- #when alternate session closes. Use implicit accept mode to test that
- #we don't need to explicitly accept
- session2 = self.conn.session("alternate-session-2", timeout=10)
- session2.message_subscribe(queue = "test-ack-queue", destination = "checker", accept_mode=1)
-
- #now close the first session, and see that the unaccepted messages are
- #then redelivered to another subscriber:
- session1.close(timeout=10)
-
- # check the statistics - the queue_query will show the non-accepted
- # messages have been released. QMF never considered them dequeued, so
- # those counts won't change
- self.assertEqual(2, session2.queue_query(queue="test-ack-queue").message_count)
- queueObj.update()
- self.assertEquals(queueObj.msgDepth, 2)
- self.assertEquals(queueObj.msgTotalEnqueues, 5)
- self.assertEquals(queueObj.msgTotalDequeues, 3)
-
- session2.message_flow(destination="checker", unit=session2.credit_unit.message, value=0xFFFFFFFFL)
- session2.message_flow(destination="checker", unit=session2.credit_unit.byte, value=0xFFFFFFFFL)
- queue = session2.incoming("checker")
-
- msg3b = queue.get(timeout=1)
- msg5b = queue.get(timeout=1)
-
- self.assertEqual("Three", msg3b.body)
- self.assertEqual("Five", msg5b.body)
-
- try:
- extra = queue.get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
- self.assertEqual(0, session2.queue_query(queue="test-ack-queue").message_count)
- queueObj.update()
- self.assertEquals(queueObj.msgDepth, 0)
- self.assertEquals(queueObj.msgTotalEnqueues, 5)
- self.assertEquals(queueObj.msgTotalDequeues, 5)
-
- # Subscribe one last time to keep the queue available, and to verify
- # that the implied accept worked by verifying no messages have been
- # returned when session2 is closed.
- self.session.message_subscribe(queue = "test-ack-queue", destination = "final-checker")
-
- session2.close(timeout=10)
-
- # check the statistics - they should not have changed
- self.assertEqual(0, self.session.queue_query(queue="test-ack-queue").message_count)
- queueObj.update()
- self.assertEquals(queueObj.msgDepth, 0)
- self.assertEquals(queueObj.msgTotalEnqueues, 5)
- self.assertEquals(queueObj.msgTotalDequeues, 5)
-
- self.session.message_flow(destination="final-checker", unit=self.session.credit_unit.message, value=0xFFFFFFFFL)
- self.session.message_flow(destination="final-checker", unit=self.session.credit_unit.byte, value=0xFFFFFFFFL)
- try:
- extra = self.session.incoming("final-checker").get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
- def test_reject(self):
- session = self.session
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True, alternate_exchange="amq.fanout")
- session.queue_declare(queue = "r", exclusive=True, auto_delete=True)
- session.exchange_bind(queue = "r", exchange = "amq.fanout")
-
- session.message_subscribe(queue = "q", destination = "consumer")
- session.message_flow(destination="consumer", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="consumer", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "blah, blah"))
- msg = session.incoming("consumer").get(timeout = 1)
- self.assertEquals(msg.body, "blah, blah")
- session.message_reject(RangedSet(msg.id))
-
- session.message_subscribe(queue = "r", destination = "checker")
- session.message_flow(destination="checker", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="checker", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- msg = session.incoming("checker").get(timeout = 1)
- self.assertEquals(msg.body, "blah, blah")
-
- def test_credit_flow_messages(self):
- """
- Test basic credit based flow control with unit = message
- """
- #declare an exclusive queue
- session = self.session
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
- #create consumer (for now that defaults to infinite credit)
- session.message_subscribe(queue = "q", destination = "c")
- session.message_set_flow_mode(flow_mode = 0, destination = "c")
- #send batch of messages to queue
- for i in range(1, 11):
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "Message %d" % i))
-
- #set message credit to finite amount (less than enough for all messages)
- session.message_flow(unit = session.credit_unit.message, value = 5, destination = "c")
- #set infinite byte credit
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "c")
- #check that expected number were received
- q = session.incoming("c")
- for i in range(1, 6):
- self.assertDataEquals(session, q.get(timeout = 1), "Message %d" % i)
- self.assertEmpty(q)
-
- #increase credit again and check more are received
- for i in range(6, 11):
- session.message_flow(unit = session.credit_unit.message, value = 1, destination = "c")
- self.assertDataEquals(session, q.get(timeout = 1), "Message %d" % i)
- self.assertEmpty(q)
-
- def test_credit_flow_bytes(self):
- """
- Test basic credit based flow control with unit = bytes
- """
- #declare an exclusive queue
- session = self.session
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
- #create consumer (for now that defaults to infinite credit)
- session.message_subscribe(queue = "q", destination = "c")
- session.message_set_flow_mode(flow_mode = 0, destination = "c")
- #send batch of messages to queue
- for i in range(10):
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "abcdefgh"))
-
- #each message is currently interpreted as requiring msg_size bytes of credit
- msg_size = 19
-
- #set byte credit to finite amount (less than enough for all messages)
- session.message_flow(unit = session.credit_unit.byte, value = msg_size*5, destination = "c")
- #set infinite message credit
- session.message_flow(unit = session.credit_unit.message, value = 0xFFFFFFFFL, destination = "c")
- #check that expected number were received
- q = session.incoming("c")
- for i in range(5):
- self.assertDataEquals(session, q.get(timeout = 1), "abcdefgh")
- self.assertEmpty(q)
-
- #increase credit again and check more are received
- for i in range(5):
- session.message_flow(unit = session.credit_unit.byte, value = msg_size, destination = "c")
- self.assertDataEquals(session, q.get(timeout = 1), "abcdefgh")
- self.assertEmpty(q)
-
-
- def test_window_flow_messages(self):
- """
- Test basic window based flow control with unit = message
- """
- #declare an exclusive queue
- session = self.session
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
- #create consumer (for now that defaults to infinite credit)
- session.message_subscribe(queue = "q", destination = "c")
- session.message_set_flow_mode(flow_mode = 1, destination = "c")
- #send batch of messages to queue
- for i in range(1, 11):
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "Message %d" % i))
-
- #set message credit to finite amount (less than enough for all messages)
- session.message_flow(unit = session.credit_unit.message, value = 5, destination = "c")
- #set infinite byte credit
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "c")
- #check that expected number were received
- q = session.incoming("c")
- ids = []
- for i in range(1, 6):
- msg = q.get(timeout = 1)
- ids.append(msg.id)
- self.assertDataEquals(session, msg, "Message %d" % i)
- self.assertEmpty(q)
-
- #acknowledge messages and check more are received
- #TODO: there may be a nicer way of doing this
- for i in ids:
- session.receiver._completed.add(i)
- session.channel.session_completed(session.receiver._completed)
-
- for i in range(6, 11):
- self.assertDataEquals(session, q.get(timeout = 1), "Message %d" % i)
- self.assertEmpty(q)
-
-
- def test_window_flow_bytes(self):
- """
- Test basic window based flow control with unit = bytes
- """
- #declare an exclusive queue
- session = self.session
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
- #create consumer (for now that defaults to infinite credit)
- session.message_subscribe(queue = "q", destination = "c")
- session.message_set_flow_mode(flow_mode = 1, destination = "c")
- #send batch of messages to queue
- for i in range(10):
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "abcdefgh"))
-
- #each message is currently interpreted as requiring msg_size bytes of credit
- msg_size = 19
-
- #set byte credit to finite amount (less than enough for all messages)
- session.message_flow(unit = session.credit_unit.byte, value = msg_size*5, destination = "c")
- #set infinite message credit
- session.message_flow(unit = session.credit_unit.message, value = 0xFFFFFFFFL, destination = "c")
- #check that expected number were received
- q = session.incoming("c")
- msgs = []
- for i in range(5):
- msg = q.get(timeout = 1)
- msgs.append(msg)
- self.assertDataEquals(session, msg, "abcdefgh")
- self.assertEmpty(q)
-
- #ack each message individually and check more are received
- for i in range(5):
- msg = msgs.pop()
- #TODO: there may be a nicer way of doing this
- session.receiver._completed.add(msg.id)
- session.channel.session_completed(session.receiver._completed)
- self.assertDataEquals(session, q.get(timeout = 1), "abcdefgh")
- self.assertEmpty(q)
-
- def test_window_flush_ack_flow(self):
- """
- Test basic window based flow control with unit = bytes
- """
- #declare an exclusive queue
- ssn = self.session
- ssn.queue_declare(queue = "q", exclusive=True, auto_delete=True)
- #create consumer
- ssn.message_subscribe(queue = "q", destination = "c",
- accept_mode=ssn.accept_mode.explicit)
- ssn.message_set_flow_mode(flow_mode = ssn.flow_mode.window, destination = "c")
-
- #send message A
- ssn.message_transfer(message=Message(ssn.delivery_properties(routing_key="q"), "A"))
-
- for unit in ssn.credit_unit.VALUES:
- ssn.message_flow("c", unit, 0xFFFFFFFFL)
-
- q = ssn.incoming("c")
- msgA = q.get(timeout=10)
-
- ssn.message_flush(destination="c")
-
- # XXX
- ssn.receiver._completed.add(msgA.id)
- ssn.channel.session_completed(ssn.receiver._completed)
- ssn.message_accept(RangedSet(msgA.id))
-
- for unit in ssn.credit_unit.VALUES:
- ssn.message_flow("c", unit, 0xFFFFFFFFL)
-
- #send message B
- ssn.message_transfer(message=Message(ssn.delivery_properties(routing_key="q"), "B"))
-
- msgB = q.get(timeout=10)
-
- def test_window_stop(self):
- """
- Ensure window based flow control reacts to stop correctly
- """
- session = self.session
- #setup subscriber on a test queue
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
- session.message_subscribe(queue = "q", destination = "c")
- session.message_set_flow_mode(flow_mode = 1, destination = "c")
- session.message_flow(unit = session.credit_unit.message, value = 5, destination = "c")
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "c")
-
-
- #send batch of messages to queue
- for i in range(0, 10):
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "Message %d" % (i+1)))
-
- #retrieve all delivered messages
- q = session.incoming("c")
- for i in range(0, 5):
- msg = q.get(timeout = 1)
- session.receiver._completed.add(msg.id)#TODO: this may be done automatically
- self.assertDataEquals(session, msg, "Message %d" % (i+1))
-
- session.message_stop(destination = "c")
-
- #now send completions, normally used to move window forward,
- #but after a stop should not do so
- session.channel.session_completed(session.receiver._completed)
-
- #check no more messages are sent
- self.assertEmpty(q)
-
- #re-establish window and check remaining messages
- session.message_flow(unit = session.credit_unit.message, value = 5, destination = "c")
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "c")
- for i in range(0, 5):
- msg = q.get(timeout = 1)
- self.assertDataEquals(session, msg, "Message %d" % (i+6))
-
- def test_credit_window_after_messagestop(self):
- """
- Tests that the broker's credit window size doesnt exceed the requested value when completing
- previous messageTransfer commands after a message_stop and message_flow.
- """
-
- session = self.session
-
- #create queue
- session.queue_declare(queue = self.test_queue_name, exclusive=True, auto_delete=True)
-
- #send 11 messages
- for i in range(1, 12):
- session.message_transfer(message=Message(session.delivery_properties(routing_key=self.test_queue_name), "message-%d" % (i)))
-
-
- #subscribe:
- session.message_subscribe(queue=self.test_queue_name, destination="a")
- a = session.incoming("a")
- session.message_set_flow_mode(flow_mode = 1, destination = "a")
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "a")
- # issue 5 message credits
- session.message_flow(unit = session.credit_unit.message, value = 5, destination = "a")
-
- # get 5 messages
- ids = RangedSet()
- for i in range(1, 6):
- msg = a.get(timeout = 1)
- self.assertEquals("message-%d" % (i), msg.body)
- ids.add(msg.id)
-
- # now try and read a 6th message. we expect this to fail due to exhausted message credit.
- try:
- extra = a.get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
- session.message_stop(destination = "a")
-
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "a")
- session.message_flow(unit = session.credit_unit.message, value = 5, destination = "a")
-
- # complete earlier messages after setting the window to 5 message credits
- session.channel.session_completed(ids)
-
- # Now continue to read the next 5 messages
- for i in range(6, 11):
- msg = a.get(timeout = 1)
- self.assertEquals("message-%d" % (i), msg.body)
-
- # now try and read the 11th message. we expect this to fail due to exhausted message credit. If we receive an
- # 11th this indicates the broker is not respecting the client's requested window size.
- try:
- extra = a.get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
- def test_no_credit_wrap(self):
- """
- Ensure that adding credit does not result in wrapround, lowering the balance.
- """
- session = self.session
-
- session.queue_declare(queue = self.test_queue_name, exclusive=True, auto_delete=True)
- session.message_subscribe(queue=self.test_queue_name, destination="a")
- a = session.incoming("a")
- session.message_set_flow_mode(flow_mode = session.flow_mode.credit, destination = "a")
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "a")
- session.message_flow(unit = session.credit_unit.message, value = 0xFFFFFFFAL, destination = "a")
- #test wraparound of credit balance does not occur
- session.message_flow(unit = session.credit_unit.message, value = 10, destination = "a")
- for i in range(1, 50):
- session.message_transfer(message=Message(session.delivery_properties(routing_key=self.test_queue_name), "message-%d" % (i)))
- session.message_flush(destination = "a")
- for i in range(1, 50):
- msg = a.get(timeout = 1)
- self.assertEquals("message-%d" % (i), msg.body)
-
-
- def test_subscribe_not_acquired(self):
- """
- Test the not-acquired modes works as expected for a simple case
- """
- session = self.session
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
- for i in range(1, 6):
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "Message %s" % i))
-
- session.message_subscribe(queue = "q", destination = "a", acquire_mode = 1)
- session.message_flow(unit = session.credit_unit.message, value = 0xFFFFFFFFL, destination = "a")
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "a")
- session.message_subscribe(queue = "q", destination = "b", acquire_mode = 1)
- session.message_flow(unit = session.credit_unit.message, value = 0xFFFFFFFFL, destination = "b")
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "b")
-
- for i in range(6, 11):
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "Message %s" % i))
-
- #both subscribers should see all messages
- qA = session.incoming("a")
- qB = session.incoming("b")
- for i in range(1, 11):
- for q in [qA, qB]:
- msg = q.get(timeout = 1)
- self.assertEquals("Message %s" % i, msg.body)
- #TODO: tidy up completion
- session.receiver._completed.add(msg.id)
-
- #TODO: tidy up completion
- session.channel.session_completed(session.receiver._completed)
- #messages should still be on the queue:
- self.assertEquals(10, session.queue_query(queue = "q").message_count)
-
- def test_acquire_with_no_accept_and_credit_flow(self):
- """
- Test that messages recieved unacquired, with accept not
- required in windowing mode can be acquired.
- """
- session = self.session
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
-
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "acquire me"))
-
- session.message_subscribe(queue = "q", destination = "a", acquire_mode = 1, accept_mode = 1)
- session.message_set_flow_mode(flow_mode = session.flow_mode.credit, destination = "a")
- session.message_flow(unit = session.credit_unit.message, value = 0xFFFFFFFFL, destination = "a")
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "a")
- msg = session.incoming("a").get(timeout = 1)
- self.assertEquals("acquire me", msg.body)
- #message should still be on the queue:
- self.assertEquals(1, session.queue_query(queue = "q").message_count)
-
- transfers = RangedSet(msg.id)
- response = session.message_acquire(transfers)
- #check that we get notification (i.e. message_acquired)
- self.assert_(msg.id in response.transfers)
- #message should have been removed from the queue:
- self.assertEquals(0, session.queue_query(queue = "q").message_count)
-
- def test_acquire(self):
- """
- Test explicit acquire function
- """
- session = self.session
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
-
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "acquire me"))
-
- session.message_subscribe(queue = "q", destination = "a", acquire_mode = 1)
- session.message_flow(destination="a", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="a", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- msg = session.incoming("a").get(timeout = 1)
- self.assertEquals("acquire me", msg.body)
- #message should still be on the queue:
- self.assertEquals(1, session.queue_query(queue = "q").message_count)
-
- transfers = RangedSet(msg.id)
- response = session.message_acquire(transfers)
- #check that we get notification (i.e. message_acquired)
- self.assert_(msg.id in response.transfers)
- #message should have been removed from the queue:
- self.assertEquals(0, session.queue_query(queue = "q").message_count)
- session.message_accept(transfers)
-
-
- def test_release(self):
- """
- Test explicit release function
- """
- session = self.session
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
-
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "release me"))
-
- session.message_subscribe(queue = "q", destination = "a")
- session.message_flow(destination="a", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="a", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- msg = session.incoming("a").get(timeout = 1)
- self.assertEquals("release me", msg.body)
- session.message_cancel(destination = "a")
- session.message_release(RangedSet(msg.id))
-
- #message should not have been removed from the queue:
- self.assertEquals(1, session.queue_query(queue = "q").message_count)
-
- def test_release_ordering(self):
- """
- Test order of released messages is as expected
- """
- session = self.session
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
- for i in range (1, 11):
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "released message %s" % (i)))
-
- session.message_subscribe(queue = "q", destination = "a")
- session.message_flow(unit = session.credit_unit.message, value = 10, destination = "a")
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "a")
- queue = session.incoming("a")
- first = queue.get(timeout = 1)
- for i in range(2, 10):
- msg = queue.get(timeout = 1)
- self.assertEquals("released message %s" % (i), msg.body)
-
- last = queue.get(timeout = 1)
- self.assertEmpty(queue)
- released = RangedSet()
- released.add(first.id, last.id)
- session.message_release(released)
-
- #TODO: may want to clean this up...
- session.receiver._completed.add(first.id, last.id)
- session.channel.session_completed(session.receiver._completed)
-
- for i in range(1, 11):
- self.assertEquals("released message %s" % (i), queue.get(timeout = 1).body)
-
- def test_ranged_ack(self):
- """
- Test acking of messages ranges
- """
- session = self.conn.session("alternate-session", timeout=10)
-
- session.queue_declare(queue = "q", auto_delete=True)
- delivery_properties = session.delivery_properties(routing_key="q")
- for i in range (1, 11):
- session.message_transfer(message=Message(delivery_properties, "message %s" % (i)))
-
- session.message_subscribe(queue = "q", destination = "a")
- session.message_flow(unit = session.credit_unit.message, value = 10, destination = "a")
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "a")
- queue = session.incoming("a")
- ids = []
- for i in range (1, 11):
- msg = queue.get(timeout = 1)
- self.assertEquals("message %s" % (i), msg.body)
- ids.append(msg.id)
-
- self.assertEmpty(queue)
-
- #ack all but the fourth message (command id 2)
- accepted = RangedSet()
- accepted.add(ids[0], ids[2])
- accepted.add(ids[4], ids[9])
- session.message_accept(accepted)
-
- #subscribe from second session here to ensure queue is not
- #auto-deleted when alternate session closes (no need to ack on these):
- self.session.message_subscribe(queue = "q", destination = "checker")
-
- #now close the session, and see that the unacked messages are
- #then redelivered to another subscriber:
- session.close(timeout=10)
-
- session = self.session
- session.message_flow(destination="checker", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="checker", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- queue = session.incoming("checker")
-
- self.assertEquals("message 4", queue.get(timeout = 1).body)
- self.assertEmpty(queue)
-
- def test_subscribe_not_acquired_2(self):
- session = self.session
-
- #publish some messages
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
- for i in range(1, 11):
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "message-%d" % (i)))
-
- #consume some of them
- session.message_subscribe(queue = "q", destination = "a")
- session.message_set_flow_mode(flow_mode = 0, destination = "a")
- session.message_flow(unit = session.credit_unit.message, value = 5, destination = "a")
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "a")
-
- queue = session.incoming("a")
- for i in range(1, 6):
- msg = queue.get(timeout = 1)
- self.assertEquals("message-%d" % (i), msg.body)
- #complete and accept
- session.message_accept(RangedSet(msg.id))
- #TODO: tidy up completion
- session.receiver._completed.add(msg.id)
- session.channel.session_completed(session.receiver._completed)
- self.assertEmpty(queue)
-
- #now create a not-acquired subscriber
- session.message_subscribe(queue = "q", destination = "b", acquire_mode=1)
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "b")
-
- #check it gets those not consumed
- queue = session.incoming("b")
- session.message_flow(unit = session.credit_unit.message, value = 1, destination = "b")
- for i in range(6, 11):
- msg = queue.get(timeout = 1)
- self.assertEquals("message-%d" % (i), msg.body)
- session.message_release(RangedSet(msg.id))
- #TODO: tidy up completion
- session.receiver._completed.add(msg.id)
- session.channel.session_completed(session.receiver._completed)
- session.message_flow(unit = session.credit_unit.message, value = 1, destination = "b")
- self.assertEmpty(queue)
-
- #check all 'browsed' messages are still on the queue
- self.assertEqual(5, session.queue_query(queue="q").message_count)
-
- def test_subscribe_not_acquired_3(self):
- session = self.session
-
- #publish some messages
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
- for i in range(1, 11):
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "message-%d" % (i)))
-
- #create a not-acquired subscriber
- session.message_subscribe(queue = "q", destination = "a", acquire_mode=1)
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "a")
- session.message_flow(unit = session.credit_unit.message, value = 10, destination = "a")
-
- #browse through messages
- queue = session.incoming("a")
- for i in range(1, 11):
- msg = queue.get(timeout = 1)
- self.assertEquals("message-%d" % (i), msg.body)
- if (i % 2):
- #try to acquire every second message
- response = session.message_acquire(RangedSet(msg.id))
- #check that acquire succeeds
- self.assert_(msg.id in response.transfers)
- session.message_accept(RangedSet(msg.id))
- else:
- session.message_release(RangedSet(msg.id))
- session.receiver._completed.add(msg.id)
- session.channel.session_completed(session.receiver._completed)
- self.assertEmpty(queue)
-
- #create a second not-acquired subscriber
- session.message_subscribe(queue = "q", destination = "b", acquire_mode=1)
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "b")
- session.message_flow(unit = session.credit_unit.message, value = 1, destination = "b")
- #check it gets those not consumed
- queue = session.incoming("b")
- for i in [2,4,6,8,10]:
- msg = queue.get(timeout = 1)
- self.assertEquals("message-%d" % (i), msg.body)
- session.message_release(RangedSet(msg.id))
- session.receiver._completed.add(msg.id)
- session.channel.session_completed(session.receiver._completed)
- session.message_flow(unit = session.credit_unit.message, value = 1, destination = "b")
- self.assertEmpty(queue)
-
- #check all 'browsed' messages are still on the queue
- self.assertEqual(5, session.queue_query(queue="q").message_count)
-
- def test_release_unacquired(self):
- session = self.session
-
- #create queue
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
-
- #send message
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "my-message"))
-
- #create two 'browsers'
- session.message_subscribe(queue = "q", destination = "a", acquire_mode=1)
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "a")
- session.message_flow(unit = session.credit_unit.message, value = 10, destination = "a")
- queueA = session.incoming("a")
-
- session.message_subscribe(queue = "q", destination = "b", acquire_mode=1)
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "b")
- session.message_flow(unit = session.credit_unit.message, value = 10, destination = "b")
- queueB = session.incoming("b")
-
- #have each browser release the message
- msgA = queueA.get(timeout = 1)
- session.message_release(RangedSet(msgA.id))
-
- msgB = queueB.get(timeout = 1)
- session.message_release(RangedSet(msgB.id))
-
- #cancel browsers
- session.message_cancel(destination = "a")
- session.message_cancel(destination = "b")
-
- #create consumer
- session.message_subscribe(queue = "q", destination = "c")
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "c")
- session.message_flow(unit = session.credit_unit.message, value = 10, destination = "c")
- queueC = session.incoming("c")
- #consume the message then ack it
- msgC = queueC.get(timeout = 1)
- session.message_accept(RangedSet(msgC.id))
- #ensure there are no other messages
- self.assertEmpty(queueC)
-
- def test_release_order(self):
- session = self.session
-
- #create queue
- session.queue_declare(queue = "q", exclusive=True, auto_delete=True)
-
- #send messages
- for i in range(1, 11):
- session.message_transfer(message=Message(session.delivery_properties(routing_key="q"), "message-%d" % (i)))
-
- #subscribe:
- session.message_subscribe(queue="q", destination="a")
- a = session.incoming("a")
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "a")
- session.message_flow(unit = session.credit_unit.message, value = 10, destination = "a")
-
- # receive all messages into list
- messages = [];
- for i in range(1, 11):
- msg = a.get(timeout = 1)
- self.assertEquals("message-%d" % (i), msg.body)
- messages.append(msg)
-
- # accept/release received messages
- for i, msg in enumerate(messages, start=1):
- if (i % 2):
- #accept all odd messages
- session.message_accept(RangedSet(msg.id))
- else:
- #release all even messages
- session.message_release(RangedSet(msg.id))
-
- session.message_subscribe(queue="q", destination="b", acquire_mode=0)
- b = session.incoming("b")
- b.start()
- for i in [2, 4, 6, 8, 10]:
- msg = b.get(timeout = 1)
- self.assertEquals("message-%d" % (i), msg.body)
-
-
- def test_empty_body(self):
- session = self.session
- session.queue_declare(queue="xyz", exclusive=True, auto_delete=True)
- props = session.delivery_properties(routing_key="xyz")
- session.message_transfer(message=Message(props, ""))
-
- consumer_tag = "tag1"
- session.message_subscribe(queue="xyz", destination=consumer_tag)
- session.message_flow(unit = session.credit_unit.message, value = 0xFFFFFFFFL, destination = consumer_tag)
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = consumer_tag)
- queue = session.incoming(consumer_tag)
- msg = queue.get(timeout=1)
- self.assertEquals("", msg.body)
- session.message_accept(RangedSet(msg.id))
-
- def test_incoming_start(self):
- q = "test_incoming_start"
- session = self.session
-
- session.queue_declare(queue=q, exclusive=True, auto_delete=True)
- session.message_subscribe(queue=q, destination="msgs")
- messages = session.incoming("msgs")
- assert messages.destination == "msgs"
-
- dp = session.delivery_properties(routing_key=q)
- session.message_transfer(message=Message(dp, "test"))
-
- messages.start()
- msg = messages.get()
- assert msg.body == "test"
-
- def test_ttl(self):
- q = "test_ttl"
- session = self.session
-
- session.queue_declare(queue=q, exclusive=True, auto_delete=True)
-
- dp = session.delivery_properties(routing_key=q, ttl=500)#expire in half a second
- session.message_transfer(message=Message(dp, "first"))
-
- dp = session.delivery_properties(routing_key=q, ttl=300000)#expire in fives minutes
- session.message_transfer(message=Message(dp, "second"))
-
- d = "msgs"
- session.message_subscribe(queue=q, destination=d)
- messages = session.incoming(d)
- sleep(1)
- session.message_flow(unit = session.credit_unit.message, value=2, destination=d)
- session.message_flow(unit = session.credit_unit.byte, value=0xFFFFFFFFL, destination=d)
- assert messages.get(timeout=1).body == "second"
- self.assertEmpty(messages)
-
- def assertDataEquals(self, session, msg, expected):
- self.assertEquals(expected, msg.body)
-
- def assertEmpty(self, queue):
- try:
- extra = queue.get(timeout=1)
- self.fail("Queue not empty, contains: " + extra.body)
- except Empty: None
-
-class SizelessContent(Content):
-
- def size(self):
- return None
diff --git a/qpid/python/qpid_tests/broker_0_10/msg_groups.py b/qpid/python/qpid_tests/broker_0_10/msg_groups.py
deleted file mode 100644
index ec015e1be4..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/msg_groups.py
+++ /dev/null
@@ -1,1195 +0,0 @@
-#
-# 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.
-#
-
-from qpid.messaging import *
-from qpid.tests.messaging import Base
-import qmf.console
-
-from time import sleep
-#
-# Tests the Broker's support for message groups
-#
-
-class MultiConsumerMsgGroupTests(Base):
- """
- Tests for the behavior of multi-consumer message groups. These tests allow
- a messages from the same group be consumed by multiple different clients as
- long as each message is processed "in sequence". See QPID-3346 for
- details.
- """
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self):
- return self.conn.session()
-
- def test_simple(self):
- """ Verify simple acquire/accept actions on a set of grouped
- messages shared between two receivers.
- """
- ## Create a msg group queue
-
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","A","A","B","B","B","C","C","C"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- ## Queue = a-0, a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8...
- ## Owners= ---, ---, ---, ---, ---, ---, ---, ---, ---,
-
- # create consumers on separate sessions: C1,C2
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- # C1 should acquire A-0, then C2 should acquire B-3
-
- m1 = c1.fetch(0);
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- m2 = c2.fetch(0);
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 3
-
- # C1 Acknowledge A-0
- c1.session.acknowledge(m1);
-
- # C2 should next acquire A-1
- m3 = c2.fetch(0);
- assert m3.properties['THE-GROUP'] == 'A'
- assert m3.content['index'] == 1
-
- # C1 should next acquire C-6, since groups A&B are held by c2
- m4 = c1.fetch(0);
- assert m4.properties['THE-GROUP'] == 'C'
- assert m4.content['index'] == 6
-
- ## Queue = XXX, a-1, a-2, b-3, b-4, b-5, c-6, c-7, c-8...
- ## Owners= ---, ^C2, +C2, ^C2, +C2, +C2, ^C1, +C1, +C1,
-
- # C2 Acknowledge B-3, freeing up the rest of B group
- c2.session.acknowledge(m2);
-
- ## Queue = XXX, a-1, a-2, XXX, b-4, b-5, c-6, c-7, c-8...
- ## Owners= ---, ^C2, +C2, ---, ---, ---, ^C1, +C1, +C1,
-
- # C1 should now acquire B-4, since it is next "free"
- m5 = c1.fetch(0);
- assert m5.properties['THE-GROUP'] == 'B'
- assert m5.content['index'] == 4
-
- ## Queue = XXX, a-1, a-2, XXX, b-4, b-5, c-6, c-7, c-8...
- ## Owners= ---, ^C2, +C2, ---, ^C1, +C1, ^C1, +C1, +C1,
-
- # C1 acknowledges C-6, freeing the C group
- c1.session.acknowledge(m4)
-
- ## Queue = XXX, a-1, a-2, XXX, b-4, b-5, XXX, c-7, c-8...
- ## Owners= ---, ^C2, +C2, ---, ^C1, +C1, ---, ---, ---
-
- # C2 should next fetch A-2, followed by C-7
- m7 = c2.fetch(0);
- assert m7.properties['THE-GROUP'] == 'A'
- assert m7.content['index'] == 2
-
- m8 = c2.fetch(0);
- assert m8.properties['THE-GROUP'] == 'C'
- assert m8.content['index'] == 7
-
- ## Queue = XXX, a-1, a-2, XXX, b-4, b-5, XXX, c-7, c-8...
- ## Owners= ---, ^C2, ^C2, ---, ^C1, +C1, ---, ^C2, +C2
-
- # have C2 ack all fetched messages, freeing C-8
- c2.session.acknowledge()
-
- ## Queue = XXX, XXX, XXX, XXX, b-4, b-5, XXX, XXX, c-8...
- ## Owners= ---, ---, ---, ---, ^C1, +C1, ---, ---, ---
-
- # the next fetch of C2 would get C-8, since B-5 is "owned"
- m9 = c2.fetch(0);
- assert m9.properties['THE-GROUP'] == 'C'
- assert m9.content['index'] == 8
-
- ## Queue = XXX, XXX, XXX, XXX, b-4, b-5, XXX, XXX, c-8...
- ## Owners= ---, ---, ---, ---, ^C1, +C1, ---, ---, ^C2
-
- # C1 acks B-4, freeing B-5 for consumption
- c1.session.acknowledge(m5)
-
- ## Queue = XXX, XXX, XXX, XXX, XXX, b-5, XXX, XXX, c-8...
- ## Owners= ---, ---, ---, ---, ---, ^C2, ---, ---, ^C2
-
- # the next fetch of C2 would get B-5
- m10 = c2.fetch(0);
- assert m10.properties['THE-GROUP'] == 'B'
- assert m10.content['index'] == 5
-
- # there should be no more left for C1:
- try:
- mx = c1.fetch(0)
- assert False # should never get here
- except Empty:
- pass
-
- c1.session.acknowledge()
- c2.session.acknowledge()
- c1.close()
- c2.close()
- snd.close()
-
- def test_simple_browse(self):
- """ Test the behavior of a browsing subscription on a message grouping
- queue.
- """
-
- ## Create a msg group queue
-
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- ## Queue = A-0, B-1, A-2, b-3, C-4
- ## Owners= ---, ---, ---, ---, ---
-
- # create consumer and browser
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- b1 = s2.receiver("msg-group-q; {mode: browse}", options={"capacity":0})
-
- m2 = b1.fetch(0);
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 0
-
- # C1 should acquire A-0
-
- m1 = c1.fetch(0);
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- ## Queue = A-0, B-1, A-2, b-3, C-4
- ## Owners= ^C1, ---, +C1, ---, ---
-
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 1
-
- # verify that the browser may see A-2, even though its group is owned
- # by C1
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 2
-
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 3
-
- # verify the consumer can own groups currently seen by the browser
- m3 = c1.fetch(0);
- assert m3.properties['THE-GROUP'] == 'B'
- assert m3.content['index'] == 1
-
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] == 'C'
- assert m2.content['index'] == 4
-
- def test_release(self):
- """ Verify releasing a message can free its assocated group
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","A","B","B"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 2
-
- # C1 release m1, and the first group
-
- s1.acknowledge(m1, Disposition(RELEASED, set_redelivered=True))
-
- # C2 should be able to get group 'A', msg 'A-0' now
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 0
-
- def test_reject(self):
- """ Verify rejecting a message can free its associated group
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","A","B","B"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 2
-
- # C1 rejects m1, and the first group is released
- s1.acknowledge(m1, Disposition(REJECTED))
-
- # C2 should be able to get group 'A', msg 'A-1' now
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 1
-
- def test_close(self):
- """ Verify behavior when a consumer that 'owns' a group closes.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","A","B","B"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- # C1 will own group A
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # C2 will own group B
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 2
-
- # C1 shuffles off the mortal coil...
- c1.close();
-
- # but the session (s1) remains active, so "A" remains blocked
- # from c2, c2 should fetch the next B-3
-
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 3
-
- # and there should be no more messages available for C2
- try:
- m2 = c2.fetch(0)
- assert False # should never get here
- except Empty:
- pass
-
- # close session s1, releasing the A group
- s1.close()
-
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 0
-
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 1
-
- # and there should be no more messages now
- try:
- m2 = c2.fetch(0)
- assert False # should never get here
- except Empty:
- pass
-
- def test_transaction(self):
- """ Verify behavior when using transactions.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","A","B","B","A","B"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- s1 = self.conn.session(transactional=True)
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.conn.session(transactional=True)
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- # C1 gets group A
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # C2 gets group B
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 2
-
- s1.acknowledge(m1) # A-0 consumed, A group freed
- s2.acknowledge(m2) # B-2 consumed, B group freed
-
- s1.commit() # A-0 consumption done, A group now free
- s2.rollback() # releases B-2, and group B
-
- ## Q: ["A1","B2","B3","A4","B5"]
-
- # C2 should be able to get the next A
- m3 = c2.fetch(0)
- assert m3.properties['THE-GROUP'] == 'A'
- assert m3.content['index'] == 1
-
- # C1 should be able to get B-2
- m4 = c1.fetch(0)
- assert m4.properties['THE-GROUP'] == 'B'
- assert m4.content['index'] == 2
-
- s2.acknowledge(m3) # C2 consumes A-1
- s1.acknowledge(m4) # C1 consumes B-2
- s1.commit() # C1 consume B-2 occurs, free group B
-
- ## Q: [["A1",]"B3","A4","B5"]
-
- # A-1 is still considered owned by C2, since the commit has yet to
- # occur, so the next available to C1 would be B-3
- m5 = c1.fetch(0) # B-3
- assert m5.properties['THE-GROUP'] == 'B'
- assert m5.content['index'] == 3
-
- # and C2 should find A-4 available, since it owns the A group
- m6 = c2.fetch(0) # A-4
- assert m6.properties['THE-GROUP'] == 'A'
- assert m6.content['index'] == 4
-
- s2.acknowledge(m6) # C2 consumes A-4
-
- # uh-oh, A-1 and A-4 released, along with A group
- s2.rollback()
-
- ## Q: ["A1",["B3"],"A4","B5"]
- m7 = c1.fetch(0) # A-1 is found
- assert m7.properties['THE-GROUP'] == 'A'
- assert m7.content['index'] == 1
-
- ## Q: [["A1"],["B3"],"A4","B5"]
- # since C1 "owns" both A and B group, C2 should find nothing available
- try:
- m8 = c2.fetch(0)
- assert False # should not get here
- except Empty:
- pass
-
- # C1 next gets A4
- m9 = c1.fetch(0)
- assert m9.properties['THE-GROUP'] == 'A'
- assert m9.content['index'] == 4
-
- s1.acknowledge()
-
- ## Q: [["A1"],["B3"],["A4"],"B5"]
- # even though C1 acknowledges A1,B3, and A4, B5 is still considered
- # owned as the commit has yet to take place
- try:
- m10 = c2.fetch(0)
- assert False # should not get here
- except Empty:
- pass
-
- # now A1,B3,A4 dequeued, B5 should be free
- s1.commit()
-
- ## Q: ["B5"]
- m11 = c2.fetch(0)
- assert m11.properties['THE-GROUP'] == 'B'
- assert m11.content['index'] == 5
-
- s2.acknowledge()
- s2.commit()
-
- def test_send_transaction(self):
- """ Verify behavior when sender is using transactions.
- """
- ssn = self.conn.session(transactional=True)
- snd = ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- msg = Message(content={'index':0}, properties={"THE-GROUP": "A"})
- snd.send(msg)
- msg = Message(content={'index':1}, properties={"THE-GROUP": "B"})
- snd.send(msg)
- snd.session.commit()
- msg = Message(content={'index':2}, properties={"THE-GROUP": "A"})
- snd.send(msg)
-
- # Queue: [A0,B1, (uncommitted: A2) ]
-
- s1 = self.conn.session(transactional=True)
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.conn.session(transactional=True)
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- # C1 gets A0, group A
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # C2 gets B2, group B
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 1
-
- # Since A2 uncommitted, there should be nothing left to fetch
- try:
- mX = c1.fetch(0)
- assert False # should not get here
- except Empty:
- pass
- try:
- mX = c2.fetch(0)
- assert False # should not get here
- except Empty:
- pass
-
- snd.session.commit()
- msg = Message(content={'index':3}, properties={"THE-GROUP": "B"})
- snd.send(msg)
-
- # Queue: [A2, (uncommitted: B3) ]
-
- # B3 has yet to be committed, so C2 should see nothing available:
- try:
- mX = c2.fetch(0)
- assert False # should not get here
- except Empty:
- pass
-
- # but A2 should be available to C1
- m3 = c1.fetch(0)
- assert m3.properties['THE-GROUP'] == 'A'
- assert m3.content['index'] == 2
-
- # now make B3 available
- snd.session.commit()
-
- # C1 should still be done:
- try:
- mX = c1.fetch(0)
- assert False # should not get here
- except Empty:
- pass
-
- # but C2 should find the new B
- m4 = c2.fetch(0)
- assert m4.properties['THE-GROUP'] == 'B'
- assert m4.content['index'] == 3
-
- # extra: have C1 rollback, verify C2 finds the released 'A' messages
- c1.session.rollback()
-
- ## Q: ["A0","A2"]
-
- # C2 should be able to get the next A
- m5 = c2.fetch(0)
- assert m5.properties['THE-GROUP'] == 'A'
- assert m5.content['index'] == 0
-
- m6 = c2.fetch(0)
- assert m6.properties['THE-GROUP'] == 'A'
- assert m6.content['index'] == 2
-
- c2.session.acknowledge()
- c2.session.commit()
-
- def test_query(self):
- """ Verify the queue query method against message groups
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","C","A","B","C","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- m1 = c1.fetch(0)
- m2 = c2.fetch(0)
-
- # at this point, group A should be owned by C1, group B by C2, and
- # group C should be available
-
- # now setup a QMF session, so we can call methods
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- brokers = self.qmf_session.getObjects(_class="broker")
- assert len(brokers) == 1
- broker = brokers[0]
-
- # verify the query method call's group information
- rc = broker.query("queue", "msg-group-q")
- assert rc.status == 0
- assert rc.text == "OK"
- results = rc.outArgs['results']
- assert 'qpid.message_group_queue' in results
- q_info = results['qpid.message_group_queue']
- assert 'group_header_key' in q_info and q_info['group_header_key'] == "THE-GROUP"
- assert 'group_state' in q_info and len(q_info['group_state']) == 3
- for g_info in q_info['group_state']:
- assert 'group_id' in g_info
- if g_info['group_id'] == "A":
- assert g_info['msg_count'] == 3
- assert g_info['consumer'] != ""
- elif g_info['group_id'] == "B":
- assert g_info['msg_count'] == 2
- assert g_info['consumer'] != ""
- elif g_info['group_id'] == "C":
- assert g_info['msg_count'] == 2
- assert g_info['consumer'] == ""
- else:
- assert(False) # should never get here
- self.qmf_session.delBroker(self.qmf_broker)
-
- def test_purge_free(self):
- """ Verify we can purge a queue of all messages of a given "unowned"
- group.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- # now setup a QMF session, so we can call methods
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- queue = self.qmf_session.getObjects(_class="queue", name="msg-group-q")[0]
- assert queue
- msg_filter = { 'filter_type' : 'header_match_str',
- 'filter_params' : { 'header_key' : "THE-GROUP",
- 'header_value' : "B" }}
- assert queue.msgDepth == 6
- rc = queue.purge(0, msg_filter)
- assert rc.status == 0
- queue.update()
- assert queue.msgDepth == 4
-
- # verify all B's removed....
- s2 = self.setup_session()
- b1 = s2.receiver("msg-group-q; {mode: browse}", options={"capacity":0})
- count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] != 'B'
- count += 1
- except Empty:
- pass
- assert count == 4
-
- self.qmf_session.delBroker(self.qmf_broker)
-
- def test_purge_acquired(self):
- """ Verify we can purge messages from an acquired group.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- # acquire group "A"
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # now setup a QMF session, so we can purge group A
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- queue = self.qmf_session.getObjects(_class="queue", name="msg-group-q")[0]
- assert queue
- msg_filter = { 'filter_type' : 'header_match_str',
- 'filter_params' : { 'header_key' : "THE-GROUP",
- 'header_value' : "A" }}
- assert queue.msgDepth == 6
- rc = queue.purge(0, msg_filter)
- assert rc.status == 0
- queue.update()
- queue.msgDepth == 4 # the pending acquired A still counts!
- s1.acknowledge()
-
- # verify all other A's removed....
- s2 = self.setup_session()
- b1 = s2.receiver("msg-group-q; {mode: browse}", options={"capacity":0})
- count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] != 'A'
- count += 1
- except Empty:
- pass
- assert count == 3 # only 3 really available
- s1.acknowledge() # ack the consumed A-0
- self.qmf_session.delBroker(self.qmf_broker)
-
- def test_purge_count(self):
- """ Verify we can purge a fixed number of messages from an acquired
- group.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- # acquire group "A"
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # now setup a QMF session, so we can purge group A
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- queue = self.qmf_session.getObjects(_class="queue", name="msg-group-q")[0]
- assert queue
- msg_filter = { 'filter_type' : 'header_match_str',
- 'filter_params' : { 'header_key' : "THE-GROUP",
- 'header_value' : "A" }}
- assert queue.msgDepth == 6
- rc = queue.purge(1, msg_filter)
- assert rc.status == 0
- queue.update()
- queue.msgDepth == 5 # the pending acquired A still counts!
-
- # verify all other A's removed....
- s2 = self.setup_session()
- b1 = s2.receiver("msg-group-q; {mode: browse}", options={"capacity":0})
- count = 0
- a_count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- if m2.properties['THE-GROUP'] != 'A':
- count += 1
- else:
- a_count += 1
- except Empty:
- pass
- assert count == 3 # non-A's
- assert a_count == 1 # assumes the acquired message was not the one purged and regular browsers don't get acquired messages
- s1.acknowledge() # ack the consumed A-0
- self.qmf_session.delBroker(self.qmf_broker)
-
- def test_move_all(self):
- """ Verify we can move messages from an acquired group.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- # set up destination queue
- rcvr = self.ssn.receiver("dest-q; {create:always, delete:receiver," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- # acquire group "A"
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # now setup a QMF session, so we can move what's left of group A
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- brokers = self.qmf_session.getObjects(_class="broker")
- assert len(brokers) == 1
- broker = brokers[0]
- msg_filter = { 'filter_type' : 'header_match_str',
- 'filter_params' : { 'header_key' : "THE-GROUP",
- 'header_value' : "A" }}
- rc = broker.queueMoveMessages("msg-group-q", "dest-q", 0, msg_filter)
- assert rc.status == 0
-
- # verify all other A's removed from msg-group-q
- s2 = self.setup_session()
- b1 = s2.receiver("msg-group-q", options={"capacity":0})
- count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] != 'A'
- count += 1
- except Empty:
- pass
- assert count == 3 # only 3 really available
-
- # verify the moved A's are at the dest-q
- s2 = self.setup_session()
- b1 = s2.receiver("dest-q; {mode: browse}", options={"capacity":0})
- count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 2 or m2.content['index'] == 5
- count += 1
- except Empty:
- pass
- assert count == 2 # two A's moved
-
- s1.acknowledge() # ack the consumed A-0
- self.qmf_session.delBroker(self.qmf_broker)
-
- def test_move_count(self):
- """ Verify we can move a fixed number of messages from an acquired group.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- # set up destination queue
- rcvr = self.ssn.receiver("dest-q; {create:always, delete:receiver," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- # now setup a QMF session, so we can move group B
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- brokers = self.qmf_session.getObjects(_class="broker")
- assert len(brokers) == 1
- broker = brokers[0]
- msg_filter = { 'filter_type' : 'header_match_str',
- 'filter_params' : { 'header_key' : "THE-GROUP",
- 'header_value' : "B" }}
- rc = broker.queueMoveMessages("msg-group-q", "dest-q", 3, msg_filter)
- assert rc.status == 0
-
- # verify all B's removed from msg-group-q
- s2 = self.setup_session()
- b1 = s2.receiver("msg-group-q; {mode: browse}", options={"capacity":0})
- count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] != 'B'
- count += 1
- except Empty:
- pass
- assert count == 4
-
- # verify the moved B's are at the dest-q
- s2 = self.setup_session()
- b1 = s2.receiver("dest-q; {mode: browse}", options={"capacity":0})
- count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 1 or m2.content['index'] == 3
- count += 1
- except Empty:
- pass
- assert count == 2
-
- self.qmf_session.delBroker(self.qmf_broker)
-
- def test_reroute(self):
- """ Verify we can reroute messages from an acquired group.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- # create a topic exchange for the reroute
- rcvr = self.ssn.receiver("reroute-q; {create: always, delete:receiver," +
- " node: {type: topic}}")
-
- # acquire group "A"
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # now setup a QMF session, so we can reroute group A
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- queue = self.qmf_session.getObjects(_class="queue", name="msg-group-q")[0]
- assert queue
- msg_filter = { 'filter_type' : 'header_match_str',
- 'filter_params' : { 'header_key' : "THE-GROUP",
- 'header_value' : "A" }}
- assert queue.msgDepth == 6
- rc = queue.reroute(0, False, "reroute-q", msg_filter)
- assert rc.status == 0
- queue.update()
- queue.msgDepth == 4 # the pending acquired A still counts!
-
- # verify all other A's removed....
- s2 = self.setup_session()
- b1 = s2.receiver("msg-group-q", options={"capacity":0})
- count = 0
- try:
- while True:
- m2 = b1.fetch(0)
- assert m2.properties['THE-GROUP'] != 'A'
- count += 1
- except Empty:
- pass
- assert count == 3 # only 3 really available
-
- # and what of reroute-q?
- count = 0
- try:
- while True:
- m2 = rcvr.fetch(0)
- assert m2.properties['THE-GROUP'] == 'A'
- assert m2.content['index'] == 2 or m2.content['index'] == 5
- count += 1
- except Empty:
- pass
- assert count == 2
-
- s1.acknowledge() # ack the consumed A-0
- self.qmf_session.delBroker(self.qmf_broker)
-
- def test_queue_delete(self):
- """ Test deleting a queue while consumers are active.
- """
-
- ## Create a msg group queue
-
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A","B","C"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- ## Queue = A-0, B-1, A-2, b-3, C-4
- ## Owners= ---, ---, ---, ---, ---
-
- # create consumers
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- # C1 should acquire A-0
- m1 = c1.fetch(0);
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- # c2 acquires B-1
- m2 = c2.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 1
-
- # with group A and B owned, and C free, delete the
- # queue
- snd.close()
- self.ssn.close()
-
- def test_default_group_id(self):
- """ Verify the queue assigns the default group id should a message
- arrive without a group identifier.
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- m = Message(content={}, properties={"NO-GROUP-HEADER":"HA-HA"})
- snd.send(m)
-
- # now setup a QMF session, so we can call methods
- self.qmf_session = qmf.console.Session()
- self.qmf_broker = self.qmf_session.addBroker(str(self.broker))
- brokers = self.qmf_session.getObjects(_class="broker")
- assert len(brokers) == 1
- broker = brokers[0]
-
- # grab the group state off the queue, and verify the default group is
- # present ("qpid.no-group" is the broker default)
- rc = broker.query("queue", "msg-group-q")
- assert rc.status == 0
- assert rc.text == "OK"
- results = rc.outArgs['results']
- assert 'qpid.message_group_queue' in results
- q_info = results['qpid.message_group_queue']
- assert 'group_header_key' in q_info and q_info['group_header_key'] == "THE-GROUP"
- assert 'group_state' in q_info and len(q_info['group_state']) == 1
- g_info = q_info['group_state'][0]
- assert 'group_id' in g_info
- assert g_info['group_id'] == 'qpid.no-group'
-
- self.qmf_session.delBroker(self.qmf_broker)
-
-
- def test_transaction_order(self):
- """ Verify that rollback does not reorder the messages with respect to
- the consumer (QPID-3804)
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","A"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- snd.send(m)
-
- s1 = self.conn.session(transactional=True)
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
-
- # C1 gets group A
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
- s1.acknowledge(m1)
-
- s1.rollback() # release A back to the queue
-
- # the order should be preserved as follows:
-
- m1 = c1.fetch(0)
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- m2 = c1.fetch(0)
- assert m2.properties['THE-GROUP'] == 'B'
- assert m2.content['index'] == 1
-
- m3 = c1.fetch(0)
- assert m3.properties['THE-GROUP'] == 'A'
- assert m3.content['index'] == 2
-
- s1.commit()
-
- c1.close()
- s1.close()
- snd.close()
-
-
- def test_ttl_expire(self):
- """ Verify that expired (TTL) group messages are skipped correctly
- """
- snd = self.ssn.sender("msg-group-q; {create:always, delete:sender," +
- " node: {x-declare: {arguments:" +
- " {'qpid.group_header_key':'THE-GROUP'," +
- "'qpid.shared_msg_group':1}}}}")
-
- groups = ["A","B","C","A","B","C"]
- messages = [Message(content={}, properties={"THE-GROUP": g}) for g in groups]
- index = 0
- for m in messages:
- m.content['index'] = index
- index += 1
- if m.properties['THE-GROUP'] == 'B':
- m.ttl = 1;
- snd.send(m)
-
- sleep(2) # let all B's expire
-
- # create consumers on separate sessions: C1,C2
- s1 = self.setup_session()
- c1 = s1.receiver("msg-group-q", options={"capacity":0})
- s2 = self.setup_session()
- c2 = s2.receiver("msg-group-q", options={"capacity":0})
-
- # C1 should acquire A-0, then C2 should acquire C-2, Group B should
- # expire and never be fetched
-
- m1 = c1.fetch(0);
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 0
-
- m2 = c2.fetch(0);
- assert m2.properties['THE-GROUP'] == 'C'
- assert m2.content['index'] == 2
-
- m1 = c1.fetch(0);
- assert m1.properties['THE-GROUP'] == 'A'
- assert m1.content['index'] == 3
-
- m2 = c2.fetch(0);
- assert m2.properties['THE-GROUP'] == 'C'
- assert m2.content['index'] == 5
-
- # there should be no more left for either consumer
- try:
- mx = c1.fetch(0)
- assert False # should never get here
- except Empty:
- pass
- try:
- mx = c2.fetch(0)
- assert False # should never get here
- except Empty:
- pass
-
- c1.session.acknowledge()
- c2.session.acknowledge()
- c1.close()
- c2.close()
- snd.close()
-
-
-class StickyConsumerMsgGroupTests(Base):
- """
- Tests for the behavior of sticky-consumer message groups. These tests
- expect all messages from the same group be consumed by the same clients.
- See QPID-3347 for details.
- """
- pass # TBD
diff --git a/qpid/python/qpid_tests/broker_0_10/new_api.py b/qpid/python/qpid_tests/broker_0_10/new_api.py
deleted file mode 100644
index 4e94395121..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/new_api.py
+++ /dev/null
@@ -1,358 +0,0 @@
-#
-# 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.
-#
-
-from qpid.tests.messaging.implementation import *
-from qpid.tests.messaging import Base
-from qpidtoollibs import BrokerAgent
-from time import sleep
-
-#
-# Broker tests using the new messaging API
-#
-
-class GeneralTests(Base):
- """
- Tests of the API and broker via the new API.
- """
-
- def assertEqual(self, left, right, text=None):
- if not left == right:
- print "assertEqual failure: %r != %r" % (left, right)
- if text:
- print " %r" % text
- assert None
-
- def fail(self, text=None):
- if text:
- print "Fail: %r" % text
- assert None
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self):
- return self.conn.session()
-
- def test_not_found(self):
- ssn = self.setup_session()
- try:
- ssn.receiver("does-not-exist")
- self.fail("Expected non-existent node to cause NotFound exception")
- except NotFound, e: None
-
- def test_qpid_3481_acquired_to_alt_exchange(self):
- """
- Verify that acquired messages are routed to the alternate when the queue is deleted.
- """
- sess1 = self.setup_session()
- sess2 = self.setup_session()
-
- tx = sess1.sender("amq.direct/key")
- rx_main = sess1.receiver("amq.direct/key;{link:{reliability:at-least-once,x-declare:{alternate-exchange:'amq.fanout'}}}")
- rx_alt = sess2.receiver("amq.fanout")
- rx_alt.capacity = 10
-
- tx.send("DATA")
- tx.send("DATA")
- tx.send("DATA")
- tx.send("DATA")
- tx.send("DATA")
-
- msg = rx_main.fetch()
- msg = rx_main.fetch()
- msg = rx_main.fetch()
-
- self.assertEqual(rx_alt.available(), 0, "No messages should have been routed to the alt_exchange")
-
- sess1.close()
- sleep(1)
- self.assertEqual(rx_alt.available(), 5, "All 5 messages should have been routed to the alt_exchange")
-
- sess2.close()
-
- def test_qpid_3481_acquired_to_alt_exchange_2_consumers(self):
- """
- Verify that acquired messages are routed to the alternate when the queue is deleted.
- """
- sess1 = self.setup_session()
- sess2 = self.setup_session()
- sess3 = self.setup_session()
- sess4 = self.setup_session()
-
- tx = sess1.sender("test_acquired;{create:always,delete:always,node:{x-declare:{alternate-exchange:'amq.fanout'}}}")
- rx_main1 = sess2.receiver("test_acquired")
- rx_main2 = sess3.receiver("test_acquired")
- rx_alt = sess4.receiver("amq.fanout")
- rx_alt.capacity = 10
-
- tx.send("DATA")
- tx.send("DATA")
- tx.send("DATA")
- tx.send("DATA")
- tx.send("DATA")
-
- msg = rx_main1.fetch()
- msg = rx_main1.fetch()
- msg = rx_main1.fetch()
-
- self.assertEqual(rx_alt.available(), 0, "No messages should have been routed to the alt_exchange")
-
- # Close sess1; This will cause the queue to be deleted and all its messages (including those acquired) to be reouted to the alternate exchange
- sess1.close()
- sleep(1)
- self.assertEqual(rx_alt.available(), 5, "All the messages should have been routed to the alt_exchange")
-
- # Close sess2; This will cause the acquired messages to be requeued and routed to the alternate
- sess2.close()
- for i in range(5):
- try:
- m = rx_alt.fetch(0)
- except:
- self.fail("failed to receive all 5 messages via alternate exchange")
-
- sess3.close()
- self.assertEqual(rx_alt.available(), 0, "No further messages should be received via the alternate exchange")
-
- sess4.close()
-
- def test_next_receiver(self):
- keys = ["a", "b", "c"]
- receivers = [self.ssn.receiver("amq.direct/%s" % k) for k in keys]
- for r in receivers:
- r.capacity = 10
-
- snd = self.ssn.sender("amq.direct")
-
- for k in keys:
- snd.send(Message(subject=k, content=k))
-
- expected = keys
- while len(expected):
- rcv = self.ssn.next_receiver(timeout=self.delay())
- c = rcv.fetch().content
- assert c in expected
- expected.remove(c)
- self.ssn.acknowledge()
-
- def test_nolocal_rerouted(self):
- conn2 = Connection.establish(self.broker, **self.connection_options())
- ssn2 = conn2.session()
-
- s1 = self.ssn.sender("holding_q; {create:always, delete:always, node:{x-declare:{alternate-exchange:'amq.fanout'}}}");
- s2 = ssn2.sender("holding_q");
-
- s2.send(Message("a"));
- s1.send(Message("b"));
- s2.send(Message("c"));
-
- r = self.ssn.receiver("amq.fanout; {link:{x-declare:{arguments:{'no-local':True}}}}")
-
- # close connection of one of the publishers
- conn2.close()
-
- # close sender which should cause the orphaned messages on
- # holding_q to be rerouted through alternate exchange onto the
- # subscription queue of the receiver above
- s1.close()
-
- received = []
- try:
- while True:
- received.append(r.fetch(0).content)
- except Empty: pass
- self.assertEqual(received, ["a", "c"])
-
- def _node_disambiguation_test(self, e, q, ambiguous_send=False):
- s1 = self.ssn.sender("ambiguous; {node:{type:topic}}");
- s2 = self.ssn.sender("ambiguous; {node:{type:queue}}");
- s1.send(Message("a"))
- s2.send(Message("b"))
- if ambiguous_send:
- # pure python client defaults to using the queue when the
- # node name is ambiguous and no type is specified; the
- # swigged version treats this as an error
- s3 = self.ssn.sender("ambiguous");
- s3.send(Message("c"))
- self.assertEqual(e.fetch().content, "a")
- self.assertEqual(q.fetch().content, "b")
- if ambiguous_send:
- self.assertEqual(q.fetch().content, "c")
- for r in [e, q]:
- try:
- m = r.fetch(timeout=0)
- self.fail("Found unexpected message %s")
- except Empty: pass
-
- def _node_disambiguation_precreated(self, ambiguous_send):
- agent = BrokerAgent(self.conn)
- agent.addExchange("fanout", "ambiguous")
- agent.addQueue("ambiguous")
- try:
- r1 = self.ssn.receiver("ambiguous; {node:{type:topic}}")
- r2 = self.ssn.receiver("ambiguous; {node:{type:queue}}")
- self._node_disambiguation_test(r1, r2, ambiguous_send=ambiguous_send)
- finally:
- agent.delExchange("ambiguous")
- agent.delQueue("ambiguous", False, False)
-
- def test_node_disambiguation_1(self):
- self._node_disambiguation_precreated(False)
-
- def test_node_disambiguation_2(self):
- self._node_disambiguation_precreated(True)
-
- def test_ambiguous_create_1(self):
- #create queue first, then exchange
- r1 = self.ssn.receiver("ambiguous; {create:receiver, node:{type:queue}}")
- r2 = self.ssn.receiver("ambiguous; {create:receiver, node:{type:topic}}")
- agent = BrokerAgent(self.conn)
- exchange = agent.getExchange("ambiguous")
- queue = agent.getQueue("ambiguous")
- try:
- assert(exchange)
- assert(queue)
- self._node_disambiguation_test(r2, r1)
- finally:
- if exchange: agent.delExchange("ambiguous")
- if queue: agent.delQueue("ambiguous", False, False)
-
- def test_ambiguous_create_2(self):
- #create exchange first, then queue
- r1 = self.ssn.receiver("ambiguous; {create:receiver, node:{type:topic}}")
- r2 = self.ssn.receiver("ambiguous; {create:receiver, node:{type:queue}}")
- agent = BrokerAgent(self.conn)
- exchange = agent.getExchange("ambiguous")
- queue = agent.getQueue("ambiguous")
- try:
- assert(exchange)
- assert(queue)
- self._node_disambiguation_test(r1, r2)
- finally:
- if exchange: agent.delExchange("ambiguous")
- if queue: agent.delQueue("ambiguous", False, False)
-
- def test_ambiguous_delete_1(self):
- agent = BrokerAgent(self.conn)
- agent.addExchange("fanout", "ambiguous")
- agent.addQueue("ambiguous")
- self.ssn.receiver("ambiguous; {delete:receiver, node:{type:topic}}").close()
- exchange = agent.getExchange("ambiguous")
- queue = agent.getQueue("ambiguous")
- try:
- assert(not exchange)
- assert(queue)
- finally:
- if exchange: agent.delExchange("ambiguous")
- if queue: agent.delQueue("ambiguous", False, False)
-
- def test_ambiguous_delete_2(self):
- agent = BrokerAgent(self.conn)
- agent.addExchange("fanout", "ambiguous")
- agent.addQueue("ambiguous")
- self.ssn.receiver("ambiguous; {delete:receiver, node:{type:queue}}").close()
- exchange = agent.getExchange("ambiguous")
- queue = agent.getQueue("ambiguous")
- try:
- assert(exchange)
- assert(not queue)
- finally:
- if exchange: agent.delExchange("ambiguous")
- if queue: agent.delQueue("ambiguous", False, False)
-
-
-class SequenceNumberTests(Base):
- """
- Tests of ring queue sequence number
- """
-
- def fail(self, text=None):
- if text:
- print "Fail: %r" % text
- assert None
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self):
- return self.conn.session()
-
- def setup_sender(self, name="ring-sequence-queue", key="qpid.queue_msg_sequence"):
- addr = "%s; {create:sender, node: {x-declare: {auto-delete: True, arguments: {'qpid.queue_msg_sequence':'%s', 'qpid.policy_type':'ring', 'qpid.max_count':4}}}}" % (name, key)
- sender = self.ssn.sender(addr)
- return sender
-
- def test_create_sequence_queue(self):
- """
- Test a queue with sequencing can be created
- """
-
- #setup, declare a queue
- try:
- sender = self.setup_sender()
- except:
- self.fail("Unable to create ring queue with sequencing enabled")
-
- def test_get_sequence_number(self):
- """
- Test retrieving sequence number for queues
- """
-
- key = "k"
- sender = self.setup_sender("ring-sequence-queue2", key=key)
-
- # send and receive 1 message and test the sequence number
- msg = Message()
- sender.send(msg)
-
- receiver = self.ssn.receiver("ring-sequence-queue2")
- msg = receiver.fetch(1)
- try:
- seqNo = msg.properties[key]
- if int(seqNo) != 1:
- txt = "Unexpected sequence number. Should be 1. Received (%s)" % seqNo
- self.fail(txt)
- except:
- txt = "Unable to get key (%s) from message properties" % key
- self.fail(txt)
- receiver.close()
-
- def test_sequence_number_gap(self):
- """
- Test that sequence number for ring queues shows gaps when queue
- messages are overwritten
- """
- key = "qpid.seq"
- sender = self.setup_sender("ring-sequence-queue3", key=key)
- receiver = self.ssn.receiver("ring-sequence-queue3")
-
- msg = Message()
- sender.send(msg)
- msg = receiver.fetch(1)
-
- # send 5 more messages to overflow the queue
- for i in range(5):
- sender.send(msg)
-
- msg = receiver.fetch(1)
- seqNo = msg.properties[key]
- if int(seqNo) != 3:
- txt = "Unexpected sequence number. Should be 3. Received (%s)" % seqNo
- self.fail(txt)
- receiver.close()
-
diff --git a/qpid/python/qpid_tests/broker_0_10/persistence.py b/qpid/python/qpid_tests/broker_0_10/persistence.py
deleted file mode 100644
index e9cf9b7caa..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/persistence.py
+++ /dev/null
@@ -1,68 +0,0 @@
-#
-# 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.
-#
-from qpid.datatypes import Message, RangedSet
-#from qpid.testlib import testrunner, TestBase010
-from qpid.testlib import TestBase010
-
-class PersistenceTests(TestBase010):
- def test_delete_queue_after_publish(self):
- session = self.session
- session.auto_sync = False
-
- #create queue
- session.queue_declare(queue = "q", auto_delete=True, durable=True)
-
- #send message
- for i in range(1, 10):
- dp = session.delivery_properties(routing_key="q", delivery_mode=2)
- session.message_transfer(message=Message(dp, "my-message"))
-
- session.auto_sync = True
- #explicitly delete queue
- session.queue_delete(queue = "q")
-
- def test_ack_message_from_deleted_queue(self):
- session = self.session
- session.auto_sync = False
-
- #create queue
- session.queue_declare(queue = "q", auto_delete=True, durable=True)
-
- #send message
- dp = session.delivery_properties(routing_key="q", delivery_mode=2)
- session.message_transfer(message=Message(dp, "my-message"))
-
- #create consumer
- session.message_subscribe(queue = "q", destination = "a", accept_mode = 1, acquire_mode=0)
- session.message_flow(unit = session.credit_unit.byte, value = 0xFFFFFFFFL, destination = "a")
- session.message_flow(unit = session.credit_unit.message, value = 10, destination = "a")
- queue = session.incoming("a")
-
- #consume the message, cancel subscription (triggering auto-delete), then ack it
- msg = queue.get(timeout = 5)
- session.message_cancel(destination = "a")
- session.message_accept(RangedSet(msg.id))
-
- def test_queue_deletion(self):
- session = self.session
- session.queue_declare(queue = "durable-subscriber-queue", exclusive=True, durable=True)
- session.exchange_bind(exchange="amq.topic", queue="durable-subscriber-queue", binding_key="xyz")
- dp = session.delivery_properties(routing_key="xyz", delivery_mode=2)
- session.message_transfer(destination="amq.topic", message=Message(dp, "my-message"))
- session.queue_delete(queue = "durable-subscriber-queue")
diff --git a/qpid/python/qpid_tests/broker_0_10/priority.py b/qpid/python/qpid_tests/broker_0_10/priority.py
deleted file mode 100644
index 47aae6dfd6..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/priority.py
+++ /dev/null
@@ -1,252 +0,0 @@
-#
-# 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.
-#
-
-from qpid.tests.messaging.implementation import *
-from qpid.tests.messaging import Base
-from qpid.compat import set
-import math
-
-class PriorityTests (Base):
- """
- Test prioritised messaging
- """
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self):
- return self.conn.session()
-
- def prioritised_delivery(self, priorities, levels=10, key="x-qpid-priorities"):
- """
- Test that message on a queue are delivered in priority order.
- """
- msgs = [Message(content=str(uuid4()), priority = p) for p in priorities]
-
- snd = self.ssn.sender("priority-queue; {create: sender, delete: receiver, node: {x-declare:{arguments:{'%s':%s}}}}" % (key, levels),
- durable=self.durable())
- for m in msgs: snd.send(m)
-
- rcv = self.ssn.receiver(snd.target)
- for expected in sorted_(msgs, key=lambda m: priority_level(m.priority,levels), reverse=True):
- msg = rcv.fetch(0)
- #print "expected priority %s got %s" % (expected.priority, msg.priority)
- assert msg.content == expected.content
- self.ssn.acknowledge(msg)
-
- def fairshare_delivery(self, priorities, default_limit=5, limits=None, levels=10, level_key="x-qpid-priorities", fairshare_key="x-qpid-fairshare"):
- msgs = [Message(content=str(uuid4()), priority = p) for p in priorities]
-
- limit_policy = "'%s':%s" % (fairshare_key, default_limit)
- if limits:
- for k, v in limits.items():
- limit_policy += ", '%s-%s':%s" % (fairshare_key, k, v)
-
- snd = self.ssn.sender("priority-queue; {create: sender, delete: receiver, node: {x-declare:{arguments:{'%s':%s, %s}}}}"
- % (level_key, levels, limit_policy),
- durable=self.durable())
- for m in msgs: snd.send(m)
-
- rcv = self.ssn.receiver(snd.target)
- if limits:
- limit_function = lambda x : limits.get(x, 0)
- else:
- limit_function = lambda x : default_limit
- for expected in fairshare(sorted_(msgs, key=lambda m: priority_level(m.priority,levels), reverse=True),
- limit_function, levels):
- msg = rcv.fetch(0)
- #print "expected priority %s got %s" % (expected.priority, msg.priority)
- assert msg.priority == expected.priority
- assert msg.content == expected.content
- self.ssn.acknowledge(msg)
-
- def test_prioritised_delivery_1(self):
- self.prioritised_delivery(priorities = [8,9,5,1,2,2,3,4,9,7,8,9,9,2], levels = 10)
-
- def test_prioritised_delivery_with_alias(self):
- self.prioritised_delivery(priorities = [8,9,5,1,2,2,3,4,15,7,8,10,10,2], levels = 10, key="qpid.priorities")
-
- def test_prioritised_delivery_2(self):
- self.prioritised_delivery(priorities = [8,9,5,1,2,2,3,4,9,7,8,9,9,2], levels = 5)
-
- def test_fairshare_1(self):
- self.fairshare_delivery(priorities = [4,5,3,6,10,10,2,10,2,10,10,1,10,10,10,3,3,3,10,10,3,10,3,10,10,10,10,10,10,2,3])
-
- def test_fairshare_with_alias(self):
- self.fairshare_delivery(priorities = [4,5,3,6,10,10,2,10,2,10,10,1,10,10,10,3,3,3,10,10,2,3], level_key="qpid.priorities", fairshare_key="qpid.fairshare")
-
- def test_fairshare_2(self):
- self.fairshare_delivery(priorities = [10 for i in range(30)])
-
- def test_fairshare_3(self):
- self.fairshare_delivery(priorities = [4,5,3,7,8,8,2,8,2,8,8,16,6,6,6,6,6,6,8,3,5,8,3,5,5,3,3,8,8,3,7,3,7,7,7,8,8,8,2,3], limits={7:0,6:4,5:3,4:2,3:2,2:2,1:2}, levels=8)
-
- def test_browsing(self):
- priorities = [4,5,3,6,0,1,2,8,2,0,2,1,6,0,1,3,3,3,8,1,3,0,3,7,9,0,1,9,0,2,3]
- msgs = [Message(content=str(uuid4()), priority = p) for p in priorities]
- snd = self.ssn.sender("priority-queue; {create: sender, node: {x-declare:{arguments:{x-qpid-priorities:10}}}}",
- durable=self.durable())
- for m in msgs: snd.send(m)
-
- rcv = self.ssn.receiver("priority-queue; {mode: browse, delete: receiver}")
- received = []
- try:
- while True: received.append(rcv.fetch(0))
- except Empty: None
- #check all messages on the queue were received by the browser; don't relay on any specific ordering at present
- assert set([m.content for m in msgs]) == set([m.content for m in received])
-
- def ring_queue_check(self, msgs, count=10):
- """
- Ensure that a ring queue removes lowest priority messages first.
- """
- snd = self.ssn.sender(address("priority-ring-queue", arguments="x-qpid-priorities:10, 'qpid.policy_type':ring, 'qpid.max_count':%s" % count),
- durable=self.durable())
- for m in msgs: snd.send(m)
-
- rcv = self.ssn.receiver(snd.target)
- received = []
- try:
- while True: received.append(rcv.fetch(0))
- except Empty: None
-
- expected = sorted_(msgs, key=lambda x: priority_level(x.priority,10))[len(msgs)-count:]
- expected = sorted_(expected, key=lambda x: priority_level(x.priority,10), reverse=True)
- #print "sent %s; expected %s; got %s" % ([m.priority for m in msgs], [m.priority for m in expected], [m.priority for m in received])
- #print "sent %s; expected %s; got %s" % ([m.content for m in msgs], [m.content for m in expected], [m.content for m in received])
- assert [m.content for m in expected] == [m.content for m in received]
-
- def test_ring_queue_1(self):
- priorities = [4,5,3,6,9,9,2,9,2,9,9,1,9,9,9,3,3,3,9,9,3,9,3,9,9,9,9,9,9,2,3]
- seq = content("msg")
- self.ring_queue_check([Message(content=seq.next(), priority = p) for p in priorities])
-
- def test_ring_queue_2(self):
- priorities = [9,0,2,3,6,3,4,2,9,2,9,9,1,9,4,7,1,1,3,9,7,3,9,3,9,1,5,1,9,7,2,3,0,9]
- seq = content("msg")
- self.ring_queue_check([Message(content=seq.next(), priority = p) for p in priorities])
-
- def test_ring_queue_3(self):
- #test case given for QPID-3866
- priorities = [8,9,5,1,2,2,3,4,9,7,8,9,9,2]
- seq = content("msg")
- self.ring_queue_check([Message(content=seq.next(), priority = p) for p in priorities], 5)
-
- def test_ring_queue_4(self):
- priorities = [9,0,2,3,6,3,4,2,9,2,9,3,1,9,4,7,1,1,3,2,7,3,9,3,6,1,5,1,9,7,2,3,0,2]
- seq = content("msg")
- self.ring_queue_check([Message(content=seq.next(), priority = p) for p in priorities])
-
- def test_requeue(self):
- priorities = [4,5,3,6,9,9,2,9,2,9,9,1,9,9,9,3,3,3,9,9,3,9,3,9,9,9,9,9,9,2,3]
- msgs = [Message(content=str(uuid4()), priority = p) for p in priorities]
-
- snd = self.ssn.sender("priority-queue; {create: sender, delete: receiver, node: {x-declare:{arguments:{x-qpid-priorities:10}}}}",
- durable=self.durable())
- #want to have some messages requeued so enable prefetch on a dummy receiver
- other = self.conn.session()
- dummy = other.receiver("priority-queue")
- dummy.capacity = 10
-
- for m in msgs: snd.send(m)
-
- #fetch some with dummy receiver on which prefetch is also enabled
- for i in range(5):
- msg = dummy.fetch(0)
- #close session without acknowledgements to requeue messages
- other.close()
-
- #now test delivery works as expected after that
- rcv = self.ssn.receiver(snd.target)
- for expected in sorted_(msgs, key=lambda m: priority_level(m.priority,10), reverse=True):
- msg = rcv.fetch(0)
- #print "expected priority %s got %s" % (expected.priority, msg.priority)
- #print "expected content %s got %s" % (expected.content, msg.content)
- assert msg.content == expected.content
- self.ssn.acknowledge(msg)
-
-def content(base, counter=1):
- while True:
- yield "%s-%s" % (base, counter)
- counter += 1
-
-def address(name, create_policy="sender", delete_policy="receiver", arguments=None):
- if arguments: node = "node: {x-declare:{arguments:{%s}}}" % arguments
- else: node = "node: {}"
- return "%s; {create: %s, delete: %s, %s}" % (name, create_policy, delete_policy, node)
-
-def fairshare(msgs, limit, levels):
- """
- Generator to return prioritised messages in expected order for a given fairshare limit
- """
- count = 0
- last_priority = None
- postponed = []
- while msgs or postponed:
- if not msgs:
- msgs = postponed
- count = 0
- last_priority = None
- postponed = []
- msg = msgs.pop(0)
- if last_priority and priority_level(msg.priority, levels) == last_priority:
- count += 1
- else:
- last_priority = priority_level(msg.priority, levels)
- count = 1
- l = limit(last_priority)
- if (l and count > l):
- postponed.append(msg)
- else:
- yield msg
- return
-
-def effective_priority(value, levels):
- """
- Method to determine effective priority given a distinct number of
- levels supported. Returns the lowest priority value that is of
- equivalent priority to the value passed in.
- """
- if value <= 5-math.ceil(levels/2.0): return 0
- if value >= 4+math.floor(levels/2.0): return 4+math.floor(levels/2.0)
- return value
-
-def priority_level(value, levels):
- """
- Method to determine which of a distinct number of priority levels
- a given value falls into.
- """
- offset = 5-math.ceil(levels/2.0)
- return min(max(value - offset, 0), levels-1)
-
-def sorted_(msgs, key=None, reverse=False):
- """
- Workaround lack of sorted builtin function in python 2.3 and lack
- of keyword arguments to list.sort()
- """
- temp = [m for m in msgs]
- temp.sort(key_to_cmp(key, reverse=reverse))
- return temp
-
-def key_to_cmp(key, reverse=False):
- if key:
- if reverse: return lambda a, b: cmp(key(b), key(a))
- else: return lambda a, b: cmp(key(a), key(b))
- else:
- return None
diff --git a/qpid/python/qpid_tests/broker_0_10/qmf_events.py b/qpid/python/qpid_tests/broker_0_10/qmf_events.py
deleted file mode 100644
index 7ab7b0a1ac..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/qmf_events.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#
-# 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.
-#
-
-from qpid.messaging import *
-from qpid.tests.messaging import Base
-from qpidtoollibs.broker import EventHelper
-import math
-
-class EventTests (Base):
- """
- Test various qmf events
- """
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self):
- return self.conn.session()
-
- def test_queue_declare(self):
- helper = EventHelper()
-
- # subscribe for queue declare events
- rcv = self.ssn.receiver(helper.eventAddress("org.apache.qpid.broker", "queueDeclare"))
- # create a queue
- snd = self.ssn.sender("myq; {create:always, delete:always}")
- # ensure we got an event
- event = helper.event(rcv.fetch(timeout=1))
- assert event.name, "org_apache_qpid_broker:queueDeclare"
- assert event.qName, "myq"
-
- def test_queue_delete(self):
- helper = EventHelper()
-
- rcv = self.ssn.receiver(helper.eventAddress("org.apache.qpid.broker", "queueDelete"))
- snd = self.ssn.sender("myq; {create:always, delete:always}")
- snd.close()
-
- event = helper.event(rcv.fetch(timeout=1))
- assert event.name, "org_apache_qpid_broker:queueDelete"
- assert event.qName, "myq"
-
- def test_queue_autodelete_exclusive(self):
- helper = EventHelper()
-
- rcv = self.ssn.receiver(helper.eventAddress("org.apache.qpid.broker", "queueDelete"))
-
- #create new session
- ssn2 = self.setup_session()
- snd = ssn2.sender("myq; {create:always, node:{x-declare:{auto-delete:True, exclusive:True}}}")
- ssn2.close()
-
- event = helper.event(rcv.fetch(timeout=5))
- assert event.name, "org_apache_qpid_broker:queueDelete"
- assert event.qName, "myq"
-
- def test_queue_autodelete_shared(self):
- helper = EventHelper()
-
- rcv = self.ssn.receiver(helper.eventAddress("org.apache.qpid.broker", "queueDelete"))
-
- rcv2 = self.ssn.receiver("myq; {create:always, node:{x-declare:{auto-delete:True}}}")
- rcv2.close()
-
- event = helper.event(rcv.fetch(timeout=5))
- assert event.name, "org_apache_qpid_broker:queueDelete"
- assert event.qName, "myq"
-
diff --git a/qpid/python/qpid_tests/broker_0_10/query.py b/qpid/python/qpid_tests/broker_0_10/query.py
deleted file mode 100644
index fd741821d5..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/query.py
+++ /dev/null
@@ -1,247 +0,0 @@
-#
-# 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.
-#
-from qpid.client import Client, Closed
-from qpid.queue import Empty
-from qpid.content import Content
-from qpid.testlib import TestBase010
-
-class QueryTests(TestBase010):
- """Tests for various query methods"""
-
- def test_queue_query(self):
- session = self.session
- session.queue_declare(queue="my-queue", exclusive=True, auto_delete=True)
- result = session.queue_query(queue="my-queue")
- self.assertEqual("my-queue", result.queue)
-
- def test_queue_query_unknown(self):
- session = self.session
- result = session.queue_query(queue="I don't exist")
- self.assert_(not result.queue)
-
- def test_exchange_query(self):
- """
- Test that the exchange_query method works as expected
- """
- session = self.session
- #check returned type for the standard exchanges
- self.assertEqual("direct", session.exchange_query(name="amq.direct").type)
- self.assertEqual("topic", session.exchange_query(name="amq.topic").type)
- self.assertEqual("fanout", session.exchange_query(name="amq.fanout").type)
- self.assertEqual("headers", session.exchange_query(name="amq.match").type)
- self.assertEqual("direct", session.exchange_query(name="").type)
- #declare an exchange
- session.exchange_declare(exchange="my-test-exchange", type= "direct", durable=False)
- #check that the result of a query is as expected
- response = session.exchange_query(name="my-test-exchange")
- self.assertEqual("direct", response.type)
- self.assert_(not response.durable)
- self.assert_(not response.not_found)
- #delete the exchange
- session.exchange_delete(exchange="my-test-exchange")
- #check that the query now reports not-found
- self.assert_(session.exchange_query(name="my-test-exchange").not_found)
-
- def test_exchange_bound_direct(self):
- """
- Test that the exchange_bound method works as expected with the direct exchange
- """
- self.exchange_bound_with_key("amq.direct")
-
- def test_exchange_bound_topic(self):
- """
- Test that the exchange_bound method works as expected with the direct exchange
- """
- self.exchange_bound_with_key("amq.topic")
-
- def exchange_bound_with_key(self, exchange_name):
- session = self.session
- #setup: create two queues
- session.queue_declare(queue="used-queue", exclusive=True, auto_delete=True)
- session.queue_declare(queue="unused-queue", exclusive=True, auto_delete=True)
-
- session.exchange_bind(exchange=exchange_name, queue="used-queue", binding_key="used-key")
-
- # test detection of any binding to specific queue
- response = session.exchange_bound(exchange=exchange_name, queue="used-queue")
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assert_(not response.queue_not_matched)
-
- # test detection of specific binding to any queue
- response = session.exchange_bound(exchange=exchange_name, binding_key="used-key")
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assert_(not response.key_not_matched)
-
- # test detection of specific binding to specific queue
- response = session.exchange_bound(exchange=exchange_name, queue="used-queue", binding_key="used-key")
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assert_(not response.queue_not_matched)
- self.assert_(not response.key_not_matched)
-
- # test unmatched queue, unspecified binding
- response = session.exchange_bound(exchange=exchange_name, queue="unused-queue")
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assertEqual(True, response.queue_not_matched)
-
- # test unspecified queue, unmatched binding
- response = session.exchange_bound(exchange=exchange_name, binding_key="unused-key")
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assertEqual(True, response.key_not_matched)
-
- # test matched queue, unmatched binding
- response = session.exchange_bound(exchange=exchange_name, queue="used-queue", binding_key="unused-key")
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assert_(not response.queue_not_matched)
- self.assertEqual(True, response.key_not_matched)
-
- # test unmatched queue, matched binding
- response = session.exchange_bound(exchange=exchange_name, queue="unused-queue", binding_key="used-key")
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assertEqual(True, response.queue_not_matched)
- self.assert_(not response.key_not_matched)
-
- # test unmatched queue, unmatched binding
- response = session.exchange_bound(exchange=exchange_name, queue="unused-queue", binding_key="unused-key")
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assertEqual(True, response.queue_not_matched)
- self.assertEqual(True, response.key_not_matched)
-
- #test exchange not found
- self.assertEqual(True, session.exchange_bound(exchange="unknown-exchange").exchange_not_found)
-
- #test exchange found, queue not found
- response = session.exchange_bound(exchange=exchange_name, queue="unknown-queue")
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(True, response.queue_not_found)
-
- #test exchange not found, queue found
- response = session.exchange_bound(exchange="unknown-exchange", queue="used-queue")
- self.assertEqual(True, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
-
- #test not exchange found, queue not found
- response = session.exchange_bound(exchange="unknown-exchange", queue="unknown-queue")
- self.assertEqual(True, response.exchange_not_found)
- self.assertEqual(True, response.queue_not_found)
-
-
- def test_exchange_bound_fanout(self):
- """
- Test that the exchange_bound method works as expected with fanout exchange
- """
- session = self.session
- #setup
- session.queue_declare(queue="used-queue", exclusive=True, auto_delete=True)
- session.queue_declare(queue="unused-queue", exclusive=True, auto_delete=True)
- session.exchange_bind(exchange="amq.fanout", queue="used-queue")
-
- # test detection of any binding to specific queue
- response = session.exchange_bound(exchange="amq.fanout", queue="used-queue")
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assert_(not response.queue_not_matched)
-
- # test unmatched queue, unspecified binding
- response = session.exchange_bound(exchange="amq.fanout", queue="unused-queue")
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assertEqual(True, response.queue_not_matched)
-
- #test exchange not found
- self.assertEqual(True, session.exchange_bound(exchange="unknown-exchange").exchange_not_found)
-
- #test queue not found
- self.assertEqual(True, session.exchange_bound(exchange="amq.fanout", queue="unknown-queue").queue_not_found)
-
- def test_exchange_bound_header(self):
- """
- Test that the exchange_bound method works as expected with headers exchanges
- """
- session = self.session
- #setup
- session.queue_declare(queue="used-queue", exclusive=True, auto_delete=True)
- session.queue_declare(queue="unused-queue", exclusive=True, auto_delete=True)
- session.exchange_bind(exchange="amq.match", queue="used-queue", arguments={"x-match":"all", "a":"A"} )
-
- # test detection of any binding to specific queue
- response = session.exchange_bound(exchange="amq.match", queue="used-queue")
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assert_(not response.queue_not_matched)
-
- # test detection of specific binding to any queue
- response = session.exchange_bound(exchange="amq.match", arguments={"x-match":"all", "a":"A"})
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assert_(not response.args_not_matched)
-
- # test detection of specific binding to specific queue
- response = session.exchange_bound(exchange="amq.match", queue="used-queue", arguments={"x-match":"all", "a":"A"})
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assert_(not response.queue_not_matched)
- self.assert_(not response.args_not_matched)
-
- # test unmatched queue, unspecified binding
- response = session.exchange_bound(exchange="amq.match", queue="unused-queue")
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assertEqual(True, response.queue_not_matched)
-
- # test unspecified queue, unmatched binding
- response = session.exchange_bound(exchange="amq.match", arguments={"x-match":"all", "b":"B"})
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assertEqual(True, response.args_not_matched)
-
- # test matched queue, unmatched binding
- response = session.exchange_bound(exchange="amq.match", queue="used-queue", arguments={"x-match":"all", "b":"B"})
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assert_(not response.queue_not_matched)
- self.assertEqual(True, response.args_not_matched)
-
- # test unmatched queue, matched binding
- response = session.exchange_bound(exchange="amq.match", queue="unused-queue", arguments={"x-match":"all", "a":"A"})
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assertEqual(True, response.queue_not_matched)
- self.assert_(not response.args_not_matched)
-
- # test unmatched queue, unmatched binding
- response = session.exchange_bound(exchange="amq.match", queue="unused-queue", arguments={"x-match":"all", "b":"B"})
- self.assert_(not response.exchange_not_found)
- self.assert_(not response.queue_not_found)
- self.assertEqual(True, response.queue_not_matched)
- self.assertEqual(True, response.args_not_matched)
-
- #test exchange not found
- self.assertEqual(True, session.exchange_bound(exchange="unknown-exchange").exchange_not_found)
-
- #test queue not found
- self.assertEqual(True, session.exchange_bound(exchange="amq.match", queue="unknown-queue").queue_not_found)
-
diff --git a/qpid/python/qpid_tests/broker_0_10/queue.py b/qpid/python/qpid_tests/broker_0_10/queue.py
deleted file mode 100644
index 132bd7b987..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/queue.py
+++ /dev/null
@@ -1,436 +0,0 @@
-#
-# 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.
-#
-from qpid.client import Client, Closed
-from qpid.queue import Empty
-from qpid.testlib import TestBase010
-from qpid.datatypes import Message, RangedSet
-from qpid.session import SessionException
-
-class QueueTests(TestBase010):
- """Tests for 'methods' on the amqp queue 'class'"""
-
- def test_purge(self):
- """
- Test that the purge method removes messages from the queue
- """
- session = self.session
- #setup, declare a queue and add some messages to it:
- session.queue_declare(queue="test-queue", exclusive=True, auto_delete=True)
- session.message_transfer(message=Message(session.delivery_properties(routing_key="test-queue"), "one"))
- session.message_transfer(message=Message(session.delivery_properties(routing_key="test-queue"), "two"))
- session.message_transfer(message=Message(session.delivery_properties(routing_key="test-queue"), "three"))
-
- #check that the queue now reports 3 messages:
- session.queue_declare(queue="test-queue")
- reply = session.queue_query(queue="test-queue")
- self.assertEqual(3, reply.message_count)
-
- #now do the purge, then test that three messages are purged and the count drops to 0
- session.queue_purge(queue="test-queue");
- reply = session.queue_query(queue="test-queue")
- self.assertEqual(0, reply.message_count)
-
- #send a further message and consume it, ensuring that the other messages are really gone
- session.message_transfer(message=Message(session.delivery_properties(routing_key="test-queue"), "four"))
- session.message_subscribe(queue="test-queue", destination="tag")
- session.message_flow(destination="tag", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="tag", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- queue = session.incoming("tag")
- msg = queue.get(timeout=1)
- self.assertEqual("four", msg.body)
-
- def test_purge_queue_exists(self):
- """
- Test that the correct exception is thrown is no queue exists
- for the name specified in purge
- """
- session = self.session
- try:
- #queue specified but doesn't exist:
- session.queue_purge(queue="invalid-queue")
- self.fail("Expected failure when purging non-existent queue")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code) #not-found
-
- def test_purge_empty_name(self):
- """
- Test that the correct exception is thrown is no queue name
- is specified for purge
- """
- session = self.session
- try:
- #queue not specified and none previously declared for channel:
- session.queue_purge()
- self.fail("Expected failure when purging unspecified queue")
- except SessionException, e:
- self.assertEquals(531, e.args[0].error_code) #illegal-argument
-
- def test_declare_exclusive(self):
- """
- Test that the exclusive field is honoured in queue.declare
- """
- # TestBase.setUp has already opened session(1)
- s1 = self.session
- # Here we open a second separate connection:
- s2 = self.conn.session("other")
-
- #declare an exclusive queue:
- s1.queue_declare(queue="exclusive-queue", exclusive=True, auto_delete=True)
- s1.exchange_bind(exchange="amq.fanout", queue="exclusive-queue")
- try:
- #other connection should not be allowed to declare this:
- s2.queue_declare(queue="exclusive-queue", exclusive=True, auto_delete=True)
- self.fail("Expected second exclusive queue_declare to raise a channel exception")
- except SessionException, e:
- self.assertEquals(405, e.args[0].error_code)
-
- s3 = self.conn.session("subscriber")
- try:
- #other connection should not be allowed to declare this:
- s3.message_subscribe(queue="exclusive-queue")
- self.fail("Expected message_subscribe on an exclusive queue to raise a channel exception")
- except SessionException, e:
- self.assertEquals(405, e.args[0].error_code)
-
- s4 = self.conn.session("deleter")
- try:
- #other connection should not be allowed to declare this:
- s4.queue_delete(queue="exclusive-queue")
- self.fail("Expected queue_delete on an exclusive queue to raise a channel exception")
- except SessionException, e:
- self.assertEquals(405, e.args[0].error_code)
-
- s5 = self.conn.session("binder")
- try:
- #other connection should not be allowed to declare this:
- s5.exchange_bind(exchange="amq.direct", queue="exclusive-queue", binding_key="abc")
- self.fail("Expected exchange_bind on an exclusive queue to raise an exception")
- except SessionException, e:
- self.assertEquals(405, e.args[0].error_code)
-
- s6 = self.conn.session("unbinder")
- try:
- #other connection should not be allowed to declare this:
- s6.exchange_unbind(exchange="amq.fanout", queue="exclusive-queue")
- self.fail("Expected exchange_unbind on an exclusive queue to raise an exception")
- except SessionException, e:
- self.assertEquals(405, e.args[0].error_code)
-
- def test_declare_exclusive_alreadyinuse(self):
- """
- Test that exclusivity is real if granted
- """
- # TestBase.setUp has already opened session(1)
- s1 = self.session
- # Here we open a second separate connection:
- s2 = self.conn.session("other")
-
- #declare an exclusive queue:
- s1.queue_declare(queue="a-queue", auto_delete=True)
- s1.message_subscribe(queue="a-queue")
- try:
- #other connection should not be allowed to declare this:
- s2.queue_declare(queue="a-queue", exclusive=True, auto_delete=True)
- self.fail("Expected request for exclusivity to fail")
- except SessionException, e:
- self.assertEquals(405, e.args[0].error_code)
-
- def test_declare_passive(self):
- """
- Test that the passive field is honoured in queue.declare
- """
- s1 = self.session
- s2 = self.conn.session("other")
-
- s1.queue_declare(queue="passive-queue-1")
-
- #ensure that same/separate sessions can passively declare same queue
- s1.queue_declare(queue="passive-queue-1", passive=True)
- s2.queue_declare(queue="passive-queue-1", passive=True)
-
- s1.queue_delete(queue="passive-queue-1")
-
- def test_declare_passive_queue_not_found(self):
- """
- Test that the passive field is honoured in queue.declare
- """
- s1 = self.session
-
- try:
- s1.queue_declare(queue="passive-queue-not-found", passive=True)
- self.fail("Expected passive declaration of non-existent queue to raise a channel exception")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code) #not-found
-
-
- def test_declare_passive_with_exclusive(self):
- """
- Test that the passive field is honoured in queue.declare
- """
- s1 = self.session
- s2 = self.conn.session("other")
-
- #declare exclusive/non-exclusive queues:
- s1.queue_declare(queue="passive-queue-exc", exclusive=True, auto_delete=True)
- s1.queue_declare(queue="passive-queue-nonexc", exclusive=False, auto_delete=True)
-
- #ensure that same/separate sessions can passively declare same queue *without* the exclusive flag
- #this is important for the request/reply pattern
- s1.queue_declare(queue="passive-queue-exc", passive=True)
- s2.queue_declare(queue="passive-queue-exc", passive=True)
-
- try:
- s2.queue_declare(queue="passive-queue-nonexc", exclusive=True, passive=True)
- self.fail("Expected exclusive passive declaration of existing queue to raise a channel exception")
- except SessionException, e:
- self.assertEquals(405, e.args[0].error_code) # resource locked
-
- def test_bind(self):
- """
- Test various permutations of the queue.bind method+
- """
- session = self.session
- session.queue_declare(queue="queue-1", exclusive=True, auto_delete=True)
-
- #straightforward case, both exchange & queue exist so no errors expected:
- session.exchange_bind(queue="queue-1", exchange="amq.direct", binding_key="key1")
-
- #use the queue name where the routing key is not specified:
- session.exchange_bind(queue="queue-1", exchange="amq.direct")
-
- #try and bind to non-existant exchange
- try:
- session.exchange_bind(queue="queue-1", exchange="an-invalid-exchange", binding_key="key1")
- self.fail("Expected bind to non-existant exchange to fail")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
-
- def test_bind_queue_existence(self):
- session = self.session
- #try and bind non-existant queue:
- try:
- session.exchange_bind(queue="queue-2", exchange="amq.direct", binding_key="key1")
- self.fail("Expected bind of non-existant queue to fail")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
- def test_unbind_direct(self):
- self.unbind_test(exchange="amq.direct", routing_key="key")
-
- def test_unbind_topic(self):
- self.unbind_test(exchange="amq.topic", routing_key="key")
-
- def test_unbind_fanout(self):
- self.unbind_test(exchange="amq.fanout")
-
- def test_unbind_headers(self):
- self.unbind_test(exchange="amq.match", args={ "x-match":"all", "a":"b"}, headers={"a":"b"})
-
- def unbind_test(self, exchange, routing_key="", args=None, headers=None):
- #bind two queues and consume from them
- session = self.session
-
- session.queue_declare(queue="queue-1", exclusive=True, auto_delete=True)
- session.queue_declare(queue="queue-2", exclusive=True, auto_delete=True)
-
- session.message_subscribe(queue="queue-1", destination="queue-1")
- session.message_flow(destination="queue-1", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="queue-1", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- session.message_subscribe(queue="queue-2", destination="queue-2")
- session.message_flow(destination="queue-2", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="queue-2", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
-
- queue1 = session.incoming("queue-1")
- queue2 = session.incoming("queue-2")
-
- session.exchange_bind(exchange=exchange, queue="queue-1", binding_key=routing_key, arguments=args)
- session.exchange_bind(exchange=exchange, queue="queue-2", binding_key=routing_key, arguments=args)
-
- dp = session.delivery_properties(routing_key=routing_key)
- if (headers):
- mp = session.message_properties(application_headers=headers)
- msg1 = Message(dp, mp, "one")
- msg2 = Message(dp, mp, "two")
- else:
- msg1 = Message(dp, "one")
- msg2 = Message(dp, "two")
-
- #send a message that will match both bindings
- session.message_transfer(destination=exchange, message=msg1)
-
- #unbind first queue
- session.exchange_unbind(exchange=exchange, queue="queue-1", binding_key=routing_key)
-
- #send another message
- session.message_transfer(destination=exchange, message=msg2)
-
- #check one queue has both messages and the other has only one
- self.assertEquals("one", queue1.get(timeout=1).body)
- try:
- msg = queue1.get(timeout=1)
- self.fail("Got extra message: %s" % msg.body)
- except Empty: pass
-
- self.assertEquals("one", queue2.get(timeout=1).body)
- self.assertEquals("two", queue2.get(timeout=1).body)
- try:
- msg = queue2.get(timeout=1)
- self.fail("Got extra message: " + msg)
- except Empty: pass
-
-
- def test_delete_simple(self):
- """
- Test core queue deletion behaviour
- """
- session = self.session
-
- #straight-forward case:
- session.queue_declare(queue="delete-me")
- session.message_transfer(message=Message(session.delivery_properties(routing_key="delete-me"), "a"))
- session.message_transfer(message=Message(session.delivery_properties(routing_key="delete-me"), "b"))
- session.message_transfer(message=Message(session.delivery_properties(routing_key="delete-me"), "c"))
- session.queue_delete(queue="delete-me")
- #check that it has gone by declaring passively
- try:
- session.queue_declare(queue="delete-me", passive=True)
- self.fail("Queue has not been deleted")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
- def test_delete_queue_exists(self):
- """
- Test core queue deletion behaviour
- """
- #check attempted deletion of non-existant queue is handled correctly:
- session = self.session
- try:
- session.queue_delete(queue="i-dont-exist", if_empty=True)
- self.fail("Expected delete of non-existant queue to fail")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
-
-
- def test_delete_ifempty(self):
- """
- Test that if_empty field of queue_delete is honoured
- """
- session = self.session
-
- #create a queue and add a message to it (use default binding):
- session.queue_declare(queue="delete-me-2")
- session.queue_declare(queue="delete-me-2", passive=True)
- session.message_transfer(message=Message(session.delivery_properties(routing_key="delete-me-2"), "message"))
-
- #try to delete, but only if empty:
- try:
- session.queue_delete(queue="delete-me-2", if_empty=True)
- self.fail("Expected delete if_empty to fail for non-empty queue")
- except SessionException, e:
- self.assertEquals(406, e.args[0].error_code)
-
- #need new session now:
- session = self.conn.session("replacement", 2)
-
- #empty queue:
- session.message_subscribe(destination="consumer_tag", queue="delete-me-2")
- session.message_flow(destination="consumer_tag", unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination="consumer_tag", unit=session.credit_unit.byte, value=0xFFFFFFFFL)
- queue = session.incoming("consumer_tag")
- msg = queue.get(timeout=1)
- self.assertEqual("message", msg.body)
- session.message_accept(RangedSet(msg.id))
- session.message_cancel(destination="consumer_tag")
-
- #retry deletion on empty queue:
- session.queue_delete(queue="delete-me-2", if_empty=True)
-
- #check that it has gone by declaring passively:
- try:
- session.queue_declare(queue="delete-me-2", passive=True)
- self.fail("Queue has not been deleted")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
- def test_delete_ifunused(self):
- """
- Test that if_unused field of queue_delete is honoured
- """
- session = self.session
-
- #create a queue and register a consumer:
- session.queue_declare(queue="delete-me-3")
- session.queue_declare(queue="delete-me-3", passive=True)
- session.message_subscribe(destination="consumer_tag", queue="delete-me-3")
-
- #need new session now:
- session2 = self.conn.session("replacement", 2)
-
- #try to delete, but only if empty:
- try:
- session2.queue_delete(queue="delete-me-3", if_unused=True)
- self.fail("Expected delete if_unused to fail for queue with existing consumer")
- except SessionException, e:
- self.assertEquals(406, e.args[0].error_code)
-
- session.message_cancel(destination="consumer_tag")
- session.queue_delete(queue="delete-me-3", if_unused=True)
- #check that it has gone by declaring passively:
- try:
- session.queue_declare(queue="delete-me-3", passive=True)
- self.fail("Queue has not been deleted")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
-
- def test_autodelete_shared(self):
- """
- Test auto-deletion (of non-exclusive queues)
- """
- session = self.session
- session2 =self.conn.session("other", 1)
-
- session.queue_declare(queue="auto-delete-me", auto_delete=True)
-
- #consume from both sessions
- tag = "my-tag"
- session.message_subscribe(queue="auto-delete-me", destination=tag)
- session2.message_subscribe(queue="auto-delete-me", destination=tag)
-
- #implicit cancel
- session2.close()
-
- #check it is still there
- session.queue_declare(queue="auto-delete-me", passive=True)
-
- #explicit cancel => queue is now unused again:
- session.message_cancel(destination=tag)
-
- #NOTE: this assumes there is no timeout in use
-
- #check that it has gone by declaring it passively
- try:
- session.queue_declare(queue="auto-delete-me", passive=True)
- self.fail("Expected queue to have been deleted")
- except SessionException, e:
- self.assertEquals(404, e.args[0].error_code)
-
-
diff --git a/qpid/python/qpid_tests/broker_0_10/stats.py b/qpid/python/qpid_tests/broker_0_10/stats.py
deleted file mode 100644
index 4f3931b78b..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/stats.py
+++ /dev/null
@@ -1,519 +0,0 @@
-#
-# 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.
-#
-
-from qpid.tests.messaging.implementation import *
-from qpid.tests.messaging import Base
-from time import sleep
-from qpidtoollibs.broker import BrokerAgent
-
-#
-# Tests the Broker's statistics reporting
-#
-
-class BrokerStatsTests(Base):
- """
- Tests of the broker's statistics
- """
-
- def assertEqual(self, left, right, text=None):
- if not left == right:
- print "assertEqual failure: %r != %r" % (left, right)
- if text:
- print " %r" % text
- assert None
-
- def failUnless(self, value, text=None):
- if value:
- return
- print "failUnless failure",
- if text:
- print ": %r" % text
- else:
- print
- assert None
-
- def fail(self, text=None):
- if text:
- print "Fail: %r" % text
- assert None
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self, tx=False):
- return self.conn.session(transactional=tx)
-
- def setup_access(self):
- return BrokerAgent(self.conn)
-
- def test_exchange_stats(self):
- agent = self.setup_access()
- start_broker = agent.getBroker()
-
- agent.addExchange("direct", "stats-test-exchange")
- try:
- sess = self.setup_session()
- tx_a = sess.sender("stats-test-exchange/a")
- tx_b = sess.sender("stats-test-exchange/b")
- rx_a = sess.receiver("stats-test-exchange/a")
-
- exchange = agent.getExchange("stats-test-exchange")
- self.failUnless(exchange, "expected a valid exchange object")
- self.assertEqual(exchange.msgReceives, 0, "msgReceives")
- self.assertEqual(exchange.msgDrops, 0, "msgDrops")
- self.assertEqual(exchange.msgRoutes, 0, "msgRoutes")
- self.assertEqual(exchange.byteReceives, 0, "byteReceives")
- self.assertEqual(exchange.byteDrops, 0, "byteDrops")
- self.assertEqual(exchange.byteRoutes, 0, "byteRoutes")
-
- tx_a.send("0123456789")
- tx_b.send("01234567890123456789")
- tx_a.send("012345678901234567890123456789")
- tx_b.send("0123456789012345678901234567890123456789")
-
- overhead = 63 #overhead added to message from headers
- exchange.update()
- self.assertEqual(exchange.msgReceives, 4, "msgReceives")
- self.assertEqual(exchange.msgDrops, 2, "msgDrops")
- self.assertEqual(exchange.msgRoutes, 2, "msgRoutes")
- self.assertEqual(exchange.byteReceives, 100+(4*overhead), "byteReceives")
- self.assertEqual(exchange.byteDrops, 60+(2*overhead), "byteDrops")
- self.assertEqual(exchange.byteRoutes, 40+(2*overhead), "byteRoutes")
- finally:
- agent.delExchange("stats-test-exchange")
-
- def test_enqueues_dequeues(self):
- agent = self.setup_access()
- start_broker = agent.getBroker()
-
- sess = self.setup_session()
- tx = sess.sender("enqueue_test;{create:always,delete:always}")
- rx = sess.receiver("enqueue_test")
-
- queue = agent.getQueue("enqueue_test")
- self.failUnless(queue, "expected a valid queue object")
- self.assertEqual(queue.msgTotalEnqueues, 0, "msgTotalEnqueues")
- self.assertEqual(queue.byteTotalEnqueues, 0, "byteTotalEnqueues")
- self.assertEqual(queue.msgTotalDequeues, 0, "msgTotalDequeues")
- self.assertEqual(queue.byteTotalDequeues, 0, "byteTotalDequeues")
- self.assertEqual(queue.msgDepth, 0, "msgDepth")
- self.assertEqual(queue.byteDepth, 0, "byteDepth")
-
- tx.send("0123456789")
- tx.send("01234567890123456789")
- tx.send("012345678901234567890123456789")
- tx.send("0123456789012345678901234567890123456789")
- overhead = 38 #overhead added to message from headers
-
- queue.update()
- self.assertEqual(queue.msgTotalEnqueues, 4, "msgTotalEnqueues")
- self.assertEqual(queue.byteTotalEnqueues, 100+(4*overhead), "byteTotalEnqueues")
- self.assertEqual(queue.msgTotalDequeues, 0, "msgTotalDequeues")
- self.assertEqual(queue.byteTotalDequeues, 0, "byteTotalDequeues")
- self.assertEqual(queue.msgDepth, 4, "msgDepth")
- self.assertEqual(queue.byteDepth, 100+(4*overhead), "byteDepth")
-
- now_broker = agent.getBroker()
- self.failUnless((now_broker.msgTotalEnqueues - start_broker.msgTotalEnqueues) >= 4, "broker msgTotalEnqueues")
- self.failUnless((now_broker.byteTotalEnqueues - start_broker.byteTotalEnqueues) >= 100, "broker byteTotalEnqueues")
-
- m = rx.fetch()
- m = rx.fetch()
- sess.acknowledge()
-
- queue.update()
- self.assertEqual(queue.msgTotalEnqueues, 4, "msgTotalEnqueues")
- self.assertEqual(queue.byteTotalEnqueues, 100+(4*overhead), "byteTotalEnqueues")
- self.assertEqual(queue.msgTotalDequeues, 2, "msgTotalDequeues")
- self.assertEqual(queue.byteTotalDequeues, 30+(2*overhead), "byteTotalDequeues")
- self.assertEqual(queue.msgDepth, 2, "msgDepth")
- self.assertEqual(queue.byteDepth, 70+(2*overhead), "byteDepth")
-
- now_broker = agent.getBroker()
- self.failUnless((now_broker.msgTotalDequeues - start_broker.msgTotalDequeues) >= 2, "broker msgTotalDequeues")
- self.failUnless((now_broker.byteTotalDequeues - start_broker.byteTotalDequeues) >= 30, "broker byteTotalDequeues")
-
- sess.close()
-
- now_broker = agent.getBroker()
- self.assertEqual(now_broker.abandoned - start_broker.abandoned, 2, "expect 2 abandoned messages")
- self.assertEqual(now_broker.msgDepth, start_broker.msgDepth, "expect broker message depth to be unchanged")
- self.assertEqual(now_broker.byteDepth, start_broker.byteDepth, "expect broker byte depth to be unchanged")
-
-
- def test_transactional_enqueues_dequeues(self):
- agent = self.setup_access()
- start_broker = agent.getBroker()
-
- sess = self.setup_session(True)
- tx = sess.sender("tx_enqueue_test;{create:always,delete:always}")
-
- tx.send("0123456789")
- tx.send("0123456789")
- tx.send("0123456789")
- tx.send("0123456789")
- overhead = 41 #overhead added to message from headers
-
- queue = agent.getQueue("tx_enqueue_test")
- self.failUnless(queue, "expected a valid queue object")
- self.assertEqual(queue.msgTotalEnqueues, 0, "msgTotalEnqueues pre-tx-commit")
- self.assertEqual(queue.byteTotalEnqueues, 0, "byteTotalEnqueues pre-tx-commit")
- self.assertEqual(queue.msgTxnEnqueues, 0, "msgTxnEnqueues pre-tx-commit")
- self.assertEqual(queue.byteTxnEnqueues, 0, "byteTxnEnqueues pre-tx-commit")
- self.assertEqual(queue.msgTotalDequeues, 0, "msgTotalDequeues pre-tx-commit")
- self.assertEqual(queue.byteTotalDequeues, 0, "byteTotalDequeues pre-tx-commit")
- self.assertEqual(queue.msgTxnDequeues, 0, "msgTxnDequeues pre-tx-commit")
- self.assertEqual(queue.byteTxnDequeues, 0, "byteTxnDequeues pre-tx-commit")
-
- sess.commit()
- queue.update()
- self.assertEqual(queue.msgTotalEnqueues, 4, "msgTotalEnqueues post-tx-commit")
- self.assertEqual(queue.byteTotalEnqueues, 40+(4*overhead), "byteTotalEnqueues post-tx-commit")
- self.assertEqual(queue.msgTxnEnqueues, 4, "msgTxnEnqueues post-tx-commit")
- self.assertEqual(queue.byteTxnEnqueues, 40+(4*overhead), "byteTxnEnqueues post-tx-commit")
- self.assertEqual(queue.msgTotalDequeues, 0, "msgTotalDequeues post-tx-commit")
- self.assertEqual(queue.byteTotalDequeues, 0, "byteTotalDequeues post-tx-commit")
- self.assertEqual(queue.msgTxnDequeues, 0, "msgTxnDequeues post-tx-commit")
- self.assertEqual(queue.byteTxnDequeues, 0, "byteTxnDequeues post-tx-commit")
-
- sess2 = self.setup_session(True)
- rx = sess2.receiver("tx_enqueue_test")
-
- m = rx.fetch()
- m = rx.fetch()
- m = rx.fetch()
- m = rx.fetch()
-
- queue.update()
- self.assertEqual(queue.msgTotalEnqueues, 4, "msgTotalEnqueues pre-rx-commit")
- self.assertEqual(queue.byteTotalEnqueues, 40+(4*overhead), "byteTotalEnqueues pre-rx-commit")
- self.assertEqual(queue.msgTxnEnqueues, 4, "msgTxnEnqueues pre-rx-commit")
- self.assertEqual(queue.byteTxnEnqueues, 40+(4*overhead), "byteTxnEnqueues pre-rx-commit")
- self.assertEqual(queue.msgTotalDequeues, 0, "msgTotalDequeues pre-rx-commit")
- self.assertEqual(queue.byteTotalDequeues, 0, "byteTotalDequeues pre-rx-commit")
- self.assertEqual(queue.msgTxnDequeues, 0, "msgTxnDequeues pre-rx-commit")
- self.assertEqual(queue.byteTxnDequeues, 0, "byteTxnDequeues pre-rx-commit")
-
- sess2.acknowledge()
- sess2.commit()
-
- queue.update()
- self.assertEqual(queue.msgTotalEnqueues, 4, "msgTotalEnqueues post-rx-commit")
- self.assertEqual(queue.byteTotalEnqueues, 40+(4*overhead), "byteTotalEnqueues post-rx-commit")
- self.assertEqual(queue.msgTxnEnqueues, 4, "msgTxnEnqueues post-rx-commit")
- self.assertEqual(queue.byteTxnEnqueues, 40+(4*overhead), "byteTxnEnqueues post-rx-commit")
- self.assertEqual(queue.msgTotalDequeues, 4, "msgTotalDequeues post-rx-commit")
- self.assertEqual(queue.byteTotalDequeues, 40+(4*overhead), "byteTotalDequeues post-rx-commit")
- self.assertEqual(queue.msgTxnDequeues, 4, "msgTxnDequeues post-rx-commit")
- self.assertEqual(queue.byteTxnDequeues, 40+(4*overhead), "byteTxnDequeues post-rx-commit")
-
- sess.close()
- sess2.close()
-
- now_broker = agent.getBroker()
- self.assertEqual(now_broker.msgTxnEnqueues - start_broker.msgTxnEnqueues, 4, "broker msgTxnEnqueues")
- self.assertEqual(now_broker.byteTxnEnqueues - start_broker.byteTxnEnqueues, 40+(4*overhead), "broker byteTxnEnqueues")
- self.assertEqual(now_broker.msgTxnDequeues - start_broker.msgTxnDequeues, 4, "broker msgTxnDequeues")
- self.assertEqual(now_broker.byteTxnDequeues - start_broker.byteTxnDequeues, 40+(4*overhead), "broker byteTxnDequeues")
-
-
- def test_discards_no_route(self):
- agent = self.setup_access()
- start_broker = agent.getBroker()
-
- sess = self.setup_session()
- tx = sess.sender("amq.topic/non.existing.key")
- tx.send("NO_ROUTE")
- tx.send("NO_ROUTE")
- tx.send("NO_ROUTE")
- tx.send("NO_ROUTE")
- tx.send("NO_ROUTE")
-
- now_broker = agent.getBroker()
-
- self.failUnless((now_broker.discardsNoRoute - start_broker.discardsNoRoute) >= 5, "Expect at least 5 no-routes")
-
- sess.close()
-
-
- def test_abandoned_alt(self):
- agent = self.setup_access()
- start_broker = agent.getBroker()
-
- sess = self.setup_session()
- tx = sess.sender("abandon_alt;{create:always,delete:always,node:{x-declare:{alternate-exchange:'amq.fanout'}}}")
- rx = sess.receiver("abandon_alt")
- rx.capacity = 2
-
- tx.send("ABANDON_ALT")
- tx.send("ABANDON_ALT")
- tx.send("ABANDON_ALT")
- tx.send("ABANDON_ALT")
- tx.send("ABANDON_ALT")
-
- rx.fetch()
-
- sess.close()
- now_broker = agent.getBroker()
- self.assertEqual(now_broker.abandonedViaAlt - start_broker.abandonedViaAlt, 5, "Expect 5 abandonedViaAlt")
- self.assertEqual(now_broker.abandoned - start_broker.abandoned, 0, "Expect 0 abandoned")
-
-
- def test_discards_ttl(self):
- agent = self.setup_access()
- start_broker = agent.getBroker()
-
- sess = self.setup_session()
- tx = sess.sender("discards_ttl;{create:always,delete:always}")
- msg = Message("TTL")
- msg.ttl = 1
-
- tx.send(msg)
- tx.send(msg)
- tx.send(msg)
- tx.send(msg)
- tx.send(msg)
- tx.send(msg)
-
- sleep(2)
-
- rx = sess.receiver("discards_ttl")
- try:
- rx.fetch(0)
- except:
- pass
-
- now_broker = agent.getBroker()
- queue = agent.getQueue("discards_ttl")
-
- self.failUnless(queue, "expected a valid queue object")
- self.assertEqual(queue.discardsTtl, 6, "expect 6 TTL discards on queue")
- self.assertEqual(now_broker.discardsTtl - start_broker.discardsTtl, 6, "expect 6 TTL discards on broker")
- self.assertEqual(queue.msgTotalDequeues, 6, "expect 6 total dequeues on queue")
-
- sess.close()
-
-
- def test_discards_limit_overflow(self):
- agent = self.setup_access()
- start_broker = agent.getBroker()
-
- sess = self.setup_session()
- tx = sess.sender("discards_limit;{create:always,node:{x-declare:{arguments:{'qpid.max_count':3,'qpid.flow_stop_count':0}}}}")
- tx.send("LIMIT")
- tx.send("LIMIT")
- tx.send("LIMIT")
- try:
- tx.send("LIMIT")
- self.fail("expected to fail sending 4th message")
- except:
- pass
-
- now_broker = agent.getBroker()
- queue = agent.getQueue("discards_limit")
-
- self.failUnless(queue, "expected a valid queue object")
- self.assertEqual(queue.discardsOverflow, 1, "expect 1 overflow discard on queue")
- self.assertEqual(now_broker.discardsOverflow - start_broker.discardsOverflow, 1, "expect 1 overflow discard on broker")
-
- ##
- ## Shut down and restart the connection to clear the error condition.
- ##
- try:
- self.conn.close(timeout=.1)
- except:
- pass
- self.conn = self.setup_connection()
-
- ##
- ## Re-create the session to delete the queue.
- ##
- sess = self.setup_session()
- tx = sess.sender("discards_limit;{create:always,delete:always}")
- sess.close()
-
-
- def test_discards_ring_overflow(self):
- agent = self.setup_access()
- start_broker = agent.getBroker()
-
- sess = self.setup_session()
- tx = sess.sender("discards_ring;{create:always,delete:always,node:{x-declare:{arguments:{'qpid.max_count':3,'qpid.flow_stop_count':0,'qpid.policy_type':ring}}}}")
-
- tx.send("RING")
- tx.send("RING")
- tx.send("RING")
- tx.send("RING")
- tx.send("RING")
-
- now_broker = agent.getBroker()
- queue = agent.getQueue("discards_ring")
-
- self.failUnless(queue, "expected a valid queue object")
- self.assertEqual(queue.discardsRing, 2, "expect 2 ring discards on queue")
- self.assertEqual(now_broker.discardsRing - start_broker.discardsRing, 2, "expect 2 ring discards on broker")
- self.assertEqual(queue.msgTotalDequeues, 2, "expect 2 total dequeues on queue")
-
- sess.close()
-
-
- def test_discards_lvq_replace(self):
- agent = self.setup_access()
- start_broker = agent.getBroker()
-
- sess = self.setup_session()
- tx = sess.sender("discards_lvq;{create:always,delete:always,node:{x-declare:{arguments:{'qpid.max_count':3,'qpid.flow_stop_count':0,'qpid.last_value_queue_key':key}}}}")
- msgA = Message("LVQ_A")
- msgA.properties['key'] = 'AAA'
- msgB = Message("LVQ_B")
- msgB.properties['key'] = 'BBB'
-
- tx.send(msgA)
- tx.send(msgB)
- tx.send(msgA)
- tx.send(msgA)
- tx.send(msgB)
-
- now_broker = agent.getBroker()
- queue = agent.getQueue("discards_lvq")
-
- self.failUnless(queue, "expected a valid queue object")
- self.assertEqual(queue.discardsLvq, 3, "expect 3 lvq discards on queue")
- self.assertEqual(now_broker.discardsLvq - start_broker.discardsLvq, 3, "expect 3 lvq discards on broker")
- self.assertEqual(queue.msgTotalDequeues, 3, "expect 3 total dequeues on queue")
-
- sess.close()
-
-
- def test_discards_reject(self):
- agent = self.setup_access()
- start_broker = agent.getBroker()
-
- sess = self.setup_session()
- tx = sess.sender("discards_reject;{create:always,delete:always}")
- tx.send("REJECT")
- tx.send("REJECT")
- tx.send("REJECT")
-
- rx = sess.receiver("discards_reject")
- m = rx.fetch()
- sess.acknowledge()
- m1 = rx.fetch()
- m2 = rx.fetch()
- sess.acknowledge(m1, Disposition(REJECTED))
- sess.acknowledge(m2, Disposition(REJECTED))
-
- now_broker = agent.getBroker()
- queue = agent.getQueue("discards_reject")
-
- self.failUnless(queue, "expected a valid queue object")
- self.assertEqual(queue.discardsSubscriber, 2, "expect 2 reject discards on queue")
- self.assertEqual(now_broker.discardsSubscriber - start_broker.discardsSubscriber, 2, "expect 2 reject discards on broker")
- self.assertEqual(queue.msgTotalDequeues, 3, "expect 3 total dequeues on queue")
-
- sess.close()
-
-
- def test_message_release(self):
- agent = self.setup_access()
- start_broker = agent.getBroker()
-
- sess = self.setup_session()
- tx = sess.sender("message_release;{create:always,delete:always}")
- tx.send("RELEASE")
- tx.send("RELEASE")
- tx.send("RELEASE")
- tx.send("RELEASE")
- tx.send("RELEASE")
-
- rx = sess.receiver("message_release")
- m1 = rx.fetch()
- m2 = rx.fetch()
- sess.acknowledge(m1, Disposition(RELEASED))
- sess.acknowledge(m2, Disposition(RELEASED))
-
- now_broker = agent.getBroker()
- queue = agent.getQueue("message_release")
-
- self.failUnless(queue, "expected a valid queue object")
- self.assertEqual(queue.acquires, 2, "expect 2 acquires on queue")
- self.failUnless(now_broker.acquires - start_broker.acquires >= 2, "expect at least 2 acquires on broker")
- self.assertEqual(queue.msgTotalDequeues, 0, "expect 0 total dequeues on queue")
-
- self.assertEqual(queue.releases, 2, "expect 2 releases on queue")
- self.failUnless(now_broker.releases - start_broker.releases >= 2, "expect at least 2 releases on broker")
-
- sess.close()
-
-
- def test_discards_purge(self):
- agent = self.setup_access()
- start_broker = agent.getBroker()
-
- sess = self.setup_session()
- tx = sess.sender("discards_purge;{create:always,delete:always}")
- tx.send("PURGE")
- tx.send("PURGE")
- tx.send("PURGE")
- tx.send("PURGE")
- tx.send("PURGE")
-
- queue = agent.getQueue("discards_purge")
- self.failUnless(queue, "expected a valid queue object")
-
- queue.purge(3)
- queue.update()
-
- now_broker = agent.getBroker()
- self.assertEqual(queue.discardsPurge, 3, "expect 3 purge discards on queue")
- self.assertEqual(now_broker.discardsPurge - start_broker.discardsPurge, 3, "expect 3 purge discards on broker")
- self.assertEqual(queue.msgTotalDequeues, 3, "expect 3 total dequeues on queue")
-
- sess.close()
-
-
- def test_reroutes(self):
- agent = self.setup_access()
- start_broker = agent.getBroker()
-
- sess = self.setup_session()
- tx = sess.sender("reroute;{create:always,delete:always}")
- tx.send("REROUTE")
- tx.send("REROUTE")
- tx.send("REROUTE")
- tx.send("REROUTE")
- tx.send("REROUTE")
- tx.send("REROUTE")
- tx.send("REROUTE")
- tx.send("REROUTE")
-
- queue = agent.getQueue("reroute")
- self.failUnless(queue, "expected a valid queue object")
-
- queue.reroute(5, False, 'amq.fanout')
- queue.update()
-
- now_broker = agent.getBroker()
- self.assertEqual(queue.reroutes, 5, "expect 5 reroutes on queue")
- self.assertEqual(now_broker.reroutes - start_broker.reroutes, 5, "expect 5 reroutes on broker")
- self.assertEqual(queue.msgTotalDequeues, 5, "expect 5 total dequeues on queue")
-
- sess.close()
-
-
diff --git a/qpid/python/qpid_tests/broker_0_10/threshold.py b/qpid/python/qpid_tests/broker_0_10/threshold.py
deleted file mode 100644
index fa172c66d2..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/threshold.py
+++ /dev/null
@@ -1,212 +0,0 @@
-#
-# 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.
-#
-
-from qpid.messaging import *
-from qpid.tests.messaging import Base
-import math
-
-class ThresholdTests (Base):
- """
- Test queue threshold events are sent and received correctly
- """
-
- def setup_connection(self):
- return Connection.establish(self.broker, **self.connection_options())
-
- def setup_session(self):
- return self.conn.session()
-
- def enqueue(self, snd, count):
- for i in range(count):
- m = Message("msg-%d" % i)
- snd.send(m)
-
- def dequeue(self, rcv, count):
- for i in range(count):
- m = rcv.fetch(timeout=1)
- self.ssn.acknowledge()
-
- def check_events(self, rcv, count):
- for i in range(count):
- m = rcv.fetch(timeout=0)
- try:
- m = rcv.fetch(timeout=0)
- assert False
- except:
- pass
-
- def do_threshold_test(self, args, messages, drain_count, bw_compat=None):
- astr = ''
- first = True
- for key, value in args.items():
- if first:
- first = None
- else:
- astr += ','
- astr += "'%s':%s" % (key, value)
- rcvUp = self.ssn.receiver("qmf.default.topic/agent.ind.event.org_apache_qpid_broker.queueThresholdCrossedUpward.#")
- rcvDn = self.ssn.receiver("qmf.default.topic/agent.ind.event.org_apache_qpid_broker.queueThresholdCrossedDownward.#")
- rcvBw = self.ssn.receiver("qmf.default.topic/agent.ind.event.org_apache_qpid_broker.queueThresholdExceeded.#")
- snd = self.ssn.sender("ttq; {create:always, node: {x-declare:{auto_delete:True,exclusive:True,arguments:{%s}}}}" % astr)
- rcv = self.ssn.receiver("ttq")
- overhead = 29 #additional bytes in broker's view of message size from headers etc
- size = 0
- count = 0
- for m in messages:
- snd.send(m)
- count = count + 1
- size = size + len(m.content) + overhead
- event = rcvUp.fetch(timeout=1)
- schema = event.content[0]["_schema_id"]
- assert schema["_class_name"] == "queueThresholdCrossedUpward"
- values = event.content[0]["_values"]
- assert values["qName"] == "ttq"
- assert values["msgDepth"] == count, "msgDepth %s, expected %s" % (values["msgDepth"], count)
- assert values["byteDepth"] == size, "byteDepth %s, expected %s" % (values["byteDepth"], size)
- if bw_compat:
- event = rcvBw.fetch(timeout=0)
-
- try:
- event = rcvUp.fetch(timeout=0)
- assert False
- except:
- pass
-
- if drain_count > 0:
- for i in range(drain_count):
- m = rcv.fetch(timeout=1)
- self.ssn.acknowledge()
- count -= 1
- size -= (len(m.content) + overhead)
- event = rcvDn.fetch(timeout=1)
- schema = event.content[0]["_schema_id"]
- assert schema["_class_name"] == "queueThresholdCrossedDownward"
- values = event.content[0]["_values"]
- assert values["qName"] == "ttq"
- assert values["msgDepth"] == count, "msgDepth %s, expected %s" % (values["msgDepth"], count)
- assert values["byteDepth"] == size, "byteDepth %s, expected %s" % (values["byteDepth"], size)
- try:
- event = rcvUp.fetch(timeout=0)
- assert False
- except:
- pass
-
- def test_alert_count(self):
- a = {'qpid.alert_count':5, 'qpid.alert_count_down':3}
- self.do_threshold_test(a, [Message("msg-%s" % i) for i in range(5)], 2)
-
- def test_alert_size(self):
- a = {'qpid.alert_size_up':150,'qpid.alert_size_down':120}
- self.do_threshold_test(a, [Message("msg-%s" % i) for i in range(5)], 2)
-
- def test_alert_count_alias(self):
- a = {'x-qpid-maximum-message-count':10}
- self.do_threshold_test(a, [Message("msg-%s" % i) for i in range(10)], 0, True)
-
- def test_alert_size_alias(self):
- a = {'x-qpid-maximum-message-size':100}
- self.do_threshold_test(a, [Message("msg-%s" % i) for i in range(3)], 0, True)
-
- def test_alert_on_alert_queue(self):
- rcv = self.ssn.receiver("qmf.default.topic/agent.ind.event.org_apache_qpid_broker.queueThresholdCrossedUpward.#; {link:{x-declare:{arguments:{'qpid.alert_count':1}}}}")
- snd = self.ssn.sender("ttq; {create:always, node: {x-declare:{auto_delete:True,exclusive:True,arguments:{'qpid.alert_count':1}}}}")
- snd.send(Message("my-message"))
- queues = []
- for i in range(2):
- event = rcv.fetch(timeout=1)
- schema = event.content[0]["_schema_id"]
- assert schema["_class_name"] == "queueThresholdCrossedUpward"
- values = event.content[0]["_values"]
- queues.append(values["qName"])
- assert "ttq" in queues, "expected event for ttq (%s)" % (queues)
-
- def test_hysteresis(self):
- astr = "'qpid.alert_count_up':10,'qpid.alert_count_down':5"
- rcvUp = self.ssn.receiver("qmf.default.topic/agent.ind.event.org_apache_qpid_broker.queueThresholdCrossedUpward.#")
- rcvDn = self.ssn.receiver("qmf.default.topic/agent.ind.event.org_apache_qpid_broker.queueThresholdCrossedDownward.#")
- snd = self.ssn.sender("thq; {create:always, node: {x-declare:{auto_delete:True,exclusive:True,arguments:{%s}}}}" % astr)
- rcv = self.ssn.receiver("thq")
-
- rcvUp.capacity = 5
- rcvDn.capacity = 5
- rcv.capacity = 5
-
- self.enqueue(snd, 8) # depth = 8
- self.check_events(rcvUp, 0)
- self.check_events(rcvDn, 0)
-
- self.dequeue(rcv, 6) # depth = 2
- self.check_events(rcvUp, 0)
- self.check_events(rcvDn, 0)
-
- self.enqueue(snd, 8) # depth = 10
- self.check_events(rcvUp, 1)
- self.check_events(rcvDn, 0)
-
- self.dequeue(rcv, 1) # depth = 9
- self.check_events(rcvUp, 0)
- self.check_events(rcvDn, 0)
-
- self.enqueue(snd, 1) # depth = 10
- self.check_events(rcvUp, 0)
- self.check_events(rcvDn, 0)
-
- self.enqueue(snd, 10) # depth = 20
- self.check_events(rcvUp, 0)
- self.check_events(rcvDn, 0)
-
- self.dequeue(rcv, 5) # depth = 15
- self.check_events(rcvUp, 0)
- self.check_events(rcvDn, 0)
-
- self.dequeue(rcv, 12) # depth = 3
- self.check_events(rcvUp, 0)
- self.check_events(rcvDn, 1)
-
- self.dequeue(rcv, 1) # depth = 2
- self.check_events(rcvUp, 0)
- self.check_events(rcvDn, 0)
-
- self.enqueue(snd, 6) # depth = 8
- self.check_events(rcvUp, 0)
- self.check_events(rcvDn, 0)
-
- self.enqueue(snd, 6) # depth = 14
- self.check_events(rcvUp, 1)
- self.check_events(rcvDn, 0)
-
- self.dequeue(rcv, 9) # depth = 5
- self.check_events(rcvUp, 0)
- self.check_events(rcvDn, 1)
-
- self.enqueue(snd, 1) # depth = 6
- self.check_events(rcvUp, 0)
- self.check_events(rcvDn, 0)
-
- self.dequeue(rcv, 1) # depth = 5
- self.check_events(rcvUp, 0)
- self.check_events(rcvDn, 0)
-
- self.dequeue(rcv, 5) # depth = 0
- self.check_events(rcvUp, 0)
- self.check_events(rcvDn, 0)
-
-
-
-
diff --git a/qpid/python/qpid_tests/broker_0_10/tx.py b/qpid/python/qpid_tests/broker_0_10/tx.py
deleted file mode 100644
index 8cdc539a08..0000000000
--- a/qpid/python/qpid_tests/broker_0_10/tx.py
+++ /dev/null
@@ -1,265 +0,0 @@
-#
-# 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.
-#
-from qpid.client import Client, Closed
-from qpid.queue import Empty
-from qpid.datatypes import Message, RangedSet
-from qpid.testlib import TestBase010
-
-class TxTests(TestBase010):
- """
- Tests for 'methods' on the amqp tx 'class'
- """
-
- def test_commit(self):
- """
- Test that commited publishes are delivered and commited acks are not re-delivered
- """
- session = self.session
-
- #declare queues and create subscribers in the checking session
- #to ensure that the queues are not auto-deleted too early:
- self.declare_queues(["tx-commit-a", "tx-commit-b", "tx-commit-c"])
- session.message_subscribe(queue="tx-commit-a", destination="qa")
- session.message_subscribe(queue="tx-commit-b", destination="qb")
- session.message_subscribe(queue="tx-commit-c", destination="qc")
-
- #use a separate session for actual work
- session2 = self.conn.session("worker", 2)
- self.perform_txn_work(session2, "tx-commit-a", "tx-commit-b", "tx-commit-c")
- session2.tx_commit()
- session2.close()
-
- session.tx_select()
-
- self.enable_flow("qa")
- queue_a = session.incoming("qa")
-
- self.enable_flow("qb")
- queue_b = session.incoming("qb")
-
- self.enable_flow("qc")
- queue_c = session.incoming("qc")
-
- #check results
- for i in range(1, 5):
- msg = queue_c.get(timeout=1)
- self.assertEqual("TxMessage %d" % i, msg.body)
- session.message_accept(RangedSet(msg.id))
-
- msg = queue_b.get(timeout=1)
- self.assertEqual("TxMessage 6", msg.body)
- session.message_accept(RangedSet(msg.id))
-
- msg = queue_a.get(timeout=1)
- self.assertEqual("TxMessage 7", msg.body)
- session.message_accept(RangedSet(msg.id))
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
- #cleanup
- session.tx_commit()
-
- def test_auto_rollback(self):
- """
- Test that a session closed with an open transaction is effectively rolled back
- """
- session = self.session
- self.declare_queues(["tx-autorollback-a", "tx-autorollback-b", "tx-autorollback-c"])
- session.message_subscribe(queue="tx-autorollback-a", destination="qa")
- session.message_subscribe(queue="tx-autorollback-b", destination="qb")
- session.message_subscribe(queue="tx-autorollback-c", destination="qc")
-
- session2 = self.conn.session("worker", 2)
- queue_a, queue_b, queue_c, ignore = self.perform_txn_work(session2, "tx-autorollback-a", "tx-autorollback-b", "tx-autorollback-c")
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
- session2.close()
-
- session.tx_select()
-
- self.enable_flow("qa")
- queue_a = session.incoming("qa")
-
- self.enable_flow("qb")
- queue_b = session.incoming("qb")
-
- self.enable_flow("qc")
- queue_c = session.incoming("qc")
-
- #check results
- for i in range(1, 5):
- msg = queue_a.get(timeout=1)
- self.assertEqual("Message %d" % i, msg.body)
- session.message_accept(RangedSet(msg.id))
-
- msg = queue_b.get(timeout=1)
- self.assertEqual("Message 6", msg.body)
- session.message_accept(RangedSet(msg.id))
-
- msg = queue_c.get(timeout=1)
- self.assertEqual("Message 7", msg.body)
- session.message_accept(RangedSet(msg.id))
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
- #cleanup
- session.tx_commit()
-
- def test_rollback(self):
- """
- Test that rolled back publishes are not delivered and rolled back acks are re-delivered
- """
- session = self.session
- queue_a, queue_b, queue_c, consumed = self.perform_txn_work(session, "tx-rollback-a", "tx-rollback-b", "tx-rollback-c")
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
- session.tx_rollback()
-
- #need to release messages to get them redelivered now:
- session.message_release(consumed)
-
- #check results
- for i in range(1, 5):
- msg = queue_a.get(timeout=1)
- self.assertEqual("Message %d" % i, msg.body)
- session.message_accept(RangedSet(msg.id))
-
- msg = queue_b.get(timeout=1)
- self.assertEqual("Message 6", msg.body)
- session.message_accept(RangedSet(msg.id))
-
- msg = queue_c.get(timeout=1)
- self.assertEqual("Message 7", msg.body)
- session.message_accept(RangedSet(msg.id))
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
- #cleanup
- session.tx_commit()
-
- def perform_txn_work(self, session, name_a, name_b, name_c):
- """
- Utility method that does some setup and some work under a transaction. Used for testing both
- commit and rollback
- """
- #setup:
- self.declare_queues([name_a, name_b, name_c])
-
- key = "my_key_" + name_b
- topic = "my_topic_" + name_c
-
- session.exchange_bind(queue=name_b, exchange="amq.direct", binding_key=key)
- session.exchange_bind(queue=name_c, exchange="amq.topic", binding_key=topic)
-
- dp = session.delivery_properties(routing_key=name_a)
- for i in range(1, 5):
- mp = session.message_properties(message_id="msg%d" % i)
- session.message_transfer(message=Message(dp, mp, "Message %d" % i))
-
- dp = session.delivery_properties(routing_key=key)
- mp = session.message_properties(message_id="msg6")
- session.message_transfer(destination="amq.direct", message=Message(dp, mp, "Message 6"))
-
- dp = session.delivery_properties(routing_key=topic)
- mp = session.message_properties(message_id="msg7")
- session.message_transfer(destination="amq.topic", message=Message(dp, mp, "Message 7"))
-
- session.tx_select()
-
- #consume and ack messages
- acked = RangedSet()
- self.subscribe(session, queue=name_a, destination="sub_a")
- queue_a = session.incoming("sub_a")
- for i in range(1, 5):
- msg = queue_a.get(timeout=1)
- acked.add(msg.id)
- self.assertEqual("Message %d" % i, msg.body)
-
- self.subscribe(session, queue=name_b, destination="sub_b")
- queue_b = session.incoming("sub_b")
- msg = queue_b.get(timeout=1)
- self.assertEqual("Message 6", msg.body)
- acked.add(msg.id)
-
- sub_c = self.subscribe(session, queue=name_c, destination="sub_c")
- queue_c = session.incoming("sub_c")
- msg = queue_c.get(timeout=1)
- self.assertEqual("Message 7", msg.body)
- acked.add(msg.id)
-
- session.message_accept(acked)
-
- dp = session.delivery_properties(routing_key=topic)
- #publish messages
- for i in range(1, 5):
- mp = session.message_properties(message_id="tx-msg%d" % i)
- session.message_transfer(destination="amq.topic", message=Message(dp, mp, "TxMessage %d" % i))
-
- dp = session.delivery_properties(routing_key=key)
- mp = session.message_properties(message_id="tx-msg6")
- session.message_transfer(destination="amq.direct", message=Message(dp, mp, "TxMessage 6"))
-
- dp = session.delivery_properties(routing_key=name_a)
- mp = session.message_properties(message_id="tx-msg7")
- session.message_transfer(message=Message(dp, mp, "TxMessage 7"))
- return queue_a, queue_b, queue_c, acked
-
- def declare_queues(self, names, session=None):
- session = session or self.session
- for n in names:
- session.queue_declare(queue=n, auto_delete=True)
-
- def subscribe(self, session=None, **keys):
- session = session or self.session
- consumer_tag = keys["destination"]
- session.message_subscribe(**keys)
- session.message_flow(destination=consumer_tag, unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination=consumer_tag, unit=session.credit_unit.byte, value=0xFFFFFFFFL)
-
- def enable_flow(self, tag, session=None):
- session = session or self.session
- session.message_flow(destination=tag, unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination=tag, unit=session.credit_unit.byte, value=0xFFFFFFFFL)
-
- def complete(self, session, msg):
- session.receiver._completed.add(msg.id)#TODO: this may be done automatically
- session.channel.session_completed(session.receiver._completed)
-
diff --git a/qpid/python/qpid_tests/broker_0_8/__init__.py b/qpid/python/qpid_tests/broker_0_8/__init__.py
deleted file mode 100644
index 526f2452f8..0000000000
--- a/qpid/python/qpid_tests/broker_0_8/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Do not delete - marks this directory as a python package.
-
-#
-# 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 basic, broker, example, exchange, queue, testlib, tx
diff --git a/qpid/python/qpid_tests/broker_0_8/basic.py b/qpid/python/qpid_tests/broker_0_8/basic.py
deleted file mode 100644
index 13f4252ffb..0000000000
--- a/qpid/python/qpid_tests/broker_0_8/basic.py
+++ /dev/null
@@ -1,441 +0,0 @@
-#
-# 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.
-#
-from qpid.client import Client, Closed
-from qpid.queue import Empty
-from qpid.content import Content
-from qpid.testlib import TestBase
-
-class BasicTests(TestBase):
- """Tests for 'methods' on the amqp basic 'class'"""
-
- def test_consume_no_local(self):
- """
- Test that the no_local flag is honoured in the consume method
- """
- channel = self.channel
- #setup, declare two queues:
- channel.queue_declare(queue="test-queue-1a", exclusive=True)
- channel.queue_declare(queue="test-queue-1b", exclusive=True)
- #establish two consumers one of which excludes delivery of locally sent messages
- channel.basic_consume(consumer_tag="local_included", queue="test-queue-1a")
- channel.basic_consume(consumer_tag="local_excluded", queue="test-queue-1b", no_local=True)
-
- #send a message
- channel.basic_publish(routing_key="test-queue-1a", content=Content("consume_no_local"))
- channel.basic_publish(routing_key="test-queue-1b", content=Content("consume_no_local"))
-
- #check the queues of the two consumers
- excluded = self.client.queue("local_excluded")
- included = self.client.queue("local_included")
- msg = included.get(timeout=1)
- self.assertEqual("consume_no_local", msg.content.body)
- try:
- excluded.get(timeout=1)
- self.fail("Received locally published message though no_local=true")
- except Empty: None
-
-
- def test_consume_exclusive(self):
- """
- Test that the exclusive flag is honoured in the consume method
- """
- channel = self.channel
- #setup, declare a queue:
- channel.queue_declare(queue="test-queue-2", exclusive=True)
-
- #check that an exclusive consumer prevents other consumer being created:
- channel.basic_consume(consumer_tag="first", queue="test-queue-2", exclusive=True)
- try:
- channel.basic_consume(consumer_tag="second", queue="test-queue-2")
- self.fail("Expected consume request to fail due to previous exclusive consumer")
- except Closed, e:
- self.assertChannelException(403, e.args[0])
-
- #open new channel and cleanup last consumer:
- channel = self.client.channel(2)
- channel.channel_open()
-
- #check that an exclusive consumer cannot be created if a consumer already exists:
- channel.basic_consume(consumer_tag="first", queue="test-queue-2")
- try:
- channel.basic_consume(consumer_tag="second", queue="test-queue-2", exclusive=True)
- self.fail("Expected exclusive consume request to fail due to previous consumer")
- except Closed, e:
- self.assertChannelException(403, e.args[0])
-
- def test_reconnect_to_durable_subscription(self):
- try:
- publisherchannel = self.channel
- my_id = "my_id"
- consumer_connection_properties_with_instance = {"instance": my_id}
- queue_for_subscription = "queue_for_subscription_%s" % my_id
- topic_name = "my_topic_name"
- test_message = self.uniqueString()
-
- durable_subscription_client = self.connect(client_properties=consumer_connection_properties_with_instance)
- consumerchannel = durable_subscription_client.channel(1)
- consumerchannel.channel_open()
-
- self._declare_and_bind_exclusive_queue_on_topic_exchange(consumerchannel, queue_for_subscription, topic_name)
-
- # disconnect
- durable_subscription_client.close()
-
- # send message to topic
- publisherchannel.basic_publish(routing_key=topic_name, exchange="amq.topic", content=Content(test_message))
-
- # reconnect and consume message
- durable_subscription_client = self.connect(client_properties=consumer_connection_properties_with_instance)
- consumerchannel = durable_subscription_client.channel(1)
- consumerchannel.channel_open()
-
- self._declare_and_bind_exclusive_queue_on_topic_exchange(consumerchannel, queue_for_subscription, topic_name)
-
- # Create consumer and consume the message that was sent whilst subscriber was disconnected. By convention we
- # declare the consumer as exclusive to forbid concurrent access.
- subscription = consumerchannel.basic_consume(queue=queue_for_subscription, exclusive=True)
- queue = durable_subscription_client.queue(subscription.consumer_tag)
-
- # consume and verify message content
- msg = queue.get(timeout=1)
- self.assertEqual(test_message, msg.content.body)
- consumerchannel.basic_ack(delivery_tag=msg.delivery_tag)
- finally:
- consumerchannel.queue_delete(queue=queue_for_subscription)
- durable_subscription_client.close()
-
- def _declare_and_bind_exclusive_queue_on_topic_exchange(self, channel, queue, topic_name):
- channel.queue_declare(queue=queue, exclusive=True, auto_delete=False, durable=True)
- channel.queue_bind(exchange="amq.topic", queue=queue, routing_key=topic_name)
-
- def test_consume_queue_errors(self):
- """
- Test error conditions associated with the queue field of the consume method:
- """
- channel = self.channel
- try:
- #queue specified but doesn't exist:
- channel.basic_consume(queue="invalid-queue")
- self.fail("Expected failure when consuming from non-existent queue")
- except Closed, e:
- self.assertChannelException(404, e.args[0])
-
- channel = self.client.channel(2)
- channel.channel_open()
- try:
- #queue not specified and none previously declared for channel:
- channel.basic_consume(queue="")
- self.fail("Expected failure when consuming from unspecified queue")
- except Closed, e:
- self.assertConnectionException(530, e.args[0])
-
- def test_consume_unique_consumers(self):
- """
- Ensure unique consumer tags are enforced
- """
- channel = self.channel
- #setup, declare a queue:
- channel.queue_declare(queue="test-queue-3", exclusive=True)
-
- #check that attempts to use duplicate tags are detected and prevented:
- channel.basic_consume(consumer_tag="first", queue="test-queue-3")
- try:
- channel.basic_consume(consumer_tag="first", queue="test-queue-3")
- self.fail("Expected consume request to fail due to non-unique tag")
- except Closed, e:
- self.assertConnectionException(530, e.args[0])
-
- def test_cancel(self):
- """
- Test compliance of the basic.cancel method
- """
- channel = self.channel
- #setup, declare a queue:
- channel.queue_declare(queue="test-queue-4", exclusive=True)
- channel.basic_consume(consumer_tag="my-consumer", queue="test-queue-4")
- channel.basic_publish(routing_key="test-queue-4", content=Content("One"))
-
- myqueue = self.client.queue("my-consumer")
- msg = myqueue.get(timeout=1)
- self.assertEqual("One", msg.content.body)
-
- #cancel should stop messages being delivered
- channel.basic_cancel(consumer_tag="my-consumer")
- channel.basic_publish(routing_key="test-queue-4", content=Content("Two"))
- try:
- msg = myqueue.get(timeout=1)
- self.fail("Got message after cancellation: " + msg)
- except Empty: None
-
- #cancellation of non-existant consumers should be handled without error
- channel.basic_cancel(consumer_tag="my-consumer")
- channel.basic_cancel(consumer_tag="this-never-existed")
-
-
- def test_ack(self):
- """
- Test basic ack/recover behaviour
- """
- channel = self.channel
- channel.queue_declare(queue="test-ack-queue", exclusive=True)
-
- reply = channel.basic_consume(queue="test-ack-queue", no_ack=False)
- queue = self.client.queue(reply.consumer_tag)
-
- channel.basic_publish(routing_key="test-ack-queue", content=Content("One"))
- channel.basic_publish(routing_key="test-ack-queue", content=Content("Two"))
- channel.basic_publish(routing_key="test-ack-queue", content=Content("Three"))
- channel.basic_publish(routing_key="test-ack-queue", content=Content("Four"))
- channel.basic_publish(routing_key="test-ack-queue", content=Content("Five"))
-
- msg1 = queue.get(timeout=1)
- msg2 = queue.get(timeout=1)
- msg3 = queue.get(timeout=1)
- msg4 = queue.get(timeout=1)
- msg5 = queue.get(timeout=1)
-
- self.assertEqual("One", msg1.content.body)
- self.assertEqual("Two", msg2.content.body)
- self.assertEqual("Three", msg3.content.body)
- self.assertEqual("Four", msg4.content.body)
- self.assertEqual("Five", msg5.content.body)
-
- channel.basic_ack(delivery_tag=msg2.delivery_tag, multiple=True) #One & Two
- channel.basic_ack(delivery_tag=msg4.delivery_tag, multiple=False) #Four
-
- channel.basic_recover(requeue=False)
-
- msg3b = queue.get(timeout=1)
- msg5b = queue.get(timeout=1)
-
- self.assertEqual("Three", msg3b.content.body)
- self.assertEqual("Five", msg5b.content.body)
-
- try:
- extra = queue.get(timeout=1)
- self.fail("Got unexpected message: " + extra.content.body)
- except Empty: None
-
- def test_recover_requeue(self):
- """
- Test requeing on recovery
- """
- channel = self.channel
- channel.queue_declare(queue="test-requeue", exclusive=True)
-
- subscription = channel.basic_consume(queue="test-requeue", no_ack=False)
- queue = self.client.queue(subscription.consumer_tag)
-
- channel.basic_publish(routing_key="test-requeue", content=Content("One"))
- channel.basic_publish(routing_key="test-requeue", content=Content("Two"))
- channel.basic_publish(routing_key="test-requeue", content=Content("Three"))
- channel.basic_publish(routing_key="test-requeue", content=Content("Four"))
- channel.basic_publish(routing_key="test-requeue", content=Content("Five"))
-
- msg1 = queue.get(timeout=1)
- msg2 = queue.get(timeout=1)
- msg3 = queue.get(timeout=1)
- msg4 = queue.get(timeout=1)
- msg5 = queue.get(timeout=1)
-
- self.assertEqual("One", msg1.content.body)
- self.assertEqual("Two", msg2.content.body)
- self.assertEqual("Three", msg3.content.body)
- self.assertEqual("Four", msg4.content.body)
- self.assertEqual("Five", msg5.content.body)
-
- channel.basic_ack(delivery_tag=msg2.delivery_tag, multiple=True) #One & Two
- channel.basic_ack(delivery_tag=msg4.delivery_tag, multiple=False) #Four
-
- channel.basic_cancel(consumer_tag=subscription.consumer_tag)
-
- channel.basic_recover(requeue=True)
-
- subscription2 = channel.basic_consume(queue="test-requeue")
- queue2 = self.client.queue(subscription2.consumer_tag)
-
- msg3b = queue2.get(timeout=1)
- msg5b = queue2.get(timeout=1)
-
- self.assertEqual("Three", msg3b.content.body)
- self.assertEqual("Five", msg5b.content.body)
-
- self.assertEqual(True, msg3b.redelivered)
- self.assertEqual(True, msg5b.redelivered)
-
- try:
- extra = queue2.get(timeout=1)
- self.fail("Got unexpected message in second queue: " + extra.content.body)
- except Empty: None
- try:
- extra = queue.get(timeout=1)
- self.fail("Got unexpected message in original queue: " + extra.content.body)
- except Empty: None
-
-
- def test_qos_prefetch_count(self):
- """
- Test that the prefetch count specified is honoured
- """
- #setup: declare queue and subscribe
- channel = self.channel
- channel.queue_declare(queue="test-prefetch-count", exclusive=True)
- subscription = channel.basic_consume(queue="test-prefetch-count", no_ack=False)
- queue = self.client.queue(subscription.consumer_tag)
-
- #set prefetch to 5:
- channel.basic_qos(prefetch_count=5)
-
- #publish 10 messages:
- for i in range(1, 11):
- channel.basic_publish(routing_key="test-prefetch-count", content=Content("Message %d" % i))
-
- #only 5 messages should have been delivered:
- for i in range(1, 6):
- msg = queue.get(timeout=1)
- self.assertEqual("Message %d" % i, msg.content.body)
- try:
- extra = queue.get(timeout=1)
- self.fail("Got unexpected 6th message in original queue: " + extra.content.body)
- except Empty: None
-
- #ack messages and check that the next set arrive ok:
- channel.basic_ack(delivery_tag=msg.delivery_tag, multiple=True)
-
- for i in range(6, 11):
- msg = queue.get(timeout=1)
- self.assertEqual("Message %d" % i, msg.content.body)
-
- channel.basic_ack(delivery_tag=msg.delivery_tag, multiple=True)
-
- try:
- extra = queue.get(timeout=1)
- self.fail("Got unexpected 11th message in original queue: " + extra.content.body)
- except Empty: None
-
-
-
- def test_qos_prefetch_size(self):
- """
- Test that the prefetch size specified is honoured
- """
- #setup: declare queue and subscribe
- channel = self.channel
- channel.queue_declare(queue="test-prefetch-size", exclusive=True)
- subscription = channel.basic_consume(queue="test-prefetch-size", no_ack=False)
- queue = self.client.queue(subscription.consumer_tag)
-
- #set prefetch to 50 bytes (each message is 9 or 10 bytes):
- channel.basic_qos(prefetch_size=50)
-
- #publish 10 messages:
- for i in range(1, 11):
- channel.basic_publish(routing_key="test-prefetch-size", content=Content("Message %d" % i))
-
- #only 5 messages should have been delivered (i.e. 45 bytes worth):
- for i in range(1, 6):
- msg = queue.get(timeout=1)
- self.assertEqual("Message %d" % i, msg.content.body)
-
- try:
- extra = queue.get(timeout=1)
- self.fail("Got unexpected 6th message in original queue: " + extra.content.body)
- except Empty: None
-
- #ack messages and check that the next set arrive ok:
- channel.basic_ack(delivery_tag=msg.delivery_tag, multiple=True)
-
- for i in range(6, 11):
- msg = queue.get(timeout=1)
- self.assertEqual("Message %d" % i, msg.content.body)
-
- channel.basic_ack(delivery_tag=msg.delivery_tag, multiple=True)
-
- try:
- extra = queue.get(timeout=1)
- self.fail("Got unexpected 11th message in original queue: " + extra.content.body)
- except Empty: None
-
- #make sure that a single oversized message still gets delivered
- large = "abcdefghijklmnopqrstuvwxyz"
- large = large + "-" + large;
- channel.basic_publish(routing_key="test-prefetch-size", content=Content(large))
- msg = queue.get(timeout=1)
- self.assertEqual(large, msg.content.body)
-
- def test_get(self):
- """
- Test basic_get method
- """
- channel = self.channel
- channel.queue_declare(queue="test-get", exclusive=True)
-
- #publish some messages (no_ack=True)
- for i in range(1, 11):
- channel.basic_publish(routing_key="test-get", content=Content("Message %d" % i))
-
- #use basic_get to read back the messages, and check that we get an empty at the end
- for i in range(1, 11):
- reply = channel.basic_get(no_ack=True)
- self.assertEqual(reply.method.klass.name, "basic")
- self.assertEqual(reply.method.name, "get_ok")
- self.assertEqual("Message %d" % i, reply.content.body)
-
- reply = channel.basic_get(no_ack=True)
- self.assertEqual(reply.method.klass.name, "basic")
- self.assertEqual(reply.method.name, "get_empty")
-
- #repeat for no_ack=False
- for i in range(11, 21):
- channel.basic_publish(routing_key="test-get", content=Content("Message %d" % i))
-
- for i in range(11, 21):
- reply = channel.basic_get(no_ack=False)
- self.assertEqual(reply.method.klass.name, "basic")
- self.assertEqual(reply.method.name, "get_ok")
- self.assertEqual("Message %d" % i, reply.content.body)
- if(i == 13):
- channel.basic_ack(delivery_tag=reply.delivery_tag, multiple=True)
- if(i in [15, 17, 19]):
- channel.basic_ack(delivery_tag=reply.delivery_tag)
-
- reply = channel.basic_get(no_ack=True)
- self.assertEqual(reply.method.klass.name, "basic")
- self.assertEqual(reply.method.name, "get_empty")
-
- #recover(requeue=True)
- channel.basic_recover(requeue=True)
-
- #get the unacked messages again (14, 16, 18, 20)
- for i in [14, 16, 18, 20]:
- reply = channel.basic_get(no_ack=False)
- self.assertEqual(reply.method.klass.name, "basic")
- self.assertEqual(reply.method.name, "get_ok")
- self.assertEqual("Message %d" % i, reply.content.body)
- channel.basic_ack(delivery_tag=reply.delivery_tag)
-
- reply = channel.basic_get(no_ack=True)
- self.assertEqual(reply.method.klass.name, "basic")
- self.assertEqual(reply.method.name, "get_empty")
-
- channel.basic_recover(requeue=True)
-
- reply = channel.basic_get(no_ack=True)
- self.assertEqual(reply.method.klass.name, "basic")
- self.assertEqual(reply.method.name, "get_empty")
diff --git a/qpid/python/qpid_tests/broker_0_8/broker.py b/qpid/python/qpid_tests/broker_0_8/broker.py
deleted file mode 100644
index 7f3fe7530e..0000000000
--- a/qpid/python/qpid_tests/broker_0_8/broker.py
+++ /dev/null
@@ -1,120 +0,0 @@
-#
-# 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.
-#
-from qpid.client import Closed
-from qpid.queue import Empty
-from qpid.content import Content
-from qpid.testlib import TestBase
-
-class BrokerTests(TestBase):
- """Tests for basic Broker functionality"""
-
- def test_ack_and_no_ack(self):
- """
- First, this test tries to receive a message with a no-ack
- consumer. Second, this test tries to explicitly receive and
- acknowledge a message with an acknowledging consumer.
- """
- ch = self.channel
- self.queue_declare(ch, queue = "myqueue")
-
- # No ack consumer
- ctag = ch.basic_consume(queue = "myqueue", no_ack = True).consumer_tag
- body = "test no-ack"
- ch.basic_publish(routing_key = "myqueue", content = Content(body))
- msg = self.client.queue(ctag).get(timeout = 5)
- self.assert_(msg.content.body == body)
-
- # Acknowledging consumer
- self.queue_declare(ch, queue = "otherqueue")
- ctag = ch.basic_consume(queue = "otherqueue", no_ack = False).consumer_tag
- body = "test ack"
- ch.basic_publish(routing_key = "otherqueue", content = Content(body))
- msg = self.client.queue(ctag).get(timeout = 5)
- ch.basic_ack(delivery_tag = msg.delivery_tag)
- self.assert_(msg.content.body == body)
-
- def test_basic_delivery_immediate(self):
- """
- Test basic message delivery where consume is issued before publish
- """
- channel = self.channel
- self.exchange_declare(channel, exchange="test-exchange", type="direct")
- self.queue_declare(channel, queue="test-queue")
- channel.queue_bind(queue="test-queue", exchange="test-exchange", routing_key="key")
- reply = channel.basic_consume(queue="test-queue", no_ack=True)
- queue = self.client.queue(reply.consumer_tag)
-
- body = "Immediate Delivery"
- channel.basic_publish(exchange="test-exchange", routing_key="key", content=Content(body), immediate=True)
- msg = queue.get(timeout=5)
- self.assert_(msg.content.body == body)
-
- # TODO: Ensure we fail if immediate=True and there's no consumer.
-
-
- def test_basic_delivery_queued(self):
- """
- Test basic message delivery where publish is issued before consume
- (i.e. requires queueing of the message)
- """
- channel = self.channel
- self.exchange_declare(channel, exchange="test-exchange", type="direct")
- self.queue_declare(channel, queue="test-queue")
- channel.queue_bind(queue="test-queue", exchange="test-exchange", routing_key="key")
- body = "Queued Delivery"
- channel.basic_publish(exchange="test-exchange", routing_key="key", content=Content(body))
- reply = channel.basic_consume(queue="test-queue", no_ack=True)
- queue = self.client.queue(reply.consumer_tag)
- msg = queue.get(timeout=5)
- self.assert_(msg.content.body == body)
-
- def test_invalid_channel(self):
- channel = self.client.channel(200)
- try:
- channel.queue_declare(exclusive=True)
- self.fail("Expected error on queue_declare for invalid channel")
- except Closed, e:
- self.assertConnectionException(504, e.args[0])
-
- def test_closed_channel(self):
- channel = self.client.channel(200)
- channel.channel_open()
- channel.channel_close()
- try:
- channel.queue_declare(exclusive=True)
- self.fail("Expected error on queue_declare for closed channel")
- except Closed, e:
- self.assertConnectionException(504, e.args[0])
-
- def test_channel_flow(self):
- channel = self.channel
- channel.queue_declare(queue="flow_test_queue", exclusive=True)
- ctag = channel.basic_consume(queue="flow_test_queue", no_ack=True).consumer_tag
- incoming = self.client.queue(ctag)
-
- channel.channel_flow(active=False)
- channel.basic_publish(routing_key="flow_test_queue", content=Content("abcdefghijklmnopqrstuvwxyz"))
- try:
- incoming.get(timeout=1)
- self.fail("Received message when flow turned off.")
- except Empty: None
-
- channel.channel_flow(active=True)
- msg = incoming.get(timeout=1)
- self.assertEqual("abcdefghijklmnopqrstuvwxyz", msg.content.body)
diff --git a/qpid/python/qpid_tests/broker_0_8/example.py b/qpid/python/qpid_tests/broker_0_8/example.py
deleted file mode 100644
index d82bad1f61..0000000000
--- a/qpid/python/qpid_tests/broker_0_8/example.py
+++ /dev/null
@@ -1,94 +0,0 @@
-#
-# 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.
-#
-
-from qpid.content import Content
-from qpid.testlib import TestBase
-
-class ExampleTest (TestBase):
- """
- An example Qpid test, illustrating the unittest frameowkr and the
- python Qpid client. The test class must inherit TestCase. The
- test code uses the Qpid client to interact with a qpid broker and
- verify it behaves as expected.
- """
-
- def test_example(self):
- """
- An example test. Note that test functions must start with 'test_'
- to be recognized by the test framework.
- """
-
- # By inheriting TestBase, self.client is automatically connected
- # and self.channel is automatically opened as channel(1)
- # Other channel methods mimic the protocol.
- channel = self.channel
-
- # Now we can send regular commands. If you want to see what the method
- # arguments mean or what other commands are available, you can use the
- # python builtin help() method. For example:
- #help(chan)
- #help(chan.exchange_declare)
-
- # If you want browse the available protocol methods without being
- # connected to a live server you can use the amqp-doc utility:
- #
- # Usage amqp-doc [<options>] <spec> [<pattern_1> ... <pattern_n>]
- #
- # Options:
- # -e, --regexp use regex instead of glob when matching
-
- # Now that we know what commands are available we can use them to
- # interact with the server.
-
- # Here we use ordinal arguments.
- self.exchange_declare(channel, 0, "test", "direct")
-
- # Here we use keyword arguments.
- self.queue_declare(channel, queue="test-queue")
- channel.queue_bind(queue="test-queue", exchange="test", routing_key="key")
-
- # Call Channel.basic_consume to register as a consumer.
- # All the protocol methods return a message object. The message object
- # has fields corresponding to the reply method fields, plus a content
- # field that is filled if the reply includes content. In this case the
- # interesting field is the consumer_tag.
- reply = channel.basic_consume(queue="test-queue")
-
- # We can use the Client.queue(...) method to access the queue
- # corresponding to our consumer_tag.
- queue = self.client.queue(reply.consumer_tag)
-
- # Now lets publish a message and see if our consumer gets it. To do
- # this we need to import the Content class.
- body = "Hello World!"
- channel.basic_publish(exchange="test",
- routing_key="key",
- content=Content(body))
-
- # Now we'll wait for the message to arrive. We can use the timeout
- # argument in case the server hangs. By default queue.get() will wait
- # until a message arrives or the connection to the server dies.
- msg = queue.get(timeout=10)
-
- # And check that we got the right response with assertEqual
- self.assertEqual(body, msg.content.body)
-
- # Now acknowledge the message.
- channel.basic_ack(msg.delivery_tag, True)
-
diff --git a/qpid/python/qpid_tests/broker_0_8/exchange.py b/qpid/python/qpid_tests/broker_0_8/exchange.py
deleted file mode 100644
index 8d610a79dd..0000000000
--- a/qpid/python/qpid_tests/broker_0_8/exchange.py
+++ /dev/null
@@ -1,349 +0,0 @@
-#
-# 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.
-#
-
-"""
-Tests for exchange behaviour.
-
-Test classes ending in 'RuleTests' are derived from rules in amqp.xml.
-"""
-
-import Queue, logging
-from qpid.testlib import TestBase
-from qpid.content import Content
-from qpid.client import Closed
-
-
-class StandardExchangeVerifier:
- """Verifies standard exchange behavior.
-
- Used as base class for classes that test standard exchanges."""
-
- def verifyDirectExchange(self, ex):
- """Verify that ex behaves like a direct exchange."""
- self.queue_declare(queue="q")
- self.channel.queue_bind(queue="q", exchange=ex, routing_key="k")
- self.assertPublishConsume(exchange=ex, queue="q", routing_key="k")
- try:
- self.assertPublishConsume(exchange=ex, queue="q", routing_key="kk")
- self.fail("Expected Empty exception")
- except Queue.Empty: None # Expected
-
- def verifyFanOutExchange(self, ex):
- """Verify that ex behaves like a fanout exchange."""
- self.queue_declare(queue="q")
- self.channel.queue_bind(queue="q", exchange=ex)
- self.queue_declare(queue="p")
- self.channel.queue_bind(queue="p", exchange=ex)
- for qname in ["q", "p"]: self.assertPublishGet(self.consume(qname), ex)
-
- def verifyTopicExchange(self, ex):
- """Verify that ex behaves like a topic exchange"""
- self.queue_declare(queue="a")
- self.channel.queue_bind(queue="a", exchange=ex, routing_key="a.#.b.*")
- q = self.consume("a")
- self.assertPublishGet(q, ex, "a.b.x")
- self.assertPublishGet(q, ex, "a.x.b.x")
- self.assertPublishGet(q, ex, "a.x.x.b.x")
- # Shouldn't match
- self.channel.basic_publish(exchange=ex, routing_key="a.b")
- self.channel.basic_publish(exchange=ex, routing_key="a.b.x.y")
- self.channel.basic_publish(exchange=ex, routing_key="x.a.b.x")
- self.channel.basic_publish(exchange=ex, routing_key="a.b")
- self.assert_(q.empty())
-
- def verifyHeadersExchange(self, ex):
- """Verify that ex is a headers exchange"""
- self.queue_declare(queue="q")
- self.channel.queue_bind(queue="q", exchange=ex, arguments={ "x-match":"all", "name":"fred" , "age":3} )
- q = self.consume("q")
- headers = {"name":"fred", "age":3}
- self.assertPublishGet(q, exchange=ex, properties={'headers':headers})
- self.channel.basic_publish(exchange=ex) # No headers, won't deliver
- self.assertEmpty(q);
-
-
-class RecommendedTypesRuleTests(TestBase, StandardExchangeVerifier):
- """
- The server SHOULD implement these standard exchange types: topic, headers.
-
- Client attempts to declare an exchange with each of these standard types.
- """
-
- def testDirect(self):
- """Declare and test a direct exchange"""
- self.exchange_declare(0, exchange="d", type="direct")
- self.verifyDirectExchange("d")
-
- def testFanout(self):
- """Declare and test a fanout exchange"""
- self.exchange_declare(0, exchange="f", type="fanout")
- self.verifyFanOutExchange("f")
-
- def testTopic(self):
- """Declare and test a topic exchange"""
- self.exchange_declare(0, exchange="t", type="topic")
- self.verifyTopicExchange("t")
-
- def testHeaders(self):
- """Declare and test a headers exchange"""
- self.exchange_declare(0, exchange="h", type="headers")
- self.verifyHeadersExchange("h")
-
-
-class RequiredInstancesRuleTests(TestBase, StandardExchangeVerifier):
- """
- The server MUST, in each virtual host, pre-declare an exchange instance
- for each standard exchange type that it implements, where the name of the
- exchange instance is amq. followed by the exchange type name.
-
- Client creates a temporary queue and attempts to bind to each required
- exchange instance (amq.fanout, amq.direct, and amq.topic, amq.match if
- those types are defined).
- """
- def testAmqDirect(self): self.verifyDirectExchange("amq.direct")
-
- def testAmqFanOut(self): self.verifyFanOutExchange("amq.fanout")
-
- def testAmqTopic(self): self.verifyTopicExchange("amq.topic")
-
- def testAmqMatch(self): self.verifyHeadersExchange("amq.match")
-
-class DefaultExchangeRuleTests(TestBase, StandardExchangeVerifier):
- """
- The server MUST predeclare a direct exchange to act as the default exchange
- for content Publish methods and for default queue bindings.
-
- Client checks that the default exchange is active by specifying a queue
- binding with no exchange name, and publishing a message with a suitable
- routing key but without specifying the exchange name, then ensuring that
- the message arrives in the queue correctly.
- """
- def testDefaultExchange(self):
- # Test automatic binding by queue name.
- self.queue_declare(queue="d")
- self.assertPublishConsume(queue="d", routing_key="d")
-
- def testDefaultExchangeExplicitBind(self):
- # Test automatic binding by queue name.
- self.queue_declare(queue="d")
- # Test explicit bind to default queue
- self.verifyDirectExchange("")
-
-
-# TODO aconway 2006-09-27: Fill in empty tests:
-
-class DefaultAccessRuleTests(TestBase):
- """
- The server MUST NOT allow clients to access the default exchange except
- by specifying an empty exchange name in the Queue.Bind and content Publish
- methods.
- """
-
-class ExtensionsRuleTests(TestBase):
- """
- The server MAY implement other exchange types as wanted.
- """
-
-
-class DeclareMethodMinimumRuleTests(TestBase):
- """
- The server SHOULD support a minimum of 16 exchanges per virtual host and
- ideally, impose no limit except as defined by available resources.
-
- The client creates as many exchanges as it can until the server reports
- an error; the number of exchanges successfuly created must be at least
- sixteen.
- """
-
-
-class DeclareMethodTicketFieldValidityRuleTests(TestBase):
- """
- The client MUST provide a valid access ticket giving "active" access to
- the realm in which the exchange exists or will be created, or "passive"
- access if the if-exists flag is set.
-
- Client creates access ticket with wrong access rights and attempts to use
- in this method.
- """
-
-
-class DeclareMethodExchangeFieldReservedRuleTests(TestBase):
- """
- Exchange names starting with "amq." are reserved for predeclared and
- standardised exchanges. The client MUST NOT attempt to create an exchange
- starting with "amq.".
-
-
- """
-
-
-class DeclareMethodTypeFieldTypedRuleTests(TestBase):
- """
- Exchanges cannot be redeclared with different types. The client MUST not
- attempt to redeclare an existing exchange with a different type than used
- in the original Exchange.Declare method.
-
-
- """
-
-
-class DeclareMethodTypeFieldSupportRuleTests(TestBase):
- """
- The client MUST NOT attempt to create an exchange with a type that the
- server does not support.
-
-
- """
-
-
-class DeclareMethodPassiveFieldNotFoundRuleTests(TestBase):
- """
- If set, and the exchange does not already exist, the server MUST raise a
- channel exception with reply code 404 (not found).
- """
- def test(self):
- try:
- self.channel.exchange_declare(exchange="humpty_dumpty", passive=True)
- self.fail("Expected 404 for passive declaration of unknown exchange.")
- except Closed, e:
- self.assertChannelException(404, e.args[0])
-
-
-class DeclareMethodDurableFieldSupportRuleTests(TestBase):
- """
- The server MUST support both durable and transient exchanges.
-
-
- """
-
-
-class DeclareMethodDurableFieldStickyRuleTests(TestBase):
- """
- The server MUST ignore the durable field if the exchange already exists.
-
-
- """
-
-
-class DeclareMethodAutoDeleteFieldStickyRuleTests(TestBase):
- """
- The server MUST ignore the auto-delete field if the exchange already
- exists.
-
-
- """
-
-
-class DeleteMethodTicketFieldValidityRuleTests(TestBase):
- """
- The client MUST provide a valid access ticket giving "active" access
- rights to the exchange's access realm.
-
- Client creates access ticket with wrong access rights and attempts to use
- in this method.
- """
-
-
-class DeleteMethodExchangeFieldExistsRuleTests(TestBase):
- """
- The client MUST NOT attempt to delete an exchange that does not exist.
- """
-
-
-class HeadersExchangeTests(TestBase):
- """
- Tests for headers exchange functionality.
- """
- def setUp(self):
- TestBase.setUp(self)
- self.queue_declare(queue="q")
- self.q = self.consume("q")
-
- def myAssertPublishGet(self, headers):
- self.assertPublishGet(self.q, exchange="amq.match", properties={'headers':headers})
-
- def myBasicPublish(self, headers):
- self.channel.basic_publish(exchange="amq.match", content=Content("foobar", properties={'headers':headers}))
-
- def testMatchAll(self):
- self.channel.queue_bind(queue="q", exchange="amq.match", arguments={ 'x-match':'all', "name":"fred", "age":3})
- self.myAssertPublishGet({"name":"fred", "age":3})
- self.myAssertPublishGet({"name":"fred", "age":3, "extra":"ignoreme"})
-
- # None of these should match
- self.myBasicPublish({})
- self.myBasicPublish({"name":"barney"})
- self.myBasicPublish({"name":10})
- self.myBasicPublish({"name":"fred", "age":2})
- self.assertEmpty(self.q)
-
- def testMatchAny(self):
- self.channel.queue_bind(queue="q", exchange="amq.match", arguments={ 'x-match':'any', "name":"fred", "age":3})
- self.myAssertPublishGet({"name":"fred"})
- self.myAssertPublishGet({"name":"fred", "ignoreme":10})
- self.myAssertPublishGet({"ignoreme":10, "age":3})
-
- # Wont match
- self.myBasicPublish({})
- self.myBasicPublish({"irrelevant":0})
- self.assertEmpty(self.q)
-
-
-class MiscellaneousErrorsTests(TestBase):
- """
- Test some miscellaneous error conditions
- """
- def testTypeNotKnown(self):
- try:
- self.channel.exchange_declare(exchange="test_type_not_known_exchange", type="invalid_type")
- self.fail("Expected 503 for declaration of unknown exchange type.")
- except Closed, e:
- self.assertConnectionException(503, e.args[0])
-
- def testDifferentDeclaredType(self):
- self.channel.exchange_declare(exchange="test_different_declared_type_exchange", type="direct")
- try:
- self.channel.exchange_declare(exchange="test_different_declared_type_exchange", type="topic")
- self.fail("Expected 530 for redeclaration of exchange with different type.")
- except Closed, e:
- self.assertConnectionException(530, e.args[0])
- #cleanup
- other = self.connect()
- c2 = other.channel(1)
- c2.channel_open()
- c2.exchange_delete(exchange="test_different_declared_type_exchange")
-
- def testReservedExchangeRedeclaredSameNameAndType(self):
- self.channel.exchange_declare(exchange="amq.direct", type="direct", passive=True)
- self.channel.exchange_declare(exchange="amq.direct", type="direct", passive=False)
-
- def testReservedExchangeNameRedeclaredDifferentType(self):
- try:
- self.channel.exchange_declare(exchange="amq.direct", type="topic", passive=False)
- self.fail("Expected 530 for redeclaration of exchange with different type.")
- except Closed, e:
- self.assertConnectionException(530, e.args[0])
-
- def testReservedExchangeNameDisallowed(self):
- try:
- self.channel.exchange_declare(exchange="amq.myexch", type="direct", passive=False)
- self.fail("Expected 530 for redeclaration of exchange with different type.")
- except Closed, e:
- self.assertConnectionException(530, e.args[0])
-
diff --git a/qpid/python/qpid_tests/broker_0_8/queue.py b/qpid/python/qpid_tests/broker_0_8/queue.py
deleted file mode 100644
index b7a41736ab..0000000000
--- a/qpid/python/qpid_tests/broker_0_8/queue.py
+++ /dev/null
@@ -1,255 +0,0 @@
-#
-# 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.
-#
-from qpid.client import Client, Closed
-from qpid.queue import Empty
-from qpid.content import Content
-from qpid.testlib import TestBase
-
-class QueueTests(TestBase):
- """Tests for 'methods' on the amqp queue 'class'"""
-
- def test_purge(self):
- """
- Test that the purge method removes messages from the queue
- """
- channel = self.channel
- #setup, declare a queue and add some messages to it:
- channel.exchange_declare(exchange="test-exchange", type="direct")
- channel.queue_declare(queue="test-queue", exclusive=True)
- channel.queue_bind(queue="test-queue", exchange="test-exchange", routing_key="key")
- channel.basic_publish(exchange="test-exchange", routing_key="key", content=Content("one"))
- channel.basic_publish(exchange="test-exchange", routing_key="key", content=Content("two"))
- channel.basic_publish(exchange="test-exchange", routing_key="key", content=Content("three"))
-
- #check that the queue now reports 3 messages:
- reply = channel.queue_declare(queue="test-queue")
- self.assertEqual(3, reply.message_count)
-
- #now do the purge, then test that three messages are purged and the count drops to 0
- reply = channel.queue_purge(queue="test-queue");
- self.assertEqual(3, reply.message_count)
- reply = channel.queue_declare(queue="test-queue")
- self.assertEqual(0, reply.message_count)
-
- #send a further message and consume it, ensuring that the other messages are really gone
- channel.basic_publish(exchange="test-exchange", routing_key="key", content=Content("four"))
- reply = channel.basic_consume(queue="test-queue", no_ack=True)
- queue = self.client.queue(reply.consumer_tag)
- msg = queue.get(timeout=1)
- self.assertEqual("four", msg.content.body)
-
- #check error conditions (use new channels):
- channel = self.client.channel(2)
- channel.channel_open()
- try:
- #queue specified but doesn't exist:
- channel.queue_purge(queue="invalid-queue")
- self.fail("Expected failure when purging non-existent queue")
- except Closed, e:
- self.assertChannelException(404, e.args[0])
-
- channel = self.client.channel(3)
- channel.channel_open()
- try:
- #queue not specified and none previously declared for channel:
- channel.queue_purge()
- self.fail("Expected failure when purging unspecified queue")
- except Closed, e:
- self.assertConnectionException(530, e.args[0])
-
- #cleanup
- other = self.connect()
- channel = other.channel(1)
- channel.channel_open()
- channel.exchange_delete(exchange="test-exchange")
-
- def test_declare_exclusive(self):
- """
- Test that the exclusive field is honoured in queue.declare
- """
- # TestBase.setUp has already opened channel(1)
- c1 = self.channel
- # Here we open a second separate connection:
- other = self.connect()
- c2 = other.channel(1)
- c2.channel_open()
-
- #declare an exclusive queue:
- c1.queue_declare(queue="exclusive-queue", exclusive="True")
- try:
- #other connection should not be allowed to declare this:
- c2.queue_declare(queue="exclusive-queue", exclusive="True")
- self.fail("Expected second exclusive queue_declare to raise a channel exception")
- except Closed, e:
- self.assertChannelException(405, e.args[0])
-
-
- def test_declare_passive(self):
- """
- Test that the passive field is honoured in queue.declare
- """
- channel = self.channel
- #declare an exclusive queue:
- channel.queue_declare(queue="passive-queue-1", exclusive="True")
- channel.queue_declare(queue="passive-queue-1", passive="True")
- try:
- #other connection should not be allowed to declare this:
- channel.queue_declare(queue="passive-queue-2", passive="True")
- self.fail("Expected passive declaration of non-existant queue to raise a channel exception")
- except Closed, e:
- self.assertChannelException(404, e.args[0])
-
-
- def test_bind(self):
- """
- Test various permutations of the queue.bind method
- """
- channel = self.channel
- channel.queue_declare(queue="queue-1", exclusive="True")
-
- #straightforward case, both exchange & queue exist so no errors expected:
- channel.queue_bind(queue="queue-1", exchange="amq.direct", routing_key="key1")
-
- #bind the default queue for the channel (i.e. last one declared):
- channel.queue_bind(exchange="amq.direct", routing_key="key2")
-
- #use the queue name where neither routing key nor queue are specified:
- channel.queue_bind(exchange="amq.direct")
-
- #try and bind to non-existant exchange
- try:
- channel.queue_bind(queue="queue-1", exchange="an-invalid-exchange", routing_key="key1")
- self.fail("Expected bind to non-existant exchange to fail")
- except Closed, e:
- self.assertChannelException(404, e.args[0])
-
- #need to reopen a channel:
- channel = self.client.channel(2)
- channel.channel_open()
-
- #try and bind non-existant queue:
- try:
- channel.queue_bind(queue="queue-2", exchange="amq.direct", routing_key="key1")
- self.fail("Expected bind of non-existant queue to fail")
- except Closed, e:
- self.assertChannelException(404, e.args[0])
-
-
- def test_delete_simple(self):
- """
- Test basic queue deletion
- """
- channel = self.channel
-
- #straight-forward case:
- channel.queue_declare(queue="delete-me")
- channel.basic_publish(routing_key="delete-me", content=Content("a"))
- channel.basic_publish(routing_key="delete-me", content=Content("b"))
- channel.basic_publish(routing_key="delete-me", content=Content("c"))
- reply = channel.queue_delete(queue="delete-me")
- self.assertEqual(3, reply.message_count)
- #check that it has gone be declaring passively
- try:
- channel.queue_declare(queue="delete-me", passive="True")
- self.fail("Queue has not been deleted")
- except Closed, e:
- self.assertChannelException(404, e.args[0])
-
- #check attempted deletion of non-existant queue is handled correctly:
- channel = self.client.channel(2)
- channel.channel_open()
- try:
- channel.queue_delete(queue="i-dont-exist", if_empty="True")
- self.fail("Expected delete of non-existant queue to fail")
- except Closed, e:
- self.assertChannelException(404, e.args[0])
-
-
-
- def test_delete_ifempty(self):
- """
- Test that if_empty field of queue_delete is honoured
- """
- channel = self.channel
-
- #create a queue and add a message to it (use default binding):
- channel.queue_declare(queue="delete-me-2")
- channel.queue_declare(queue="delete-me-2", passive="True")
- channel.basic_publish(routing_key="delete-me-2", content=Content("message"))
-
- #try to delete, but only if empty:
- try:
- channel.queue_delete(queue="delete-me-2", if_empty="True")
- self.fail("Expected delete if_empty to fail for non-empty queue")
- except Closed, e:
- self.assertChannelException(406, e.args[0])
-
- #need new channel now:
- channel = self.client.channel(2)
- channel.channel_open()
-
- #empty queue:
- reply = channel.basic_consume(queue="delete-me-2", no_ack=True)
- queue = self.client.queue(reply.consumer_tag)
- msg = queue.get(timeout=1)
- self.assertEqual("message", msg.content.body)
- channel.basic_cancel(consumer_tag=reply.consumer_tag)
-
- #retry deletion on empty queue:
- channel.queue_delete(queue="delete-me-2", if_empty="True")
-
- #check that it has gone by declaring passively:
- try:
- channel.queue_declare(queue="delete-me-2", passive="True")
- self.fail("Queue has not been deleted")
- except Closed, e:
- self.assertChannelException(404, e.args[0])
-
- def test_delete_ifunused(self):
- """
- Test that if_unused field of queue_delete is honoured
- """
- channel = self.channel
-
- #create a queue and register a consumer:
- channel.queue_declare(queue="delete-me-3")
- channel.queue_declare(queue="delete-me-3", passive="True")
- reply = channel.basic_consume(queue="delete-me-3", no_ack=True)
-
- #need new channel now:
- channel2 = self.client.channel(2)
- channel2.channel_open()
- #try to delete, but only if empty:
- try:
- channel2.queue_delete(queue="delete-me-3", if_unused="True")
- self.fail("Expected delete if_unused to fail for queue with existing consumer")
- except Closed, e:
- self.assertChannelException(406, e.args[0])
-
-
- channel.basic_cancel(consumer_tag=reply.consumer_tag)
- channel.queue_delete(queue="delete-me-3", if_unused="True")
- #check that it has gone by declaring passively:
- try:
- channel.queue_declare(queue="delete-me-3", passive="True")
- self.fail("Queue has not been deleted")
- except Closed, e:
- self.assertChannelException(404, e.args[0])
-
-
diff --git a/qpid/python/qpid_tests/broker_0_8/testlib.py b/qpid/python/qpid_tests/broker_0_8/testlib.py
deleted file mode 100644
index 76f7e964a2..0000000000
--- a/qpid/python/qpid_tests/broker_0_8/testlib.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#
-# 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.
-#
-
-#
-# Tests for the testlib itself.
-#
-
-from qpid.content import Content
-from qpid.testlib import TestBase
-from Queue import Empty
-
-import sys
-from traceback import *
-
-def mytrace(frame, event, arg):
- print_stack(frame);
- print "===="
- return mytrace
-
-class TestBaseTest(TestBase):
- """Verify TestBase functions work as expected"""
-
- def testAssertEmptyPass(self):
- """Test assert empty works"""
- self.queue_declare(queue="empty")
- q = self.consume("empty")
- self.assertEmpty(q)
- try:
- q.get(timeout=1)
- self.fail("Queue is not empty.")
- except Empty: None # Ignore
-
- def testAssertEmptyFail(self):
- self.queue_declare(queue="full")
- q = self.consume("full")
- self.channel.basic_publish(routing_key="full")
- try:
- self.assertEmpty(q);
- self.fail("assertEmpty did not assert on non-empty queue")
- except AssertionError: None # Ignore
-
- def testMessageProperties(self):
- """Verify properties are passed with message"""
- props={"headers":{"x":1, "y":2}}
- self.queue_declare(queue="q")
- q = self.consume("q")
- self.assertPublishGet(q, routing_key="q", properties=props)
-
-
-
diff --git a/qpid/python/qpid_tests/broker_0_8/tx.py b/qpid/python/qpid_tests/broker_0_8/tx.py
deleted file mode 100644
index 9faddb1110..0000000000
--- a/qpid/python/qpid_tests/broker_0_8/tx.py
+++ /dev/null
@@ -1,209 +0,0 @@
-#
-# 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.
-#
-from qpid.client import Client, Closed
-from qpid.queue import Empty
-from qpid.content import Content
-from qpid.testlib import TestBase
-
-class TxTests(TestBase):
- """
- Tests for 'methods' on the amqp tx 'class'
- """
-
- def test_commit(self):
- """
- Test that commited publishes are delivered and commited acks are not re-delivered
- """
- channel = self.channel
- queue_a, queue_b, queue_c = self.perform_txn_work(channel, "tx-commit-a", "tx-commit-b", "tx-commit-c")
- channel.tx_commit()
-
- #check results
- for i in range(1, 5):
- msg = queue_c.get(timeout=1)
- self.assertEqual("TxMessage %d" % i, msg.content.body)
-
- msg = queue_b.get(timeout=1)
- self.assertEqual("TxMessage 6", msg.content.body)
-
- msg = queue_a.get(timeout=1)
- self.assertEqual("TxMessage 7", msg.content.body)
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.content.body)
- except Empty: None
-
- #cleanup
- channel.basic_ack(delivery_tag=0, multiple=True)
- channel.tx_commit()
-
- def test_auto_rollback(self):
- """
- Test that a channel closed with an open transaction is effectively rolled back
- """
- channel = self.channel
- queue_a, queue_b, queue_c = self.perform_txn_work(channel, "tx-autorollback-a", "tx-autorollback-b", "tx-autorollback-c")
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.content.body)
- except Empty: None
-
- channel.tx_rollback()
-
- #check results
- for i in range(1, 5):
- msg = queue_a.get(timeout=1)
- self.assertEqual("Message %d" % i, msg.content.body)
-
- msg = queue_b.get(timeout=1)
- self.assertEqual("Message 6", msg.content.body)
-
- msg = queue_c.get(timeout=1)
- self.assertEqual("Message 7", msg.content.body)
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.content.body)
- except Empty: None
-
- #cleanup
- channel.basic_ack(delivery_tag=0, multiple=True)
- channel.tx_commit()
-
- def test_rollback(self):
- """
- Test that rolled back publishes are not delivered and rolled back acks are re-delivered
- """
- channel = self.channel
- queue_a, queue_b, queue_c = self.perform_txn_work(channel, "tx-rollback-a", "tx-rollback-b", "tx-rollback-c")
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.content.body)
- except Empty: None
-
- channel.tx_rollback()
-
- #check results
- for i in range(1, 5):
- msg = queue_a.get(timeout=1)
- self.assertEqual("Message %d" % i, msg.content.body)
-
- msg = queue_b.get(timeout=1)
- self.assertEqual("Message 6", msg.content.body)
-
- msg = queue_c.get(timeout=1)
- self.assertEqual("Message 7", msg.content.body)
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.content.body)
- except Empty: None
-
- #cleanup
- channel.basic_ack(delivery_tag=0, multiple=True)
- channel.tx_commit()
-
- def perform_txn_work(self, channel, name_a, name_b, name_c):
- """
- Utility method that does some setup and some work under a transaction. Used for testing both
- commit and rollback
- """
- #setup:
- channel.queue_declare(queue=name_a, exclusive=True)
- channel.queue_declare(queue=name_b, exclusive=True)
- channel.queue_declare(queue=name_c, exclusive=True)
-
- key = "my_key_" + name_b
- topic = "my_topic_" + name_c
-
- channel.queue_bind(queue=name_b, exchange="amq.direct", routing_key=key)
- channel.queue_bind(queue=name_c, exchange="amq.topic", routing_key=topic)
-
- for i in range(1, 5):
- channel.basic_publish(routing_key=name_a, content=Content("Message %d" % i))
-
- channel.basic_publish(routing_key=key, exchange="amq.direct", content=Content("Message 6"))
- channel.basic_publish(routing_key=topic, exchange="amq.topic", content=Content("Message 7"))
-
- channel.tx_select()
-
- #consume and ack messages
- sub_a = channel.basic_consume(queue=name_a, no_ack=False)
- queue_a = self.client.queue(sub_a.consumer_tag)
- for i in range(1, 5):
- msg = queue_a.get(timeout=1)
- self.assertEqual("Message %d" % i, msg.content.body)
- channel.basic_ack(delivery_tag=msg.delivery_tag, multiple=True)
-
- sub_b = channel.basic_consume(queue=name_b, no_ack=False)
- queue_b = self.client.queue(sub_b.consumer_tag)
- msg = queue_b.get(timeout=1)
- self.assertEqual("Message 6", msg.content.body)
- channel.basic_ack(delivery_tag=msg.delivery_tag)
-
- sub_c = channel.basic_consume(queue=name_c, no_ack=False)
- queue_c = self.client.queue(sub_c.consumer_tag)
- msg = queue_c.get(timeout=1)
- self.assertEqual("Message 7", msg.content.body)
- channel.basic_ack(delivery_tag=msg.delivery_tag)
-
- #publish messages
- for i in range(1, 5):
- channel.basic_publish(routing_key=topic, exchange="amq.topic", content=Content("TxMessage %d" % i))
-
- channel.basic_publish(routing_key=key, exchange="amq.direct", content=Content("TxMessage 6"))
- channel.basic_publish(routing_key=name_a, content=Content("TxMessage 7"))
-
- return queue_a, queue_b, queue_c
-
- def test_commit_overlapping_acks(self):
- """
- Test that logically 'overlapping' acks do not cause errors on commit
- """
- channel = self.channel
- channel.queue_declare(queue="commit-overlapping", exclusive=True)
- for i in range(1, 10):
- channel.basic_publish(routing_key="commit-overlapping", content=Content("Message %d" % i))
-
-
- channel.tx_select()
-
- sub = channel.basic_consume(queue="commit-overlapping", no_ack=False)
- queue = self.client.queue(sub.consumer_tag)
- for i in range(1, 10):
- msg = queue.get(timeout=1)
- self.assertEqual("Message %d" % i, msg.content.body)
- if i in [3, 6, 10]:
- channel.basic_ack(delivery_tag=msg.delivery_tag)
-
- channel.tx_commit()
-
- #check all have been acked:
- try:
- extra = queue.get(timeout=1)
- self.fail("Got unexpected message: " + extra.content.body)
- except Empty: None
diff --git a/qpid/python/qpid_tests/broker_0_9/__init__.py b/qpid/python/qpid_tests/broker_0_9/__init__.py
deleted file mode 100644
index 72e69a51b9..0000000000
--- a/qpid/python/qpid_tests/broker_0_9/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Do not delete - marks this directory as a python package.
-
-#
-# 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 query, queue, messageheader, echo
diff --git a/qpid/python/qpid_tests/broker_0_9/echo.py b/qpid/python/qpid_tests/broker_0_9/echo.py
deleted file mode 100644
index a883568e35..0000000000
--- a/qpid/python/qpid_tests/broker_0_9/echo.py
+++ /dev/null
@@ -1,159 +0,0 @@
-#
-# 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.
-#
-
-from qpid.testlib import TestBase
-from qpid.content import Content
-import qpid.client
-
-
-
-class EchoTests(TestBase):
- """Verify that messages can be sent and received retaining fidelity"""
-
- def test_small_message(self):
-
- channel = self.channel
-
- self.queue_declare(queue="q")
-
- channel.tx_select()
- consumer = self.consume("q", no_ack=False)
-
- body = self.uniqueString()
- channel.basic_publish(
- content=Content(body),
- routing_key="q")
- channel.tx_commit()
-
- msg = consumer.get(timeout=1)
- channel.basic_ack(delivery_tag=msg.delivery_tag)
- channel.tx_commit()
- self.assertEqual(body, msg.content.body)
-
- def test_large_message(self):
-
- channel = self.channel
-
- self.queue_declare(queue="q")
-
- channel.tx_select()
- consumer = self.consume("q", no_ack=False)
-
- # This is default maximum frame size supported by the Java Broker. Python
- # currently does not support framing of oversized messages in multiple frames.
- body = self.randomLongString()
- channel.basic_publish(
- content=Content(body),
- routing_key="q")
- channel.tx_commit()
-
- msg = consumer.get(timeout=1)
- channel.basic_ack(delivery_tag=msg.delivery_tag)
- channel.tx_commit()
- self.assertEqual(len(body), len(msg.content.body))
- self.assertEqual(body, msg.content.body)
-
-
- def test_large_message_received_in_many_content_frames(self):
- channel = self.channel
-
- queue_name = "q"
- self.queue_declare(queue=queue_name)
-
- channel.tx_select()
-
- body = self.randomLongString()
- channel.basic_publish(
- content=Content(body),
- routing_key=queue_name)
- channel.tx_commit()
-
- consuming_client = None
- try:
- # Create a second connection with minimum framesize. The Broker will then be forced to chunk
- # the content in order to send it to us.
- consuming_client = qpid.client.Client(self.config.broker.host, self.config.broker.port)
- tune_params = { "channel_max" : 256, "frame_max" : 4096 }
- consuming_client.start(username = self.config.broker.user, password = self.config.broker.password, tune_params = tune_params)
-
- consuming_channel = consuming_client.channel(1)
- consuming_channel.channel_open()
- consuming_channel.tx_select()
-
- consumer_reply = consuming_channel.basic_consume(queue=queue_name, no_ack=False)
- consumer = consuming_client.queue(consumer_reply.consumer_tag)
- msg = consumer.get(timeout=1)
- consuming_channel.basic_ack(delivery_tag=msg.delivery_tag)
- consuming_channel.tx_commit()
-
- self.assertEqual(len(body), len(msg.content.body))
- self.assertEqual(body, msg.content.body)
- finally:
- if consuming_client:
- consuming_client.close()
-
- def test_commit_ok_possibly_interleaved_with_message_delivery(self):
- """This test exposes an defect on the Java Broker (QPID-6094). The Java Client
- can contravene the AMQP spec by sending other frames between the message header/frames.
- As this is a long standing defect in the Java Broker, QPID-6082 changed
- the Python client to allow it to tolerate such illegal interleaving.
- """
- channel = self.channel
-
- queue_name = "q"
- self.queue_declare(queue=queue_name)
-
- count = 25
- channel.basic_qos(prefetch_count=count)
-
- channel.tx_select()
-
- bodies = []
- for i in range(count):
- body = self.randomLongString()
- bodies.append(body)
- channel.basic_publish(
- content=Content(bodies[i]),
- routing_key=queue_name)
- channel.tx_commit()
-
- # Start consuming. Prefetch will mean the Broker will start to send us
- # all the messages accumulating them in the client.
- consumer = self.consume("q", no_ack=False)
-
- # Get and ack/commit the first message
- msg = consumer.get(timeout=1)
- channel.basic_ack(delivery_tag=msg.delivery_tag)
- channel.tx_commit()
- # In the problematic case, the Broker interleaves our commit-ok response amongst the content
- # frames of message. QPID-6082 means the Python client now tolerates this
- # problem and all messages should arrive correctly.
-
- expectedBody = bodies[0]
- self.assertEqual(len(expectedBody), len(msg.content.body))
- self.assertEqual(expectedBody, msg.content.body)
-
- for i in range(1, len(bodies)):
- msg = consumer.get(timeout=5)
-
- expectedBody = bodies[i]
- self.assertEqual(len(expectedBody), len(msg.content.body))
- self.assertEqual(expectedBody, msg.content.body)
-
-
diff --git a/qpid/python/qpid_tests/broker_0_9/messageheader.py b/qpid/python/qpid_tests/broker_0_9/messageheader.py
deleted file mode 100644
index 3d64adfcf0..0000000000
--- a/qpid/python/qpid_tests/broker_0_9/messageheader.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#
-# 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.
-#
-
-from qpid.testlib import TestBase
-
-class MessageHeaderTests(TestBase):
- """Verify that messages with headers work as expected"""
-
- def test_message_with_integer_header(self):
- props={"headers":{"one":1, "zero":0}}
- self.queue_declare(queue="q")
- q = self.consume("q")
- self.assertPublishGet(q, routing_key="q", properties=props)
-
- def test_message_with_string_header(self):
- props={"headers":{"mystr":"hello world", "myempty":""}}
- self.queue_declare(queue="q")
- q = self.consume("q")
- self.assertPublishGet(q, routing_key="q", properties=props)
-
- def test_message_with_boolean_header(self):
- """The AMQP boolean type is not officially supported until 0-91 but the 0-8/9 Java client use its field value typecode.
- Note: If you run this test with QPID_CODEC_DISABLE_0_91_BOOLEAN set, this test will still pass as the booleans are
- coerced into integer."""
-
- props={"headers":{"trueHeader":True, "falseHeader":False}}
- self.queue_declare(queue="q")
- q = self.consume("q")
- self.assertPublishGet(q, routing_key="q", properties=props)
-
- def test_message_with_negatives_longints_floats_and_None(self):
- """ Tests sending and then receiving negative integers, longs, the None (void) value, and doubles."""
- props={"headers":{"myIntMin": -2147483648,
- "myIntMax": 2147483647,
- "myLongMax": 9223372036854775807,
- "myLongMin": -9223372036854775808,
- "myNullString": None,
- "myDouble1.1": 1.1,
- "myDoubleMin": 4.9E-324,
- "myDoubleMax": 1.7976931348623157E308}}
-
- self.queue_declare(queue="q")
- q = self.consume("q")
- self.assertPublishGet(q, routing_key="q", properties=props)
-
diff --git a/qpid/python/qpid_tests/broker_0_9/query.py b/qpid/python/qpid_tests/broker_0_9/query.py
deleted file mode 100644
index cb66d079e5..0000000000
--- a/qpid/python/qpid_tests/broker_0_9/query.py
+++ /dev/null
@@ -1,224 +0,0 @@
-#
-# 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.
-#
-from qpid.client import Client, Closed
-from qpid.queue import Empty
-from qpid.content import Content
-from qpid.testlib import TestBase
-
-class QueryTests(TestBase):
- """Tests for various query methods introduced in 0-10 and available in 0-9 for preview"""
-
- def test_exchange_query(self):
- """
- Test that the exchange_query method works as expected
- """
- channel = self.channel
- #check returned type for the standard exchanges
- self.assertEqual("direct", channel.exchange_query(name="amq.direct").type)
- self.assertEqual("topic", channel.exchange_query(name="amq.topic").type)
- self.assertEqual("fanout", channel.exchange_query(name="amq.fanout").type)
- self.assertEqual("headers", channel.exchange_query(name="amq.match").type)
- self.assertEqual("direct", channel.exchange_query(name="").type)
- #declare an exchange
- channel.exchange_declare(exchange="my-test-exchange", type= "direct", durable=False)
- #check that the result of a query is as expected
- response = channel.exchange_query(name="my-test-exchange")
- self.assertEqual("direct", response.type)
- self.assertEqual(False, response.durable)
- self.assertEqual(False, response.not_found)
- #delete the exchange
- channel.exchange_delete(exchange="my-test-exchange")
- #check that the query now reports not-found
- self.assertEqual(True, channel.exchange_query(name="my-test-exchange").not_found)
-
- def test_binding_query_direct(self):
- """
- Test that the binding_query method works as expected with the direct exchange
- """
- self.binding_query_with_key("amq.direct")
-
- def test_binding_query_topic(self):
- """
- Test that the binding_query method works as expected with the direct exchange
- """
- self.binding_query_with_key("amq.topic")
-
- def binding_query_with_key(self, exchange_name):
- channel = self.channel
- #setup: create two queues
- channel.queue_declare(queue="used-queue", exclusive=True)
- channel.queue_declare(queue="unused-queue", exclusive=True)
-
- channel.queue_bind(exchange=exchange_name, queue="used-queue", routing_key="used-key")
-
- # test detection of any binding to specific queue
- response = channel.binding_query(exchange=exchange_name, queue="used-queue")
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(False, response.queue_not_matched)
-
- # test detection of specific binding to any queue
- response = channel.binding_query(exchange=exchange_name, routing_key="used-key")
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(False, response.key_not_matched)
-
- # test detection of specific binding to specific queue
- response = channel.binding_query(exchange=exchange_name, queue="used-queue", routing_key="used-key")
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(False, response.queue_not_matched)
- self.assertEqual(False, response.key_not_matched)
-
- # test unmatched queue, unspecified binding
- response = channel.binding_query(exchange=exchange_name, queue="unused-queue")
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(True, response.queue_not_matched)
-
- # test unspecified queue, unmatched binding
- response = channel.binding_query(exchange=exchange_name, routing_key="unused-key")
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(True, response.key_not_matched)
-
- # test matched queue, unmatched binding
- response = channel.binding_query(exchange=exchange_name, queue="used-queue", routing_key="unused-key")
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(False, response.queue_not_matched)
- self.assertEqual(True, response.key_not_matched)
-
- # test unmatched queue, matched binding
- response = channel.binding_query(exchange=exchange_name, queue="unused-queue", routing_key="used-key")
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(True, response.queue_not_matched)
- self.assertEqual(False, response.key_not_matched)
-
- # test unmatched queue, unmatched binding
- response = channel.binding_query(exchange=exchange_name, queue="unused-queue", routing_key="unused-key")
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(True, response.queue_not_matched)
- self.assertEqual(True, response.key_not_matched)
-
- #test exchange not found
- self.assertEqual(True, channel.binding_query(exchange="unknown-exchange").exchange_not_found)
-
- #test queue not found
- self.assertEqual(True, channel.binding_query(exchange=exchange_name, queue="unknown-queue").queue_not_found)
-
-
- def test_binding_query_fanout(self):
- """
- Test that the binding_query method works as expected with fanout exchange
- """
- channel = self.channel
- #setup
- channel.queue_declare(queue="used-queue", exclusive=True)
- channel.queue_declare(queue="unused-queue", exclusive=True)
- channel.queue_bind(exchange="amq.fanout", queue="used-queue")
-
- # test detection of any binding to specific queue
- response = channel.binding_query(exchange="amq.fanout", queue="used-queue")
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(False, response.queue_not_matched)
-
- # test unmatched queue, unspecified binding
- response = channel.binding_query(exchange="amq.fanout", queue="unused-queue")
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(True, response.queue_not_matched)
-
- #test exchange not found
- self.assertEqual(True, channel.binding_query(exchange="unknown-exchange").exchange_not_found)
-
- #test queue not found
- self.assertEqual(True, channel.binding_query(exchange="amq.fanout", queue="unknown-queue").queue_not_found)
-
- def test_binding_query_header(self):
- """
- Test that the binding_query method works as expected with headers exchanges
- """
- channel = self.channel
- #setup
- channel.queue_declare(queue="used-queue", exclusive=True)
- channel.queue_declare(queue="unused-queue", exclusive=True)
- channel.queue_bind(exchange="amq.match", queue="used-queue", arguments={"x-match":"all", "a":"A"} )
-
- # test detection of any binding to specific queue
- response = channel.binding_query(exchange="amq.match", queue="used-queue")
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(False, response.queue_not_matched)
-
- # test detection of specific binding to any queue
- response = channel.binding_query(exchange="amq.match", arguments={"x-match":"all", "a":"A"})
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(False, response.args_not_matched)
-
- # test detection of specific binding to specific queue
- response = channel.binding_query(exchange="amq.match", queue="used-queue", arguments={"x-match":"all", "a":"A"})
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(False, response.queue_not_matched)
- self.assertEqual(False, response.args_not_matched)
-
- # test unmatched queue, unspecified binding
- response = channel.binding_query(exchange="amq.match", queue="unused-queue")
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(True, response.queue_not_matched)
-
- # test unspecified queue, unmatched binding
- response = channel.binding_query(exchange="amq.match", arguments={"x-match":"all", "b":"B"})
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(True, response.args_not_matched)
-
- # test matched queue, unmatched binding
- response = channel.binding_query(exchange="amq.match", queue="used-queue", arguments={"x-match":"all", "b":"B"})
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(False, response.queue_not_matched)
- self.assertEqual(True, response.args_not_matched)
-
- # test unmatched queue, matched binding
- response = channel.binding_query(exchange="amq.match", queue="unused-queue", arguments={"x-match":"all", "a":"A"})
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(True, response.queue_not_matched)
- self.assertEqual(False, response.args_not_matched)
-
- # test unmatched queue, unmatched binding
- response = channel.binding_query(exchange="amq.match", queue="unused-queue", arguments={"x-match":"all", "b":"B"})
- self.assertEqual(False, response.exchange_not_found)
- self.assertEqual(False, response.queue_not_found)
- self.assertEqual(True, response.queue_not_matched)
- self.assertEqual(True, response.args_not_matched)
-
- #test exchange not found
- self.assertEqual(True, channel.binding_query(exchange="unknown-exchange").exchange_not_found)
-
- #test queue not found
- self.assertEqual(True, channel.binding_query(exchange="amq.match", queue="unknown-queue").queue_not_found)
-
diff --git a/qpid/python/qpid_tests/broker_0_9/queue.py b/qpid/python/qpid_tests/broker_0_9/queue.py
deleted file mode 100644
index 249850caf9..0000000000
--- a/qpid/python/qpid_tests/broker_0_9/queue.py
+++ /dev/null
@@ -1,148 +0,0 @@
-#
-# 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 time
-from qpid.client import Client, Closed
-from qpid.queue import Empty
-from qpid.content import Content
-from qpid.testlib import TestBase
-from qpid.exceptions import Timeout
-
-class QueueTests(TestBase):
- """Tests for 'methods' on the amqp queue 'class'"""
-
- def test_unbind_direct(self):
- self.unbind_test(exchange="amq.direct", routing_key="key")
-
- def test_unbind_topic(self):
- self.unbind_test(exchange="amq.topic", routing_key="key")
-
- def test_unbind_fanout(self):
- self.unbind_test(exchange="amq.fanout")
-
- def test_unbind_headers(self):
- self.unbind_test(exchange="amq.match", args={ "x-match":"all", "a":"b"}, headers={"a":"b"})
-
- def unbind_test(self, exchange, routing_key="", args=None, headers={}):
- #bind two queues and consume from them
- channel = self.channel
-
- channel.queue_declare(queue="queue-1", exclusive="True")
- channel.queue_declare(queue="queue-2", exclusive="True")
-
- channel.basic_consume(queue="queue-1", consumer_tag="queue-1", no_ack=True)
- channel.basic_consume(queue="queue-2", consumer_tag="queue-2", no_ack=True)
-
- queue1 = self.client.queue("queue-1")
- queue2 = self.client.queue("queue-2")
-
- channel.queue_bind(exchange=exchange, queue="queue-1", routing_key=routing_key, arguments=args)
- channel.queue_bind(exchange=exchange, queue="queue-2", routing_key=routing_key, arguments=args)
-
- #send a message that will match both bindings
- channel.basic_publish(exchange=exchange, routing_key=routing_key,
- content=Content("one", properties={"headers": headers}))
-
- #unbind first queue
- channel.queue_unbind(exchange=exchange, queue="queue-1", routing_key=routing_key, arguments=args)
-
- #send another message
- channel.basic_publish(exchange=exchange, routing_key=routing_key,
- content=Content("two", properties={"headers": headers}))
-
- #check one queue has both messages and the other has only one
- self.assertEquals("one", queue1.get(timeout=1).content.body)
- try:
- msg = queue1.get(timeout=1)
- self.fail("Got extra message: %s" % msg.body)
- except Empty: pass
-
- self.assertEquals("one", queue2.get(timeout=1).content.body)
- self.assertEquals("two", queue2.get(timeout=1).content.body)
- try:
- msg = queue2.get(timeout=1)
- self.fail("Got extra message: " + msg)
- except Empty: pass
-
- def test_autodelete_shared(self):
- """
- Test auto-deletion (of non-exclusive queues)
- """
- channel = self.channel
- other = self.connect()
- channel2 = other.channel(1)
- channel2.channel_open()
-
- channel.queue_declare(queue="auto-delete-me", auto_delete=True)
-
- #consume from both channels
- reply = channel.basic_consume(queue="auto-delete-me", no_ack=True)
- channel2.basic_consume(queue="auto-delete-me", no_ack=True)
-
- #implicit cancel
- channel2.channel_close()
-
- #check it is still there
- channel.queue_declare(queue="auto-delete-me", passive=True)
-
- #explicit cancel => queue is now unused again:
- channel.basic_cancel(consumer_tag=reply.consumer_tag)
-
- #NOTE: this assumes there is no timeout in use
-
- #check that it has gone be declaring passively
- try:
- channel.queue_declare(queue="auto-delete-me", passive=True)
- self.fail("Expected queue to have been deleted")
- except Closed, e:
- self.assertChannelException(404, e.args[0])
-
- def test_flow_control(self):
- queue_name="flow-controled-queue"
-
- connection = self.connect(channel_options={"qpid.flow_control_wait_failure" : 1})
- channel = connection.channel(1)
- channel.channel_open()
- channel.queue_declare(queue=queue_name, arguments={"x-qpid-capacity" : 25, "x-qpid-flow-resume-capacity" : 15})
-
- try:
- for i in xrange(100):
- channel.basic_publish(exchange="", routing_key=queue_name,
- content=Content("This is a message with more than 25 bytes. This should trigger flow control."))
- time.sleep(.1)
- self.fail("Flow Control did not work")
- except Timeout:
- # this is expected
- pass
-
- consumer_reply = channel.basic_consume(queue=queue_name, consumer_tag="consumer", no_ack=True)
- queue = self.client.queue(consumer_reply.consumer_tag)
- while True:
- try:
- msg = queue.get(timeout=1)
- except Empty:
- break
- channel.basic_cancel(consumer_tag=consumer_reply.consumer_tag)
-
- try:
- channel.basic_publish(exchange="", routing_key=queue_name,
- content=Content("This should not block because we have just cleared the queue."))
- except Timeout:
- self.fail("Unexpected Timeout. Flow Control should not be in effect.")
-
- connection.close()
diff --git a/qpid/python/qpid_tests/broker_1_0/__init__.py b/qpid/python/qpid_tests/broker_1_0/__init__.py
deleted file mode 100644
index b14bb96dc8..0000000000
--- a/qpid/python/qpid_tests/broker_1_0/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Do not delete - marks this directory as a python package.
-
-#
-# 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.
-#
-
-from general import *
-from legacy_exchanges import *
-from selector import *
-from translation import *
-from tx import *
diff --git a/qpid/python/qpid_tests/broker_1_0/general.py b/qpid/python/qpid_tests/broker_1_0/general.py
deleted file mode 100644
index a5b9779add..0000000000
--- a/qpid/python/qpid_tests/broker_1_0/general.py
+++ /dev/null
@@ -1,81 +0,0 @@
-#
-# 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.
-#
-
-from qpid.tests.messaging.implementation import *
-from qpid.tests.messaging import VersionTest
-
-class GeneralTests (VersionTest):
- """
- Miscellaneous tests for core AMQP 1.0 messaging behaviour.
- """
- def test_request_response(self):
- snd_request = self.ssn.sender("#")
- rcv_response = self.ssn.receiver("#")
-
- #send request
- snd_request.send(Message(reply_to=rcv_response.source, id="a1", content="request"))
-
- #receive request
- rcv_request = self.ssn.receiver(snd_request.target)
- request = rcv_request.fetch(5)
- assert request.content == "request" and request.id == "a1", request
- #send response
- snd_response = self.ssn.sender(request.reply_to)
- snd_response.send(Message(correlation_id=request.id, content="response"))
-
- #receive response
- response = rcv_response.fetch(5)
- assert response.content == "response" and response.correlation_id == "a1", response
-
- self.ssn.acknowledge()
-
-
- def test_browse(self):
- snd = self.ssn.sender("#")
- rcv = self.ssn.receiver("%s; {mode: browse}" % snd.target)
-
- msgs = [Message(content=s, subject = s) for s in ['a','b','c','d']]
-
- for m in msgs: snd.send(m)
-
- for expected in msgs:
- msg = rcv.fetch(0)
- assert msg.content == expected.content
- try:
- assert msg.properties.get('x-amqp-delivery-count') == 0, (msg.properties.get('x-amqp-delivery-count'))
- except KeyError, e: None #default is 0
- self.ssn.acknowledge(msg)
- rcv.close()
-
- rcv = self.ssn.receiver(snd.target)
- for expected in msgs:
- msg = rcv.fetch(0)
- assert msg.content == expected.content
- self.ssn.acknowledge(msg)
-
- def test_anonymous_relay(self):
- snd = self.ssn.sender("<null>")
- rcv = self.ssn.receiver("#")
-
- snd.send(Message(id="a1", content="my-message", properties={'x-amqp-to':rcv.source}))
-
- request = rcv.fetch(5)
- assert request.content == "my-message" and request.id == "a1", request
-
- self.ssn.acknowledge()
diff --git a/qpid/python/qpid_tests/broker_1_0/legacy_exchanges.py b/qpid/python/qpid_tests/broker_1_0/legacy_exchanges.py
deleted file mode 100644
index eefa49e817..0000000000
--- a/qpid/python/qpid_tests/broker_1_0/legacy_exchanges.py
+++ /dev/null
@@ -1,96 +0,0 @@
-#
-# 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.
-#
-
-from qpid.tests.messaging.implementation import *
-from qpid.tests.messaging import VersionTest
-
-class LegacyExchangeTests (VersionTest):
- """
- Tests for the legacy (i.e. pre 1.0) AMQP exchanges and the filters
- defined for them and registered for AMQP 1.0.
- """
- def test_fanout(self):
- msgs = [Message(content=s, subject = s) for s in ['a','b','c','d']]
-
- snd = self.ssn.sender("amq.fanout")
- rcv = self.ssn.receiver("amq.fanout")
-
- for m in msgs: snd.send(m)
-
- for expected in msgs:
- msg = rcv.fetch(0)
- assert msg.content == expected.content
- self.ssn.acknowledge(msg)
- rcv.close()
-
- def test_direct(self):
- msgs = [Message(content=c, subject=s) for s, c in [('a', 'one'), ('b', 'two'),('a', 'three'),('b', 'four')]]
-
- snd = self.ssn.sender("amq.direct")
- rcv_a = self.ssn.receiver("amq.direct/a")
- rcv_b = self.ssn.receiver("amq.direct/b")
-
- for m in msgs: snd.send(m)
-
- for expected in ['one', 'three']:
- msg = rcv_a.fetch(0)
- assert msg.content == expected, (msg, expected)
- self.ssn.acknowledge(msg)
-
- for expected in ['two', 'four']:
- msg = rcv_b.fetch(0)
- assert msg.content == expected
- self.ssn.acknowledge(msg), (msg, expected)
-
- def test_topic(self):
- msgs = [Message(content=s, subject=s) for s in ['red.dog', 'black.cat', 'red.squirrel', 'grey.squirrel']]
-
- snd = self.ssn.sender("amq.topic")
- rcv_a = self.ssn.receiver("amq.topic/red.*")
- rcv_b = self.ssn.receiver("amq.topic/*.squirrel")
-
- for m in msgs: snd.send(m)
-
- for expected in ['red.dog', 'red.squirrel']:
- msg = rcv_a.fetch(0)
- assert msg.content == expected, (msg, expected)
- self.ssn.acknowledge(msg)
-
- for expected in ['red.squirrel', 'grey.squirrel']:
- msg = rcv_b.fetch(0)
- assert msg.content == expected
- self.ssn.acknowledge(msg), (msg, expected)
-
- def test_headers(self):
- msgs = [Message(content="%s.%s" % (colour, creature), properties={'creature':creature,'colour':colour}) for colour, creature in [('red','dog'), ('black', 'cat'), ('red', 'squirrel'), ('grey', 'squirrel')]]
-
- snd = self.ssn.sender("amq.match")
- rcv_a = self.ssn.receiver("amq.match; {link:{filter:{descriptor:'apache.org:legacy-amqp-headers-binding:map',name:'red-things',value:{'colour':'red','x-match':'all'}}}}")
- rcv_b = self.ssn.receiver("amq.match; {link:{filter:{descriptor:'apache.org:legacy-amqp-headers-binding:map',name:'cats-and-squirrels',value:{'creature':'squirrel','colour':'black','x-match':'any'}}}}")
- for m in msgs: snd.send(m)
-
- for expected in ['red.dog', 'red.squirrel']:
- msg = rcv_a.fetch(0)
- assert msg.content == expected, (msg, expected)
- self.ssn.acknowledge(msg)
-
- for expected in ['black.cat', 'red.squirrel', 'grey.squirrel']:
- msg = rcv_b.fetch(0)
- assert msg.content == expected
- self.ssn.acknowledge(msg), (msg, expected)
diff --git a/qpid/python/qpid_tests/broker_1_0/selector.py b/qpid/python/qpid_tests/broker_1_0/selector.py
deleted file mode 100644
index 323baaab07..0000000000
--- a/qpid/python/qpid_tests/broker_1_0/selector.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#
-# 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.
-#
-
-from qpid.tests.messaging.implementation import *
-from qpid.tests.messaging import VersionTest
-
-class SelectorTests (VersionTest):
- """
- Tests for the selector filter registered for AMQP 1.0 under the
- apache namespace.
- """
- def basic_selection_test(self, node):
- properties = [(1, 'red','dog'), (2, 'black', 'cat'), (3, 'red', 'squirrel'), (4, 'grey', 'squirrel')]
- msgs = [Message(content="%s.%s" % (colour, creature), properties={'sequence':sequence,'colour':colour}) for sequence, colour, creature in properties]
-
- snd = self.ssn.sender(node)
- rcv = self.ssn.receiver("%s; {link:{selector:\"colour IN ('red', 'grey') AND (sequence > 3 OR sequence = 1)\"}}" % snd.target)
-
- for m in msgs: snd.send(m)
-
- for expected in ["red.dog", "grey.squirrel"]:
- msg = rcv.fetch(0)
- assert msg.content == expected
- self.ssn.acknowledge(msg)
-
- def test_topic(self):
- self.basic_selection_test(self.config.defines.get("topic_name", "amq.fanout"))
-
- def test_queue(self):
- self.basic_selection_test("#")
-
- def test_special_fields(self):
- msgs = [Message(content=i, id=i, correlation_id=i, priority=p+1) for p, i in enumerate(['a', 'b', 'c', 'd'])]
-
- snd = self.ssn.sender("#")
- rcv_1 = self.ssn.receiver("%s; {link:{selector:\"amqp.message_id = 'c'\"}}" % snd.target)
- rcv_2 = self.ssn.receiver("%s; {link:{selector:\"amqp.correlation_id = 'b'\"}}" % snd.target)
- rcv_3 = self.ssn.receiver("%s; {link:{selector:\"amqp.priority = 1\"}}" % snd.target)
-
- for m in msgs: snd.send(m)
-
- msg = rcv_1.fetch(0)
- assert msg.content == 'c', msg
- self.ssn.acknowledge(msg)
-
- msg = rcv_2.fetch(0)
- assert msg.content == 'b', msg
- self.ssn.acknowledge(msg)
-
- msg = rcv_3.fetch(0)
- assert msg.content == 'a', msg
- self.ssn.acknowledge(msg)
-
- rcv_4 = self.ssn.receiver(snd.target)
- msg = rcv_4.fetch(0)
- assert msg.content == 'd'
- self.ssn.acknowledge(msg)
-
- def check_selected(self,node, selector, expected_content):
- rcv = self.ssn.receiver("%s; {mode:browse, link:{selector:\"%s\"}}" % (node, selector))
- msg = rcv.fetch(0)
- assert msg.content == expected_content, msg
- rcv.close()
-
- def test_jms_header_names(self):
- """
- The new AMQP 1.0 based JMS client uses these rather than the special names above
- """
- msgs = [Message(content=i, id=i, correlation_id=i, subject=i, priority=p+1, reply_to=i, properties={'x-amqp-to':i}) for p, i in enumerate(['a', 'b', 'c', 'd'])]
-
- snd = self.ssn.sender("#")
- for m in msgs: snd.send(m)
-
- self.check_selected(snd.target, "JMSMessageID = 'a'", 'a')
- self.check_selected(snd.target, "JMSCorrelationID = 'b'", 'b')
- self.check_selected(snd.target, "JMSPriority = 3", 'c')
- self.check_selected(snd.target, "JMSDestination = 'a'", 'a')
- self.check_selected(snd.target, "JMSReplyTo = 'b'", 'b')
- self.check_selected(snd.target, "JMSType = 'c'", 'c')
diff --git a/qpid/python/qpid_tests/broker_1_0/translation.py b/qpid/python/qpid_tests/broker_1_0/translation.py
deleted file mode 100644
index a6394fb8c5..0000000000
--- a/qpid/python/qpid_tests/broker_1_0/translation.py
+++ /dev/null
@@ -1,87 +0,0 @@
-#
-# 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.
-#
-
-from qpid.tests.messaging.implementation import *
-from qpid.tests.messaging import VersionTest
-
-class TranslationTests (VersionTest):
- """
- Testing translation of messages between 1.0 and 0-10
- """
- def send_receive_messages(self, msgs, send_version, receive_version, address):
- rcon = self.create_connection(receive_version, True)
- rcv = rcon.session().receiver(address)
-
- scon = self.create_connection(send_version, True)
- snd = scon.session().sender(rcv.source)
-
- for m in msgs: snd.send(m)
-
- for expected in msgs:
- msg = rcv.fetch()
- assert msg.content == expected.content, (msg.content, expected.content)
- assert msg.subject == expected.subject, (msg.subject, expected.subject)
- self.ssn.acknowledge(msg)
- scon.close()
- rcon.close()
-
- def send_receive(self, send_version, receive_version, address):
- self.send_receive_messages([Message(content=s, subject = s) for s in ['a','b','c','d']], send_version, receive_version, address)
-
- def send_receive_map(self, send_version, receive_version, address):
- self.send_receive_messages([Message(content={'s':'abc','i':10})], send_version, receive_version, address)
-
- def send_receive_list(self, send_version, receive_version, address):
- self.send_receive_messages([Message(content=['a', 1, 'c'])], send_version, receive_version, address)
-
- def test_translation_queue_1(self):
- self.send_receive("amqp0-10", "amqp1.0", '#')
-
- def test_translation_queue_2(self):
- self.send_receive("amqp1.0", "amqp0-10", '#')
-
- def test_translation_exchange_1(self):
- self.send_receive("amqp0-10", "amqp1.0", 'amq.fanout')
-
- def test_translation_exchange_2(self):
- self.send_receive("amqp1.0", "amqp0-10", 'amq.fanout')
-
- def test_send_receive_queue_1(self):
- self.send_receive("amqp1.0", "amqp1.0", '#')
-
- def test_send_receive_queue_2(self):
- self.send_receive("amqp0-10", "amqp0-10", '#')
-
- def test_send_receive_exchange_1(self):
- self.send_receive("amqp1.0", "amqp1.0", 'amq.fanout')
-
- def test_send_receive_exchange_2(self):
- self.send_receive("amqp0-10", "amqp0-10", 'amq.fanout')
-
- def test_translate_map_1(self):
- self.send_receive_map("amqp0-10", "amqp1.0", '#')
-
- def test_translate_map_2(self):
- self.send_receive_map("amqp1.0", "amqp0-10", '#')
-
- def test_translate_list_1(self):
- self.send_receive_list("amqp0-10", "amqp1.0", '#')
-
- def test_translate_list_2(self):
- self.send_receive_list("amqp1.0", "amqp0-10", '#')
diff --git a/qpid/python/qpid_tests/broker_1_0/tx.py b/qpid/python/qpid_tests/broker_1_0/tx.py
deleted file mode 100644
index 45817fc64f..0000000000
--- a/qpid/python/qpid_tests/broker_1_0/tx.py
+++ /dev/null
@@ -1,264 +0,0 @@
-#
-# 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.
-#
-from qpid.client import Client, Closed
-from qpid.queue import Empty
-from qpid.datatypes import Message, RangedSet
-from qpid.testlib import TestBase010
-
-class TxTests(TestBase010):
- """
- Tests for 'methods' on the amqp tx 'class'
- """
-
- def test_commit(self):
- """
- Test that commited publishes are delivered and commited acks are not re-delivered
- """
- session = self.session
-
- #declare queues and create subscribers in the checking session
- #to ensure that the queues are not auto-deleted too early:
- self.declare_queues(["tx-commit-a", "tx-commit-b", "tx-commit-c"])
- session.message_subscribe(queue="tx-commit-a", destination="qa")
- session.message_subscribe(queue="tx-commit-b", destination="qb")
- session.message_subscribe(queue="tx-commit-c", destination="qc")
-
- #use a separate session for actual work
- session2 = self.conn.session("worker", 2)
- self.perform_txn_work(session2, "tx-commit-a", "tx-commit-b", "tx-commit-c")
- session2.tx_commit()
- session2.close()
-
- session.tx_select()
-
- self.enable_flow("qa")
- queue_a = session.incoming("qa")
-
- self.enable_flow("qb")
- queue_b = session.incoming("qb")
-
- self.enable_flow("qc")
- queue_c = session.incoming("qc")
-
- #check results
- for i in range(1, 5):
- msg = queue_c.get(timeout=1)
- self.assertEqual("TxMessage %d" % i, msg.body)
- session.message_accept(RangedSet(msg.id))
-
- msg = queue_b.get(timeout=1)
- self.assertEqual("TxMessage 6", msg.body)
- session.message_accept(RangedSet(msg.id))
-
- msg = queue_a.get(timeout=1)
- self.assertEqual("TxMessage 7", msg.body)
- session.message_accept(RangedSet(msg.id))
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
- #cleanup
- session.tx_commit()
-
- def test_auto_rollback(self):
- """
- Test that a session closed with an open transaction is effectively rolled back
- """
- session = self.session
- self.declare_queues(["tx-autorollback-a", "tx-autorollback-b", "tx-autorollback-c"])
- session.message_subscribe(queue="tx-autorollback-a", destination="qa")
- session.message_subscribe(queue="tx-autorollback-b", destination="qb")
- session.message_subscribe(queue="tx-autorollback-c", destination="qc")
-
- session2 = self.conn.session("worker", 2)
- queue_a, queue_b, queue_c, ignore = self.perform_txn_work(session2, "tx-autorollback-a", "tx-autorollback-b", "tx-autorollback-c")
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
- session2.close()
-
- session.tx_select()
-
- self.enable_flow("qa")
- queue_a = session.incoming("qa")
-
- self.enable_flow("qb")
- queue_b = session.incoming("qb")
-
- self.enable_flow("qc")
- queue_c = session.incoming("qc")
-
- #check results
- for i in range(1, 5):
- msg = queue_a.get(timeout=1)
- self.assertEqual("Message %d" % i, msg.body)
- session.message_accept(RangedSet(msg.id))
-
- msg = queue_b.get(timeout=1)
- self.assertEqual("Message 6", msg.body)
- session.message_accept(RangedSet(msg.id))
-
- msg = queue_c.get(timeout=1)
- self.assertEqual("Message 7", msg.body)
- session.message_accept(RangedSet(msg.id))
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
- #cleanup
- session.tx_commit()
-
- def test_rollback(self):
- """
- Test that rolled back publishes are not delivered and rolled back acks are re-delivered
- """
- session = self.session
- queue_a, queue_b, queue_c, consumed = self.perform_txn_work(session, "tx-rollback-a", "tx-rollback-b", "tx-rollback-c")
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
- session.tx_rollback()
-
- #need to release messages to get them redelivered now:
- session.message_release(consumed)
-
- #check results
- for i in range(1, 5):
- msg = queue_a.get(timeout=1)
- self.assertEqual("Message %d" % i, msg.body)
- session.message_accept(RangedSet(msg.id))
-
- msg = queue_b.get(timeout=1)
- self.assertEqual("Message 6", msg.body)
- session.message_accept(RangedSet(msg.id))
-
- msg = queue_c.get(timeout=1)
- self.assertEqual("Message 7", msg.body)
- session.message_accept(RangedSet(msg.id))
-
- for q in [queue_a, queue_b, queue_c]:
- try:
- extra = q.get(timeout=1)
- self.fail("Got unexpected message: " + extra.body)
- except Empty: None
-
- #cleanup
- session.tx_commit()
-
- def perform_txn_work(self, session, name_a, name_b, name_c):
- """
- Utility method that does some setup and some work under a transaction. Used for testing both
- commit and rollback
- """
- #setup:
- self.declare_queues([name_a, name_b, name_c])
-
- key = "my_key_" + name_b
- topic = "my_topic_" + name_c
-
- session.exchange_bind(queue=name_b, exchange="amq.direct", binding_key=key)
- session.exchange_bind(queue=name_c, exchange="amq.topic", binding_key=topic)
-
- dp = session.delivery_properties(routing_key=name_a)
- for i in range(1, 5):
- mp = session.message_properties(message_id="msg%d" % i)
- session.message_transfer(message=Message(dp, mp, "Message %d" % i))
-
- dp = session.delivery_properties(routing_key=key)
- mp = session.message_properties(message_id="msg6")
- session.message_transfer(destination="amq.direct", message=Message(dp, mp, "Message 6"))
-
- dp = session.delivery_properties(routing_key=topic)
- mp = session.message_properties(message_id="msg7")
- session.message_transfer(destination="amq.topic", message=Message(dp, mp, "Message 7"))
-
- session.tx_select()
-
- #consume and ack messages
- acked = RangedSet()
- self.subscribe(session, queue=name_a, destination="sub_a")
- queue_a = session.incoming("sub_a")
- for i in range(1, 5):
- msg = queue_a.get(timeout=1)
- acked.add(msg.id)
- self.assertEqual("Message %d" % i, msg.body)
-
- self.subscribe(session, queue=name_b, destination="sub_b")
- queue_b = session.incoming("sub_b")
- msg = queue_b.get(timeout=1)
- self.assertEqual("Message 6", msg.body)
- acked.add(msg.id)
-
- sub_c = self.subscribe(session, queue=name_c, destination="sub_c")
- queue_c = session.incoming("sub_c")
- msg = queue_c.get(timeout=1)
- self.assertEqual("Message 7", msg.body)
- acked.add(msg.id)
-
- session.message_accept(acked)
-
- dp = session.delivery_properties(routing_key=topic)
- #publish messages
- for i in range(1, 5):
- mp = session.message_properties(message_id="tx-msg%d" % i)
- session.message_transfer(destination="amq.topic", message=Message(dp, mp, "TxMessage %d" % i))
-
- dp = session.delivery_properties(routing_key=key)
- mp = session.message_properties(message_id="tx-msg6")
- session.message_transfer(destination="amq.direct", message=Message(dp, mp, "TxMessage 6"))
-
- dp = session.delivery_properties(routing_key=name_a)
- mp = session.message_properties(message_id="tx-msg7")
- session.message_transfer(message=Message(dp, mp, "TxMessage 7"))
- return queue_a, queue_b, queue_c, acked
-
- def declare_queues(self, names, session=None):
- session = session or self.session
- for n in names:
- session.queue_declare(queue=n, auto_delete=True)
-
- def subscribe(self, session=None, **keys):
- session = session or self.session
- consumer_tag = keys["destination"]
- session.message_subscribe(**keys)
- session.message_flow(destination=consumer_tag, unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination=consumer_tag, unit=session.credit_unit.byte, value=0xFFFFFFFFL)
-
- def enable_flow(self, tag, session=None):
- session = session or self.session
- session.message_flow(destination=tag, unit=session.credit_unit.message, value=0xFFFFFFFFL)
- session.message_flow(destination=tag, unit=session.credit_unit.byte, value=0xFFFFFFFFL)
-
- def complete(self, session, msg):
- session.receiver._completed.add(msg.id)#TODO: this may be done automatically
- session.channel.session_completed(session.receiver._completed)
diff --git a/qpid/python/qpid_tests/client/client-api-example-tests.py b/qpid/python/qpid_tests/client/client-api-example-tests.py
deleted file mode 100755
index 43e0aada46..0000000000
--- a/qpid/python/qpid_tests/client/client-api-example-tests.py
+++ /dev/null
@@ -1,338 +0,0 @@
-#!/usr/bin/env 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.
-#
-"""
- client-api-examples-interop.py
-
-"""
-
-"""
-
-** TODO Add XML Exchange tests
-
-"""
-
-import os
-import shlex
-import subprocess
-import unittest
-import uuid
-import re
-from time import sleep
-
-import logging
-
-logging.basicConfig(level=logging.DEBUG,
- format='%(asctime)s %(levelname)s %(message)s',
- filename='./client-api-example-tests.log',
- filemode='w')
-
-#######################################################################################
-#
-# !!! Configure your paths here !!!
-#
-#######################################################################################
-
-## If you set qpid_root on a source tree, from the default install for
-## this script, you're good to go. If running from elsewhere against a
-## source tree, set QPID_ROOT. If running from an installed system,
-## set QPID_CPP_EXAMPLES, QPID_PYTHON_EXAMPLES, QPID_PYTHON_TOOLS,
-## etc. to the directories below.
-
-qpid_root = os.getenv("QPID_ROOT", os.path.abspath("../../../../../../qpid"))
-logging.debug("Qpid Root: " + qpid_root)
-
-qpid_broker = os.getenv("QPID_BROKER", "localhost:5672")
-logging.debug("Qpid Broker: " + qpid_broker)
-
-########################################################################################
-#
-# If you are working from a source tree, setting the above paths is
-# sufficient.
-#
-# If your examples are installed somewhere else, you have to tell us
-# where examples in each language are kept
-#
-########################################################################################
-
-cpp_examples_path = os.getenv("QPID_CPP_EXAMPLES", qpid_root + "/cpp/examples/messaging/")
-
-python_examples_path = os.getenv("QPID_PYTHON_EXAMPLES", qpid_root + "/python/examples/api/")
-python_path = os.getenv("PYTHONPATH", qpid_root+"/python:" + qpid_root+"/extras/qmf/src/py")
-os.environ["PYTHONPATH"] = python_path
-logging.debug("PYTHONPATH: " + os.environ["PYTHONPATH"])
-
-python_tools_path = os.getenv("QPID_PYTHON_TOOLS", qpid_root + "/tools/src/py/")
-logging.debug("QPID_PYTHON_TOOLS: " + python_tools_path)
-
-java_qpid_home = os.getenv("QPID_HOME", qpid_root + "/java/build/lib/")
-os.environ["QPID_HOME"] = java_qpid_home
-logging.debug("Java's QPID_HOME: " + os.environ["QPID_HOME"])
-java_examples_path = os.getenv("QPID_JAVA_EXAMPLES", qpid_root + "/java/client/example/")
-find = "find " + java_qpid_home + " -name '*.jar'"
-args = shlex.split(find)
-popen = subprocess.Popen(args, stdout=subprocess.PIPE)
-out, err = popen.communicate()
-os.environ["CLASSPATH"] = java_examples_path + ":" + re.sub("\\n", ":", out)
-logging.debug("Java CLASSPATH = " + os.environ["CLASSPATH"])
-
-java_invoke = "java " + "-Dlog4j.configuration=log4j.conf "
-
-############################################################################################
-
-
-drains = [
- {'lang': 'CPP', 'command': cpp_examples_path + "drain" },
- {'lang': 'PYTHON', 'command': python_examples_path + "drain"},
- {'lang': 'JAVA', 'command': java_invoke + "org.apache.qpid.example.Drain"}
- ]
-
-spouts = [
- {'lang': 'CPP', 'command': cpp_examples_path + "spout" },
- {'lang': 'PYTHON', 'command': python_examples_path + "spout"},
- {'lang': 'JAVA', 'command': java_invoke + "org.apache.qpid.example.Spout"}
- ]
-
-mapSenders = [
- {'lang': 'CPP', 'command': cpp_examples_path + "map_sender" },
- {'lang': 'JAVA', 'command': java_invoke + "org.apache.qpid.example.MapSender"}
- ]
-
-mapReceivers = [
- {'lang': 'CPP', 'command': cpp_examples_path + "map_receiver" },
- {'lang': 'JAVA', 'command': java_invoke + "org.apache.qpid.example.MapReceiver"}
- ]
-
-
-hellos = [
- {'lang': 'CPP', 'command': cpp_examples_path + "hello_world" },
- {'lang': 'PYTHON', 'command': python_examples_path + "hello" },
- {'lang': 'JAVA', 'command': java_invoke + "org.apache.qpid.example.Hello"}
- ]
-
-wockyClients = [
- {'lang': 'CPP', 'command': cpp_examples_path + "client" },
- ]
-
-wockyServers = [
- {'lang': 'CPP', 'command': cpp_examples_path + "server" },
- ]
-
-
-shortWait = 0.5
-longWait = 3 # use sparingly!
-
-class TestDrainSpout(unittest.TestCase):
-
- # setUp / tearDown
-
- def setUp(self):
- logging.debug('----------------------------')
- logging.debug('START: ' + self.tcaseName())
-
- def tearDown(self):
- pass
-
- #############################################################################
- #
- # Lemmas
- #
- #############################################################################
-
- def tcaseName(self):
- return re.split('[.]', self.id())[-1]
-
- # Python utilities
-
- def qpid_config(self, args):
- commandS = python_tools_path + "qpid-config" + ' ' + args
- args = shlex.split(commandS)
- logging.debug("qpid_config(): " + commandS)
- popen = subprocess.Popen(args, stdout=subprocess.PIPE)
- out, err = popen.communicate()
- logging.debug("qpid-config() - out=" + str(out) + ", err=" + str(err))
-
- # Send / receive methods in various languages
-
- def send(self, spout=spouts[0], content="", destination="amq.topic", create=1, wait=0):
- if wait:
- sleep(wait)
-
- createS = ";{create:always}" if create else ""
- addressS = "'" + destination + createS + "'"
- brokerS = "-b " + qpid_broker
- if spout['lang']=='CPP':
- contentS = " ".join(['--content',"'"+content+"'"]) if content else ""
- commandS = " ".join([spout['command'], brokerS, contentS, addressS])
- elif spout['lang']=='PYTHON':
- commandS = " ".join([spout['command'], brokerS, addressS, content])
- elif spout['lang']=='JAVA':
- brokerS = "-b guest:guest@" + qpid_broker
- commandS = " ".join([spout['command'], brokerS, "--content="+"'"+content+"'", addressS])
- else:
- raise "Ain't no such language ...."
- logging.debug("send(): " + commandS)
- args = shlex.split(commandS)
- popen = subprocess.Popen(args, stdout=subprocess.PIPE)
- out, err = popen.communicate()
- logging.debug("send() - out=" + str(out) + ", err=" + str(err))
-
-
- def receive(self, drain=drains[0], destination="amq.topic", delete=1):
- deleteS = ";{delete:always}" if delete else ""
- addressS = "'" + destination + deleteS + "'"
- brokerS = "-b " + qpid_broker
- optionS = "-c 1 -t 30"
- if drain['lang']=='CPP':
- commandS = " ".join([drain['command'], optionS, brokerS, optionS, addressS])
- elif drain['lang']=='PYTHON':
- commandS = " ".join([drain['command'], brokerS, optionS, addressS])
- elif drain['lang']=='JAVA':
- brokerS = "-b guest:guest@" + qpid_broker
- commandS = " ".join([drain['command'], brokerS, optionS, addressS])
- else:
- raise "Ain't no such language ...."
- logging.debug("receive() " + commandS)
- args = shlex.split(commandS)
- popen = subprocess.Popen(args, stdout=subprocess.PIPE)
- out, err = popen.communicate()
- logging.debug("receive() - out=" + str(out) + ", err=" + str(err))
- return out
-
- def subscribe(self, drain=drains[0], destination="amq.topic", create=0):
- optionS = "-t 30 -c 1"
- brokerS = "-b " + qpid_broker
- if drain['lang']=='CPP':
- commandS = " ".join([drain['command'], brokerS, optionS, destination])
- elif drain['lang']=='PYTHON':
- commandS = " ".join([drain['command'], brokerS, optionS, destination])
- elif drain['lang']=='JAVA':
- logging.debug("Java working directory: ")
- brokerS = "-b guest:guest@" + qpid_broker
- commandS = " ".join([drain['command'], brokerS, optionS, destination])
- else:
- logging.debug("subscribe() - no such language!")
- raise "Ain't no such language ...."
- logging.debug("subscribe() " + commandS)
- args = shlex.split(commandS)
- return subprocess.Popen(args, stdout=subprocess.PIPE)
-
- def listen(self, popen):
- out,err = popen.communicate()
- logging.debug("listen(): out=" + str(out) + ", err=" + str(err))
- return out
-
- #############################################################################
- #
- # Tests
- #
- #############################################################################
-
- # Hello world!
-
- def test_hello_world(self):
- for hello_world in hellos:
- args = shlex.split(hello_world['command'])
- popen = subprocess.Popen(args, stdout=subprocess.PIPE)
- out = popen.communicate()[0]
- logging.debug(out)
- self.assertTrue(out.find("world!") > 0)
-
- def test_jabberwocky(self):
- for i, s in enumerate(wockyServers):
- for j, c in enumerate(wockyClients):
- args = shlex.split(s['command'])
- server = subprocess.Popen(args, stdout=subprocess.PIPE)
- args = shlex.split(c['command'])
- client = subprocess.Popen(args, stdout=subprocess.PIPE)
- out = client.communicate()[0]
- logging.debug(out)
- self.assertTrue(out.find("BRILLIG") >= 0)
- server.terminate()
-
- def test_maps(self):
- for s in mapSenders:
- for r in mapReceivers:
- args = shlex.split(s['command'])
- sender = subprocess.Popen(args, stdout=subprocess.PIPE)
- args = shlex.split(r['command'])
- receiver = subprocess.Popen(args, stdout=subprocess.PIPE)
- out = receiver.communicate()[0]
- logging.debug(out)
- sender.terminate()
-
- def test_queues(self):
- for i, s in enumerate(spouts):
- for j, d in enumerate(drains):
- content = self.tcaseName() + ": " + s['lang'] + str(i) + " => " + d['lang'] + str(j)
- self.send(s, content=content, destination="hello_world", create=1)
- out = self.receive(d, destination="hello_world", delete=1)
- self.assertTrue(out.find(content) >= 0)
-
- def test_direct_exchange(self):
- for i, s in enumerate(spouts):
- for j, d in enumerate(drains):
- content = self.tcaseName() + ": " + s['lang'] + str(i) + " => " + d['lang'] + str(j)
- popen1 = self.subscribe(d, destination="amq.direct/subject")
- popen2 = self.subscribe(d, destination="amq.direct/subject")
- self.send(s, content=content, destination="amq.direct/subject", create=0, wait=2)
- out1 = self.listen(popen1)
- out2 = self.listen(popen2)
- self.assertTrue(out1.find(self.tcaseName()) >= 0)
- self.assertTrue(out2.find(self.tcaseName()) >= 0)
-
- def test_fanout_exchange(self):
- for i, s in enumerate(spouts):
- for j, d in enumerate(drains):
- content = self.tcaseName() + ": " + s['lang'] + str(i) + " => " + d['lang'] + str(j)
- popen1 = self.subscribe(d, destination="amq.fanout")
- popen2 = self.subscribe(d, destination="amq.fanout")
- self.send(s, content=content, destination="amq.fanout", create=0, wait=2)
- out1 = self.listen(popen1)
- out2 = self.listen(popen2)
- self.assertTrue(out1.find(self.tcaseName()) >= 0)
- self.assertTrue(out2.find(self.tcaseName()) >= 0)
-
-
- def test_topic_exchange(self):
- for i, s in enumerate(spouts):
- for j, d in enumerate(drains):
- content = self.tcaseName() + ": " + s['lang'] + str(i) + " => " + d['lang'] + str(j)
- popen1 = self.subscribe(d, destination="amq.topic" + "/" + s['lang'] + "." + d['lang'])
- popen2 = self.subscribe(d, destination="amq.topic" + "/" + "*" + "." + d['lang'])
- popen3 = self.subscribe(d, destination="amq.topic" + "/" + s['lang'] + "." + "*")
- popen4 = self.subscribe(d, destination="amq.topic" + "/" + "#" + "." + d['lang'])
- self.send(s, content=content, destination="amq.topic"+ "/" + s['lang'] + "." + d['lang'], create=0, wait=4)
- out1 = self.listen(popen1)
- out2 = self.listen(popen2)
- out3 = self.listen(popen3)
- out4 = self.listen(popen4)
- logging.debug("out1:"+out1)
- logging.debug("out2:"+out2)
- logging.debug("out3:"+out3)
- logging.debug("out4:"+out4)
- self.assertTrue(out1.find(self.tcaseName()) >= 0)
- self.assertTrue(out2.find(self.tcaseName()) >= 0)
- self.assertTrue(out3.find(self.tcaseName()) >= 0)
- self.assertTrue(out4.find(self.tcaseName()) >= 0)
-
-
-if __name__ == '__main__':
- unittest.main()
-
diff --git a/qpid/python/qpid_tests/client/log4j.conf b/qpid/python/qpid_tests/client/log4j.conf
deleted file mode 100644
index 2c7bd74e29..0000000000
--- a/qpid/python/qpid_tests/client/log4j.conf
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# 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.
-#
-log4j.logger.org.apache.qpid=WARN, console
-log4j.additivity.org.apache.qpid=false
-
-log4j.appender.console=org.apache.log4j.ConsoleAppender
-log4j.appender.console.Threshold=all
-log4j.appender.console.layout=org.apache.log4j.PatternLayout
-log4j.appender.console.layout.ConversionPattern=%t %d %p [%c{4}] %m%n
diff --git a/qpid/python/setup.py b/qpid/python/setup.py
deleted file mode 100755
index fece3d91b3..0000000000
--- a/qpid/python/setup.py
+++ /dev/null
@@ -1,323 +0,0 @@
-#!/usr/bin/env 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 os, re, sys, string, platform
-from distutils.core import setup, Command
-from distutils.command.build import build as _build
-from distutils.command.build_py import build_py as _build_py
-from distutils.command.clean import clean as _clean
-from distutils.command.install_lib import install_lib as _install_lib
-from distutils.dep_util import newer
-from distutils.dir_util import remove_tree
-from distutils.dist import Distribution
-from distutils.errors import DistutilsFileError, DistutilsOptionError
-from distutils import log
-from stat import ST_ATIME, ST_MTIME, ST_MODE, S_IMODE
-
-MAJOR, MINOR = sys.version_info[0:2]
-
-class preprocessor:
-
- def copy_file(self, src, dst, preserve_mode=1, preserve_times=1,
- link=None, level=1):
- name, actor = self.actor(src, dst)
- if actor:
- if not os.path.isfile(src):
- raise DistutilsFileError, \
- "can't copy '%s': doesn't exist or not a regular file" % src
-
- if os.path.isdir(dst):
- dir = dst
- dst = os.path.join(dst, os.path.basename(src))
- else:
- dir = os.path.dirname(dst)
-
- if not self.force and not newer(src, dst):
- return dst, 0
-
- if os.path.basename(dst) == os.path.basename(src):
- log.info("%s %s -> %s", name, src, dir)
- else:
- log.info("%s %s -> %s", name, src, dst)
-
- if self.dry_run:
- return (dst, 1)
- else:
- try:
- fsrc = open(src, 'rb')
- except os.error, (errno, errstr):
- raise DistutilsFileError, \
- "could not open '%s': %s" % (src, errstr)
-
- if os.path.exists(dst):
- try:
- os.unlink(dst)
- except os.error, (errno, errstr):
- raise DistutilsFileError, \
- "could not delete '%s': %s" % (dst, errstr)
-
- try:
- fdst = open(dst, 'wb')
- except os.error, (errno, errstr):
- raise DistutilsFileError, \
- "could not create '%s': %s" % (dst, errstr)
-
- try:
- fdst.write(actor(fsrc.read()))
- finally:
- fsrc.close()
- fdst.close()
-
- if preserve_mode or preserve_times:
- st = os.stat(src)
-
- if preserve_times:
- os.utime(dst, (st[ST_ATIME], st[ST_MTIME]))
- if preserve_mode:
- os.chmod(dst, S_IMODE(st[ST_MODE]))
-
- return (dst, 1)
- else:
- return Command.copy_file(self, src, dst, preserve_mode, preserve_times,
- link, level)
-
-doc_option = [('build-doc', None, 'build directory for documentation')]
-
-class build(_build):
-
- user_options = _build.user_options + doc_option
-
- def initialize_options(self):
- _build.initialize_options(self)
- self.build_doc = None
-
- def finalize_options(self):
- _build.finalize_options(self)
- if self.build_doc is None:
- self.build_doc = "%s/doc" % self.build_base
-
- def get_sub_commands(self):
- return _build.get_sub_commands(self) + ["build_doc"]
-
-class build_doc(Command):
-
- user_options = doc_option
-
- def initialize_options(self):
- self.build_doc = None
-
- def finalize_options(self):
- self.set_undefined_options('build', ('build_doc', 'build_doc'))
-
- def run(self):
- try:
- from epydoc.docbuilder import build_doc_index
- from epydoc.docwriter.html import HTMLWriter
- except ImportError, e:
- log.warn('%s -- skipping build_doc', e)
- return
-
- names = ["qpid.messaging"]
- doc_index = build_doc_index(names, True, True)
- html_writer = HTMLWriter(doc_index, show_private=False)
- self.mkpath(self.build_doc)
- log.info('epydoc %s to %s' % (", ".join(names), self.build_doc))
- html_writer.write(self.build_doc)
-
-class clean(_clean):
-
- user_options = _clean.user_options + doc_option
-
- def initialize_options(self):
- _clean.initialize_options(self)
- self.build_doc = None
-
- def finalize_options(self):
- _clean.finalize_options(self)
- self.set_undefined_options('build', ('build_doc', 'build_doc'))
-
- def run(self):
- if self.all:
- if os.path.exists(self.build_doc):
- remove_tree(self.build_doc, dry_run=self.dry_run)
- else:
- log.debug("%s doesn't exist -- can't clean it", self.build_doc)
- _clean.run(self)
-
-if MAJOR <= 2 and MINOR <= 3:
- from glob import glob
- from distutils.util import convert_path
- class distclass(Distribution):
-
- def __init__(self, *args, **kwargs):
- self.package_data = None
- Distribution.__init__(self, *args, **kwargs)
-else:
- distclass = Distribution
-
-ann = re.compile(r"([ \t]*)@([_a-zA-Z][_a-zA-Z0-9]*)([ \t\n\r]+def[ \t]+)([_a-zA-Z][_a-zA-Z0-9]*)")
-line = re.compile(r"\n([ \t]*)[^ \t\n#]+")
-
-class build_py(preprocessor, _build_py):
-
- if MAJOR <= 2 and MINOR <= 3:
- def initialize_options(self):
- _build_py.initialize_options(self)
- self.package_data = None
-
- def finalize_options(self):
- _build_py.finalize_options(self)
- self.package_data = self.distribution.package_data
- self.data_files = self.get_data_files()
-
- def get_data_files (self):
- data = []
- if not self.packages:
- return data
- for package in self.packages:
- # Locate package source directory
- src_dir = self.get_package_dir(package)
-
- # Compute package build directory
- build_dir = os.path.join(*([self.build_lib] + package.split('.')))
-
- # Length of path to strip from found files
- plen = 0
- if src_dir:
- plen = len(src_dir)+1
-
- # Strip directory from globbed filenames
- filenames = [file[plen:]
- for file in self.find_data_files(package, src_dir)]
- data.append((package, src_dir, build_dir, filenames))
- return data
-
- def find_data_files (self, package, src_dir):
- globs = (self.package_data.get('', [])
- + self.package_data.get(package, []))
- files = []
- for pattern in globs:
- # Each pattern has to be converted to a platform-specific path
- filelist = glob(os.path.join(src_dir, convert_path(pattern)))
- # Files that match more than one pattern are only added once
- files.extend([fn for fn in filelist if fn not in files])
- return files
-
- def build_package_data (self):
- lastdir = None
- for package, src_dir, build_dir, filenames in self.data_files:
- for filename in filenames:
- target = os.path.join(build_dir, filename)
- self.mkpath(os.path.dirname(target))
- self.copy_file(os.path.join(src_dir, filename), target,
- preserve_mode=False)
-
- def build_packages(self):
- _build_py.build_packages(self)
- self.build_package_data()
-
- # end if MAJOR <= 2 and MINOR <= 3
-
- def backport(self, input):
- output = ""
- pos = 0
- while True:
- m = ann.search(input, pos)
- if m:
- indent, decorator, idef, function = m.groups()
- output += input[pos:m.start()]
- output += "%s#@%s%s%s" % (indent, decorator, idef, function)
- pos = m.end()
-
- subst = "\n%s%s = %s(%s)\n" % (indent, function, decorator, function)
- npos = pos
- while True:
- n = line.search(input, npos)
- if not n:
- input += subst
- break
- if len(n.group(1)) <= len(indent):
- idx = n.start()
- input = input[:idx] + subst + input[idx:]
- break
- npos = n.end()
- else:
- break
-
- output += input[pos:]
- return output
-
- def actor(self, src, dst):
- base, ext = os.path.splitext(src)
- if ext == ".py" and MAJOR <= 2 and MINOR <= 3:
- return "backporting", self.backport
- else:
- return None, None
-
-def pclfile(xmlfile):
- return "%s.pcl" % os.path.splitext(xmlfile)[0]
-
-class install_lib(_install_lib):
-
- def get_outputs(self):
- outputs = _install_lib.get_outputs(self)
- extra = []
- for of in outputs:
- if os.path.basename(of) == "amqp-0-10-qpid-errata-stripped.xml":
- extra.append(pclfile(of))
- return outputs + extra
-
- def install(self):
- outfiles = _install_lib.install(self)
- extra = []
- for of in outfiles:
- if os.path.basename(of) == "amqp-0-10-qpid-errata-stripped.xml":
- tgt = pclfile(of)
- if self.force or newer(of, tgt):
- log.info("caching %s to %s" % (of, os.path.basename(tgt)))
- if not self.dry_run:
- from qpid.ops import load_types
- load_types(of)
- extra.append(tgt)
- return outfiles + extra
-
-scripts = ["qpid-python-test"]
-
-if platform.system() == "Windows":
- scripts.append("qpid-python-test.bat")
-
-setup(name="qpid-python",
- version="0.35",
- author="Apache Qpid",
- author_email="users@qpid.apache.org",
- packages=["mllib", "qpid", "qpid.messaging", "qpid.tests",
- "qpid.tests.messaging", "qpid.saslmech", "qpid.tests.saslmech",
- "qpid_tests", "qpid_tests.broker_1_0", "qpid_tests.broker_0_10",
- "qpid_tests.broker_0_9", "qpid_tests.broker_0_8"],
- package_data={"qpid": ["specs/*.dtd", "specs/*.xml"]},
- scripts=scripts,
- url="http://qpid.apache.org/",
- license="Apache Software License",
- description="Python client implementation and AMQP conformance tests for Apache Qpid",
- cmdclass={"build": build,
- "build_py": build_py,
- "build_doc": build_doc,
- "clean": clean,
- "install_lib": install_lib},
- distclass=distclass)