Use Catch for our test suite
`make check` is also added to compile and run the tests Catch is fetched with cmake automatically into the build directory when needed
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <bridge/colors.hpp>
|
||||
#include <xmpp/xmpp_stanza.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
TEST_CASE("IRC colors parsing")
|
||||
{
|
||||
std::unique_ptr<XmlNode> xhtml;
|
||||
std::string cleaned_up;
|
||||
|
||||
std::tie(cleaned_up, xhtml) = irc_format_to_xhtmlim("bold");
|
||||
CHECK(xhtml);
|
||||
CHECK(xhtml->to_string() == "<body xmlns='http://www.w3.org/1999/xhtml'><span style='font-weight:bold;'>bold</span></body>");
|
||||
|
||||
std::tie(cleaned_up, xhtml) =
|
||||
irc_format_to_xhtmlim("normalboldunder-and-boldbold normal"
|
||||
"5red,5default-on-red10,2cyan-on-blue");
|
||||
CHECK(xhtml);
|
||||
CHECK(xhtml->to_string() == "<body xmlns='http://www.w3.org/1999/xhtml'>normal<span style='font-weight:bold;'>bold</span><span style='font-weight:bold;text-decoration:underline;'>under-and-bold</span><span style='font-weight:bold;'>bold</span> normal<span style='color:red;'>red</span><span style='background-color:red;'>default-on-red</span><span style='color:cyan;background-color:blue;'>cyan-on-blue</span></body>");
|
||||
CHECK(cleaned_up == "normalboldunder-and-boldbold normalreddefault-on-redcyan-on-blue");
|
||||
|
||||
std::tie(cleaned_up, xhtml) = irc_format_to_xhtmlim("normal");
|
||||
CHECK_FALSE(xhtml);
|
||||
CHECK(cleaned_up == "normal");
|
||||
|
||||
std::tie(cleaned_up, xhtml) = irc_format_to_xhtmlim("");
|
||||
CHECK(xhtml);
|
||||
CHECK(!xhtml->has_children());
|
||||
CHECK(cleaned_up.empty());
|
||||
|
||||
std::tie(cleaned_up, xhtml) = irc_format_to_xhtmlim(",a");
|
||||
CHECK(xhtml);
|
||||
CHECK(!xhtml->has_children());
|
||||
CHECK(cleaned_up == "a");
|
||||
|
||||
std::tie(cleaned_up, xhtml) = irc_format_to_xhtmlim(",");
|
||||
CHECK(xhtml);
|
||||
CHECK(!xhtml->has_children());
|
||||
CHECK(cleaned_up.empty());
|
||||
|
||||
std::tie(cleaned_up, xhtml) = irc_format_to_xhtmlim("[\x1D13dolphin-emu/dolphin\x1D] 03foo commented on #283 (Add support for the guide button to XInput): 02http://example.com");
|
||||
CHECK(xhtml->to_string() == "<body xmlns='http://www.w3.org/1999/xhtml'>[<span style='font-style:italic;'/><span style='font-style:italic;color:lightmagenta;'>dolphin-emu/dolphin</span><span style='color:lightmagenta;'>] </span><span style='color:green;'>foo</span> commented on #283 (Add support for the guide button to XInput): <span style='text-decoration:underline;'/><span style='text-decoration:underline;color:blue;'>http://example.com</span><span style='text-decoration:underline;'/></body>");
|
||||
CHECK(cleaned_up == "[dolphin-emu/dolphin] foo commented on #283 (Add support for the guide button to XInput): http://example.com");
|
||||
|
||||
std::tie(cleaned_up, xhtml) = irc_format_to_xhtmlim("0e46ab by 03Pierre Dindon [090|091|040] 02http://example.net/Ojrh4P media: avoid pop-in effect when loading thumbnails by specifying an explicit size");
|
||||
CHECK(cleaned_up == "0e46ab by Pierre Dindon [0|1|0] http://example.net/Ojrh4P media: avoid pop-in effect when loading thumbnails by specifying an explicit size");
|
||||
CHECK(xhtml->to_string() == "<body xmlns='http://www.w3.org/1999/xhtml'>0e46ab by <span style='color:green;'>Pierre Dindon</span> [<span style='color:lightgreen;'>0</span>|<span style='color:lightgreen;'>1</span>|<span style='color:indianred;'>0</span>] <span style='text-decoration:underline;'/><span style='text-decoration:underline;color:blue;'>http://example.net/Ojrh4P</span><span style='text-decoration:underline;'/> media: avoid pop-in effect when loading thumbnails by specifying an explicit size</body>");
|
||||
|
||||
std::tie(cleaned_up, xhtml) = irc_format_to_xhtmlim("test\ncoucou");
|
||||
CHECK(cleaned_up == "test\ncoucou");
|
||||
CHECK(xhtml->to_string() == "<body xmlns='http://www.w3.org/1999/xhtml'>test<br/>coucou</body>");
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <config/config.hpp>
|
||||
|
||||
TEST_CASE("Config basic")
|
||||
{
|
||||
Config::filename = "test.cfg";
|
||||
Config::file_must_exist = false;
|
||||
Config::set("coucou", "bonjour", true);
|
||||
Config::close();
|
||||
|
||||
bool error = false;
|
||||
try
|
||||
{
|
||||
Config::file_must_exist = true;
|
||||
CHECK(Config::get("coucou", "") == "bonjour");
|
||||
CHECK(Config::get("does not exist", "default") == "default");
|
||||
Config::close();
|
||||
}
|
||||
catch (const std::ios::failure& e)
|
||||
{
|
||||
error = true;
|
||||
}
|
||||
CHECK_FALSE(error);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <database/database.hpp>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <config/config.hpp>
|
||||
|
||||
TEST_CASE("Database")
|
||||
{
|
||||
#ifdef USE_DATABASE
|
||||
// Remove any potential existing db
|
||||
::unlink("./test.db");
|
||||
Config::set("db_name", "test.db");
|
||||
Database::set_verbose(false);
|
||||
auto o = Database::get_irc_server_options("zouzou@example.com", "irc.example.com");
|
||||
o.update();
|
||||
auto a = Database::get_irc_server_options("zouzou@example.com", "irc.example.com");
|
||||
auto b = Database::get_irc_server_options("moumou@example.com", "irc.example.com");
|
||||
|
||||
// b does not yet exist in the db, the object is created but not yet
|
||||
// inserted
|
||||
CHECK(1 == Database::count<db::IrcServerOptions>());
|
||||
|
||||
b.update();
|
||||
CHECK(2 == Database::count<db::IrcServerOptions>());
|
||||
|
||||
CHECK(b.pass == "");
|
||||
CHECK(b.pass.value() == "");
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <network/dns_handler.hpp>
|
||||
#include <network/resolver.hpp>
|
||||
#include <network/poller.hpp>
|
||||
|
||||
#include <utils/timed_events.hpp>
|
||||
|
||||
TEST_CASE("DNS resolver")
|
||||
{
|
||||
Resolver resolver;
|
||||
|
||||
/**
|
||||
* If we are using cares, we need to run a poller loop until each
|
||||
* resolution is finished. Without cares we get the result before
|
||||
* resolve() returns because it’s blocking.
|
||||
*/
|
||||
#ifdef CARES_FOUND
|
||||
auto p = std::make_shared<Poller>();
|
||||
|
||||
const auto loop = [&p]()
|
||||
{
|
||||
do
|
||||
{
|
||||
DNSHandler::instance.watch_dns_sockets(p);
|
||||
}
|
||||
while (p->poll(utils::no_timeout) != -1);
|
||||
};
|
||||
#else
|
||||
// We don’t need to do anything if we are not using cares.
|
||||
const auto loop = [](){};
|
||||
#endif
|
||||
|
||||
std::string hostname;
|
||||
std::string port = "6667";
|
||||
|
||||
bool success = true;
|
||||
|
||||
auto error_cb = [&success, &hostname, &port](const char* msg)
|
||||
{
|
||||
INFO("Failed to resolve " << hostname << ":" << port << ": " << msg);
|
||||
success = false;
|
||||
};
|
||||
auto success_cb = [&success, &hostname, &port](const struct addrinfo* addr)
|
||||
{
|
||||
INFO("Successfully resolved " << hostname << ":" << port << ": " << addr_to_string(addr));
|
||||
success = true;
|
||||
};
|
||||
|
||||
hostname = "example.com";
|
||||
resolver.resolve(hostname, port,
|
||||
success_cb, error_cb);
|
||||
loop();
|
||||
CHECK(success);
|
||||
|
||||
hostname = "this.should.fail.because.it.is..misformatted";
|
||||
resolver.resolve(hostname, port,
|
||||
success_cb, error_cb);
|
||||
loop();
|
||||
CHECK(!success);
|
||||
|
||||
hostname = "this.should.fail.because.it.is.does.not.exist.invalid";
|
||||
resolver.resolve(hostname, port,
|
||||
success_cb, error_cb);
|
||||
loop();
|
||||
CHECK(!success);
|
||||
|
||||
hostname = "localhost6";
|
||||
resolver.resolve(hostname, port,
|
||||
success_cb, error_cb);
|
||||
loop();
|
||||
CHECK(success);
|
||||
|
||||
hostname = "localhost";
|
||||
resolver.resolve(hostname, port,
|
||||
success_cb, error_cb);
|
||||
loop();
|
||||
CHECK(success);
|
||||
|
||||
#ifdef CARES_FOUND
|
||||
DNSHandler::instance.destroy();
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <utils/encoding.hpp>
|
||||
|
||||
|
||||
TEST_CASE("UTF-8 validation")
|
||||
{
|
||||
const char* valid = "C̡͔͕̩͙̽ͫ̈́ͥ̿̆ͧ̚r̸̩̘͍̻͖̆͆͛͊̉̕͡o͇͈̳̤̱̊̈͢q̻͍̦̮͕ͥͬͬ̽ͭ͌̾ͅǔ͉͕͇͚̙͉̭͉̇̽ȇ͈̮̼͍͔ͣ͊͞͝ͅ ͫ̾ͪ̓ͥ̆̋̔҉̢̦̠͈͔̖̲̯̦ụ̶̯͐̃̋ͮ͆͝n̬̱̭͇̻̱̰̖̤̏͛̏̿̑͟ë́͐҉̸̥̪͕̹̻̙͉̰ ̹̼̱̦̥ͩ͑̈́͑͝ͅt͍̥͈̹̝ͣ̃̔̈̔ͧ̕͝ḙ̸̖̟̙͙ͪ͢ų̯̞̼̲͓̻̞͛̃̀́b̮̰̗̩̰̊̆͗̾̎̆ͯ͌͝.̗̙͎̦ͫ̈́ͥ͌̈̓ͬ";
|
||||
CHECK(utils::is_valid_utf8(valid));
|
||||
CHECK_FALSE(utils::is_valid_utf8("\xF0\x0F"));
|
||||
CHECK_FALSE(utils::is_valid_utf8("\xFE\xFE\xFF\xFF"));
|
||||
|
||||
std::string in = "Biboumi ╯°□°)╯︵ ┻━┻";
|
||||
INFO(in);
|
||||
CHECK(utils::is_valid_utf8(in.data()));
|
||||
}
|
||||
|
||||
TEST_CASE("UTF-8 conversion")
|
||||
{
|
||||
std::string in = "Biboumi ╯°□°)╯︵ ┻━┻";
|
||||
REQUIRE(utils::is_valid_utf8(in.data()));
|
||||
|
||||
SECTION("Converting UTF-8 to UTF-8 should return the same string")
|
||||
{
|
||||
std::string res = utils::convert_to_utf8(in, "UTF-8");
|
||||
CHECK(utils::is_valid_utf8(res.c_str()) == true);
|
||||
CHECK(res == in);
|
||||
}
|
||||
|
||||
SECTION("Testing latin-1 conversion")
|
||||
{
|
||||
std::string original_utf8("couc¥ou");
|
||||
std::string original_latin1("couc\xa5ou");
|
||||
|
||||
SECTION("Convert proper latin-1 to UTF-8")
|
||||
{
|
||||
std::string from_latin1 = utils::convert_to_utf8(original_latin1.c_str(), "ISO-8859-1");
|
||||
CHECK(from_latin1 == original_utf8);
|
||||
}
|
||||
SECTION("Check the behaviour when the decoding fails (here because we provide a wrong charset)")
|
||||
{
|
||||
std::string from_ascii = utils::convert_to_utf8(original_latin1, "US-ASCII");
|
||||
CHECK(from_ascii == "couc�ou");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Remove invalid XML chars")
|
||||
{
|
||||
std::string without_ctrl_char("𤭢€¢$");
|
||||
std::string in = "Biboumi ╯°□°)╯︵ ┻━┻";
|
||||
INFO(in);
|
||||
CHECK(utils::remove_invalid_xml_chars(without_ctrl_char) == without_ctrl_char);
|
||||
CHECK(utils::remove_invalid_xml_chars(in) == in);
|
||||
CHECK(utils::remove_invalid_xml_chars("\acouco\u0008u\uFFFEt\uFFFFe\r\n♥") == "coucoute\r\n♥");
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <irc/iid.hpp>
|
||||
#include <irc/irc_user.hpp>
|
||||
|
||||
#include <config/config.hpp>
|
||||
|
||||
TEST_CASE("Irc user parsing")
|
||||
{
|
||||
const std::map<char, char> prefixes{{'!', 'a'}, {'@', 'o'}};
|
||||
|
||||
IrcUser user1("!nick!~some@host.bla", prefixes);
|
||||
CHECK(user1.nick == "nick");
|
||||
CHECK(user1.host == "~some@host.bla");
|
||||
CHECK(user1.modes.size() == 1);
|
||||
CHECK(user1.modes.find('a') != user1.modes.end());
|
||||
|
||||
IrcUser user2("coucou!~other@host.bla", prefixes);
|
||||
CHECK(user2.nick == "coucou");
|
||||
CHECK(user2.host == "~other@host.bla");
|
||||
CHECK(user2.modes.empty());
|
||||
CHECK(user2.modes.find('a') == user2.modes.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Let Catch know how to display Iid objects
|
||||
*/
|
||||
namespace Catch
|
||||
{
|
||||
template<>
|
||||
struct StringMaker<Iid>
|
||||
{
|
||||
static std::string convert(const Iid& value)
|
||||
{
|
||||
return std::to_string(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("Iid creation")
|
||||
{
|
||||
Iid iid1("foo!irc.example.org");
|
||||
CHECK(std::to_string(iid1) == "foo!irc.example.org");
|
||||
CHECK(iid1.get_local() == "foo");
|
||||
CHECK(iid1.get_server() == "irc.example.org");
|
||||
CHECK(!iid1.is_channel);
|
||||
CHECK(iid1.is_user);
|
||||
|
||||
Iid iid2("#test%irc.example.org");
|
||||
CHECK(std::to_string(iid2) == "#test%irc.example.org");
|
||||
CHECK(iid2.get_local() == "#test");
|
||||
CHECK(iid2.get_server() == "irc.example.org");
|
||||
CHECK(iid2.is_channel);
|
||||
CHECK(!iid2.is_user);
|
||||
|
||||
Iid iid3("%irc.example.org");
|
||||
CHECK(std::to_string(iid3) == "%irc.example.org");
|
||||
CHECK(iid3.get_local() == "");
|
||||
CHECK(iid3.get_server() == "irc.example.org");
|
||||
CHECK(iid3.is_channel);
|
||||
CHECK(!iid3.is_user);
|
||||
|
||||
Iid iid4("irc.example.org");
|
||||
CHECK(std::to_string(iid4) == "irc.example.org");
|
||||
CHECK(iid4.get_local() == "");
|
||||
CHECK(iid4.get_server() == "irc.example.org");
|
||||
CHECK(!iid4.is_channel);
|
||||
CHECK(!iid4.is_user);
|
||||
|
||||
Iid iid5("nick!");
|
||||
CHECK(std::to_string(iid5) == "nick!");
|
||||
CHECK(iid5.get_local() == "nick");
|
||||
CHECK(iid5.get_server() == "");
|
||||
CHECK(!iid5.is_channel);
|
||||
CHECK(iid5.is_user);
|
||||
|
||||
Iid iid6("##channel%");
|
||||
CHECK(std::to_string(iid6) == "##channel%");
|
||||
CHECK(iid6.get_local() == "##channel");
|
||||
CHECK(iid6.get_server() == "");
|
||||
CHECK(iid6.is_channel);
|
||||
CHECK(!iid6.is_user);
|
||||
}
|
||||
|
||||
TEST_CASE("Iid creation in fixed_server mode")
|
||||
{
|
||||
Config::set("fixed_irc_server", "fixed.example.com", false);
|
||||
|
||||
Iid iid1("foo!irc.example.org");
|
||||
CHECK(std::to_string(iid1) == "foo!");
|
||||
CHECK(iid1.get_local() == "foo");
|
||||
CHECK(iid1.get_server() == "fixed.example.com");
|
||||
CHECK(!iid1.is_channel);
|
||||
CHECK(iid1.is_user);
|
||||
|
||||
Iid iid2("#test%irc.example.org");
|
||||
CHECK(std::to_string(iid2) == "#test%irc.example.org");
|
||||
CHECK(iid2.get_local() == "#test%irc.example.org");
|
||||
CHECK(iid2.get_server() == "fixed.example.com");
|
||||
CHECK(iid2.is_channel);
|
||||
CHECK(!iid2.is_user);
|
||||
|
||||
// Note that it is impossible to adress the IRC server directly, or to
|
||||
// use the virtual channel, in that mode
|
||||
|
||||
// Iid iid3("%irc.example.org");
|
||||
// Iid iid4("irc.example.org");
|
||||
|
||||
Iid iid5("nick!");
|
||||
CHECK(std::to_string(iid5) == "nick!");
|
||||
CHECK(iid5.get_local() == "nick");
|
||||
CHECK(iid5.get_server() == "fixed.example.com");
|
||||
CHECK(!iid5.is_channel);
|
||||
CHECK(iid5.is_user);
|
||||
|
||||
Iid iid6("##channel%");
|
||||
CHECK(std::to_string(iid6) == "##channel%");
|
||||
CHECK(iid6.get_local() == "##channel%");
|
||||
CHECK(iid6.get_server() == "fixed.example.com");
|
||||
CHECK(iid6.is_channel);
|
||||
CHECK(!iid6.is_user);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <xmpp/jid.hpp>
|
||||
#include <louloulibs.h>
|
||||
|
||||
TEST_CASE("Jid")
|
||||
{
|
||||
Jid jid1("♥@ツ.coucou/coucou@coucou/coucou");
|
||||
CHECK(jid1.local == "♥");
|
||||
CHECK(jid1.domain == "ツ.coucou");
|
||||
CHECK(jid1.resource == "coucou@coucou/coucou");
|
||||
|
||||
// Domain and resource
|
||||
Jid jid2("ツ.coucou/coucou@coucou/coucou");
|
||||
CHECK(jid2.local == "");
|
||||
CHECK(jid2.domain == "ツ.coucou");
|
||||
CHECK(jid2.resource == "coucou@coucou/coucou");
|
||||
|
||||
// Jidprep
|
||||
const std::string badjid("~zigougou™@EpiK-7D9D1FDE.poez.io/Boujour/coucou/slt™");
|
||||
const std::string correctjid = jidprep(badjid);
|
||||
#ifdef LIBIDN_FOUND
|
||||
CHECK(correctjid == "~zigougoutm@epik-7d9d1fde.poez.io/Boujour/coucou/sltTM");
|
||||
// Check that the cache does not break things when we prep the same string
|
||||
// multiple times
|
||||
CHECK(jidprep(badjid) == "~zigougoutm@epik-7d9d1fde.poez.io/Boujour/coucou/sltTM");
|
||||
CHECK(jidprep(badjid) == "~zigougoutm@epik-7d9d1fde.poez.io/Boujour/coucou/sltTM");
|
||||
|
||||
const std::string badjid2("Zigougou@poez.io");
|
||||
const std::string correctjid2 = jidprep(badjid2);
|
||||
CHECK(correctjid2 == "zigougou@poez.io");
|
||||
|
||||
const std::string crappy("~Bisous@7ea8beb1:c5fd2849:da9a048e:ip");
|
||||
const std::string fixed_crappy = jidprep(crappy);
|
||||
CHECK(fixed_crappy == "~bisous@7ea8beb1-c5fd2849-da9a048e-ip");
|
||||
#else // Without libidn, jidprep always returns an empty string
|
||||
CHECK(jidprep(badjid) == "");
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <utils/timed_events.hpp>
|
||||
|
||||
/**
|
||||
* Let Catch know how to display std::chrono::duration values
|
||||
*/
|
||||
namespace Catch
|
||||
{
|
||||
template<typename Rep, typename Period> struct StringMaker<std::chrono::duration<Rep, Period>>
|
||||
{
|
||||
static std::string convert(const std::chrono::duration<Rep, Period>& value)
|
||||
{
|
||||
return std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(value).count()) + "ms";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO, use a mock clock instead of relying on the real time with a sleep:
|
||||
* it’s unreliable on heavy load.
|
||||
*/
|
||||
#include <thread>
|
||||
|
||||
TEST_CASE("Test timed event expiration")
|
||||
{
|
||||
SECTION("Check what happens when there is no events")
|
||||
{
|
||||
CHECK(TimedEventsManager::instance().get_timeout() == utils::no_timeout);
|
||||
CHECK(TimedEventsManager::instance().execute_expired_events() == 0);
|
||||
}
|
||||
|
||||
// Add a single event
|
||||
TimedEventsManager::instance().add_event(TimedEvent(std::chrono::steady_clock::now() + 50ms, [](){}));
|
||||
|
||||
// The event should not yet be expired
|
||||
CHECK(TimedEventsManager::instance().get_timeout() > 0ms);
|
||||
CHECK(TimedEventsManager::instance().execute_expired_events() == 0);
|
||||
|
||||
std::chrono::milliseconds timoute = TimedEventsManager::instance().get_timeout();
|
||||
INFO("Sleeping for " << timoute.count() << "ms");
|
||||
std::this_thread::sleep_for(timoute);
|
||||
|
||||
// Event is now expired
|
||||
CHECK(TimedEventsManager::instance().execute_expired_events() == 1);
|
||||
CHECK(TimedEventsManager::instance().get_timeout() == utils::no_timeout);
|
||||
}
|
||||
|
||||
TEST_CASE("Test timed event cancellation")
|
||||
{
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
TimedEventsManager::instance().add_event(TimedEvent(now + 100ms, [](){ }, "un"));
|
||||
TimedEventsManager::instance().add_event(TimedEvent(now + 200ms, [](){ }, "deux"));
|
||||
TimedEventsManager::instance().add_event(TimedEvent(now + 300ms, [](){ }, "deux"));
|
||||
|
||||
CHECK(TimedEventsManager::instance().get_timeout() > 0ms);
|
||||
CHECK(TimedEventsManager::instance().size() == 3);
|
||||
CHECK(TimedEventsManager::instance().cancel("un") == 1);
|
||||
CHECK(TimedEventsManager::instance().size() == 2);
|
||||
CHECK(TimedEventsManager::instance().cancel("deux") == 2);
|
||||
CHECK(TimedEventsManager::instance().get_timeout() == utils::no_timeout);
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <utils/tolower.hpp>
|
||||
#include <utils/revstr.hpp>
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/split.hpp>
|
||||
#include <utils/xdg.hpp>
|
||||
|
||||
TEST_CASE("String split")
|
||||
{
|
||||
std::vector<std::string> splitted = utils::split("a::a", ':', false);
|
||||
CHECK(splitted.size() == 2);
|
||||
splitted = utils::split("a::a", ':', true);
|
||||
CHECK(splitted.size() == 3);
|
||||
CHECK(splitted[0] == "a");
|
||||
CHECK(splitted[1] == "");
|
||||
CHECK(splitted[2] == "a");
|
||||
splitted = utils::split("\na", '\n', true);
|
||||
CHECK(splitted.size() == 2);
|
||||
CHECK(splitted[0] == "");
|
||||
CHECK(splitted[1] == "a");
|
||||
}
|
||||
|
||||
TEST_CASE("tolower")
|
||||
{
|
||||
const std::string lowercase = utils::tolower("CoUcOu LeS CoPaiNs ♥");
|
||||
CHECK(lowercase == "coucou les copains ♥");
|
||||
|
||||
const std::string ltr = "coucou";
|
||||
CHECK(utils::revstr(ltr) == "uocuoc");
|
||||
}
|
||||
|
||||
TEST_CASE("to_bool")
|
||||
{
|
||||
CHECK(to_bool("true"));
|
||||
CHECK(!to_bool("trou"));
|
||||
CHECK(to_bool("1"));
|
||||
CHECK(!to_bool("0"));
|
||||
CHECK(!to_bool("-1"));
|
||||
CHECK(!to_bool("false"));
|
||||
}
|
||||
|
||||
TEST_CASE("xdg_*_path")
|
||||
{
|
||||
::unsetenv("XDG_CONFIG_HOME");
|
||||
::unsetenv("HOME");
|
||||
std::string res;
|
||||
|
||||
SECTION("Without XDG_CONFIG_HOME nor HOME")
|
||||
{
|
||||
res = xdg_config_path("coucou.txt");
|
||||
CHECK(res == "coucou.txt");
|
||||
}
|
||||
SECTION("With only HOME")
|
||||
{
|
||||
::setenv("HOME", "/home/user", 1);
|
||||
res = xdg_config_path("coucou.txt");
|
||||
CHECK(res == "/home/user/.config/biboumi/coucou.txt");
|
||||
}
|
||||
SECTION("With only XDG_CONFIG_HOME")
|
||||
{
|
||||
::setenv("XDG_CONFIG_HOME", "/some_weird_dir", 1);
|
||||
res = xdg_config_path("coucou.txt");
|
||||
CHECK(res == "/some_weird_dir/biboumi/coucou.txt");
|
||||
}
|
||||
SECTION("With XDG_DATA_HOME")
|
||||
{
|
||||
::setenv("XDG_DATA_HOME", "/datadir", 1);
|
||||
res = xdg_data_path("bonjour.txt");
|
||||
CHECK(res == "/datadir/biboumi/bonjour.txt");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <xmpp/xmpp_component.hpp>
|
||||
|
||||
TEST_CASE("id generation")
|
||||
{
|
||||
const std::string first_uuid = XmppComponent::next_id();
|
||||
const std::string second_uuid = XmppComponent::next_id();
|
||||
|
||||
CHECK(first_uuid.size() == 36);
|
||||
CHECK(second_uuid.size() == 36);
|
||||
CHECK(first_uuid != second_uuid);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <xmpp/xmpp_parser.hpp>
|
||||
|
||||
TEST_CASE("Test basic XML parsing")
|
||||
{
|
||||
XmppParser xml;
|
||||
|
||||
const std::string doc = "<stream xmlns='stream_ns'><stanza b='c'>inner<child1><grandchild/></child1><child2 xmlns='child2_ns'/>tail</stanza></stream>";
|
||||
|
||||
auto check_stanza = [](const Stanza& stanza)
|
||||
{
|
||||
CHECK(stanza.get_name() == "stanza");
|
||||
CHECK(stanza.get_tag("xmlns") == "stream_ns");
|
||||
CHECK(stanza.get_tag("b") == "c");
|
||||
CHECK(stanza.get_inner() == "inner");
|
||||
CHECK(stanza.get_tail() == "");
|
||||
CHECK(stanza.get_child("child1", "stream_ns") != nullptr);
|
||||
CHECK(stanza.get_child("child2", "stream_ns") == nullptr);
|
||||
CHECK(stanza.get_child("child2", "child2_ns") != nullptr);
|
||||
CHECK(stanza.get_child("child2", "child2_ns")->get_tail() == "tail");
|
||||
};
|
||||
xml.add_stanza_callback([check_stanza](const Stanza& stanza)
|
||||
{
|
||||
check_stanza(stanza);
|
||||
// Do the same checks on a copy of that stanza.
|
||||
Stanza copy(stanza);
|
||||
check_stanza(copy);
|
||||
});
|
||||
xml.feed(doc.data(), doc.size(), true);
|
||||
|
||||
const std::string doc2 = "<stream xmlns='s'><stanza>coucou\r\n\a</stanza></stream>";
|
||||
xml.add_stanza_callback([](const Stanza& stanza)
|
||||
{
|
||||
CHECK(stanza.get_inner() == "coucou\r\n");
|
||||
});
|
||||
|
||||
xml.feed(doc2.data(), doc.size(), true);
|
||||
}
|
||||
|
||||
TEST_CASE("XML escape/unescape")
|
||||
{
|
||||
const std::string unescaped = "'coucou'<cc>/&\"gaga\"";
|
||||
CHECK(xml_escape(unescaped) == "'coucou'<cc>/&"gaga"");
|
||||
CHECK(xml_unescape(xml_escape(unescaped)) == unescaped);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user