diff --git a/src/command_events.cc b/src/command_events.cc index 8420cc5a..2afd600d 100644 --- a/src/command_events.cc +++ b/src/command_events.cc @@ -128,7 +128,7 @@ apply_remove_untied() { } torrent::Object -apply_schedule(const torrent::Object::list_type& args) { +apply_schedule(const torrent::Object::list_type& args, bool if_absent) { if (args.size() != 4) throw torrent::input_error("Wrong number of arguments."); @@ -138,6 +138,9 @@ apply_schedule(const torrent::Object::list_type& args) { auto& arg2 = (itr++)->as_string(); auto& arg3 = (itr++)->as_string(); + if (if_absent && control->command_scheduler()->find(arg1) != control->command_scheduler()->end()) + return torrent::Object(); + control->command_scheduler()->parse(arg1, arg2, arg3, *itr); return torrent::Object(); @@ -340,7 +343,8 @@ initialize_command_events() { CMD2_ANY ("close_untied", [](auto, auto) { return apply_close_untied(); }); CMD2_ANY ("remove_untied", [](auto, auto) { return apply_remove_untied(); }); - CMD2_ANY_LIST ("schedule", [](auto, auto& args) { return apply_schedule(args); }); + CMD2_ANY_LIST ("schedule", [](auto, auto& args) { return apply_schedule(args, false); }); + CMD2_ANY_LIST ("schedule.if_absent", [](auto, auto& args) { return apply_schedule(args, true); }); CMD2_ANY_STRING_V("schedule.remove", [](auto, auto& str) { return control->command_scheduler()->erase_str(str); }); CMD2_ANY_STRING_V("import", [](auto, auto& str) { return apply_import(str); }); diff --git a/test/Makefile.am b/test/Makefile.am index 599d1b3b..550051f8 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -35,6 +35,8 @@ rtorrent_Test_Rpc_SOURCES = $(rtorrent_Test_Common) \ rpc/test_command.h \ rpc/test_command_map.cc \ rpc/test_command_map.h \ + rpc/test_command_scheduler.cc \ + rpc/test_command_scheduler.h \ rpc/test_jsonrpc.cc \ rpc/test_jsonrpc.h \ rpc/test_xmlrpc.cc \ diff --git a/test/rpc/test_command_scheduler.cc b/test/rpc/test_command_scheduler.cc new file mode 100644 index 00000000..6ab4cb33 --- /dev/null +++ b/test/rpc/test_command_scheduler.cc @@ -0,0 +1,65 @@ +#include "config.h" + +#include "test/rpc/test_command_scheduler.h" + +#include + +#include "rpc/command_scheduler.h" +#include "rpc/command_scheduler_item.h" +#include "torrent/object.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(TestCommandScheduler); + +namespace { + +const torrent::Object test_command = torrent::Object(std::string("print=scheduled")); + +std::chrono::microseconds +time_scheduled(rpc::CommandScheduler& scheduler, const std::string& key) { + auto itr = scheduler.find(key); + + CPPUNIT_ASSERT(itr != scheduler.end()); + + return (*itr)->time_scheduled(); +} + +} + +void +TestCommandScheduler::setUp() { + TestFixtureWithMainThread::setUp(); + + m_main_thread->test_set_cached_time(std::chrono::seconds(0)); +} + +void +TestCommandScheduler::tearDown() { + TestFixtureWithMainThread::tearDown(); +} + +void +TestCommandScheduler::test_parse_rearms_existing_key() { + rpc::CommandScheduler scheduler; + + scheduler.parse("key", "3600", "3600", test_command); + + auto first = time_scheduled(scheduler, "key"); + + m_main_thread->test_add_cached_time(std::chrono::seconds(600)); + scheduler.parse("key", "3600", "3600", test_command); + + CPPUNIT_ASSERT_EQUAL(size_t{1}, scheduler.size()); + CPPUNIT_ASSERT(time_scheduled(scheduler, "key") == first + std::chrono::seconds(600)); +} + +void +TestCommandScheduler::test_find_locates_a_scheduled_key() { + rpc::CommandScheduler scheduler; + + CPPUNIT_ASSERT(scheduler.find("key") == scheduler.end()); + + scheduler.parse("key", "3600", "3600", test_command); + + CPPUNIT_ASSERT(scheduler.find("key") != scheduler.end()); + CPPUNIT_ASSERT(scheduler.find("other") == scheduler.end()); +} diff --git a/test/rpc/test_command_scheduler.h b/test/rpc/test_command_scheduler.h new file mode 100644 index 00000000..c23cf938 --- /dev/null +++ b/test/rpc/test_command_scheduler.h @@ -0,0 +1,17 @@ +#include "test/helpers/test_main_thread.h" + +class TestCommandScheduler : public TestFixtureWithMainThread { + CPPUNIT_TEST_SUITE(TestCommandScheduler); + + CPPUNIT_TEST(test_parse_rearms_existing_key); + CPPUNIT_TEST(test_find_locates_a_scheduled_key); + + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp(); + void tearDown(); + + void test_parse_rearms_existing_key(); + void test_find_locates_a_scheduled_key(); +};