diff options
Diffstat (limited to 'qpid/cpp/src/tests/amqp_0_10/handlers.cpp')
-rw-r--r-- | qpid/cpp/src/tests/amqp_0_10/handlers.cpp | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/qpid/cpp/src/tests/amqp_0_10/handlers.cpp b/qpid/cpp/src/tests/amqp_0_10/handlers.cpp new file mode 100644 index 0000000000..035429a15d --- /dev/null +++ b/qpid/cpp/src/tests/amqp_0_10/handlers.cpp @@ -0,0 +1,125 @@ +/* + * + * 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. + * + */ + +#include "unit_test.h" +#include "qpid/Exception.h" +#include "qpid/amqp_0_10/Unit.h" +#include "qpid/amqp_0_10/ControlHolder.h" +#include "qpid/amqp_0_10/CommandHolder.h" +#include "qpid/amqp_0_10/handlers.h" +#include "qpid/amqp_0_10/specification.h" + +QPID_AUTO_TEST_SUITE(handler_tests) + +using namespace qpid::amqp_0_10; +using namespace std; + +string called; // Set by called handler function + +// Note on handlers: +// +// Control and Command handlers are separate, both behave the same way, +// so substitute "control or command" for command in the following. +// +// Command handlers derive from CommandHandler and implement functions +// for all the commands they handle. Handling an unimplemented command +// will raise NotImplementedException. +// +// Using virtual inheritance from CommandHandler allows multiple +// handlers to be aggregated into one with multiple inheritance, +// See test code for example. +// +// E.g. the existing broker model would have two control handlers: +// - ConnectionHandler: ControlHandler for connection controls. +// - SessionHandler: ControlHandler for session controls. +// It would have class-command handlers for each AMQP class: +// - QueueHandler, MessageHandler etc.. handle each class. +// And an aggregate handler in place of BrokerAdapter +// - BrokerCommandHandler: public QueueHandler, MessageHandler ... +// +// In other applications (e.g. cluster) any combination of commands +// can be handled by a given handler. It _might_ simplify the code +// to collaps ConnectionHandler and SessionHandler into a single +// ControlHandler (or it might not.) + +struct TestExecutionHandler : public virtual CommandHandler { + void executionSync() { called = "executionSync"; } + // ... etc. for all execution commands +}; + +struct TestMessageHandler : public virtual CommandHandler { + void messageCancel(const Str8&) { called="messageCancel"; } + // ... etc. +}; + +// Aggregate handler for all recognised commands. +struct TestCommandHandler : + public TestExecutionHandler, + public TestMessageHandler + // ... etc. handlers for all command classes. +{}; // Nothing to do. + + +// Sample unit handler, written as a static_visitor. +// Note it could equally be written with if/else statements +// in handle. +// +struct TestUnitHandler : public boost::static_visitor<void> { + TestCommandHandler handler; + void handle(const Unit& u) { u.applyVisitor(*this); } + + void operator()(const Body&) { called="Body"; } + void operator()(const Header&) { called="Header"; } + void operator()(const ControlHolder&) { throw qpid::Exception("I don't do controls."); } + void operator()(const CommandHolder& c) { c.invoke(handler); } +}; + +BOOST_AUTO_TEST_CASE(testHandlers) { + TestUnitHandler handler; + Unit u; + + u = Body(); + handler.handle(u); + BOOST_CHECK_EQUAL("Body", called); + + u = Header(); + handler.handle(u); + BOOST_CHECK_EQUAL("Header", called); + + // in_place<Foo>(...) is equivalent to Foo(...) but + // constructs Foo directly in the holder, avoiding + // a copy. + + u = CommandHolder(in_place<execution::Sync>()); + handler.handle(u); + BOOST_CHECK_EQUAL("executionSync", called); + + u = ControlHolder(in_place<connection::Start>(Map(), Str16Array(), Str16Array())); + try { + handler.handle(u); + } catch (const qpid::Exception&) {} + + u = CommandHolder(in_place<message::Cancel>(Str8())); + handler.handle(u); + BOOST_CHECK_EQUAL("messageCancel", called); +} + +QPID_AUTO_TEST_SUITE_END() |