test.cpp 11.3 KB
Newer Older
1 2 3 4
/**
 * Just a very simple test suite, by hand, using assert()
 */

louiz’'s avatar
louiz’ committed
5
#include <xmpp/xmpp_component.hpp>
louiz’'s avatar
louiz’ committed
6
#include <utils/timed_events.hpp>
7
#include <xmpp/xmpp_parser.hpp>
8
#include <utils/encoding.hpp>
louiz’'s avatar
louiz’ committed
9
#include <logger/logger.hpp>
10 11
#include <config/config.hpp>
#include <bridge/colors.hpp>
louiz’'s avatar
louiz’ committed
12
#include <utils/tolower.hpp>
13
#include <irc/irc_user.hpp>
14 15
#include <utils/split.hpp>
#include <xmpp/jid.hpp>
louiz’'s avatar
louiz’ committed
16
#include <irc/iid.hpp>
17 18
#include <string.h>

19
#include <iostream>
louiz’'s avatar
louiz’ committed
20
#include <thread>
21
#include <vector>
22

23
#include <assert.h>
24

25 26 27
static const std::string color("");
static const std::string reset("");

28 29
int main()
{
louiz’'s avatar
louiz’ committed
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
  /**
   * Timed events
   */
  std::cout << color << "Testing timed events…" << reset << std::endl;
  TimedEventsManager te_manager;
  // No event.
  assert(te_manager.get_timeout() == utils::no_timeout);
  assert(te_manager.execute_expired_events() == 0);

  // Add a single event
  te_manager.add_event(TimedEvent(std::chrono::steady_clock::now() + 50ms, [](){ std::cout << "Timeout expired" << std::endl; }));
  // The event should not yet be expired
  assert(te_manager.get_timeout() > 0ms);
  assert(te_manager.execute_expired_events() == 0);
  std::chrono::milliseconds timoute = te_manager.get_timeout();
  std::cout << "Sleeping for " << timoute.count() << "ms" << std::endl;
  std::this_thread::sleep_for(timoute);

  // Event is now expired
  assert(te_manager.execute_expired_events() == 1);
  assert(te_manager.get_timeout() == utils::no_timeout);

52 53 54
  /**
   * Encoding
   */
55
  std::cout << color << "Testing encoding…" << reset << std::endl;
56 57 58 59 60 61 62
  const char* valid = "C̡͔͕̩͙̽ͫ̈́ͥ̿̆ͧ̚r̸̩̘͍̻͖̆͆͛͊̉̕͡o͇͈̳̤̱̊̈͢q̻͍̦̮͕ͥͬͬ̽ͭ͌̾ͅǔ͉͕͇͚̙͉̭͉̇̽ȇ͈̮̼͍͔ͣ͊͞͝ͅ ͫ̾ͪ̓ͥ̆̋̔҉̢̦̠͈͔̖̲̯̦ụ̶̯͐̃̋ͮ͆͝n̬̱̭͇̻̱̰̖̤̏͛̏̿̑͟ë́͐҉̸̥̪͕̹̻̙͉̰ ̹̼̱̦̥ͩ͑̈́͑͝ͅt͍̥͈̹̝ͣ̃̔̈̔ͧ̕͝ḙ̸̖̟̙͙ͪ͢ų̯̞̼̲͓̻̞͛̃̀́b̮̰̗̩̰̊̆͗̾̎̆ͯ͌͝.̗̙͎̦ͫ̈́ͥ͌̈̓ͬ";
  assert(utils::is_valid_utf8(valid) == true);
  const char* invalid = "\xF0\x0F";
  assert(utils::is_valid_utf8(invalid) == false);
  const char* invalid2 = "\xFE\xFE\xFF\xFF";
  assert(utils::is_valid_utf8(invalid2) == false);

63 64
  std::string in = "Biboumi ╯°□°)╯︵ ┻━┻";
  std::cout << in << std::endl;
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
  assert(utils::is_valid_utf8(in.c_str()) == true);
  std::string res = utils::convert_to_utf8(in, "UTF-8");
  assert(utils::is_valid_utf8(res.c_str()) == true && res == in);

  std::string original_utf8("couc¥ou");
  std::string original_latin1("couc\xa5ou");

  // When converting back to utf-8
  std::string from_latin1 = utils::convert_to_utf8(original_latin1.c_str(), "ISO-8859-1");
  assert(from_latin1 == original_utf8);

  // 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");
  assert(from_ascii == "couc�ou");
80
  std::cout << from_ascii << std::endl;
81

82 83 84 85 86
  std::string without_ctrl_char("𤭢€¢$");
  assert(utils::remove_invalid_xml_chars(without_ctrl_char) == without_ctrl_char);
  assert(utils::remove_invalid_xml_chars(in) == in);
  assert(utils::remove_invalid_xml_chars("\acouco\u0008u\uFFFEt\uFFFFe\r\n♥") == "coucoute\r\n♥");

louiz’'s avatar
louiz’ committed
87 88 89 90 91 92 93
  /**
   * Id generation
   */
  assert(XmppComponent::next_id() == "0");
  assert(XmppComponent::next_id() == "1");
  assert(XmppComponent::next_id() == "2");

94 95 96
  /**
   * Utils
   */
97
  std::cout << color << "Testing utils…" << reset << std::endl;
98 99 100 101 102 103 104 105 106 107 108 109
  std::vector<std::string> splitted = utils::split("a::a", ':', false);
  assert(splitted.size() == 2);
  splitted = utils::split("a::a", ':', true);
  assert(splitted.size() == 3);
  assert(splitted[0] == "a");
  assert(splitted[1] == "");
  assert(splitted[2] == "a");
  splitted = utils::split("\na", '\n', true);
  assert(splitted.size() == 2);
  assert(splitted[0] == "");
  assert(splitted[1] == "a");

louiz’'s avatar
louiz’ committed
110 111 112 113
  const std::string lowercase = utils::tolower("CoUcOu LeS CoPaiNs ♥");
  std::cout << lowercase << std::endl;
  assert(lowercase == "coucou les copains ♥");

114 115 116
  /**
   * XML parsing
   */
117
  std::cout << color << "Testing XML parsing…" << reset << std::endl;
118
  XmppParser xml;
119
  const std::string doc = "<stream xmlns='stream_ns'><stanza b='c'>inner<child1><grandchild/></child1><child2 xmlns='child2_ns'/>tail</stanza></stream>";
120 121
  xml.add_stanza_callback([](const Stanza& stanza)
      {
122
        std::cout << stanza.to_string() << std::endl;
123
        assert(stanza.get_name() == "stream_ns:stanza");
124
        assert(stanza.get_tag("b") == "c");
125 126 127 128 129 130 131 132
        assert(stanza.get_inner() == "inner");
        assert(stanza.get_tail() == "");
        assert(stanza.get_child("stream_ns:child1") != nullptr);
        assert(stanza.get_child("stream_ns:child2") == nullptr);
        assert(stanza.get_child("child2_ns:child2") != nullptr);
        assert(stanza.get_child("child2_ns:child2")->get_tail() == "tail");
      });
  xml.feed(doc.data(), doc.size(), true);
133

134 135 136 137 138 139 140 141
  const std::string doc2 = "<stream xmlns='s'><stanza>coucou\r\n\a</stanza></stream>";
  xml.add_stanza_callback([](const Stanza& stanza)
      {
        std::cout << stanza.to_string() << std::endl;
        assert(stanza.get_inner() == "coucou\r\n");
      });
  xml.feed(doc2.data(), doc.size(), true);

louiz’'s avatar
louiz’ committed
142 143 144
  /**
   * XML escape/escape
   */
145
  std::cout << color << "Testing XML escaping…" << reset << std::endl;
louiz’'s avatar
louiz’ committed
146 147 148 149
  const std::string unescaped = "'coucou'<cc>/&\"gaga\"";
  assert(xml_escape(unescaped) == "&apos;coucou&apos;&lt;cc&gt;/&amp;&quot;gaga&quot;");
  assert(xml_unescape(xml_escape(unescaped)) == unescaped);

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
  /**
   * Irc user parsing
   */
  const std::map<char, char> prefixes{{'!', 'a'}, {'@', 'o'}};

  IrcUser user1("!nick!~some@host.bla", prefixes);
  assert(user1.nick == "nick");
  assert(user1.host == "~some@host.bla");
  assert(user1.modes.size() == 1);
  assert(user1.modes.find('a') != user1.modes.end());
  IrcUser user2("coucou!~other@host.bla", prefixes);
  assert(user2.nick == "coucou");
  assert(user2.host == "~other@host.bla");
  assert(user2.modes.size() == 0);
  assert(user2.modes.find('a') == user2.modes.end());

166 167 168
  /**
   * Colors conversion
   */
169
  std::cout << color << "Testing IRC colors conversion…" << reset << std::endl;
170 171 172
  std::unique_ptr<XmlNode> xhtml;
  std::string cleaned_up;

173 174 175 176
  std::tie(cleaned_up, xhtml) = irc_format_to_xhtmlim("bold");
  std::cout << xhtml->to_string() << std::endl;
  assert(xhtml && xhtml->to_string() == "<body xmlns='http://www.w3.org/1999/xhtml'><span style='font-weight:bold;'>bold</span></body>");

177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
  std::tie(cleaned_up, xhtml) =
    irc_format_to_xhtmlim("normalboldunder-and-boldbold normal"
                          "5red,5default-on-red10,2cyan-on-blue");
  assert(xhtml);
  assert(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>");
  assert(cleaned_up == "normalboldunder-and-boldbold normalreddefault-on-redcyan-on-blue");

  std::tie(cleaned_up, xhtml) = irc_format_to_xhtmlim("normal");
  assert(!xhtml && cleaned_up == "normal");

  std::tie(cleaned_up, xhtml) = irc_format_to_xhtmlim("");
  assert(xhtml && !xhtml->has_children() && cleaned_up.empty());

  std::tie(cleaned_up, xhtml) = irc_format_to_xhtmlim(",a");
  assert(xhtml && !xhtml->has_children() && cleaned_up == "a");

  std::tie(cleaned_up, xhtml) = irc_format_to_xhtmlim(",");
  assert(xhtml && !xhtml->has_children() && cleaned_up.empty());

196 197 198 199
  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");
  assert(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>");
  assert(cleaned_up == "[dolphin-emu/dolphin] foo commented on #283 (Add support for the guide button to XInput): http://example.com");

200 201 202 203
  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");
  assert(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");
  assert(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>");

Link Mauve's avatar
Link Mauve committed
204 205 206
  /**
   * JID parsing
   */
207
  std::cout << color << "Testing JID parsing…" << reset << std::endl;
Link Mauve's avatar
Link Mauve committed
208 209
  // Full JID
  Jid jid1("♥@ツ.coucou/coucou@coucou/coucou");
210
  std::cout << jid1.local << "@" << jid1.domain << "/" << jid1.resource << std::endl;
Link Mauve's avatar
Link Mauve committed
211 212 213 214 215 216
  assert(jid1.local == "♥");
  assert(jid1.domain == "ツ.coucou");
  assert(jid1.resource == "coucou@coucou/coucou");

  // Domain and resource
  Jid jid2("ツ.coucou/coucou@coucou/coucou");
217
  std::cout << jid2.local << "@" << jid2.domain << "/" << jid2.resource << std::endl;
Link Mauve's avatar
Link Mauve committed
218 219 220 221
  assert(jid2.local == "");
  assert(jid2.domain == "ツ.coucou");
  assert(jid2.resource == "coucou@coucou/coucou");

222
  // Jidprep
louiz’'s avatar
louiz’ committed
223
  const std::string& badjid("~zigougou™@EpiK-7D9D1FDE.poez.io/Boujour/coucou/slt™");
224
  const std::string correctjid = jidprep(badjid);
louiz’'s avatar
louiz’ committed
225
  assert(correctjid == "~zigougoutm@epik-7d9d1fde.poez.io/Boujour/coucou/sltTM");
226 227 228 229 230

  const std::string& badjid2("Zigougou@poez.io");
  const std::string correctjid2 = jidprep(badjid2);
  std::cout << correctjid2 << std::endl;
  assert(correctjid2 == "zigougou@poez.io");
231

232 233 234
  /**
   * Config
   */
235
  std::cout << color << "Testing config…" << reset << std::endl;
236 237
  Config::filename = "test.cfg";
  Config::file_must_exist = false;
238
  Config::set("coucou", "bonjour", true);
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
  Config::close();

  bool error = false;
  try
    {
      Config::file_must_exist = true;
      assert(Config::get("coucou", "") == "bonjour");
      assert(Config::get("does not exist", "default") == "default");
      Config::close();
    }
  catch (const std::ios::failure& e)
    {
      error = true;
    }
  assert(error == false);
254

louiz’'s avatar
louiz’ committed
255
  Config::set("log_level", "2");
louiz’'s avatar
louiz’ committed
256 257
  Config::set("log_file", "");

louiz’'s avatar
louiz’ committed
258 259 260 261 262
  std::cout << color << "Testing logging…" << reset << std::endl;
  log_debug("If you see this, the test FAILED.");
  log_info("If you see this, the test FAILED.");
  log_warning("You wust see this message. And the next one too.");
  log_error("It’s not an error, don’t worry, the test passed.");
louiz’'s avatar
louiz’ committed
263

264 265
  return 0;
}