Added system.files.advise_random.set command.

This commit is contained in:
Jari Sundell
2025-03-28 11:21:25 +01:00
committed by GitHub
parent 9a2ce2b231
commit 3a227c190f
14 changed files with 348 additions and 105 deletions
+1 -1
View File
@@ -370,7 +370,7 @@ f_multicall(core::Download* download, const torrent::Object::list_type& args) {
for (torrent::Object::list_const_iterator cItr = ++args.begin(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
row.push_back(rpc::parse_command(rpc::make_target(*itr), cmd.c_str(), cmd.c_str() + cmd.size()).first);
row.push_back(rpc::parse_command(rpc::make_target(itr->get()), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
+4 -36
View File
@@ -1,39 +1,3 @@
// 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 <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <fcntl.h>
@@ -242,6 +206,7 @@ initialize_command_local() {
CMD2_VAR_C_STRING("system.api_version", (int64_t)API_VERSION);
CMD2_VAR_C_STRING("system.client_version", PACKAGE_VERSION);
CMD2_VAR_C_STRING("system.library_version", torrent::version());
CMD2_VAR_VALUE ("system.file.allocate", 0);
CMD2_VAR_VALUE ("system.file.max_size", (int64_t)512 << 30);
CMD2_VAR_VALUE ("system.file.split_size", -1);
@@ -255,6 +220,9 @@ initialize_command_local() {
CMD2_VAR_LIST ("file.prioritize_toc.first");
CMD2_VAR_LIST ("file.prioritize_toc.last");
CMD2_ANY ("system.files.advise_random", std::bind(&FM_t::advise_random, fileManager));
CMD2_ANY_VALUE_V ("system.files.advise_random.set", std::bind(&FM_t::set_advise_random, fileManager, std::placeholders::_2));
CMD2_ANY ("system.files.opened_counter", std::bind(&FM_t::files_opened_counter, fileManager));
CMD2_ANY ("system.files.closed_counter", std::bind(&FM_t::files_closed_counter, fileManager));
CMD2_ANY ("system.files.failed_counter", std::bind(&FM_t::files_failed_counter, fileManager));
+1 -1
View File
@@ -69,7 +69,7 @@ initialize_rpc() {
if (index >= d->file_list()->size_files())
throw torrent::input_error("invalid parameters: index not found");
return (*d->file_list())[index];
return (*d->file_list())[index].get();
};
rpc::rpc.slot_find_tracker() = [](core::Download* d, uint32_t index) -> torrent::tracker::Tracker {
if (index >= d->tracker_list()->size())
-1
View File
@@ -101,7 +101,6 @@ WindowDownloadList::redraw() {
m_canvas->set_attr(0, 0, -1, RCOLOR_TITLE);
int layout_height;
const std::string layout_name = rpc::call_command_string("ui.torrent_list.layout");
typedef std::pair<core::View::iterator, core::View::iterator> Range;
+3 -39
View File
@@ -1,39 +1,3 @@
// 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 <jaris@ifi.uio.no>
//
// Skomakerveien 33
// 3185 Skoppum, NORWAY
#include "config.h"
#include <locale>
@@ -172,13 +136,13 @@ WindowFileList::redraw() {
} else if (itr.is_entering()) {
m_canvas->print(0, pos, "%*c %ls", 16 + itr.depth(), '\\',
itr.depth() < (*itr)->path()->size() ? wstring_width((*itr)->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
itr.depth() < itr.file()->path()->size() ? wstring_width(itr.file()->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
} else if (itr.is_leaving()) {
m_canvas->print(0, pos, "%*c %-*s", 16 + (itr.depth() - 1), '/', filenameWidth - (itr.depth() - 1), "");
} else if (itr.is_file()) {
torrent::File* e = *itr;
torrent::File* e = itr.file();
const char* priority;
@@ -203,7 +167,7 @@ WindowFileList::redraw() {
m_canvas->print(8, pos, "%5.1f T", (double)val / (int64_t(1) << 40));
m_canvas->print(15, pos, "%*c %ls", 1 + itr.depth(), '|',
itr.depth() < (*itr)->path()->size() ? wstring_width((*itr)->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
itr.depth() < itr.file()->path()->size() ? wstring_width(itr.file()->path()->at(itr.depth()), filenameWidth - itr.depth() - 1).c_str() : L"UNKNOWN");
} else {
m_canvas->print(0, pos, "BORK BORK");
+27 -7
View File
@@ -1,10 +1,25 @@
TESTS = rtorrentTest
TESTS = \
rtorrent_Test_Rpc \
rtorrent_Test_Src
check_PROGRAMS = $(TESTS)
rtorrentTest_LDADD = ../src/libsub_root.a
rtorrentTest_SOURCES = \
rtorrent_Test_LDADD = \
../src/libsub_root.a
rtorrent_Test_Rpc_LDADD = $(rtorrent_Test_LDADD)
rtorrent_Test_Src_LDADD = $(rtorrent_Test_LDADD)
rtorrent_Test_Common = \
main.cc \
\
helpers/assert.h \
helpers/progress_listener.cc \
helpers/progress_listener.h \
helpers/protectors.cc \
helpers/protectors.h
rtorrent_Test_Rpc_SOURCES = $(rtorrent_Test_Common) \
rpc/command_test.cc \
rpc/command_test.h \
rpc/command_map_test.cc \
@@ -20,10 +35,15 @@ rtorrentTest_SOURCES = \
rpc/test_parse_options.cc \
rpc/test_parse_options.h \
src/command_dynamic_test.cc \
src/command_dynamic_test.h \
main.cc
src/command_dynamic_test.h
rtorrentTest_CXXFLAGS = $(CPPUNIT_CFLAGS)
rtorrentTest_LDFLAGS = $(CPPUNIT_LIBS) -ldl
rtorrent_Test_Src_SOURCES = $(rtorrent_Test_Common) \
src/command_dynamic_test.cc \
src/command_dynamic_test.h
rtorrent_Test_Rpc_CXXFLAGS = $(CPPUNIT_CFLAGS)
rtorrent_Test_Rpc_LDFLAGS = $(CPPUNIT_LIBS) -ldl
rtorrent_Test_Src_CXXFLAGS = $(CPPUNIT_CFLAGS)
rtorrent_Test_Src_LDFLAGS = $(CPPUNIT_LIBS) -ldl
AM_CPPFLAGS = -I$(srcdir) -I$(top_srcdir) -I$(top_srcdir)/src
+64
View File
@@ -0,0 +1,64 @@
#include "config.h"
#include "progress_listener.h"
#include <algorithm>
#include <iostream>
#include <iterator>
#include <numeric>
#include <stdexcept>
#include "torrent/utils/log.h"
#include "torrent/utils/log_buffer.h"
static std::string
get_test_path(const test_list_type& tl) {
if (tl.size() < 2)
return "";
return std::accumulate(std::next(tl.begin()), std::prev(tl.end()), std::string(), [](std::string result, CppUnit::Test* test) {
return std::move(result) + test->getName() + "::";
});
}
void
progress_listener::startTest(CppUnit::Test *test) {
std::cout << get_test_path(m_test_path) << test->getName() << std::flush;
torrent::log_cleanup();
m_last_test_failed = false;
m_current_log_buffer = torrent::log_open_log_buffer("test_output");
}
void
progress_listener::addFailure(const CppUnit::TestFailure &failure) {
// AddFailure is called for parent test suits, so only deal with leafs.
if (m_current_log_buffer == nullptr)
return;
std::cout << " : " << (failure.isError() ? "error" : "assertion") << std::flush;
m_last_test_failed = true;
m_failures.push_back(failure_type{ failure.failedTestName(), std::move(m_current_log_buffer) });
}
void
progress_listener::endTest(CppUnit::Test *test) {
std::cout << (m_last_test_failed ? "" : " : OK") << std::endl;
m_current_log_buffer.reset();
torrent::log_cleanup();
}
void
progress_listener::startSuite(CppUnit::Test *suite) {
m_test_path.push_back(suite);
if (suite->countTestCases() > 0)
std::cout << std::endl << get_test_path(m_test_path) << suite->getName() << ":" << std::endl;
}
void
progress_listener::endSuite(CppUnit::Test *suite) {
m_test_path.pop_back();
}
+47
View File
@@ -0,0 +1,47 @@
#include <memory>
#include <vector>
#include <cppunit/Test.h>
#include <cppunit/TestFailure.h>
#include <cppunit/TestListener.h>
#include "torrent/utils/log_buffer.h"
struct failure_type {
std::string name;
torrent::log_buffer_ptr log;
};
typedef std::unique_ptr<CppUnit::TestFailure> test_failure_ptr;
typedef std::vector<CppUnit::Test*> test_list_type;
typedef std::vector<failure_type> failure_list_type;
class progress_listener : public CppUnit::TestListener {
public:
progress_listener() : m_last_test_failed(false) {}
void startTest(CppUnit::Test *test) override;
void addFailure(const CppUnit::TestFailure &failure) override;
void endTest(CppUnit::Test *test) override;
void startSuite(CppUnit::Test *suite) override;
void endSuite(CppUnit::Test *suite) override;
//Called by a TestRunner before running the test.
// void startTestRun(CppUnit::Test *test, CppUnit::TestResult *event_manager) override;
// Called by a TestRunner after running the test.
// void endTestRun(CppUnit::Test *test, CppUnit::TestResult *event_manager) override;
const failure_list_type& failures() { return m_failures; }
failure_list_type&& move_failures() { return std::move(m_failures); }
private:
progress_listener(const progress_listener& rhs) = delete;
void operator =(const progress_listener& rhs) = delete;
test_list_type m_test_path;
failure_list_type m_failures;
bool m_last_test_failed;
torrent::log_buffer_ptr m_current_log_buffer;
};
+35
View File
@@ -0,0 +1,35 @@
#include <cppunit/Exception.h>
#include <cppunit/Message.h>
#include <cppunit/extensions/TypeInfoHelper.h>
#include <test/helpers/protectors.h>
#include <torrent/exceptions.h>
#include <typeinfo>
bool
ExceptionProtector::protect(const CppUnit::Functor& functor, const CppUnit::ProtectorContext& context) {
try {
return functor();
} catch (CppUnit::Exception &failure) {
reportFailure( context, failure );
} catch (torrent::base_error& e) {
std::string short_description("uncaught exception of base type torrent::base_error: " + std::string(typeid(e).name()));
CppUnit::Message message(short_description, e.what());
reportError(context, message);
} catch ( std::exception &e ) {
std::string short_description("uncaught exception of type ");
short_description += CppUnit::TypeInfoHelper::getClassName(typeid(e));
CppUnit::Message message(short_description, e.what());
reportError(context, message);
} catch ( ... ) {
reportError(context, CppUnit::Message("uncaught exception of unknown type"));
}
return false;
}
+13
View File
@@ -0,0 +1,13 @@
#ifndef LIBTORRENT_HELPER_PROTECTORS_H
#define LIBTORRENT_HELPER_PROTECTORS_H
#include <functional>
#include <string>
#include <cppunit/Protector.h>
class ExceptionProtector : public CppUnit::Protector {
public:
bool protect(const CppUnit::Functor &functor, const CppUnit::ProtectorContext &context) override;
};
#endif // LIBTORRENT_HELPER_PROTECTORS_H
+60
View File
@@ -0,0 +1,60 @@
#ifndef LIBTORRENT_HELPER_UTILS_H
#define LIBTORRENT_HELPER_UTILS_H
#include <algorithm>
#include <iostream>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <torrent/utils/log.h>
static void
dump_failure_log(const failure_type& failure) {
if (failure.log->empty())
return;
std::cout << std::endl << failure.name << std::endl;
// Doesn't print dump messages as log_buffer drops them.
std::for_each(failure.log->begin(), failure.log->end(), [](const torrent::log_entry& entry) {
std::cout << entry.timestamp << ' ' << entry.message << '\n';
});
std::cout << std::flush;
}
static void
dump_failures(const failure_list_type& failures) {
if (failures.empty())
return;
std::cout << std::endl
<< "=================" << std::endl
<< "Failed Test Logs:" << std::endl
<< "=================" << std::endl;
std::for_each(failures.begin(), failures.end(), [](const failure_type& failure) {
dump_failure_log(failure);
});
std::cout << std::endl;
}
static
void add_tests(CppUnit::TextUi::TestRunner& runner, const char* c_test_names) {
if (c_test_names == NULL || std::string(c_test_names).empty()) {
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
return;
}
const std::string& test_names(c_test_names);
size_t pos = 0;
size_t next = 0;
while ((next = test_names.find(',', pos)) < test_names.size()) {
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry(test_names.substr(pos, next - pos)).makeTest());
pos = next + 1;
}
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry(test_names.substr(pos)).makeTest());
}
#endif
+89 -14
View File
@@ -1,22 +1,97 @@
#include "config.h"
#include <cstdlib>
#include <stdexcept>
#include <signal.h>
#include <string.h>
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
int main(int argc, char* argv[])
{
// Get the top level suite from the registry
CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
#ifdef HAVE_BACKTRACE
#include <execinfo.h>
#endif
// Adds the test to the list of test to run
CppUnit::TextUi::TestRunner runner;
runner.addTest( suite );
#include "helpers/progress_listener.h"
#include "helpers/protectors.h"
#include "helpers/utils.h"
// Change the default outputter to a compiler error format outputter
runner.setOutputter( new CppUnit::CompilerOutputter( &runner.result(),
std::cerr ) );
// Run the tests.
bool wasSucessful = runner.run();
CPPUNIT_REGISTRY_ADD_TO_DEFAULT("rpc");
CPPUNIT_REGISTRY_ADD_TO_DEFAULT("src");
// Return error code 1 if the one of test failed.
return wasSucessful ? 0 : 1;
void
do_test_panic(int signum) {
signal(signum, SIG_DFL);
std::cout << std::endl << std::endl << "Caught " << strsignal(signum) << ", dumping stack:" << std::endl << std::endl;
#ifdef HAVE_BACKTRACE
void* stackPtrs[20];
// Print the stack and exit.
int stackSize = backtrace(stackPtrs, 20);
char** stackStrings = backtrace_symbols(stackPtrs, stackSize);
for (int i = 0; i < stackSize; ++i)
std::cout << stackStrings[i] << std::endl;
#else
std::cout << "Stack dump not enabled." << std::endl;
#endif
std::cout << std::endl;
torrent::log_cleanup();
std::abort();
}
void
register_signal_handlers() {
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = &do_test_panic;
if (sigaction(SIGSEGV, &sa, NULL) == -1) {
std::cout << "Could not register signal handlers." << std::endl;
exit(-1);
}
}
int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) {
register_signal_handlers();
CppUnit::TestResult controller;
CppUnit::TestResultCollector result;
progress_listener progress;
controller.addListener(&result);
controller.addListener(&progress);
controller.popProtector();
controller.pushProtector(new ExceptionProtector());
CppUnit::TextUi::TestRunner runner;
add_tests(runner, std::getenv("TEST_NAME"));
try {
std::cout << "Running ";
runner.run( controller );
// TODO: Make outputter.
dump_failures(progress.failures());
// Print test in a compiler compatible format.
CppUnit::CompilerOutputter outputter( &result, std::cerr );
outputter.write();
} catch ( std::invalid_argument &e ) { // Test path not resolved
std::cerr << std::endl << "ERROR: " << e.what() << std::endl;
return 1;
}
return result.wasSuccessful() ? 0 : 1;
}
+1 -2
View File
@@ -10,7 +10,7 @@
CPPUNIT_TEST_SUITE_REGISTRATION(XmlrpcTest);
torrent::Object xmlrpc_cmd_test_reflect(rpc::target_type t, const torrent::Object& obj) { return obj; }
torrent::Object xmlrpc_cmd_test_reflect([[maybe_unused]] rpc::target_type t, const torrent::Object& obj) { return obj; }
void initialize_command_dynamic();
@@ -100,7 +100,6 @@ std::vector<std::tuple<std::string, std::string, std::string>> basic_requests =
void
XmlrpcTest::setUp() {
m_commandItr = m_commands;
m_xmlrpc = rpc::XmlRpc();
m_xmlrpc.initialize();
setlocale(LC_ALL, "");
-1
View File
@@ -26,5 +26,4 @@ private:
rpc::CommandMap m_map;
rpc::command_base m_commands[cmd_size];
rpc::command_base* m_commandItr;
};