diff options
author | Alan Conway <aconway@apache.org> | 2007-06-27 00:12:26 +0000 |
---|---|---|
committer | Alan Conway <aconway@apache.org> | 2007-06-27 00:12:26 +0000 |
commit | d032f5584b0f1de890844a2796d6ba158b011fca (patch) | |
tree | 7ffc500423a1cee3c39d2a5e27d301057fbcd0e9 /cpp/src | |
parent | 2e15ee024a7f47bda7bd6ea5991657a820bd0714 (diff) | |
download | qpid-python-d032f5584b0f1de890844a2796d6ba158b011fca.tar.gz |
Make check now starts a broker on a dynamically assigned port, so
multiple qpid builds on one host will not conflict.
* src/tests/run_test, start_broker, kill_broker:
Broker writes port to file, run_test sets QPID_PORT
in environment of all tests.
* src/tests/topic_publisher.cpp, topic_listener.cpp, client_test.cpp:
All test clients use TestOptions to parse options from args and env.
* src/qpid/Options.h: Renamed from CommonOptions.h
Simplified use of Options class.
* src/qpid/Url.h: Renamed defaultPort constant.
* src/tests/logging.cpp:
* src/tests/interop_runner.cpp:
* src/tests/TestOptions.h:
* src/qpidd.cpp:
* src/qpid/log/Options.cpp:
* src/qpid/log/Logger.cpp:
* src/qpid/broker/Broker.cpp:
Updated for changes to Options.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@550993 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/Makefile.am | 6 | ||||
-rw-r--r-- | cpp/src/qpid/CommonOptions.cpp | 95 | ||||
-rw-r--r-- | cpp/src/qpid/CommonOptions.h | 121 | ||||
-rw-r--r-- | cpp/src/qpid/Options.cpp | 92 | ||||
-rw-r--r-- | cpp/src/qpid/Options.h | 148 | ||||
-rw-r--r-- | cpp/src/qpid/Url.h | 8 | ||||
-rw-r--r-- | cpp/src/qpid/broker/Broker.cpp | 17 | ||||
-rw-r--r-- | cpp/src/qpid/broker/Broker.h | 12 | ||||
-rw-r--r-- | cpp/src/qpid/log/Logger.cpp | 5 | ||||
-rw-r--r-- | cpp/src/qpid/log/Options.cpp | 21 | ||||
-rw-r--r-- | cpp/src/qpid/log/Options.h | 8 | ||||
-rw-r--r-- | cpp/src/qpidd.cpp | 105 | ||||
-rw-r--r-- | cpp/src/tests/Makefile.am | 6 | ||||
-rw-r--r-- | cpp/src/tests/SimpleTestCaseBase.cpp | 2 | ||||
-rw-r--r-- | cpp/src/tests/TestOptions.h | 51 | ||||
-rw-r--r-- | cpp/src/tests/client_test.cpp | 30 | ||||
-rwxr-xr-x | cpp/src/tests/daemon_test | 31 | ||||
-rw-r--r-- | cpp/src/tests/interop_runner.cpp | 67 | ||||
-rwxr-xr-x | cpp/src/tests/kill_broker | 2 | ||||
-rw-r--r-- | cpp/src/tests/logging.cpp | 77 | ||||
-rwxr-xr-x | cpp/src/tests/run_test | 18 | ||||
-rwxr-xr-x | cpp/src/tests/start_broker | 5 | ||||
-rw-r--r-- | cpp/src/tests/topic_listener.cpp | 100 | ||||
-rw-r--r-- | cpp/src/tests/topic_publisher.cpp | 161 | ||||
-rwxr-xr-x | cpp/src/tests/topictest | 2 |
25 files changed, 507 insertions, 683 deletions
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am index 8c904f6aff..1235c4d7fa 100644 --- a/cpp/src/Makefile.am +++ b/cpp/src/Makefile.am @@ -162,7 +162,8 @@ libqpidcommon_la_SOURCES = \ qpid/QpidError.cpp \ qpid/sys/Runnable.cpp \ qpid/sys/ProducerConsumer.cpp \ - qpid/CommonOptions.cpp \ + qpid/Options.cpp \ + qpid/Options.h \ qpid/log/Options.cpp \ qpid/log/Options.h \ qpid/log/Selector.cpp \ @@ -368,8 +369,7 @@ nobase_include_HEADERS = \ qpid/ExceptionHolder.h \ qpid/QpidError.h \ qpid/SharedObject.h \ - qpid/shared_ptr.h \ - qpid/CommonOptions.h + qpid/shared_ptr.h # Force build of qpidd during dist phase so help2man will work. dist-hook: qpidd diff --git a/cpp/src/qpid/CommonOptions.cpp b/cpp/src/qpid/CommonOptions.cpp deleted file mode 100644 index 2224f0e75b..0000000000 --- a/cpp/src/qpid/CommonOptions.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * 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. - * - */ - -#include "CommonOptions.h" -#include "qpid/Exception.h" -#include <fstream> -#include <algorithm> -#include <iostream> - -namespace qpid { -namespace program_options { - -char env2optchar(char env) { - return (env=='_') ? '-' : tolower(env); -} - -const std::string envPrefix("QPID_"); - -std::string env2option(const std::string& env) { - if (env.find(envPrefix) == 0) { - std::string opt = env.substr(envPrefix.size()); - std::transform(opt.begin(), opt.end(), opt.begin(), env2optchar); - return opt; - } - return std::string(); -} - -std::string prettyArg(const std::string& name, const std::string& value) { - return value.empty() ? name : name+" (="+value+")"; -} - -} // namespace program_options - -const int CommonOptions::DEFAULT_PORT=5672; - -CommonOptions::CommonOptions() : trace(false), port(DEFAULT_PORT) {} - -void CommonOptions::addTo(po::options_description& desc) -{ - using namespace po; - desc.add_options() - ("trace,t", optValue(trace), "Enable debug tracing" ) - ("port,p", optValue(port,"PORT"), "Use PORT for AMQP connections."); -} - -void parseOptions( - po::options_description& desc, int argc, char** argv, - const std::string& configFile) -{ - po::variables_map vm; - po::store(po::parse_command_line(argc, argv, desc), vm); - try { - po::store(po::parse_environment(desc, po::env2option), vm); - } - catch (const po::unknown_option& e) { - std::cerr << e.what() << std::endl; - } - catch (const po::error& e) { - throw po::error(std::string("parsing environment variables: ") - + e.what()); - } - po::notify(vm); // configFile may be updated from arg/env options. - if (!configFile.empty()) { - try { - using namespace std; - ifstream conf(configFile.c_str()); - if (conf.good()) { - conf.exceptions(ifstream::failbit|ifstream::badbit); - po::store(po::parse_config_file(conf, desc), vm); - } - } - catch (const std::exception& e) { - throw Exception(std::string("error parsing config file: ")+ e.what()); - } - } - po::notify(vm); -} - -} // namespace qpid - diff --git a/cpp/src/qpid/CommonOptions.h b/cpp/src/qpid/CommonOptions.h deleted file mode 100644 index 8a67babfde..0000000000 --- a/cpp/src/qpid/CommonOptions.h +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef QPID_COMMONOPTIONS_H -#define QPID_COMMONOPTIONS_H - -/* - * - * 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 <boost/program_options.hpp> -#include <boost/format.hpp> -#include <sstream> -#include <iterator> -#include <algorithm> - -namespace qpid { - -/**@Qpid extensions to boost::program_options */ -namespace program_options { - -using namespace boost::program_options; - -/** @internal Normally only constructed by optValue() */ -template <class T> -class OptionValue : public typed_value<T> { - public: - OptionValue(T& value, const std::string& arg) - : typed_value<T>(&value), argName(arg) {} - std::string name() const { return argName; } - private: - std::string argName; -}; - -///@internal -std::string prettyArg(const std::string& name, const std::string& value); - -/** - * Like boost::program_options::value() with more convenient signature - * for updating a value by reference and prettier help formatting. - * - *@param value displayed as default in help, updated from options. - * Must support ostream << operator. - *@param arg name for arguments in help. - * - *@see CommonOptions.cpp for example of use. - */ -template<class T> -value_semantic* optValue(T& value, const char* name) { - std::string valstr(boost::lexical_cast<std::string>(value)); - return new OptionValue<T>(value, prettyArg(name, valstr)); -} - -template <class T> -value_semantic* optValue(std::vector<T>& value, const char* name) { - using namespace std; - ostringstream os; - copy(value.begin(), value.end(), ostream_iterator<T>(os, " ")); - string val=os.str(); - if (!val.empty()) - val.erase(val.end()-1); // Remove trailing " " - return (new OptionValue<vector<T> >(value, prettyArg(name, val))); -} - -/** Environment-to-option name mapping. - * Maps env variable "QPID_SOME_VAR" to option "some-var" - */ -std::string env2option(const std::string& env); - -/** - * Like boost::program_options::bool_switch but takes reference, not pointer. - */ -inline value_semantic* optValue(bool& value) { return bool_switch(&value); } - -} // namespace program_options - -namespace po=program_options; // Convenience alias. - -/** - * Common options for client and broker - */ -struct CommonOptions { - static const int DEFAULT_PORT; - - CommonOptions(); - - bool trace; - int port; - - /** Add members to program_options to be updated */ - void addTo(po::options_description&); - -}; - -/** Convenience function to parse an options_description. - * Parses argc/argv, environment variables and config file. - * Note the filename argument can reference a variable that - * is updated by argc/argv or environment variable parsing. - */ -void parseOptions(po::options_description&, - int argc, char** argv, - const std::string& filename=std::string()); - - -} // namespace qpid - -#endif /*!QPID_COMMONOPTIONS_H*/ diff --git a/cpp/src/qpid/Options.cpp b/cpp/src/qpid/Options.cpp new file mode 100644 index 0000000000..18a3f726f9 --- /dev/null +++ b/cpp/src/qpid/Options.cpp @@ -0,0 +1,92 @@ +/* + * + * Copyright (c) 2006 The Apache Software Foundation + * + * 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. + * + */ + +#include "Options.h" +#include "qpid/Exception.h" +#include <fstream> +#include <algorithm> +#include <iostream> + +namespace qpid { + +using namespace std; + +namespace { +const std::string prefix("QPID_"); +char env2optchar(char env) { return (env=='_') ? '-' : tolower(env); } + +struct Mapper { + Mapper(const Options& o) : opts(o) {} + string operator()(const string& env) { + if (env.substr(0, prefix.size()) == prefix) { + string opt = env.substr(prefix.size()); + transform(opt.begin(), opt.end(), opt.begin(), env2optchar); + // Ignore env vars that don't match to known options. + if (opts.find_nothrow(opt, false)) + return opt; + } + return string(); + } + const Options& opts; +}; + +} +std::string prettyArg(const std::string& name, const std::string& value) { + return value.empty() ? name : name+" (="+value+")"; +} + +Options::Options(const string& name) : po::options_description(name) {} + +void Options::parse(int argc, char** argv, const std::string& configFile) +{ + string parsing; + try { + po::variables_map vm; + parsing="command line options"; + po::store(po::parse_command_line(argc, argv, *this), vm); + parsing="environment variables"; + po::store(po::parse_environment(*this, Mapper(*this)), vm); + po::notify(vm); // configFile may be updated from arg/env options. + if (!configFile.empty()) { + parsing="configuration file "+configFile; + ifstream conf(configFile.c_str()); + if (conf.good()) { + conf.exceptions(ifstream::failbit|ifstream::badbit); + po::store(po::parse_config_file(conf, *this), vm); + } + } + po::notify(vm); + } + catch (const std::exception& e) { + ostringstream msg; + msg << "Error in " << parsing << ": " << e.what() << endl; + if (find_nothrow("help", false)) + msg << "Use --help to see valid options" << endl; + throw Exception(msg.str()); + } +} + +CommonOptions::CommonOptions(const string& name) : Options(name) { + addOptions() + ("help,h", optValue(help), "Print help message.") + ("version,v", optValue(version), "Print version information.") + ("config", optValue(config, "FILE"), "Configuation file."); +} + +} // namespace qpid + diff --git a/cpp/src/qpid/Options.h b/cpp/src/qpid/Options.h new file mode 100644 index 0000000000..0821dca7e5 --- /dev/null +++ b/cpp/src/qpid/Options.h @@ -0,0 +1,148 @@ +#ifndef QPID_COMMONOPTIONS_H +#define QPID_COMMONOPTIONS_H + +/* + * + * 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 "qpid/Exception.h" +#include <boost/program_options.hpp> +#include <boost/format.hpp> +#include <sstream> +#include <iterator> +#include <algorithm> + +namespace qpid { +namespace po=boost::program_options; + +///@internal +std::string prettyArg(const std::string&, const std::string&); + +/** @internal Normally only constructed by optValue() */ +template <class T> +class OptionValue : public po::typed_value<T> { + public: + OptionValue(T& value, const std::string& arg) + : po::typed_value<T>(&value), argName(arg) {} + std::string name() const { return argName; } + + private: + std::string argName; +}; + + +/** Create an option value. + * name, value appear after the option name in help like this: + * <name> (=<value>) + * T must support operator <<. + *@see Options for example of use. + */ +template<class T> +po::value_semantic* optValue(T& value, const char* name) { + std::string valstr(boost::lexical_cast<std::string>(value)); + return new OptionValue<T>(value, prettyArg(name, valstr)); +} + +/** Create a vector value. Multiple occurences of the option are + * accumulated into the vector + */ +template <class T> +po::value_semantic* optValue(std::vector<T>& value, const char* name) { + using namespace std; + ostringstream os; + copy(value.begin(), value.end(), ostream_iterator<T>(os, " ")); + string val=os.str(); + if (!val.empty()) + val.erase(val.end()-1); // Remove trailing " " + return (new OptionValue<vector<T> >(value, prettyArg(name, val))); +} + +/** Create a boolean switch value. Presence of the option sets the value. */ +inline po::value_semantic* optValue(bool& value) { return po::bool_switch(&value); } + +/** + * Base class for options. + * Example of use: + @code + struct MySubOptions : public Options { + int x; + string y; + MySubOptions() : Options("Sub options") { + addOptions() + ("x", optValue(x,"XUNIT"), "Option X") + ("y", optValue(y, "YUNIT"), "Option Y"); + } + }; + + struct MyOptions : public Options { + bool z; + vector<string> foo; + MySubOptions subOptions; + MyOptions() : Options("My Options") { + addOptions() + ("z", boolSwitch(z), "Option Z") + ("foo", optValue(foo), "Multiple option foo."); + add(subOptions); + } + + main(int argc, char** argv) { + Options opts; + opts.parse(argc, char** argv); + // Use values + dosomething(opts.subOptions.x); + if (error) + cout << opts << end; // Help message. + } + + @endcode + */ +struct Options : public po::options_description { + struct Exception : public qpid::Exception { + Exception(const std::string& msg) : qpid::Exception(msg) {} + }; + + Options(const std::string& name=std::string()); + + boost::program_options::options_description_easy_init addOptions() { + return add_options(); + } + + /** + * Parses options from argc/argv, environment variables and config file. + * Note the filename argument can reference an options variable that + * is updated by argc/argv or environment variable parsing. + */ + void parse(int argc, char** argv, + const std::string& configfile=std::string()); +}; + +/** + * Standard options for configuration + */ +struct CommonOptions : public Options { + CommonOptions(const std::string& name=std::string()); + bool help; + bool version; + std::string config; +}; + +} // namespace qpid + +#endif /*!QPID_COMMONOPTIONS_H*/ diff --git a/cpp/src/qpid/Url.h b/cpp/src/qpid/Url.h index f45192ce23..93a53afde6 100644 --- a/cpp/src/qpid/Url.h +++ b/cpp/src/qpid/Url.h @@ -30,19 +30,19 @@ namespace qpid { /** TCP address of a broker - host:port */ struct TcpAddress { - static const uint16_t defaultPort=5672; + static const uint16_t DEFAULT_PORT=5672; TcpAddress(const std::string& host_=std::string(), - uint16_t port_=defaultPort) + uint16_t port_=DEFAULT_PORT) : host(host_), port(port_) {} std::string host; uint16_t port; }; -bool operator==(const TcpAddress& x, const TcpAddress& y) { +inline bool operator==(const TcpAddress& x, const TcpAddress& y) { return y.host==x.host && y.port == x.port; } -std::ostream& operator<<(std::ostream& os, const TcpAddress& a) { +inline std::ostream& operator<<(std::ostream& os, const TcpAddress& a) { return os << "tcp:" << a.host << ":" << a.port; } diff --git a/cpp/src/qpid/broker/Broker.cpp b/cpp/src/qpid/broker/Broker.cpp index 01e049bdda..4354f6d38a 100644 --- a/cpp/src/qpid/broker/Broker.cpp +++ b/cpp/src/qpid/broker/Broker.cpp @@ -35,6 +35,7 @@ #include "qpid/sys/ConnectionInputHandler.h" #include "qpid/sys/ConnectionInputHandlerFactory.h" #include "qpid/sys/TimeoutHandler.h" +#include "qpid/Url.h" #include <iostream> #include <memory> @@ -44,19 +45,17 @@ using qpid::sys::Acceptor; namespace qpid { namespace broker { -Broker::Options::Options() : +Broker::Options::Options(const std::string& name) : + qpid::Options(name), + port(TcpAddress::DEFAULT_PORT), workerThreads(5), maxConnections(500), connectionBacklog(10), store(), stagingThreshold(5000000) -{} - -void Broker::Options::addTo(po::options_description& desc) { - using namespace po; - CommonOptions::addTo(desc); - desc.add_options() + addOptions() + ("port,p", optValue(port,"PORT"), "Use PORT for AMQP connections.") ("worker-threads", optValue(workerThreads, "N"), "Broker thread pool size") ("max-connections", optValue(maxConnections, "N"), @@ -114,7 +113,7 @@ Broker::shared_ptr Broker::create(const Options& config) { MessageStore* Broker::createStore(const Options& config) { if (config.store.empty()) - return new NullMessageStore(config.trace); + return new NullMessageStore(false); else return new MessageStoreModule(config.store); } @@ -141,7 +140,7 @@ Acceptor& Broker::getAcceptor() const { Acceptor::create(config.port, config.connectionBacklog, config.workerThreads, - config.trace); + false); return *acceptor; } diff --git a/cpp/src/qpid/broker/Broker.h b/cpp/src/qpid/broker/Broker.h index 187167ebe7..efefbd2e3e 100644 --- a/cpp/src/qpid/broker/Broker.h +++ b/cpp/src/qpid/broker/Broker.h @@ -23,6 +23,7 @@ */ #include "ConnectionFactory.h" +#include "qpid/Url.h" #include "qpid/sys/Runnable.h" #include "qpid/sys/Acceptor.h" #include "qpid/SharedObject.h" @@ -35,7 +36,7 @@ #include "qpid/framing/OutputHandler.h" #include "qpid/framing/ProtocolInitiation.h" #include "QueueRegistry.h" -#include "qpid/CommonOptions.h" +#include "qpid/Options.h" namespace qpid { namespace broker { @@ -46,9 +47,10 @@ class Broker : public sys::Runnable, public SharedObject<Broker> { public: - struct Options : public CommonOptions { - Options(); - void addTo(po::options_description&); + struct Options : public qpid::Options { + Options(const std::string& name="Broker Options"); + + uint16_t port; int workerThreads; int maxConnections; int connectionBacklog; @@ -62,7 +64,7 @@ class Broker : public sys::Runnable, * Create a broker. * @param port Port to listen on or 0 to pick a port dynamically. */ - static shared_ptr create(int16_t port = CommonOptions::DEFAULT_PORT); + static shared_ptr create(int16_t port = TcpAddress::DEFAULT_PORT); /** * Create a broker with the options in config. diff --git a/cpp/src/qpid/log/Logger.cpp b/cpp/src/qpid/log/Logger.cpp index 065d4508c7..ceb3977106 100644 --- a/cpp/src/qpid/log/Logger.cpp +++ b/cpp/src/qpid/log/Logger.cpp @@ -188,8 +188,11 @@ void Logger::remove(Statement& s) { statements.erase(&s); } -void Logger::configure(const Options& o, const std::string& prog) +void Logger::configure(const Options& opts, const std::string& prog) { + Options o(opts); + if (o.trace) + o.selectors.push_back("trace+"); { ScopedLock l(lock); syslogName=prog; diff --git a/cpp/src/qpid/log/Options.cpp b/cpp/src/qpid/log/Options.cpp index 3e117663ff..b15630ebb2 100644 --- a/cpp/src/qpid/log/Options.cpp +++ b/cpp/src/qpid/log/Options.cpp @@ -18,36 +18,34 @@ #include "Options.h" #include "Statement.h" -#include "qpid/CommonOptions.h" +#include "qpid/Options.h" namespace qpid { namespace log { using namespace std; -Options::Options() : - time(true), level(true), thread(false), source(false), function(false) +Options::Options(const std::string& name) : qpid::Options(name), + time(true), level(true), thread(false), source(false), function(false), trace(false) { outputs.push_back("stderr"); selectors.push_back("error+"); -} -void Options::addTo(po::options_description& desc) { - using namespace po; ostringstream levels; levels << LevelTraits::name(Level(0)); for (int i = 1; i < LevelTraits::COUNT; ++i) levels << " " << LevelTraits::name(Level(i)); - desc.add_options() + addOptions() + ("trace,t", optValue(trace), "Enable full debug tracing." ) ("log.enable", optValue(selectors, "RULE"), - "You can specify this option mutliple times.\n" + ("You can specify this option mutliple times.\n" "RULE is of the form 'LEVEL[+][:COMPONENT]'" - "Levels are: trace, debug, info, notice, warning, error, critical." + "Levels are: "+levels.str()+"\n" "For example:\n" "\t'--log.enable warning+' " "enables all warning, error and critical messages.\n" "\t'--log.enable debug:framing' " - "enables debug messages from the framing component.") + "enables debug messages from the framing component.").c_str()) ("log.output", optValue(outputs, "FILE"), "File to receive log output, or one of these special values: " "'stderr', 'stdout', 'syslog'.") @@ -61,9 +59,6 @@ void Options::addTo(po::options_description& desc) { "Include thread ID in log messages") ("log.function", optValue(function,"yes|no"), "Include function signature in log messages"); - } - - }} // namespace qpid::log diff --git a/cpp/src/qpid/log/Options.h b/cpp/src/qpid/log/Options.h index 39261c9b5d..441c6e8a8d 100644 --- a/cpp/src/qpid/log/Options.h +++ b/cpp/src/qpid/log/Options.h @@ -18,20 +18,20 @@ * limitations under the License. * */ -#include "qpid/CommonOptions.h" +#include "qpid/Options.h" namespace qpid { namespace log { /** Logging options for config parser. */ -struct Options { - Options(); - void addTo(po::options_description&); +struct Options : public qpid::Options { + Options(const std::string& name="Logging options"); std::vector<std::string> selectors; std::vector<std::string> outputs; bool time, level, thread, source, function; + bool trace; }; diff --git a/cpp/src/qpidd.cpp b/cpp/src/qpidd.cpp index 3378fcdc96..aa84f1d6ac 100644 --- a/cpp/src/qpidd.cpp +++ b/cpp/src/qpidd.cpp @@ -37,67 +37,45 @@ using namespace qpid::broker; using namespace qpid::sys; using namespace std; -/** Command line options */ -struct QpiddOptions : public Broker::Options, public log::Options -{ - bool help; - bool longHelp; - bool version; +struct DaemonOptions : public qpid::Options { bool daemon; bool quit; - bool kill; bool check; int wait; - string config; - po::options_description mainOpts; - po::options_description allOpts; - - QpiddOptions() : - help(false), version(false), daemon(false), - quit(false), check(false), - wait(10), - config("/etc/qpidd.conf"), - mainOpts("Broker Options") + + DaemonOptions() : qpid::Options("Daemon options"), daemon(false), quit(false), check(false), wait(10) { - using namespace po; - // First set up the sub-option groups. - options_description daemonOpts("Daemon Options"); - daemonOpts.add_options() + addOptions() ("daemon,d", optValue(daemon), "Run as a daemon. With --port 0 print actual listening port.") ("wait,w", optValue(wait, "SECONDS"), "Maximum wait for daemon response.") ("check,c", optValue(check), "If a daemon is running print its pid to stdout and return 0.") ("quit,q", optValue(quit), "Stop the running daemon politely."); + } +}; - options_description logOpts("Logging Options"); - log::Options::addTo(logOpts); - - // Populate the main options group for --help - Broker::Options::addTo(mainOpts); - mainOpts.add_options() - ("config", optValue(config, "FILE"), "Configuation file.") - ("help,h", optValue(help), "Print help message.") - ("long-help", optValue(longHelp), "Show complete list of options.") - ("version,v", optValue(version), "Print version information."); - mainOpts.add(daemonOpts); - - // Populate the all options group - allOpts.add(mainOpts).add(logOpts); +struct QpiddOptions : public qpid::Options { + DaemonOptions daemon; + Broker::Options broker; + log::Options log; + CommonOptions common; + + QpiddOptions() : qpid::Options("Options") { + common.config = "/etc/qpidd.conf"; + add(common); + add(broker); + add(daemon); + add(log); } - void parse(int argc, char* argv[]) { - parseOptions(allOpts, argc, argv, config); - } - - void usage(const po::options_description& opts) const { - cout << "Usage: qpidd [OPTIONS]" << endl << endl - << opts << endl; + void usage() const { + cout << "Usage: qpidd [OPTIONS]" << endl << endl << *this << endl; }; }; // Globals Broker::shared_ptr brokerPtr; -QpiddOptions config; +QpiddOptions options; void handle_signal(int /*signal*/){ QPID_LOG(notice, "Shutting down..."); @@ -106,7 +84,7 @@ void handle_signal(int /*signal*/){ /** Compute a name for the pid file */ std::string pidFileFn() { - uint16_t port=brokerPtr ? brokerPtr->getPort() : config.port; + uint16_t port=brokerPtr ? brokerPtr->getPort() : options.broker.port; string file=(boost::format("qpidd.%d.pid") % port).str(); string pidPath; if (getuid() == 0) // Use standard pid file for root. @@ -128,13 +106,13 @@ std::string pidFileFn() { /** Code for forked parent */ void parent(Daemon& demon) { uint16_t realPort = demon.wait(); - if (config.port == 0) + if (options.broker.port == 0) cout << realPort << endl; } /** Code for forked child */ void child(Daemon& demon) { - brokerPtr=Broker::create(config); + brokerPtr=Broker::create(options.broker); uint16_t realPort=brokerPtr->getPort(); demon.ready(realPort); // Notify parent. brokerPtr->run(); @@ -144,34 +122,30 @@ void child(Daemon& demon) { int main(int argc, char* argv[]) { // Spelled 'demon' to avoid clash with daemon.h function. - Daemon demon(pidFileFn, config.wait); + Daemon demon(pidFileFn, options.daemon.wait); try { - config.parse(argc, argv); - if (config.trace) - config.selectors.push_back("trace+"); - log::Logger::instance().configure(config, argv[0]); + options.parse(argc, argv, options.common.config); + log::Logger::instance().configure(options.log, argv[0]); // Options that just print information. - if(config.help || config.longHelp || config.version) { - if (config.version) + if(options.common.help || options.common.version) { + if (options.common.version) cout << "qpidd (" << PACKAGE_NAME << ") version " << PACKAGE_VERSION << endl; - if (config.longHelp) - config.usage(config.allOpts); - else if (config.help) - config.usage(config.mainOpts); + else if (options.common.help) + options.usage(); return 0; } // Stop running daemon - if (config.quit) { + if (options.daemon.quit) { demon.quit(); return 0; } // Query running daemon - if (config.check) { + if (options.daemon.check) { pid_t pid = demon.check(); if (pid < 0) return 1; @@ -183,25 +157,20 @@ int main(int argc, char* argv[]) // Starting the broker: signal(SIGINT, handle_signal); - if (config.daemon) { // Daemon broker + if (options.daemon.daemon) { // Daemon broker demon.fork(parent, child); } else { // Non-daemon broker. - brokerPtr = Broker::create(config); - if (config.port == 0) + brokerPtr = Broker::create(options.broker); + if (options.broker.port == 0) cout << uint16_t(brokerPtr->getPort()) << endl; brokerPtr->run(); } return 0; } - catch(const po::error& e) { - // Command line parsing error. - cerr << "Error: " << e.what() << endl - << "Type 'qpidd --long-help' for full usage." << endl; - } catch(const exception& e) { if (demon.isParent()) - cerr << "Error: " << e.what() << endl; + cerr << e.what() << endl; else QPID_LOG(critical, e.what()); } diff --git a/cpp/src/tests/Makefile.am b/cpp/src/tests/Makefile.am index 9b15b68c04..ebf1aa9f41 100644 --- a/cpp/src/tests/Makefile.am +++ b/cpp/src/tests/Makefile.am @@ -89,14 +89,14 @@ testprogs = \ check_PROGRAMS += $(unit_progs) $(testprogs) interop_runner -TESTS_ENVIRONMENT = VALGRIND=$(VALGRIND) srcdir=$(srcdir) ./run_test +TESTS_ENVIRONMENT = VALGRIND=$(VALGRIND) srcdir=$(srcdir) $(srcdir)/run_test system_tests = client_test quick_topictest -TESTS = dummy_test $(unit_progs) $(unit_wrappers) run-unit-tests start_broker $(system_tests) python_tests kill_broker daemon_test +TESTS = dummy_test $(unit_progs) $(unit_wrappers) run-unit-tests start_broker $(system_tests) python_tests kill_broker EXTRA_DIST = \ test_env run_test \ - run-unit-tests start_broker python_tests kill_broker daemon_test \ + run-unit-tests start_broker python_tests kill_broker \ quick_topictest \ topictest \ .valgrind.supp-default \ diff --git a/cpp/src/tests/SimpleTestCaseBase.cpp b/cpp/src/tests/SimpleTestCaseBase.cpp index 5f37fd0eb3..4f071cd02b 100644 --- a/cpp/src/tests/SimpleTestCaseBase.cpp +++ b/cpp/src/tests/SimpleTestCaseBase.cpp @@ -70,7 +70,7 @@ void SimpleTestCaseBase::Sender::start(){ SimpleTestCaseBase::Worker::Worker(TestOptions& options, const int _messages) : connection(options.trace), messages(_messages), count(0) { - connection.open(options.broker, options.port); + connection.open(options.host, options.port); connection.openChannel(channel); } diff --git a/cpp/src/tests/TestOptions.h b/cpp/src/tests/TestOptions.h index 45575ba450..ee3af0873a 100644 --- a/cpp/src/tests/TestOptions.h +++ b/cpp/src/tests/TestOptions.h @@ -21,46 +21,35 @@ * */ -#include "qpid/CommonOptions.h" +#include "qpid/Options.h" +#include "qpid/Url.h" namespace qpid { -struct TestOptions : public qpid::CommonOptions +struct TestOptions : public qpid::Options { - TestOptions() : desc("Options"), broker("localhost"), virtualhost(""), clientid("cpp"), help(false) + TestOptions() : Options("Test Options"), host("localhost"), port(TcpAddress::DEFAULT_PORT), clientid("cpp"), trace(false), help(false) { - using namespace qpid::program_options; - using namespace boost::program_options; - CommonOptions::addTo(desc); - desc.add_options() - ("broker,b", optValue(broker, "HOSTNAME"), "the hostname to connect to") - ("virtualhost,v", optValue(virtualhost, "VIRTUAL_HOST"), "virtual host") + addOptions() + ("host,h", optValue(host, "HOST"), "Broker host to connect to") + // TODO aconway 2007-06-26: broker is synonym for host. Drop broker? + ("broker,b", optValue(host, "HOST"), "Broker host to connect to") + ("port,p", optValue(port, "PORT"), "Broker port to connect to") + ("virtualhost,v", optValue(virtualhost, "VHOST"), "virtual host") ("clientname,n", optValue(clientid, "ID"), "unique client identifier") - ("help,h", optValue(help), "print this usage statement"); + ("username", optValue(username, "USER"), "user name for broker log in.") + ("password", optValue(password, "USER"), "password for broker log in.") + ("trace,t", optValue(trace), "Turn on debug tracing.") + ("help", optValue(help), "print this usage statement"); } - void parse(int argc, char** argv) - { - using namespace boost::program_options; - try { - variables_map vm; - store(parse_command_line(argc, argv, desc), vm); - notify(vm); - } catch(const error& e) { - std::cerr << "Error: " << e.what() << std::endl - << "Specify '--help' for usage." << std::endl; - } - } - - void usage() - { - std::cout << desc << std::endl; - } - - boost::program_options::options_description desc; - std::string broker; + std::string host; + uint16_t port; std::string virtualhost; - std::string clientid; + std::string clientid; + std::string username; + std::string password; + bool trace; bool help; }; diff --git a/cpp/src/tests/client_test.cpp b/cpp/src/tests/client_test.cpp index a05c01043f..3b8a3a2ee6 100644 --- a/cpp/src/tests/client_test.cpp +++ b/cpp/src/tests/client_test.cpp @@ -28,6 +28,7 @@ #include <iostream> +#include "TestOptions.h" #include "qpid/QpidError.h" #include "qpid/client/ClientChannel.h" #include "qpid/client/Connection.h" @@ -59,38 +60,39 @@ public: } }; -int main(int argc, char**) +int main(int argc, char** argv) { - verbose = argc > 1; try { + qpid::TestOptions opts; + opts.parse(argc, argv); + //Use a custom exchange Exchange exchange("MyExchange", Exchange::TOPIC_EXCHANGE); //Use a named, temporary queue Queue queue("MyQueue", true); - Connection con(verbose); - string host("localhost"); - con.open(host, 5672, "guest", "guest", "/test"); - if (verbose) + Connection con(opts.trace); + con.open(opts.host, opts.port, opts.username, opts.password, opts.virtualhost); + if (opts.trace) std::cout << "Opened connection." << std::endl; //Create and open a channel on the connection through which //most functionality is exposed Channel channel; con.openChannel(channel); - if (verbose) std::cout << "Opened channel." << std::endl; + if (opts.trace) std::cout << "Opened channel." << std::endl; //'declare' the exchange and the queue, which will create them //as they don't exist channel.declareExchange(exchange); - if (verbose) std::cout << "Declared exchange." << std::endl; + if (opts.trace) std::cout << "Declared exchange." << std::endl; channel.declareQueue(queue); - if (verbose) std::cout << "Declared queue." << std::endl; + if (opts.trace) std::cout << "Declared queue." << std::endl; //now bind the queue to the exchange channel.bind(exchange, queue, "MyTopic"); - if (verbose) std::cout << "Bound queue to exchange." << std::endl; + if (opts.trace) std::cout << "Bound queue to exchange." << std::endl; //Set up a message listener to receive any messages that //arrive in our queue on the broker. We only expect one, and @@ -101,7 +103,7 @@ int main(int argc, char**) SimpleListener listener(&monitor); string tag("MyTag"); channel.consume(queue, tag, &listener); - if (verbose) std::cout << "Registered consumer." << std::endl; + if (opts.trace) std::cout << "Registered consumer." << std::endl; //we need to enable the message dispatching for this channel //and we want that to occur on another thread so we call @@ -114,7 +116,7 @@ int main(int argc, char**) string data("MyMessage"); msg.setData(data); channel.publish(msg, exchange, "MyTopic"); - if (verbose) std::cout << "Published message: " << data << std::endl; + if (opts.trace) std::cout << "Published message: " << data << std::endl; { Monitor::ScopedLock l(monitor); @@ -125,9 +127,9 @@ int main(int argc, char**) //close the channel & connection channel.close(); - if (verbose) std::cout << "Closed channel." << std::endl; + if (opts.trace) std::cout << "Closed channel." << std::endl; con.close(); - if (verbose) std::cout << "Closed connection." << std::endl; + if (opts.trace) std::cout << "Closed connection." << std::endl; return 0; } catch(const std::exception& e) { std::cout << e.what() << std::endl; diff --git a/cpp/src/tests/daemon_test b/cpp/src/tests/daemon_test deleted file mode 100755 index 6d1fc73923..0000000000 --- a/cpp/src/tests/daemon_test +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -# Without arguments run all daemon tests, exit status is number of failures. -# With arguments run just the test named by $1. -# - -TEMP=`mktemp` -qpidd="../qpidd --log.output qpidd.log" -client_tests=./client_test -trap 'rm -f $TEMP' 0 - -fail() { echo FAIL: $0:$* 1>&2; exit 1; } - -# Start and stop daemon on default port. -PID=`$qpidd --check` && fail $LINENO: qpidd already running pid=$PID -$qpidd -d || fail $LINENO: $qpidd -d failed -$qpidd -c >/dev/null || fail $LINENO: qpidd --check says qpidd did not start -./client_test > $TEMP || fail $LINENO: client_test: `cat $TEMP` -$qpidd -q || fail $LINENO: qpidd -q failed -$qpidd -c >/dev/null && fail $LINENO: Still running after quit. - -# Start and stop daemon on dynamic port. -export QPID_PORT=`$qpidd -dp0` -# Note: QPID_PORT fom environment will be used below here: -$qpidd -c >/dev/null || fail $LINENO: qpidd did not start. QPID_PORT=$QPID_PORT -$qpidd -q || fail $LINENO: qpidd -q failed. QPID_PORT=$QPID_PORT -$qpidd -c >/dev/null && fail $LINENO: Still running after start. QPID_PORT=$QPID_PORT - -# FIXME aconway 2007-06-11: run client test, needs a --port option. - - -true diff --git a/cpp/src/tests/interop_runner.cpp b/cpp/src/tests/interop_runner.cpp index 7d40eeedb1..7c47edafa0 100644 --- a/cpp/src/tests/interop_runner.cpp +++ b/cpp/src/tests/interop_runner.cpp @@ -19,7 +19,7 @@ * */ -#include "qpid/CommonOptions.h" +#include "qpid/Options.h" #include "qpid/Exception.h" #include "qpid/QpidError.h" #include "qpid/client/ClientChannel.h" @@ -47,13 +47,13 @@ using namespace qpid::sys; using qpid::TestCase; using qpid::TestOptions; using qpid::framing::FieldTable; -using std::string; +using namespace std; class DummyRun : public TestCase { public: DummyRun() {} - void assign(const std::string&, FieldTable&, TestOptions&) {} + void assign(const string&, FieldTable&, TestOptions&) {} void start() {} void stop() {} void report(qpid::client::Message&) {} @@ -64,7 +64,7 @@ string parse_next_word(const string& input, const string& delims, string::size_t /** */ class Listener : public MessageListener, private Runnable{ - typedef boost::ptr_map<std::string, TestCase> TestMap; + typedef boost::ptr_map<string, TestCase> TestMap; Channel& channel; TestOptions& options; @@ -72,7 +72,7 @@ class Listener : public MessageListener, private Runnable{ const string name; const string topic; TestMap::iterator test; - std::auto_ptr<Thread> runner; + auto_ptr<Thread> runner; string reportTo; string reportCorrelator; @@ -88,44 +88,41 @@ public: Listener(Channel& channel, TestOptions& options); void received(Message& msg); void bindAndConsume(); - void registerTest(std::string name, TestCase* test); + void registerTest(string name, TestCase* test); }; -/** - */ -int main(int argc, char** argv){ - TestOptions options; - options.parse(argc, argv); - - if (options.help) { - options.usage(); - } else { - try{ +int main(int argc, char** argv) { + try { + TestOptions options; + options.parse(argc, argv); + if (options.help) + cout << options; + else { Connection connection(options.trace); - connection.open(options.broker, options.port, "guest", "guest", options.virtualhost); + connection.open(options.host, options.port, "guest", "guest", options.virtualhost); - Channel channel; - connection.openChannel(channel); + Channel channel; + connection.openChannel(channel); - Listener listener(channel, options); - listener.registerTest("TC1_DummyRun", new DummyRun()); - listener.registerTest("TC2_BasicP2P", new qpid::BasicP2PTest()); - listener.registerTest("TC3_BasicPubSub", new qpid::BasicPubSubTest()); + Listener listener(channel, options); + listener.registerTest("TC1_DummyRun", new DummyRun()); + listener.registerTest("TC2_BasicP2P", new qpid::BasicP2PTest()); + listener.registerTest("TC3_BasicPubSub", new qpid::BasicPubSubTest()); - listener.bindAndConsume(); + listener.bindAndConsume(); - channel.run(); - connection.close(); - } catch(const std::exception& error) { - std::cout << error.what() << std::endl; + channel.run(); + connection.close(); } + } catch(const exception& error) { + cout << error.what() << endl << "Type " << argv[0] << " --help for help" << endl; } } Listener::Listener(Channel& _channel, TestOptions& _options) : channel(_channel), options(_options), name(options.clientid), topic("iop.control." + name) {} -void Listener::registerTest(std::string name, TestCase* test) +void Listener::registerTest(string name, TestCase* test) { tests.insert(name, test); } @@ -139,7 +136,7 @@ void Listener::bindAndConsume() channel.bind(Exchange::STANDARD_TOPIC_EXCHANGE, control, "iop.control", bindArgs); channel.bind(Exchange::STANDARD_TOPIC_EXCHANGE, control, topic, bindArgs); - std::string tag; + string tag; channel.consume(control, tag, this); } @@ -178,14 +175,14 @@ void Listener::sendResponse(Message& response, string replyTo) void Listener::received(Message& message) { - std::string type(message.getHeaders().getString("CONTROL_TYPE")); + string type(message.getHeaders().getString("CONTROL_TYPE")); if (type == "INVITE") { - std::string name(message.getHeaders().getString("TEST_NAME")); + string name(message.getHeaders().getString("TEST_NAME")); if (name.empty() || invite(name)) { sendSimpleResponse("ENLIST", message); } else { - std::cout << "Can't take part in '" << name << "'" << std::endl; + cout << "Can't take part in '" << name << "'" << endl; } } else if (type == "ASSIGN_ROLE") { test->assign(message.getHeaders().getString("ROLE"), message.getHeaders(), options); @@ -193,7 +190,7 @@ void Listener::received(Message& message) } else if (type == "START") { reportTo = message.getReplyTo(); reportCorrelator = message.getCorrelationId(); - runner = std::auto_ptr<Thread>(new Thread(this)); + runner = auto_ptr<Thread>(new Thread(this)); } else if (type == "STATUS_REQUEST") { reportTo = message.getReplyTo(); reportCorrelator = message.getCorrelationId(); @@ -203,7 +200,7 @@ void Listener::received(Message& message) if (test != tests.end()) test->stop(); shutdown(); } else { - std::cerr <<"ERROR!: Received unknown control message: " << type << std::endl; + cerr <<"ERROR!: Received unknown control message: " << type << endl; shutdown(); } } diff --git a/cpp/src/tests/kill_broker b/cpp/src/tests/kill_broker index e6331d6876..1887eee50d 100755 --- a/cpp/src/tests/kill_broker +++ b/cpp/src/tests/kill_broker @@ -1,2 +1,2 @@ #!/bin/sh -../qpidd --quit +QPID_PORT=`cat qpidd.port` ../qpidd --quit && rm -f qpidd.port diff --git a/cpp/src/tests/logging.cpp b/cpp/src/tests/logging.cpp index ebe8f4d6e8..f5402aaad7 100644 --- a/cpp/src/tests/logging.cpp +++ b/cpp/src/tests/logging.cpp @@ -22,7 +22,7 @@ #include "qpid/log/Logger.h" #include "qpid/log/Options.h" #include "qpid/memory.h" -#include "qpid/CommonOptions.h" +#include "qpid/Options.h" #include <boost/test/floating_point_comparison.hpp> #include <boost/format.hpp> #include <exception> @@ -255,14 +255,6 @@ Statement statement( } -struct TestOptions : public Options { - TestOptions(int argc, char** argv) { - qpid::po::options_description desc; - addTo(desc); - qpid::parseOptions(desc, argc, argv); - } -}; - #define ARGC(argv) (sizeof(argv)/sizeof(char*)) BOOST_AUTO_TEST_CASE(testOptionsParse) { @@ -278,7 +270,8 @@ BOOST_AUTO_TEST_CASE(testOptionsParse) { "--log.thread", "true", "--log.function", "YES" }; - TestOptions opts(ARGC(argv), argv); + qpid::log::Options opts; + opts.parse(ARGC(argv), argv); vector<string> expect=list_of("error+:foo")("debug:bar")("info"); BOOST_CHECK_EQUAL(expect, opts.selectors); expect=list_of("x")("y"); @@ -306,7 +299,8 @@ BOOST_AUTO_TEST_CASE(testSelectorFromOptions) { "--log.enable", "debug:bar", "--log.enable", "info" }; - TestOptions opts(ARGC(argv), argv); + qpid::log::Options opts; + opts.parse(ARGC(argv), argv); vector<string> expect=list_of("error+:foo")("debug:bar")("info"); BOOST_CHECK_EQUAL(expect, opts.selectors); Selector s(opts); @@ -319,37 +313,36 @@ BOOST_AUTO_TEST_CASE(testSelectorFromOptions) { BOOST_AUTO_TEST_CASE(testOptionsFormat) { Logger& l = clearLogger(); - Options opts; - BOOST_CHECK_EQUAL(Logger::TIME|Logger::LEVEL, l.format(opts)); - char* argv[]={ - 0, - "--log.time", "no", - "--log.level", "no", - "--log.source", "1", - "--log.thread", "1" - }; - qpid::po::options_description desc; - opts.addTo(desc); - qpid::parseOptions(desc, ARGC(argv), argv); - BOOST_CHECK_EQUAL( - Logger::FILE|Logger::LINE|Logger::THREAD, l.format(opts)); - opts = Options(); // Clear. - char* argv2[]={ - 0, - "--log.level", "no", - "--log.thread", "true", - "--log.function", "YES", - "--log.time", "YES" - }; - qpid::po::options_description desc2; - opts.addTo(desc2); - qpid::parseOptions(desc2, ARGC(argv2), argv2); - BOOST_CHECK_EQUAL( - Logger::THREAD|Logger::FUNCTION|Logger::TIME, - l.format(opts)); + { + Options opts; + BOOST_CHECK_EQUAL(Logger::TIME|Logger::LEVEL, l.format(opts)); + char* argv[]={ + 0, + "--log.time", "no", + "--log.level", "no", + "--log.source", "1", + "--log.thread", "1" + }; + opts.parse(ARGC(argv), argv); + BOOST_CHECK_EQUAL( + Logger::FILE|Logger::LINE|Logger::THREAD, l.format(opts)); + } + { + Options opts; // Clear. + char* argv[]={ + 0, + "--log.level", "no", + "--log.thread", "true", + "--log.function", "YES", + "--log.time", "YES" + }; + opts.parse(ARGC(argv), argv); + BOOST_CHECK_EQUAL( + Logger::THREAD|Logger::FUNCTION|Logger::TIME, + l.format(opts)); + } } - BOOST_AUTO_TEST_CASE(testLoggerConfigure) { Logger& l = clearLogger(); Options opts; @@ -360,9 +353,7 @@ BOOST_AUTO_TEST_CASE(testLoggerConfigure) { "--log.output", "logging.tmp", "--log.enable", "critical" }; - qpid::po::options_description desc; - opts.addTo(desc); - qpid::parseOptions(desc, ARGC(argv), argv); + opts.parse(ARGC(argv), argv); l.configure(opts, "test"); QPID_LOG(critical, "foo"); int srcline=__LINE__; ifstream log("logging.tmp"); diff --git a/cpp/src/tests/run_test b/cpp/src/tests/run_test index bfd6991481..deb22b4450 100755 --- a/cpp/src/tests/run_test +++ b/cpp/src/tests/run_test @@ -1,12 +1,15 @@ #!/bin/sh # -# Run a test executable. Output nothing if test passes, -# show the output if it fails. Leave output in <test>.log for -# examination. +# Set up environment and run a test executable or script. +# +# Output nothing if test passes, show the output if it fails and +# leave output in <test>.log for examination. +# +# If qpidd.port exists run test with QPID_PORT=`cat qpidd.port` # -# If $VALGRIND if is set run under valgrind. If there are -# valgrind erros show valgrind output, also leave it in -# <test>.valgrind for examination. +# If $VALGRIND if is set run under valgrind. If there are valgrind +# erros show valgrind output, also leave it in <test>.valgrind for +# examination. # vg_failed() { @@ -33,6 +36,9 @@ vg_check() # Export variables from makefile. export VALGRIND srcdir +# Export QPID_PORT if qpidd.port exists. +test -f qpidd.port && export QPID_PORT=`cat qpidd.port` + VG_LOG="$1.vglog" TEST_LOG="$1.log" rm -f $VG_LOG $TEST_LOG diff --git a/cpp/src/tests/start_broker b/cpp/src/tests/start_broker index 92a12e6e8a..b8a83fd5e3 100755 --- a/cpp/src/tests/start_broker +++ b/cpp/src/tests/start_broker @@ -1,5 +1,2 @@ #!/bin/sh -fail() { echo FAIL: $0:$* 1>&2; exit 1; } -qpidd=../qpidd -PID=`$qpidd --check` && fail $qpidd already running $PID -$qpidd --log.output qpidd.log --daemon || fail $qpidd startup: `cat qpidd.log` +../qpidd --daemon --port 0 --log.output qpidd.log > qpidd.port diff --git a/cpp/src/tests/topic_listener.cpp b/cpp/src/tests/topic_listener.cpp index 9fb3ee8371..cb6bafcd8e 100644 --- a/cpp/src/tests/topic_listener.cpp +++ b/cpp/src/tests/topic_listener.cpp @@ -33,6 +33,7 @@ */ #include "qpid/QpidError.h" +#include "TestOptions.h" #include "qpid/client/ClientChannel.h" #include "qpid/client/Connection.h" #include "qpid/client/ClientExchange.h" @@ -42,6 +43,7 @@ #include <iostream> #include <sstream> +using namespace qpid; using namespace qpid::client; using namespace qpid::sys; using namespace std; @@ -68,44 +70,35 @@ public: /** * A utility class for managing the options passed in. */ -class Args{ - string host; - int port; - AckMode ackMode; +struct Args : public qpid::TestOptions { + int ackmode; bool transactional; int prefetch; - bool trace; - bool help; -public: - inline Args() : host("localhost"), port(5672), ackMode(NO_ACK), transactional(false), prefetch(1000), trace(false), help(false){} - void parse(int argc, char** argv); - void usage(); - - const string& getHost() const { return host;} - int getPort() const { return port; } - AckMode getAckMode(){ return ackMode; } - bool getTransactional() const { return transactional; } - int getPrefetch(){ return prefetch; } - bool getTrace() const { return trace; } - bool getHelp() const { return help; } + Args() : ackmode(NO_ACK), transactional(false), prefetch(1000) { + addOptions() + ("ack", optValue(ackmode, "MODE"), "Ack mode: 0=NO_ACK, 1=AUTO_ACK, 2=LAZY_ACK") + ("transactional", optValue(transactional), "Use transactions") + ("prefetch", optValue(prefetch, "N"), "prefetch count"); + } }; + /** * The main routine creates a Listener instance and sets it up to * consume from a private queue bound to the exchange with the * appropriate topic name. */ int main(int argc, char** argv){ - Args args; - args.parse(argc, argv); - if(args.getHelp()){ - args.usage(); - }else{ - try{ + try{ + Args args; + args.parse(argc, argv); + if(args.help) + cout << args << endl; + else { cout << "topic_listener: Started." << endl; - Connection connection(args.getTrace()); - connection.open(args.getHost(), args.getPort(), "guest", "guest", "/test"); - Channel channel(args.getTransactional(), args.getPrefetch()); + Connection connection(args.trace); + connection.open(args.host, args.port, args.username, args.password, args.virtualhost); + Channel channel(args.transactional, args.prefetch); connection.openChannel(channel); //declare exchange, queue and bind them: @@ -117,17 +110,17 @@ int main(int argc, char** argv){ qpid::framing::FieldTable bindArgs; channel.bind(Exchange::STANDARD_TOPIC_EXCHANGE, control, "topic_control", bindArgs); //set up listener - Listener listener(&channel, response.getName(), args.getTransactional()); + Listener listener(&channel, response.getName(), args.transactional); string tag; - channel.consume(control, tag, &listener, args.getAckMode()); + channel.consume(control, tag, &listener, AckMode(args.ackmode)); cout << "topic_listener: Consuming." << endl; channel.run(); connection.close(); cout << "topic_listener: normal exit" << endl; - return 0; - }catch(const std::exception& error){ - cout << "topic_listener: " << error.what() << endl; } + return 0; + } catch (const std::exception& error) { + cout << "topic_listener: " << error.what() << endl; } return 1; } @@ -172,46 +165,3 @@ void Listener::report(){ } } - -void Args::parse(int argc, char** argv){ - for(int i = 1; i < argc; i++){ - string name(argv[i]); - if("-help" == name){ - help = true; - break; - }else if("-host" == name){ - host = argv[++i]; - }else if("-port" == name){ - port = atoi(argv[++i]); - }else if("-ack_mode" == name){ - ackMode = AckMode(atoi(argv[++i])); - }else if("-transactional" == name){ - transactional = true; - }else if("-prefetch" == name){ - prefetch = atoi(argv[++i]); - }else if("-trace" == name){ - trace = true; - }else{ - cout << "Warning: unrecognised option " << name << endl; - } - } -} - -void Args::usage(){ - cout << "Options:" << endl; - cout << " -help" << endl; - cout << " Prints this usage message" << endl; - cout << " -host <host>" << endl; - cout << " Specifies host to connect to (default is localhost)" << endl; - cout << " -port <port>" << endl; - cout << " Specifies port to conect to (default is 5762)" << endl; - cout << " -ack_mode <mode>" << endl; - cout << " Sets the acknowledgement mode" << endl; - cout << " 0=NO_ACK (default), 1=AUTO_ACK, 2=LAZY_ACK" << endl; - cout << " -transactional" << endl; - cout << " Indicates the client should use transactions" << endl; - cout << " -prefetch <count>" << endl; - cout << " Specifies the prefetch count (default is 1000)" << endl; - cout << " -trace" << endl; - cout << " Indicates that the frames sent and received should be logged" << endl; -} diff --git a/cpp/src/tests/topic_publisher.cpp b/cpp/src/tests/topic_publisher.cpp index 9384053e68..f792540c09 100644 --- a/cpp/src/tests/topic_publisher.cpp +++ b/cpp/src/tests/topic_publisher.cpp @@ -34,6 +34,7 @@ * subscriber shutdown. */ +#include "TestOptions.h" #include "qpid/QpidError.h" #include "qpid/client/ClientChannel.h" #include "qpid/client/Connection.h" @@ -46,9 +47,10 @@ #include <cstdlib> #include <iostream> +using namespace qpid; using namespace qpid::client; using namespace qpid::sys; -using std::string; +using namespace std; /** * The publishing logic is defined in this class. It implements @@ -57,7 +59,7 @@ using std::string; */ class Publisher : public MessageListener{ Channel* const channel; - const std::string controlTopic; + const string controlTopic; const bool transactional; Monitor monitor; int count; @@ -66,7 +68,7 @@ class Publisher : public MessageListener{ string generateData(int size); public: - Publisher(Channel* channel, const std::string& controlTopic, bool tx); + Publisher(Channel* channel, const string& controlTopic, bool tx); virtual void received(Message& msg); int64_t publish(int msgs, int listeners, int size); void terminate(); @@ -75,51 +77,42 @@ public: /** * A utility class for managing the options passed in to the test */ -class Args{ - string host; - int port; +struct Args : public TestOptions { int messages; int subscribers; - AckMode ackMode; + int ackmode; bool transactional; int prefetch; int batches; int delay; int size; - bool trace; - bool help; -public: - inline Args() : host("localhost"), port(5672), messages(1000), subscribers(1), - ackMode(NO_ACK), transactional(false), prefetch(1000), batches(1), - delay(0), size(256), trace(false), help(false){} - - void parse(int argc, char** argv); - void usage(); - const string& getHost() const { return host;} - int getPort() const { return port; } - int getMessages() const { return messages; } - int getSubscribers() const { return subscribers; } - AckMode getAckMode(){ return ackMode; } - bool getTransactional() const { return transactional; } - int getPrefetch(){ return prefetch; } - int getBatches(){ return batches; } - int getDelay(){ return delay; } - int getSize(){ return size; } - bool getTrace() const { return trace; } - bool getHelp() const { return help; } + Args() : messages(1000), subscribers(1), + ackmode(NO_ACK), transactional(false), prefetch(1000), + batches(1), delay(0), size(256) + { + addOptions() + ("messages", optValue(messages, "N"), "how many messages to send") + ("subscribers", optValue(subscribers, "N"), "how many subscribers to expect reports from") + ("ackmode", optValue(ackmode, "MODE"), "Acknowledgement mode:0=NO_ACK, 1=AUTO_ACK, 2=LAZY_ACK") + ("transactional", optValue(transactional), "client should use transactions") + ("prefetch", optValue(prefetch, "N"), "prefetch count") + ("batches", optValue(batches, "N"), "how many batches to run") + ("delay", optValue(delay, "SECONDS"), "Causes a delay between each batch") + ("size", optValue(size, "BYTES"), "size of the published messages"); + } }; int main(int argc, char** argv) { - Args args; - args.parse(argc, argv); - if(args.getHelp()){ - args.usage(); - } else { - try{ - Connection connection(args.getTrace()); - connection.open(args.getHost(), args.getPort(), "guest", "guest", "/test"); - Channel channel(args.getTransactional(), args.getPrefetch()); + try{ + Args args; + args.parse(argc, argv); + if(args.help) + cout << args << endl; + else { + Connection connection(args.trace); + connection.open(args.host, args.port, args.username, args.password, args.virtualhost); + Channel channel(args.transactional, args.prefetch); connection.openChannel(channel); //declare queue (relying on default binding): @@ -127,44 +120,44 @@ int main(int argc, char** argv) { channel.declareQueue(response); //set up listener - Publisher publisher(&channel, "topic_control", args.getTransactional()); - std::string tag("mytag"); - channel.consume(response, tag, &publisher, args.getAckMode()); + Publisher publisher(&channel, "topic_control", args.transactional); + string tag("mytag"); + channel.consume(response, tag, &publisher, AckMode(args.ackmode)); channel.start(); - int batchSize(args.getBatches()); + int batchSize(args.batches); int64_t max(0); int64_t min(0); int64_t sum(0); for(int i = 0; i < batchSize; i++){ - if(i > 0 && args.getDelay()) sleep(args.getDelay()); + if(i > 0 && args.delay) sleep(args.delay); int64_t msecs = - publisher.publish(args.getMessages(), - args.getSubscribers(), - args.getSize()) / TIME_MSEC; + publisher.publish(args.messages, + args.subscribers, + args.size) / TIME_MSEC; if(!max || msecs > max) max = msecs; if(!min || msecs < min) min = msecs; sum += msecs; - std::cout << "Completed " << (i+1) << " of " << batchSize - << " in " << msecs << "ms" << std::endl; + cout << "Completed " << (i+1) << " of " << batchSize + << " in " << msecs << "ms" << endl; } publisher.terminate(); int64_t avg = sum / batchSize; if(batchSize > 1){ - std::cout << batchSize << " batches completed. avg=" << avg << - ", max=" << max << ", min=" << min << std::endl; + cout << batchSize << " batches completed. avg=" << avg << + ", max=" << max << ", min=" << min << endl; } channel.close(); connection.close(); - return 0; - }catch(std::exception& error) { - std::cout << error.what() << std::endl; } + return 0; + }catch(exception& error) { + cout << error.what() << endl; } return 1; } -Publisher::Publisher(Channel* _channel, const std::string& _controlTopic, bool tx) : +Publisher::Publisher(Channel* _channel, const string& _controlTopic, bool tx) : channel(_channel), controlTopic(_controlTopic), transactional(tx){} void Publisher::received(Message& ){ @@ -223,65 +216,3 @@ void Publisher::terminate(){ } } -void Args::parse(int argc, char** argv){ - for(int i = 1; i < argc; i++){ - string name(argv[i]); - if("-help" == name){ - help = true; - break; - }else if("-host" == name){ - host = argv[++i]; - }else if("-port" == name){ - port = atoi(argv[++i]); - }else if("-messages" == name){ - messages = atoi(argv[++i]); - }else if("-subscribers" == name){ - subscribers = atoi(argv[++i]); - }else if("-ack_mode" == name){ - ackMode = AckMode(atoi(argv[++i])); - }else if("-transactional" == name){ - transactional = true; - }else if("-prefetch" == name){ - prefetch = atoi(argv[++i]); - }else if("-batches" == name){ - batches = atoi(argv[++i]); - }else if("-delay" == name){ - delay = atoi(argv[++i]); - }else if("-size" == name){ - size = atoi(argv[++i]); - }else if("-trace" == name){ - trace = true; - }else{ - std::cout << "Warning: unrecognised option " << name << std::endl; - } - } -} - -void Args::usage(){ - std::cout << "Options:" << std::endl; - std::cout << " -help" << std::endl; - std::cout << " Prints this usage message" << std::endl; - std::cout << " -host <host>" << std::endl; - std::cout << " Specifies host to connect to (default is localhost)" << std::endl; - std::cout << " -port <port>" << std::endl; - std::cout << " Specifies port to conect to (default is 5762)" << std::endl; - std::cout << " -messages <count>" << std::endl; - std::cout << " Specifies how many messages to send" << std::endl; - std::cout << " -subscribers <count>" << std::endl; - std::cout << " Specifies how many subscribers to expect reports from" << std::endl; - std::cout << " -ack_mode <mode>" << std::endl; - std::cout << " Sets the acknowledgement mode" << std::endl; - std::cout << " 0=NO_ACK (default), 1=AUTO_ACK, 2=LAZY_ACK" << std::endl; - std::cout << " -transactional" << std::endl; - std::cout << " Indicates the client should use transactions" << std::endl; - std::cout << " -prefetch <count>" << std::endl; - std::cout << " Specifies the prefetch count (default is 1000)" << std::endl; - std::cout << " -batches <count>" << std::endl; - std::cout << " Specifies how many batches to run" << std::endl; - std::cout << " -delay <seconds>" << std::endl; - std::cout << " Causes a delay between each batch" << std::endl; - std::cout << " -size <bytes>" << std::endl; - std::cout << " Sets the size of the published messages (default is 256 bytes)" << std::endl; - std::cout << " -trace" << std::endl; - std::cout << " Indicates that the frames sent and received should be logged" << std::endl; -} diff --git a/cpp/src/tests/topictest b/cpp/src/tests/topictest index 92e40b2c37..21387ac3bd 100755 --- a/cpp/src/tests/topictest +++ b/cpp/src/tests/topictest @@ -28,7 +28,7 @@ subscribe() { } publish() { - ./topic_publisher -messages $MESSAGES -batches $BATCHES -subscribers $SUBSCRIBERS + ./topic_publisher --messages $MESSAGES --batches $BATCHES --subscribers $SUBSCRIBERS } for ((i=$SUBSCRIBERS ; i--; )); do |