#include "config.h" #include "test/rpc/test_xmlrpc.h" #include #include "control.h" #include "globals.h" #include "command_helpers.h" #include "rpc/command_map.h" CPPUNIT_TEST_SUITE_REGISTRATION(TestXmlrpc); torrent::Object xmlrpc_cmd_test_reflect([[maybe_unused]] rpc::target_type t, const torrent::Object& obj) { return obj; } torrent::Object xmlrpc_cmd_test_reflect_string([[maybe_unused]] rpc::target_type t, const std::string& obj) { return obj; } void initialize_command_dynamic(); #if defined(HAVE_XMLRPC_TINYXML2) && !defined(HAVE_XMLRPC_C) std::vector> basic_requests = { std::make_tuple("Basic call", "xmlrpc_reflect", ""), std::make_tuple("Basic call without params", "xmlrpc_reflect", ""), std::make_tuple("UTF-8 string", "xmlrpc_reflectчао", "чао"), std::make_tuple("emoji string", "xmlrpc_reflect😊", "😊"), std::make_tuple("base64 data (which gets returned as a string)", "xmlrpc_reflectZm9vYmFy", "foobar"), std::make_tuple("i8 ints", "xmlrpc_reflect41", "41"), std::make_tuple("i8 ints", "xmlrpc_reflect2247483647", "2247483647"), std::make_tuple("negative i8 ints", "xmlrpc_reflect-2347483647", "-2347483647"), std::make_tuple("Simple array", "xmlrpc_reflect2247483647", "2247483647"), std::make_tuple("Empty array", "xmlrpc_reflect", ""), std::make_tuple("Empty struct", "xmlrpc_reflect", ""), std::make_tuple("Simple struct", "xmlrpc_reflectlowerBound18upperBound139", "lowerBound18upperBound139"), std::make_tuple("Invalid - missing method", "no_such_method41", "faultCode-506faultStringmethod 'no_such_method' not defined"), std::make_tuple("Invalid - i8 target", "xmlrpc_reflect41", "faultCode-500faultStringinvalid parameters: target must be a string"), std::make_tuple("Invalid - empty int tag", "xmlrpc_reflect", "faultCode-501faultStringunable to parse empty integer"), std::make_tuple("Invalid - empty int text", "xmlrpc_reflect", "faultCode-501faultStringunable to parse empty integer"), std::make_tuple("Invalid - broken XML", "thodCall>test_a41faultCode-503faultStringError=XML_ERROR_PARSING_ELEMENT ErrorID=6 (0x6) Line number=1: XMLElement name=method"), std::make_tuple("Invalid - non-integer i8", "xmlrpc_reflectstring value", "faultCode-501faultStringunable to parse integer value"), std::make_tuple("Invalid - float i8", "xmlrpc_reflect3.14", "faultCode-501faultStringunable to parse integer value"), std::make_tuple("Invalid - non-boolean boolean", "xmlrpc_reflectstring value", "faultCode-501faultStringunknown boolean value: string value"), std::make_tuple("CMD2_ANY_STRING", "xmlrpc_reflect_stringtest", "test") }; void TestXmlrpc::setUp() { m_test_main_thread = TestMainThread::create(); m_test_main_thread->init_thread(); m_xmlrpc = rpc::XmlRpc(); m_xmlrpc.initialize(); setlocale(LC_ALL, ""); control = new Control; if (rpc::commands.find("xmlrpc_reflect") == rpc::commands.end()) CMD2_ANY("xmlrpc_reflect", &xmlrpc_cmd_test_reflect); if (rpc::commands.find("xmlrpc_reflect_string") == rpc::commands.end()) CMD2_ANY_STRING("xmlrpc_reflect_string", &xmlrpc_cmd_test_reflect_string); } void TestXmlrpc::tearDown() { m_test_main_thread.reset(); } void TestXmlrpc::test_basics() { for (auto& test : basic_requests) { std::string output; m_xmlrpc.process(std::get<1>(test).c_str(), std::get<1>(test).size(), [&output](const char* c, uint32_t l){ output.append(c, l); return true;}); CPPUNIT_ASSERT_EQUAL_MESSAGE(std::get<0>(test), std::get<2>(test), output); } } void TestXmlrpc::test_invalid_utf8() { // Surprisingly, this call doesn't fail. TinyXML-2 technically expects // valid UTF-8, but doesn't check strings, and Object strings are // just a series of bytes so it reflects just fine. std::string input = "xmlrpc_reflect\xc3\x28"; std::string expected = "\xc3\x28"; std::string output; m_xmlrpc.process(input.c_str(), input.size(), [&output](const char* c, uint32_t l){ output.append(c, l); return true;}); CPPUNIT_ASSERT_EQUAL(expected, output); } void TestXmlrpc::test_size_limit() { std::string input = "xmlrpc_reflect\xc3\x28"; std::string expected = "faultCode-509faultStringContent size exceeds maximum XML-RPC limit"; std::string output; m_xmlrpc.set_size_limit(1); m_xmlrpc.process(input.c_str(), input.size(), [&output](const char* c, uint32_t l){ output.append(c, l); return true;}); CPPUNIT_ASSERT_EQUAL(expected, output); } #else void TestXmlrpc::test_invalid_utf8() {} void TestXmlrpc::test_basics() {} void TestXmlrpc::test_size_limit() {} void TestXmlrpc::setUp() {} void TestXmlrpc::tearDown() {} #endif