diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 000000000..af1189f2b --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,7 @@ +;;; Directory Local Variables +;;; For more information see (info "(emacs) Directory Variables") + +((c++-mode + (flycheck-clang-language-standard . "c++11") + (flycheck-gcc-language-standard . "c++11"))) + diff --git a/.travis.yml b/.travis.yml index 9577ab92e..53dec4aee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -73,6 +73,7 @@ before_install: - git clone https://github.com/rakshasa/libtorrent.git - | pushd libtorrent \ + && (git checkout ${TRAVIS_BRANCH} || true) \ && ./autogen.sh \ && CXX="$COMPILER" ./configure --prefix=/usr \ && make \ diff --git a/rak/file_stat.h b/rak/file_stat.h index 5ad45e8fd..f1ad8c2b2 100644 --- a/rak/file_stat.h +++ b/rak/file_stat.h @@ -38,7 +38,7 @@ #define RAK_FILE_STAT_H #include -#include +#include #include namespace rak { diff --git a/rak/fs_stat.h b/rak/fs_stat.h index 5e8442779..2d73ff1b2 100644 --- a/rak/fs_stat.h +++ b/rak/fs_stat.h @@ -38,7 +38,7 @@ #define RAK_FS_STAT_H #include -#include +#include #include diff --git a/rak/functional_fun.h b/rak/functional_fun.h index f793db53f..054290210 100644 --- a/rak/functional_fun.h +++ b/rak/functional_fun.h @@ -53,8 +53,7 @@ #include #include -#include lt_tr1_functional -#include lt_tr1_memory +#include namespace rak { diff --git a/rak/partial_queue.h b/rak/partial_queue.h index 6650a6339..1abfdddf2 100644 --- a/rak/partial_queue.h +++ b/rak/partial_queue.h @@ -39,7 +39,7 @@ #include #include -#include +#include namespace rak { diff --git a/rak/priority_queue_default.h b/rak/priority_queue_default.h index 01a0070e2..a7bba0ceb 100644 --- a/rak/priority_queue_default.h +++ b/rak/priority_queue_default.h @@ -37,7 +37,7 @@ #ifndef RAK_PRIORITY_QUEUE_DEFAULT_H #define RAK_PRIORITY_QUEUE_DEFAULT_H -#include lt_tr1_functional +#include #include #include #include diff --git a/rak/socket_address.h b/rak/socket_address.h index d1d5b7224..8eb601168 100644 --- a/rak/socket_address.h +++ b/rak/socket_address.h @@ -47,9 +47,12 @@ #ifndef RAK_SOCKET_ADDRESS_H #define RAK_SOCKET_ADDRESS_H +#include +#include #include -#include #include +#include + #include #include #include @@ -77,11 +80,13 @@ class socket_address { static const int pf_local = PF_UNIX; #endif + bool is_any() const; bool is_valid() const; bool is_bindable() const; bool is_address_any() const; - // Should we need to set AF_UNSPEC? + bool is_valid_inet_class() const { return family() == af_inet || family() == af_inet6; } + void clear() { std::memset(this, 0, sizeof(socket_address)); set_family(); } sa_family_t family() const { return m_sockaddr.sa_family; } @@ -93,6 +98,8 @@ class socket_address { std::string address_str() const; bool address_c_str(char* buf, socklen_t size) const; + std::string pretty_address_str() const; + // Attemts to set it as an inet, then an inet6 address. It will // never set anything but net addresses, no local/unix. bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); } @@ -119,6 +126,7 @@ class socket_address { // extranous bytes and ensure it does not go beyond the size of this // struct. void copy(const socket_address& src, size_t length); + void copy_sockaddr(const sockaddr* src); static socket_address* cast_from(sockaddr* sa) { return reinterpret_cast(sa); } static const socket_address* cast_from(const sockaddr* sa) { return reinterpret_cast(sa); } @@ -215,6 +223,8 @@ class socket_address_inet6 { void set_address_any() { set_port(0); set_address(in6addr_any); } + std::string pretty_address_str() const; + sa_family_t family() const { return m_sockaddr.sin6_family; } void set_family() { m_sockaddr.sin6_family = AF_INET6; } @@ -233,6 +243,18 @@ class socket_address_inet6 { struct sockaddr_in6 m_sockaddr; }; +inline bool +socket_address::is_any() const { + switch (family()) { + case af_inet: + return sa_inet()->is_any(); + case af_inet6: + return sa_inet6()->is_any(); + default: + return false; + } +} + inline bool socket_address::is_valid() const { switch (family()) { @@ -317,6 +339,21 @@ socket_address::address_c_str(char* buf, socklen_t size) const { } } +inline std::string +socket_address::pretty_address_str() const { + switch (family()) { + case af_inet: + return sa_inet()->address_str(); + case af_inet6: + return sa_inet6()->pretty_address_str(); + case af_unspec: + return std::string("unspec"); + default: + return std::string("invalid"); + } +} + + inline bool socket_address::set_address_c_str(const char* a) { if (sa_inet()->set_address_c_str(a)) { @@ -348,13 +385,16 @@ socket_address::length() const { inline void socket_address::copy(const socket_address& src, size_t length) { length = std::min(length, sizeof(socket_address)); - - // Does this get properly optimized? + std::memset(this, 0, sizeof(socket_address)); std::memcpy(this, &src, length); } -// Should we be able to compare af_unspec? +inline void +socket_address::copy_sockaddr(const sockaddr* src) { + std::memset(this, 0, sizeof(socket_address)); + std::memcpy(this, src, socket_address::cast_from(src)->length()); +} inline bool socket_address::operator == (const socket_address& rhs) const { @@ -456,6 +496,35 @@ socket_address_inet6::set_address_c_str(const char* a) { return inet_pton(AF_INET6, a, &m_sockaddr.sin6_addr); } +inline std::string +socket_address_inet6::pretty_address_str() const { + char buf[INET6_ADDRSTRLEN + 2 + 6]; + + if (inet_ntop(family(), &m_sockaddr.sin6_addr, buf + 1, INET6_ADDRSTRLEN) == NULL) + return std::string(); + + buf[0] = '['; + + char* last_char = (char*)std::memchr(buf + 1, 0, INET6_ADDRSTRLEN); + + // TODO: Throw exception here. + + if (last_char == NULL || last_char >= buf + 1 + INET6_ADDRSTRLEN) + throw std::logic_error("inet_ntop for inet6 returned bad buffer"); + + *(last_char++) = ']'; + + if (!is_port_any()) { + if (snprintf(last_char, 7, ":%" PRIu16, port()) == -1) + return std::string("error"); // TODO: Throw here. + + } else { + *last_char = '\0'; + } + + return std::string(buf); +} + inline socket_address socket_address_inet6::normalize_address() const { const uint32_t *addr32 = reinterpret_cast(m_sockaddr.sin6_addr.s6_addr); diff --git a/rak/timer.h b/rak/timer.h index e25ad2e6c..842a2e533 100644 --- a/rak/timer.h +++ b/rak/timer.h @@ -38,7 +38,7 @@ #define RAK_TIMER_H #include -#include +#include #include namespace rak { diff --git a/scripts/rak_cxx.m4 b/scripts/rak_cxx.m4 index 3660f3a75..0db61b838 100644 --- a/scripts/rak_cxx.m4 +++ b/scripts/rak_cxx.m4 @@ -12,50 +12,3 @@ AC_DEFUN([RAK_CHECK_CXX11], [ ] ) ]) - -AC_DEFUN([RAK_CHECK_TR1_LIB], [ - AC_LANG_PUSH(C++) - AC_MSG_CHECKING(should use TR1 headers) - - AC_COMPILE_IFELSE([AC_LANG_SOURCE([ - #include - class Foo; typedef std::unordered_map Bar; - Bar b1; - ]) - ], [ - AC_MSG_RESULT(no) - AC_DEFINE(USE_TR1_LIB, 0, Define to 1 if you need to use TR1 containers.) - - AC_DEFINE([lt_tr1_array], [], [TR1 array]) - AC_DEFINE([lt_tr1_functional], [], [TR1 functional]) - AC_DEFINE([lt_tr1_memory], [], [TR1 memory]) - AC_DEFINE([lt_tr1_unordered_map], [], [TR1 unordered_map]) - - ], [ - AC_COMPILE_IFELSE([AC_LANG_SOURCE([ - #include - class Foo; typedef std::tr1::unordered_map Bar; - Bar b1; - ]) - ], [ - AC_MSG_RESULT([yes]) - AC_DEFINE(USE_TR1_LIB, 1, Define to 1 if you need to use TR1 containers.) - - AC_DEFINE([lt_tr1_array], [], [TR1 array]) - AC_DEFINE([lt_tr1_functional], [], [TR1 functional]) - AC_DEFINE([lt_tr1_memory], [], [TR1 memory]) - AC_DEFINE([lt_tr1_unordered_map], [], [TR1 unordered_map]) - - ], [ - AC_MSG_ERROR([No support for C++11 standard library nor TR1 extensions found.]) - ]) - ]) - - AH_VERBATIM(lt_tr1_zzz, [ -#if USE_TR1_LIB == 1 -namespace std { namespace tr1 {} using namespace tr1; } -#endif -]) - - AC_LANG_POP(C++) -]) diff --git a/src/command_download.cc b/src/command_download.cc index 5806c667a..25db01e64 100644 --- a/src/command_download.cc +++ b/src/command_download.cc @@ -140,7 +140,7 @@ apply_d_change_link(core::Download* download, const torrent::Object::list_type& case 0: if (symlink(target.c_str(), link.c_str()) == -1){ lt_log_print(torrent::LOG_TORRENT_WARN, "create_link failed: %s", - rak::error_number::current().c_str()); + rak::error_number::current().c_str()); } break; @@ -324,7 +324,7 @@ struct call_add_d_peer_t { void operator() (const sockaddr* sa, int err) { if (sa == NULL) { - lt_log_print(torrent::LOG_CONNECTION_WARN, "Could not resolve hostname for added peer."); + lt_log_print(torrent::LOG_TORRENT_WARN, "could not resolve hostname for added peer"); } else { m_download->download()->add_peer(sa, m_port); } @@ -872,8 +872,10 @@ initialize_command_download() { CMD2_DL ("d.wanted_chunks", CMD2_ON_DATA(wanted_chunks)); - CMD2_DL_V ("d.tracker_announce", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, false)); - CMD2_DL_V ("d.tracker_announce.force", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, true)); + // Do not exposre d.tracker_announce.force to regular users. + CMD2_DL_V ("d.tracker_announce", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, false)); + CMD2_DL_V ("d.tracker_announce.force", std::bind(&torrent::Download::manual_request, CMD2_BIND_DL, true)); + CMD2_DL ("d.tracker_numwant", std::bind(&torrent::TrackerList::numwant, CMD2_BIND_TL)); CMD2_DL_VALUE_V ("d.tracker_numwant.set", std::bind(&torrent::TrackerList::set_numwant, CMD2_BIND_TL, std::placeholders::_2)); // TODO: Deprecate 'd.tracker_focus'. diff --git a/src/command_dynamic.cc b/src/command_dynamic.cc index a8d0ff02f..0a1f8e7b4 100644 --- a/src/command_dynamic.cc +++ b/src/command_dynamic.cc @@ -44,6 +44,30 @@ #include "control.h" #include "command_helpers.h" #include "rpc/parse.h" +#include "rpc/parse_options.h" + +static std::vector> object_storage_flags = { + { "multi", rpc::object_storage::flag_multi_type }, + { "simple", rpc::object_storage::flag_function_type }, + { "value", rpc::object_storage::flag_value_type }, + { "bool", rpc::object_storage::flag_bool_type }, + { "string", rpc::object_storage::flag_string_type }, + { "list", rpc::object_storage::flag_list_type }, + + { "static", rpc::object_storage::flag_static }, + { "private", rpc::object_storage::flag_private }, + { "const", rpc::object_storage::flag_constant }, + { "rlookup", rpc::object_storage::flag_rlookup } +}; + +static int +object_storage_parse_flag(const std::string& flag) { + for (auto f : object_storage_flags) + if (f.first == flag) + return f.second; + + throw torrent::input_error("unknown flag"); +} std::string system_method_generate_command(torrent::Object::list_const_iterator first, torrent::Object::list_const_iterator last) { @@ -263,87 +287,33 @@ system_method_insert(const torrent::Object::list_type& args) { throw torrent::input_error("Invalid key."); int flags = rpc::CommandMap::flag_delete_key | rpc::CommandMap::flag_modifiable | rpc::CommandMap::flag_public_xmlrpc; + int new_flags = rpc::parse_option_flags(itrArgs->as_string(), std::bind(&object_storage_parse_flag, std::placeholders::_1)); - const std::string& options = itrArgs->as_string(); - - // TODO: Replace find with a method that does '|' separated search - // for all valid options, and then cross-checks that unmixable ones - // aren't in there. Use a bitfield. - - if (options.find("private") != std::string::npos) + if ((new_flags & rpc::object_storage::flag_private)) flags &= ~rpc::CommandMap::flag_public_xmlrpc; - if (options.find("const") != std::string::npos) - flags &= ~rpc::CommandMap::flag_modifiable; - if (options.find("multi") != std::string::npos) { - torrent::Object::list_type new_args; - new_args.push_back(rawKey); - new_args.push_back(system_method_generate_command(++itrArgs, args.end())); - - int new_flags = rpc::object_storage::flag_multi_type; - - if (options.find("static") != std::string::npos) - new_flags |= rpc::object_storage::flag_static; - if (options.find("private") != std::string::npos) - new_flags |= rpc::object_storage::flag_private; - if (options.find("const") != std::string::npos) - new_flags |= rpc::object_storage::flag_constant; - if (options.find("rlookup") != std::string::npos) - new_flags |= rpc::object_storage::flag_rlookup; + if ((new_flags & rpc::object_storage::flag_constant)) + flags &= ~rpc::CommandMap::flag_modifiable; - return system_method_insert_object(new_args, new_flags); + torrent::Object::list_type new_args; + new_args.push_back(rawKey); - } else if (options.find("simple") != std::string::npos) { - torrent::Object::list_type new_args; - new_args.push_back(rawKey); + if ((new_flags & rpc::object_storage::flag_function_type) || + (new_flags & rpc::object_storage::flag_multi_type)) { new_args.push_back(system_method_generate_command(++itrArgs, args.end())); - int new_flags = rpc::object_storage::flag_function_type; - - if (options.find("static") != std::string::npos) - new_flags |= rpc::object_storage::flag_static; - if (options.find("private") != std::string::npos) - new_flags |= rpc::object_storage::flag_private; - if (options.find("const") != std::string::npos) - new_flags |= rpc::object_storage::flag_constant; - - return system_method_insert_object(new_args, new_flags); - - } else if (options.find("value") != std::string::npos || - options.find("bool") != std::string::npos || - options.find("string") != std::string::npos || - options.find("list") != std::string::npos) { - torrent::Object::list_type new_args; - new_args.push_back(rawKey); - + } else if ((new_flags & rpc::object_storage::flag_value_type) || + (new_flags & rpc::object_storage::flag_bool_type) || + (new_flags & rpc::object_storage::flag_string_type) || + (new_flags & rpc::object_storage::flag_list_type)) { if (++itrArgs != args.end()) new_args.insert(new_args.end(), itrArgs, args.end()); - int new_flags; - - if (options.find("value") != std::string::npos) - new_flags = rpc::object_storage::flag_value_type; - else if (options.find("bool") != std::string::npos) - new_flags = rpc::object_storage::flag_bool_type; - else if (options.find("string") != std::string::npos) - new_flags = rpc::object_storage::flag_string_type; - else if (options.find("list") != std::string::npos) - new_flags = rpc::object_storage::flag_list_type; - - if (options.find("static") != std::string::npos) - new_flags |= rpc::object_storage::flag_static; - if (options.find("private") != std::string::npos) - new_flags |= rpc::object_storage::flag_private; - if (options.find("const") != std::string::npos) - new_flags |= rpc::object_storage::flag_constant; - - return system_method_insert_object(new_args, new_flags); - } else { - // THROW. + throw torrent::input_error("No object type specified."); } - return torrent::Object(); + return system_method_insert_object(new_args, new_flags); } // method.erase <> {name} @@ -457,7 +427,7 @@ cmd_catch(rpc::target_type target, const torrent::Object& args) { void initialize_command_dynamic() { - CMD2_VAR_BOOL ("method.use_deprecated", false); + CMD2_VAR_BOOL ("method.use_deprecated", true); CMD2_VAR_VALUE ("method.use_intermediate", 1); CMD2_ANY_LIST ("method.insert", std::bind(&system_method_insert, std::placeholders::_2)); diff --git a/src/command_ip.cc b/src/command_ip.cc index b13db0a1e..e812709f5 100644 --- a/src/command_ip.cc +++ b/src/command_ip.cc @@ -286,7 +286,7 @@ ipv4_filter_parse(const char* address, int value) { inet_ntop(AF_INET, &net_start, start_str, INET_ADDRSTRLEN); inet_ntop(AF_INET, &net_end, end_str, INET_ADDRSTRLEN); - lt_log_print(torrent::LOG_CONNECTION_DEBUG, "Adding ip filter for %s-%s.", start_str, end_str); + lt_log_print(torrent::LOG_CONNECTION_FILTER, "Adding ip filter for %s-%s.", start_str, end_str); } } @@ -355,7 +355,7 @@ apply_ipv4_filter_load(const torrent::Object::list_type& args) { throw torrent::input_error(buffer); } - lt_log_print(torrent::LOG_CONNECTION_INFO, "Loaded %u %s address blocks (%u kb in-memory) from '%s'.", + lt_log_print(torrent::LOG_CONNECTION_FILTER, "loaded %u %s address blocks (%u kb in-memory) from '%s'", lineNumber, value_name.c_str(), torrent::PeerList::ipv4_filter()->sizeof_data() / 1024, diff --git a/src/command_local.cc b/src/command_local.cc index 553368af3..e26b9ebb7 100644 --- a/src/command_local.cc +++ b/src/command_local.cc @@ -195,7 +195,7 @@ file_print_list(torrent::Object::list_const_iterator first, torrent::Object::lis fprintf(output, (const char*)" %s" + !(flags & file_print_use_space), first->as_string().c_str()); break; case torrent::Object::TYPE_VALUE: - fprintf(output, (const char*)" %lli" + !(flags & file_print_use_space), first->as_value()); + fprintf(output, (const char*)" %" PRIi64 + !(flags & file_print_use_space), first->as_value()); break; case torrent::Object::TYPE_LIST: file_print_list(first->as_list().begin(), first->as_list().end(), output, 0); diff --git a/src/control.h b/src/control.h index 92a188931..023ecffc2 100644 --- a/src/control.h +++ b/src/control.h @@ -37,7 +37,7 @@ #ifndef RTORRENT_CONTROL_H #define RTORRENT_CONTROL_H -#include +#include #include #include #include diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc index b1bdd64b9..e096140cc 100644 --- a/src/core/download_factory.cc +++ b/src/core/download_factory.cc @@ -38,10 +38,11 @@ #include #include +#include #include #include + #include -#include lt_tr1_functional #include #include #include diff --git a/src/core/download_factory.h b/src/core/download_factory.h index 01695e882..c9c3491fa 100644 --- a/src/core/download_factory.h +++ b/src/core/download_factory.h @@ -41,10 +41,11 @@ #ifndef RTORRENT_CORE_DOWNLOAD_FACTORY_H #define RTORRENT_CORE_DOWNLOAD_FACTORY_H +#include #include + #include #include -#include lt_tr1_functional #include "http_queue.h" diff --git a/src/core/download_slot_map.h b/src/core/download_slot_map.h index 3fc04d5fb..ab48df640 100644 --- a/src/core/download_slot_map.h +++ b/src/core/download_slot_map.h @@ -37,9 +37,9 @@ #ifndef RTORRENT_CORE_DOWNLOAD_SLOT_MAP_H #define RTORRENT_CORE_DOWNLOAD_SLOT_MAP_H +#include #include #include -#include lt_tr1_functional #include "download.h" diff --git a/src/core/http_queue.h b/src/core/http_queue.h index 17ab95738..becb2152a 100644 --- a/src/core/http_queue.h +++ b/src/core/http_queue.h @@ -37,9 +37,9 @@ #ifndef RTORRENT_CORE_HTTP_QUEUE_H #define RTORRENT_CORE_HTTP_QUEUE_H -#include +#include #include -#include lt_tr1_functional +#include namespace core { diff --git a/src/core/manager.h b/src/core/manager.h index b5ce1a8c8..21833c1f4 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -1,43 +1,8 @@ -// rTorrent - BitTorrent client -// Copyright (C) 2005-2011, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - #ifndef RTORRENT_CORE_MANAGER_H #define RTORRENT_CORE_MANAGER_H #include +#include #include #include @@ -86,8 +51,8 @@ class Manager { View* hashing_view() { return m_hashingView; } void set_hashing_view(View* v); - torrent::log_buffer* log_important() { return m_log_important; } - torrent::log_buffer* log_complete() { return m_log_complete; } + torrent::log_buffer* log_important() { return m_log_important.get(); } + torrent::log_buffer* log_complete() { return m_log_complete.get(); } ThrottleMap& throttles() { return m_throttles; } torrent::ThrottlePair get_throttle(const std::string& name); @@ -155,8 +120,8 @@ class Manager { ThrottleMap m_throttles; AddressThrottleMap m_addressThrottles; - torrent::log_buffer* m_log_important; - torrent::log_buffer* m_log_complete; + torrent::log_buffer_ptr m_log_important; + torrent::log_buffer_ptr m_log_complete; }; // Meh, cleanup. diff --git a/src/core/view.h b/src/core/view.h index f69baac56..c6e3d0859 100644 --- a/src/core/view.h +++ b/src/core/view.h @@ -49,11 +49,12 @@ #ifndef RTORRENT_CORE_VIEW_DOWNLOADS_H #define RTORRENT_CORE_VIEW_DOWNLOADS_H +#include #include #include + #include #include -#include lt_tr1_functional #include "globals.h" diff --git a/src/display/frame.cc b/src/display/frame.cc index b9e47f97e..aa01d8334 100644 --- a/src/display/frame.cc +++ b/src/display/frame.cc @@ -38,7 +38,7 @@ #include #include -#include lt_tr1_functional + #include #include diff --git a/src/display/frame.h b/src/display/frame.h index 463729520..1e9362244 100644 --- a/src/display/frame.h +++ b/src/display/frame.h @@ -37,7 +37,7 @@ #ifndef RTORRENT_DISPLAY_FRAME_H #define RTORRENT_DISPLAY_FRAME_H -#include +#include namespace display { diff --git a/src/display/text_element.h b/src/display/text_element.h index 6ab3fdf3b..a24a479a2 100644 --- a/src/display/text_element.h +++ b/src/display/text_element.h @@ -37,8 +37,8 @@ #ifndef RTORRENT_DISPLAY_TEXT_ELEMENT_H #define RTORRENT_DISPLAY_TEXT_ELEMENT_H +#include #include -#include #include "display/canvas.h" #include "rpc/command_map.h" diff --git a/src/display/text_element_value.h b/src/display/text_element_value.h index c62be92fc..bf7e082c3 100644 --- a/src/display/text_element_value.h +++ b/src/display/text_element_value.h @@ -38,7 +38,6 @@ #define RTORRENT_DISPLAY_TEXT_ELEMENT_VALUE_H #include -#include #include "text_element.h" diff --git a/src/display/window_http_queue.h b/src/display/window_http_queue.h index 70223e0c9..59b20d85d 100644 --- a/src/display/window_http_queue.h +++ b/src/display/window_http_queue.h @@ -37,7 +37,7 @@ #ifndef RTORRENT_DISPLAY_WINDOW_HTTP_QUEUE_H #define RTORRENT_DISPLAY_WINDOW_HTTP_QUEUE_H -#include lt_tr1_functional +#include #include "window.h" diff --git a/src/display/window_statusbar.h b/src/display/window_statusbar.h index b4df3126e..9f1fa237b 100644 --- a/src/display/window_statusbar.h +++ b/src/display/window_statusbar.h @@ -37,7 +37,7 @@ #ifndef RTORRENT_DISPLAY_WINDOW_STATUSBAR_H #define RTORRENT_DISPLAY_WINDOW_STATUSBAR_H -#include +#include #include "window.h" diff --git a/src/input/bindings.h b/src/input/bindings.h index 30b9e1f61..8d53ab374 100644 --- a/src/input/bindings.h +++ b/src/input/bindings.h @@ -37,8 +37,8 @@ #ifndef RTORRENT_INPUT_BINDINGS_H #define RTORRENT_INPUT_BINDINGS_H +#include #include -#include lt_tr1_functional #include "display/attributes.h" diff --git a/src/input/input_event.h b/src/input/input_event.h index 25405bfe9..c82150c6a 100644 --- a/src/input/input_event.h +++ b/src/input/input_event.h @@ -37,9 +37,10 @@ #ifndef RTORRENT_INPUT_INPUT_EVENT_H #define RTORRENT_INPUT_INPUT_EVENT_H +#include + #include #include -#include lt_tr1_functional namespace input { diff --git a/src/input/path_input.h b/src/input/path_input.h index fe7e16532..11bbb8245 100644 --- a/src/input/path_input.h +++ b/src/input/path_input.h @@ -37,8 +37,8 @@ #ifndef RTORRENT_INPUT_PATH_INPUT_H #define RTORRENT_INPUT_PATH_INPUT_H +#include #include -#include lt_tr1_functional #include "utils/directory.h" #include "text_input.h" diff --git a/src/main.cc b/src/main.cc index 6be6a4dee..2ef96ebe1 100644 --- a/src/main.cc +++ b/src/main.cc @@ -81,6 +81,9 @@ #include "thread_worker.h" +#define LT_LOG(log_fmt, ...) \ + lt_log_print(torrent::LOG_SYSTEM, "system: " log_fmt, __VA_ARGS__); + void handle_sigbus(int signum, siginfo_t* sa, void* ptr); void do_panic(int signum); void print_help(); @@ -466,6 +469,8 @@ main(int argc, char** argv) { } } + LT_LOG("seeded srandom and srand48 (seed:%u)", random_seed); + control->initialize(); control->ui()->load_input_history(); @@ -668,7 +673,7 @@ print_help() { std::cout << " o View trackers" << std::endl; std::cout << std::endl; - std::cout << "Report bugs to ." << std::endl; + std::cout << "Report bugs to ." << std::endl; exit(0); } diff --git a/src/option_parser.h b/src/option_parser.h index 20504a6f8..5134dd52a 100644 --- a/src/option_parser.h +++ b/src/option_parser.h @@ -37,9 +37,9 @@ #ifndef RTORRENT_OPTION_PARSER_H #define RTORRENT_OPTION_PARSER_H +#include #include #include -#include lt_tr1_functional // Throws std::runtime_error upon receiving bad input. diff --git a/src/rpc/Makefile.am b/src/rpc/Makefile.am index 02ae61d96..a0df38783 100644 --- a/src/rpc/Makefile.am +++ b/src/rpc/Makefile.am @@ -20,6 +20,8 @@ libsub_rpc_a_SOURCES = \ parse.h \ parse_commands.cc \ parse_commands.h \ + parse_options.cc \ + parse_options.h \ scgi.cc \ scgi.h \ scgi_task.cc \ diff --git a/src/rpc/command.h b/src/rpc/command.h index dcd71030d..c1ac2f388 100644 --- a/src/rpc/command.h +++ b/src/rpc/command.h @@ -39,9 +39,7 @@ #include #include -#include #include -#include lt_tr1_functional #include #include diff --git a/src/rpc/command_scheduler.h b/src/rpc/command_scheduler.h index d2bcef209..75c43ea3c 100644 --- a/src/rpc/command_scheduler.h +++ b/src/rpc/command_scheduler.h @@ -37,9 +37,9 @@ #ifndef RTORRENT_COMMAND_SCHEDULER_H #define RTORRENT_COMMAND_SCHEDULER_H +#include #include #include -#include #include namespace torrent { diff --git a/src/rpc/command_scheduler_item.h b/src/rpc/command_scheduler_item.h index dfe2ab7ec..f0a96c713 100644 --- a/src/rpc/command_scheduler_item.h +++ b/src/rpc/command_scheduler_item.h @@ -39,7 +39,8 @@ #include "globals.h" -#include lt_tr1_functional +#include + #include namespace rpc { diff --git a/src/rpc/object_storage.h b/src/rpc/object_storage.h index f72bdbb5b..cabe7b3d5 100644 --- a/src/rpc/object_storage.h +++ b/src/rpc/object_storage.h @@ -42,7 +42,7 @@ #define RTORRENT_RPC_OBJECT_STORAGE_H #include -#include lt_tr1_unordered_map +#include #include #include "rak/unordered_vector.h" @@ -92,18 +92,18 @@ class object_storage : private object_storage_base_type { static const unsigned int flag_generic_type = 0x1; static const unsigned int flag_bool_type = 0x2; - static const unsigned int flag_value_type = 0x3; - static const unsigned int flag_string_type = 0x4; - static const unsigned int flag_list_type = 0x5; - static const unsigned int flag_function_type = 0x6; - static const unsigned int flag_multi_type = 0x7; - - static const unsigned int mask_type = 0xf; - - static const unsigned int flag_constant = 0x10; - static const unsigned int flag_static = 0x20; - static const unsigned int flag_private = 0x40; - static const unsigned int flag_rlookup = 0x80; + static const unsigned int flag_value_type = 0x4; + static const unsigned int flag_string_type = 0x8; + static const unsigned int flag_list_type = 0x10; + static const unsigned int flag_function_type = 0x20; + static const unsigned int flag_multi_type = 0x40; + + static const unsigned int mask_type = 0xff; + + static const unsigned int flag_constant = 0x100; + static const unsigned int flag_static = 0x200; + static const unsigned int flag_private = 0x400; + static const unsigned int flag_rlookup = 0x800; static const size_t key_size = key_type::max_size; diff --git a/src/rpc/parse_options.cc b/src/rpc/parse_options.cc new file mode 100644 index 000000000..4a63628a5 --- /dev/null +++ b/src/rpc/parse_options.cc @@ -0,0 +1,169 @@ +// rTorrent - BitTorrent client +// Copyright (C) 2005-2011, Jari Sundell +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// In addition, as a special exception, the copyright holders give +// permission to link the code of portions of this program with the +// OpenSSL library under certain conditions as described in each +// individual source file, and distribute linked combinations +// including the two. +// +// You must obey the GNU General Public License in all respects for +// all of the code used other than OpenSSL. If you modify file(s) +// with this exception, you may extend this exception to your version +// of the file(s), but you are not obligated to do so. If you do not +// wish to do so, delete this exception statement from your version. +// If you delete this exception statement from all source files in the +// program, then also delete it here. +// +// Contact: Jari Sundell +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +#include "parse_options.h" + +#include +#include +#include + +namespace rpc { + +int +parse_option_flag(const std::string& option, parse_option_flag_type ftor) { + auto first = option.begin(); + auto last = option.end(); + + first = std::find_if(first, last, [](char c) { return !std::isspace(c, std::locale::classic()); }); + + if (first == last) + throw torrent::input_error(option); + + auto next = std::find_if(first, last, [](char c) { return !std::isalnum(c, std::locale::classic()) && c != '_'; }); + + if (first == next) + throw torrent::input_error(option); + + if (std::find_if(next, last, [](char c) { return !std::isspace(c, std::locale::classic()); }) != last) + throw torrent::input_error(option); + + return ftor(std::string(first, next)); +} + +int +parse_option_flags(const std::string& option, parse_option_flag_type ftor, int flags) { + auto first = option.begin(); + auto last = option.end(); + + while (first != last) { + first = std::find_if(first, last, [](char c) { return !std::isspace(c, std::locale::classic()); }); + + if (first == last) + break; + + auto next = std::find_if(first, last, [](char c) { return !std::isalnum(c, std::locale::classic()) && c != '_'; }); + + if (first == next) + throw torrent::input_error(option); + + int f = ftor(std::string(first, next)); + + if (f < 0) + flags &= f; + else + flags |= f; + + first = std::find_if(next, last, [](char c) { return !std::isspace(c, std::locale::classic()); }); + + if (first == last) + break; + + if (*first++ != '|' || first == last) + throw torrent::input_error(option); + } + + return flags; +} + +void +parse_option_for_each(const std::string& option, parse_option_flag_type ftor) { + auto first = option.begin(); + auto last = option.end(); + + while (first != last) { + first = std::find_if(first, last, [](char c) { return !std::isspace(c, std::locale::classic()); }); + + if (first == last) + break; + + auto next = std::find_if(first, last, [](char c) { return !std::isalnum(c, std::locale::classic()) && c != '_'; }); + + if (first == next) + throw torrent::input_error(option); + + ftor(std::string(first, next)); + + first = std::find_if(next, last, [](char c) { return !std::isspace(c, std::locale::classic()); }); + + if (first == last) + break; + + if (*first++ != '|' || first == last) + throw torrent::input_error(option); + } +} + +std::string +parse_option_print_vector(int flags, const std::vector>& flag_list) { + std::string result; + + for (auto f : flag_list) { + if (f.second < 0) { + if ((flags & f.second) != flags) + continue; + } else { + if ((flags & f.second) != f.second) + continue; + } + + if (!result.empty()) + result += '|'; + + result += f.first; + } + + return result; +} + +std::string +parse_option_print_flags(unsigned int flags, parse_option_rflag_type ftor) { + std::string result; + + for (int i = 1; flags != 0; i <<= 1) { + if (!(flags & i)) + continue; + + if (!result.empty()) + result += '|'; + + result += ftor(i); + flags &= ~i; + } + + return result; +} + +} diff --git a/src/rpc/parse_options.h b/src/rpc/parse_options.h new file mode 100644 index 000000000..f3ba100af --- /dev/null +++ b/src/rpc/parse_options.h @@ -0,0 +1,63 @@ +// rTorrent - BitTorrent client +// Copyright (C) 2005-2011, Jari Sundell +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// In addition, as a special exception, the copyright holders give +// permission to link the code of portions of this program with the +// OpenSSL library under certain conditions as described in each +// individual source file, and distribute linked combinations +// including the two. +// +// You must obey the GNU General Public License in all respects for +// all of the code used other than OpenSSL. If you modify file(s) +// with this exception, you may extend this exception to your version +// of the file(s), but you are not obligated to do so. If you do not +// wish to do so, delete this exception statement from your version. +// If you delete this exception statement from all source files in the +// program, then also delete it here. +// +// Contact: Jari Sundell +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +#ifndef RTORRENT_RPC_PARSE_OPTIONS_H +#define RTORRENT_RPC_PARSE_OPTIONS_H + +#include +#include +#include +#include + +namespace rpc { + +// If a flag returned by the functor is negative it is treated as a +// negation of the flag. + +typedef std::function parse_option_flag_type; +typedef std::function parse_option_rflag_type; + +int parse_option_flag(const std::string& option, parse_option_flag_type ftor); +int parse_option_flags(const std::string& option, parse_option_flag_type ftor, int flags = int()); + +void parse_option_for_each(const std::string& option, parse_option_flag_type ftor); + +std::string parse_option_print_vector(int flags, const std::vector>& flag_list); +std::string parse_option_print_flags(unsigned int flags, parse_option_rflag_type ftor); + +} + +#endif diff --git a/src/rpc/xmlrpc.h b/src/rpc/xmlrpc.h index 72baaef77..c1e9f8879 100644 --- a/src/rpc/xmlrpc.h +++ b/src/rpc/xmlrpc.h @@ -37,7 +37,8 @@ #ifndef RTORRENT_RPC_XMLRPC_H #define RTORRENT_RPC_XMLRPC_H -#include lt_tr1_functional +#include + #include namespace core { diff --git a/src/signal_handler.h b/src/signal_handler.h index 36079595a..04f120c69 100644 --- a/src/signal_handler.h +++ b/src/signal_handler.h @@ -37,8 +37,8 @@ #ifndef RTORRENT_SIGNAL_HANDLER_H #define RTORRENT_SIGNAL_HANDLER_H +#include #include -#include lt_tr1_functional class SignalHandler { public: diff --git a/src/ui/root.h b/src/ui/root.h index 5dd669b2a..e69503228 100644 --- a/src/ui/root.h +++ b/src/ui/root.h @@ -37,7 +37,7 @@ #ifndef RTORRENT_UI_ROOT_H #define RTORRENT_UI_ROOT_H -#include +#include #include "input/bindings.h" #include "download_list.h" diff --git a/src/utils/directory.h b/src/utils/directory.h index ec8027b07..8bd4a29d2 100644 --- a/src/utils/directory.h +++ b/src/utils/directory.h @@ -37,9 +37,9 @@ #ifndef RTORRENT_UTILS_DIRECTORY_H #define RTORRENT_UTILS_DIRECTORY_H +#include #include #include -#include namespace utils { diff --git a/src/utils/list_focus.h b/src/utils/list_focus.h index d60e7d14a..c80d0f7d0 100644 --- a/src/utils/list_focus.h +++ b/src/utils/list_focus.h @@ -37,7 +37,7 @@ #ifndef RTORRENT_UTILS_LIST_FOCUS_H #define RTORRENT_UTILS_LIST_FOCUS_H -#include lt_tr1_functional +#include namespace utils { diff --git a/test/Makefile.am b/test/Makefile.am index fc488d99a..9df024c9d 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -20,6 +20,8 @@ rtorrentTest_SOURCES = \ rpc/command_slot_test.h \ rpc/object_storage_test.cc \ rpc/object_storage_test.h \ + rpc/test_parse_options.cc \ + rpc/test_parse_options.h \ src/command_dynamic_test.cc \ src/command_dynamic_test.h \ main.cc diff --git a/test/helpers/assert.h b/test/helpers/assert.h new file mode 100644 index 000000000..e2cfa3329 --- /dev/null +++ b/test/helpers/assert.h @@ -0,0 +1,7 @@ +#ifndef HELPERS_ASSERT_H +#define HELPERS_ASSERT_H + +#define ASSERT_CATCH_INPUT_ERROR(some_code) \ + try { some_code; CPPUNIT_ASSERT("torrent::input_error not caught" && false); } catch (torrent::input_error& e) { } + +#endif diff --git a/test/rpc/object_storage_test.cc b/test/rpc/object_storage_test.cc index cf5804049..c58666f07 100644 --- a/test/rpc/object_storage_test.cc +++ b/test/rpc/object_storage_test.cc @@ -1,12 +1,10 @@ #include "config.h" #include "object_storage_test.h" +#include "helpers/assert.h" CPPUNIT_TEST_SUITE_REGISTRATION(ObjectStorageTest); -#define ASSERT_CATCH_INPUT_ERROR(some_code) \ - try { some_code; CPPUNIT_ASSERT("torrent::input_error not caught" && false); } catch (torrent::input_error& e) { } - void ObjectStorageTest::test_basics() { rpc::object_storage::iterator itr; diff --git a/test/rpc/test_parse_options.cc b/test/rpc/test_parse_options.cc new file mode 100644 index 000000000..6f7ce289a --- /dev/null +++ b/test/rpc/test_parse_options.cc @@ -0,0 +1,189 @@ +#include "config.h" + +#include "test_parse_options.h" + +#include "helpers/assert.h" + +#include +#include +#include +#include +#include + +#include "rpc/parse_options.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(TestParseOptions); + +static const int flag_1 = 1 << 0; +static const int flag_2 = 1 << 1; +static const int flag_3 = 1 << 2; +static const int flag_4 = 1 << 3; +static const int flag_5 = 1 << 4; +static const int flag_6 = 1 << 5; + +static std::vector> flag_list = { + { "foo", flag_1 }, + { "bar", flag_2 }, + { "baz", flag_3 }, + { "a12", flag_4 }, + { "not_bar", ~flag_2 }, + { "45b", flag_5 }, + { "a_b_c__e_3_g", flag_6 }, + { "not_a12", ~flag_4 }, +}; + +static int +flag_to_int(const std::string& flag) { + for (auto f : flag_list) + if (f.first == flag) + return f.second; + + throw torrent::input_error("unknown flag"); +} + +const char* +int_to_flag(int flag) { + for (auto f : flag_list) { + if (f.second == flag) + return f.first; + } + + throw torrent::input_error("unknown flag"); +} + +#define FLAG_ASSERT(flags, result) \ + CPPUNIT_ASSERT(rpc::parse_option_flag(flags, std::bind(&flag_to_int, std::placeholders::_1)) == (result)) + +#define FLAGS_ASSERT(flags, result) \ + CPPUNIT_ASSERT(rpc::parse_option_flags(flags, std::bind(&flag_to_int, std::placeholders::_1)) == (result)) + +#define FLAGS_ASSERT_VALUE(flags, value, result) \ + CPPUNIT_ASSERT(rpc::parse_option_flags(flags, std::bind(&flag_to_int, std::placeholders::_1), value) == (result)) + +#define FLAG_ASSERT_ERROR(flags) \ + ASSERT_CATCH_INPUT_ERROR( { rpc::parse_option_flag(flags, std::bind(&flag_to_int, std::placeholders::_1)); } ) + +#define FLAGS_ASSERT_ERROR(flags) \ + ASSERT_CATCH_INPUT_ERROR( { rpc::parse_option_flags(flags, std::bind(&flag_to_int, std::placeholders::_1)); } ) + +#define FLAGS_ASSERT_VALUE_ERROR(flags, value) \ + ASSERT_CATCH_INPUT_ERROR( { rpc::parse_option_flags(flags, std::bind(&flag_to_int, std::placeholders::_1), value); } ) + +void +TestParseOptions::test_flag_basic() { + FLAG_ASSERT("foo", flag_1); + + FLAG_ASSERT(" foo ", flag_1); + FLAG_ASSERT(" foo ", flag_1); + + FLAG_ASSERT("a12", flag_4); + FLAG_ASSERT("45b", flag_5); + FLAG_ASSERT("a_b_c__e_3_g", flag_6); +} + +void +TestParseOptions::test_flag_error() { + FLAG_ASSERT_ERROR(""); + FLAG_ASSERT_ERROR("foo|bar"); + FLAG_ASSERT_ERROR("foo|bar|baz"); + + FLAG_ASSERT_ERROR("foo |bar"); + FLAG_ASSERT_ERROR("foo | bar| baz"); +} + +void +TestParseOptions::test_flags_basic() { + FLAGS_ASSERT("", 0); + FLAGS_ASSERT("foo", flag_1); + FLAGS_ASSERT("foo|bar", flag_1 | flag_2); + FLAGS_ASSERT("foo|bar|baz", flag_1 | flag_2 | flag_3); + + FLAGS_ASSERT(" foo ", flag_1); + FLAGS_ASSERT(" foo ", flag_1); + FLAGS_ASSERT("foo |bar", flag_1 | flag_2); + FLAGS_ASSERT("foo | bar| baz", flag_1 | flag_2 | flag_3); + + FLAGS_ASSERT("a12", flag_4); + FLAGS_ASSERT("45b", flag_5); + FLAGS_ASSERT("a_b_c__e_3_g", flag_6); +} + +void +TestParseOptions::test_flags_error() { + FLAGS_ASSERT_ERROR("fooa"); + FLAGS_ASSERT_ERROR("afoo"); + + FLAGS_ASSERT_ERROR("|"); + FLAGS_ASSERT_ERROR("foo|"); + FLAGS_ASSERT_ERROR("|foo"); + FLAGS_ASSERT_ERROR(",foo"); +} + +void +TestParseOptions::test_flags_complex() { + FLAGS_ASSERT_VALUE("", 0, 0); + FLAGS_ASSERT_VALUE("", flag_1, flag_1); + FLAGS_ASSERT_VALUE("bar", flag_1, flag_1 | flag_2); + FLAGS_ASSERT_VALUE("bar|baz", flag_1, flag_1 | flag_2 | flag_3); + + FLAGS_ASSERT_VALUE("not_bar", flag_2, 0); + FLAGS_ASSERT_VALUE("not_bar|not_a12", flag_2, 0); + + FLAGS_ASSERT_VALUE("bar|not_a12", flag_3 | flag_4, flag_2 | flag_3); +} + +#define FLAGS_ASSERT_PRINT(value, result) \ + CPPUNIT_ASSERT(rpc::parse_option_print_vector(value, flag_list) == (result)); +#define FLAGS_ASSERT_PRINT_FLAGS(value, result) \ + CPPUNIT_ASSERT(rpc::parse_option_print_flags(value, std::bind(&int_to_flag, std::placeholders::_1)) == (result)); +#define FLAGS_ASSERT_ERROR_PRINT_FLAGS(value) \ + ASSERT_CATCH_INPUT_ERROR({ rpc::parse_option_print_flags(value, std::bind(&int_to_flag, std::placeholders::_1)); }); + +void +TestParseOptions::test_flags_print_vector() { + FLAGS_ASSERT_PRINT(0, "not_bar|not_a12"); + FLAGS_ASSERT_PRINT(flag_2, "bar|not_a12"); + FLAGS_ASSERT_PRINT(flag_2 | flag_4, "bar|a12"); + FLAGS_ASSERT_PRINT(flag_1, "foo|not_bar|not_a12"); +} + +void +TestParseOptions::test_flags_print_flags() { + FLAGS_ASSERT_PRINT_FLAGS(0, ""); + FLAGS_ASSERT_PRINT_FLAGS(flag_1, "foo"); + FLAGS_ASSERT_PRINT_FLAGS(flag_1 | flag_2, "foo|bar"); + FLAGS_ASSERT_PRINT_FLAGS(flag_1 | flag_2 | flag_3, "foo|bar|baz"); + + FLAGS_ASSERT_ERROR_PRINT_FLAGS(100); + // Test int min. +} + +#define FLAG_LT_LOG_ASSERT(flags, result) \ + CPPUNIT_ASSERT(rpc::parse_option_flag(flags, std::bind(&torrent::option_find_string_str, torrent::OPTION_LOG_GROUP, std::placeholders::_1)) == (result)) + +#define FLAG_LT_LOG_ASSERT_ERROR(flags) \ + ASSERT_CATCH_INPUT_ERROR(rpc::parse_option_flag(flags, std::bind(&torrent::option_find_string_str, torrent::OPTION_LOG_GROUP, std::placeholders::_1))) + +void +TestParseOptions::test_flag_libtorrent() { + FLAG_LT_LOG_ASSERT("resume_data", torrent::LOG_RESUME_DATA); + + FLAG_LT_LOG_ASSERT_ERROR("resume_data|rpc_dump"); +} + +#define FLAGS_LT_ENCRYPTION_ASSERT(flags, result) \ + CPPUNIT_ASSERT(rpc::parse_option_flags(flags, std::bind(&torrent::option_find_string_str, torrent::OPTION_ENCRYPTION, std::placeholders::_1)) == (result)) + +#define FLAGS_LT_ENCRYPTION_ASSERT_ERROR(flags) \ + ASSERT_CATCH_INPUT_ERROR(rpc::parse_option_flags(flags, std::bind(&torrent::option_find_string_str, torrent::OPTION_ENCRYPTION, std::placeholders::_1))) + +void +TestParseOptions::test_flags_libtorrent() { + FLAGS_LT_ENCRYPTION_ASSERT("", torrent::ConnectionManager::encryption_none); + FLAGS_LT_ENCRYPTION_ASSERT("none", torrent::ConnectionManager::encryption_none); + FLAGS_LT_ENCRYPTION_ASSERT("require_rc4", torrent::ConnectionManager::encryption_require_RC4); + FLAGS_LT_ENCRYPTION_ASSERT("require_RC4", torrent::ConnectionManager::encryption_require_RC4); + FLAGS_LT_ENCRYPTION_ASSERT("require_RC4 | enable_retry", torrent::ConnectionManager::encryption_require_RC4 | torrent::ConnectionManager::encryption_enable_retry); + + FLAGS_LT_ENCRYPTION_ASSERT_ERROR("require_"); +} diff --git a/test/rpc/test_parse_options.h b/test/rpc/test_parse_options.h new file mode 100644 index 000000000..e0f14562a --- /dev/null +++ b/test/rpc/test_parse_options.h @@ -0,0 +1,35 @@ +#include + +class TestParseOptions : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(TestParseOptions); + CPPUNIT_TEST(test_flag_basic); + CPPUNIT_TEST(test_flag_error); + + CPPUNIT_TEST(test_flags_basic); + CPPUNIT_TEST(test_flags_error); + CPPUNIT_TEST(test_flags_complex); + + CPPUNIT_TEST(test_flags_print_vector); + CPPUNIT_TEST(test_flags_print_flags); + + CPPUNIT_TEST(test_flag_libtorrent); + CPPUNIT_TEST(test_flags_libtorrent); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp() { } + void tearDown() {} + + void test_flag_basic(); + void test_flag_error(); + + void test_flags_basic(); + void test_flags_error(); + void test_flags_complex(); + + void test_flags_print_vector(); + void test_flags_print_flags(); + + void test_flag_libtorrent(); + void test_flags_libtorrent(); +}; diff --git a/test/src/command_dynamic_test.cc b/test/src/command_dynamic_test.cc index 377141ef6..c13d701df 100644 --- a/test/src/command_dynamic_test.cc +++ b/test/src/command_dynamic_test.cc @@ -4,15 +4,14 @@ #include "command_dynamic_test.h" +#include "helpers/assert.h" + #include "rpc/parse_commands.h" #include "control.h" #include "globals.h" CPPUNIT_TEST_SUITE_REGISTRATION(CommandDynamicTest); -#define ASSERT_CATCH_INPUT_ERROR(some_code) \ - try { some_code; CPPUNIT_ASSERT("torrent::input_error not caught" && false); } catch (torrent::input_error& e) { } - void initialize_command_dynamic(); void initialize_command_ui();