diff --git a/.gitignore b/.gitignore index d1d39a8f..014dd13a 100644 --- a/.gitignore +++ b/.gitignore @@ -56,13 +56,19 @@ ircd/version.c ircd/version.c.last ssld/ssld wsockd/wsockd +tests/core tests/msgbuf_parse1 tests/msgbuf_unparse1 tests/rb_linebuf_put1 tests/rb_snprintf_append1 tests/rb_snprintf_try_append1 +tests/send1 tests/substitution1 tests/runtests +tests/*.c.ban.db +tests/*.c.ban.db-journal +tests/*.c.log +tests/*.c.pid testsuite/ircd.pid.* tools/charybdis-mkpasswd tools/charybdis-mkfingerprint diff --git a/ircd/ircd.c b/ircd/ircd.c index d6843072..c224d40e 100644 --- a/ircd/ircd.c +++ b/ircd/ircd.c @@ -823,13 +823,6 @@ charybdis_main(int argc, char * const argv[]) ircd_ssl_ok = true; } - if (testing_conf) - { - fprintf(stderr, "\nConfig testing complete.\n"); - fflush(stderr); - return 0; /* Why? We want the launcher to exit out. */ - } - me.from = &me; me.servptr = &me; SetMe(&me); @@ -843,6 +836,13 @@ charybdis_main(int argc, char * const argv[]) construct_umodebuf(); + if (testing_conf) + { + fprintf(stderr, "\nConfig testing complete.\n"); + fflush(stderr); + return 0; /* Why? We want the launcher to exit out. */ + } + check_class(); write_pidfile(pidFileName); load_help(); diff --git a/tests/Makefile.am b/tests/Makefile.am index c57b876a..20da4da9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,6 +4,7 @@ check_PROGRAMS = runtests \ rb_linebuf_put1 \ rb_snprintf_append1 \ rb_snprintf_try_append1 \ + send1 \ substitution1 AM_CFLAGS=$(WARNFLAGS) AM_CPPFLAGS = $(DEFAULT_INCLUDES) -I../librb/include -I.. @@ -24,7 +25,16 @@ msgbuf_unparse1_SOURCES = msgbuf_unparse1.c rb_linebuf_put1_SOURCES = rb_linebuf_put1.c rb_snprintf_append1_SOURCES = rb_snprintf_append1.c rb_snprintf_try_append1_SOURCES = rb_snprintf_try_append1.c +send1_SOURCES = send1.c ircd_util.c client_util.c substitution1_SOURCES = substitution1.c -check-local: $(check_PROGRAMS) +check-local: $(check_PROGRAMS) \ + ../authd/authd \ + ../bandb/bandb \ + ../ssld/ssld \ + ../wsockd/wsockd \ + $(patsubst ../modules/%.c,../modules/.libs/%.so,$(wildcard ../modules/*.c)) \ + $(patsubst ../modules/core/%.c,../modules/core/.libs/%.so,$(wildcard ../modules/core/*.c)) \ + $(patsubst ../extensions/%.c,../extensions/.libs/%.so,$(wildcard ../extensions/*.c)) + ./runtests -l $(abs_top_srcdir)/tests/TESTS diff --git a/tests/TESTS b/tests/TESTS index e5849bef..e4a4acb5 100644 --- a/tests/TESTS +++ b/tests/TESTS @@ -3,4 +3,5 @@ msgbuf_unparse1 rb_linebuf_put1 rb_snprintf_append1 rb_snprintf_try_append1 +send1 substitution1 diff --git a/tests/client_util.c b/tests/client_util.c new file mode 100644 index 00000000..9a6468e9 --- /dev/null +++ b/tests/client_util.c @@ -0,0 +1,94 @@ +/* + * client_util.c: Utility functions for making test clients + * Copyright 2017 Simon Arlott + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ +#include +#include +#include +#include +#include "tap/basic.h" + +#include "stdinc.h" +#include "ircd_defs.h" +#include "client_util.h" + +#define MSG "%s:%d (%s)", __FILE__, __LINE__, __FUNCTION__ + +struct Client *make_local_person(void) +{ + return make_local_person_nick(TEST_NICK); +} + +struct Client *make_local_person_nick(const char *nick) +{ + return make_local_person_full(nick, TEST_USERNAME, TEST_HOSTNAME, TEST_IP, TEST_REALNAME); +} + +struct Client *make_local_person_full(const char *nick, const char *username, const char *hostname, const char *ip, const char *realname) +{ + struct Client *client; + + client = make_client(NULL); + rb_dlinkMoveNode(&client->localClient->tnode, &unknown_list, &lclient_list); + client->servptr = &me; + rb_dlinkAdd(client, &client->lnode, &client->servptr->serv->users); + SetClient(client); + make_user(client); + + rb_inet_pton_sock(ip, (struct sockaddr *)&client->localClient->ip); + rb_strlcpy(client->name, nick, sizeof(client->name)); + rb_strlcpy(client->username, username, sizeof(client->username)); + rb_strlcpy(client->host, hostname, sizeof(client->host)); + rb_inet_ntop_sock((struct sockaddr *)&client->localClient->ip, client->sockhost, sizeof(client->sockhost)); + rb_strlcpy(client->info, realname, sizeof(client->info)); + + return client; +} + +void remove_local_person(struct Client *client) +{ + exit_client(NULL, client, &me, "Test client removed"); +} + +char *get_client_sendq(const struct Client *client) +{ + static char buf[EXT_BUFSIZE + sizeof(CRLF)]; + + if (rb_linebuf_len(&client->localClient->buf_sendq)) { + int ret; + + memset(buf, 0, sizeof(buf)); + ret = rb_linebuf_get(&client->localClient->buf_sendq, buf, sizeof(buf), 0, 1); + + if (is_bool(ret > 0, true, MSG)) { + return buf; + } else { + return ""; + } + } + + return ""; +} + +void client_util_init(void) +{ +} + +void client_util_free(void) +{ +} diff --git a/tests/client_util.h b/tests/client_util.h new file mode 100644 index 00000000..5bacac08 --- /dev/null +++ b/tests/client_util.h @@ -0,0 +1,55 @@ +/* + * client_util.c: Utility functions for making test clients + * Copyright 2017 Simon Arlott + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ +#include +#include +#include +#include + +#include "stdinc.h" +#include "ircd_defs.h" +#include "msg.h" +#include "client.h" + +#define TEST_NICK "test" +#define TEST_USERNAME "username" +#define TEST_HOSTNAME "example.test" +#define TEST_IP "2001:db8::1:5ee:bad:c0de" +#define TEST_REALNAME "Test user" + +#define CRLF "\r\n" + +void client_util_init(void); +void client_util_free(void); + +struct Client *make_local_person(void); +struct Client *make_local_person_nick(const char *nick); +struct Client *make_local_person_full(const char *nick, const char *username, const char *hostname, const char *ip, const char *realname); +void remove_local_person(struct Client *client); + +char *get_client_sendq(const struct Client *client); + +#define is_client_sendq_empty(client, message, ...) do { \ + is_string("", get_client_sendq(client), message, ##__VA_ARGS__); \ + } while (0) + +#define is_client_sendq(queue, client, message, ...) do { \ + is_string(queue, get_client_sendq(client), message, ##__VA_ARGS__); \ + is_client_sendq_empty(client, message, ##__VA_ARGS__); \ + } while (0) diff --git a/tests/ircd_util.c b/tests/ircd_util.c new file mode 100644 index 00000000..b6e895d3 --- /dev/null +++ b/tests/ircd_util.c @@ -0,0 +1,102 @@ +/* + * ircd_util.c: Utility functions for making test ircds + * Copyright 2017 Simon Arlott + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ +#include +#include +#include +#include +#include "tap/basic.h" + +#include "stdinc.h" +#include "ircd_defs.h" +#include "defaults.h" +#include "client.h" +#include "ircd_util.h" + +#define MSG "%s:%d (%s)", __FILE__, __LINE__, __FUNCTION__ + +extern int charybdis_main(int argc, const char *argv[]); + +static char argv0[BUFSIZE]; +static char configfile[BUFSIZE]; +static char logfile[BUFSIZE]; +static char pidfile[BUFSIZE]; + +static const char *argv[] = { + argv0, + "-configfile", configfile, + "-logfile", logfile, + "-pidfile", pidfile, + "-conftest", + NULL, +}; + +void ircd_util_init(const char *name) +{ + rb_strlcpy(argv0, name, sizeof(argv0)); + snprintf(configfile, sizeof(configfile), "%sonf", name); + snprintf(logfile, sizeof(logfile), "%s.log", name); + snprintf(pidfile, sizeof(pidfile), "%s.pid", name); + unlink(logfile); + unlink(pidfile); + + rb_lib_init(NULL, NULL, NULL, 0, 1024, DNODE_HEAP_SIZE, FD_HEAP_SIZE); + rb_linebuf_init(LINEBUF_HEAP_SIZE); + + char buf[BUFSIZE]; + ircd_paths[IRCD_PATH_IRCD_EXEC] = argv0; + ircd_paths[IRCD_PATH_PREFIX] = "."; + + snprintf(buf, sizeof(buf), "runtime%cmodules", RB_PATH_SEPARATOR); + ircd_paths[IRCD_PATH_MODULES] = rb_strdup(buf); + + snprintf(buf, sizeof(buf), "runtime%1$cmodules%1$cautoload", RB_PATH_SEPARATOR); + ircd_paths[IRCD_PATH_AUTOLOAD_MODULES] = rb_strdup(buf); + + ircd_paths[IRCD_PATH_ETC] = "runtime"; + ircd_paths[IRCD_PATH_LOG] = "runtime"; + + snprintf(buf, sizeof(buf), "runtime%1$chelp%1$cusers", RB_PATH_SEPARATOR); + ircd_paths[IRCD_PATH_USERHELP] = rb_strdup(buf); + + snprintf(buf, sizeof(buf), "runtime%1$chelp%1$copers", RB_PATH_SEPARATOR); + ircd_paths[IRCD_PATH_OPERHELP] = rb_strdup(buf); + + snprintf(buf, sizeof(buf), "runtime%cmotd", RB_PATH_SEPARATOR); + ircd_paths[IRCD_PATH_IRCD_MOTD] = rb_strdup(buf); + ircd_paths[IRCD_PATH_IRCD_OMOTD] = rb_strdup(buf); + + snprintf(buf, sizeof(buf), "%s.ban.db", name); + ircd_paths[IRCD_PATH_BANDB] = rb_strdup(buf); + snprintf(buf, sizeof(buf), "%s.ban.db-journal", name); + unlink(buf); + + ircd_paths[IRCD_PATH_IRCD_PID] = rb_strdup(pidfile); + ircd_paths[IRCD_PATH_IRCD_LOG] = rb_strdup(logfile); + + snprintf(buf, sizeof(buf), "runtime%cbin", RB_PATH_SEPARATOR); + ircd_paths[IRCD_PATH_BIN] = rb_strdup(buf); + ircd_paths[IRCD_PATH_LIBEXEC] = rb_strdup(buf); + + is_int(0, charybdis_main(ARRAY_SIZE(argv) - 1, argv), MSG); +} + +void ircd_util_free(void) +{ +} diff --git a/tests/ircd_util.h b/tests/ircd_util.h new file mode 100644 index 00000000..cde5adb8 --- /dev/null +++ b/tests/ircd_util.h @@ -0,0 +1,31 @@ +/* + * ircd_util.c: Utility functions for making test ircds + * Copyright 2017 Simon Arlott + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ +#include +#include +#include +#include + +#include "stdinc.h" +#include "ircd_defs.h" + +#define TEST_ME_NAME "me.test" + +void ircd_util_init(const char *name); +void ircd_util_free(void); diff --git a/tests/runtime/bin/authd b/tests/runtime/bin/authd new file mode 120000 index 00000000..e4c0453f --- /dev/null +++ b/tests/runtime/bin/authd @@ -0,0 +1 @@ +../../../authd/authd \ No newline at end of file diff --git a/tests/runtime/bin/bandb b/tests/runtime/bin/bandb new file mode 120000 index 00000000..3543deba --- /dev/null +++ b/tests/runtime/bin/bandb @@ -0,0 +1 @@ +../../../bandb/bandb \ No newline at end of file diff --git a/tests/runtime/bin/ssld b/tests/runtime/bin/ssld new file mode 120000 index 00000000..0f55f62f --- /dev/null +++ b/tests/runtime/bin/ssld @@ -0,0 +1 @@ +../../../ssld/ssld \ No newline at end of file diff --git a/tests/runtime/bin/wsockd b/tests/runtime/bin/wsockd new file mode 120000 index 00000000..0331b166 --- /dev/null +++ b/tests/runtime/bin/wsockd @@ -0,0 +1 @@ +../../../wsockd/wsockd \ No newline at end of file diff --git a/tests/runtime/help b/tests/runtime/help new file mode 120000 index 00000000..92f65004 --- /dev/null +++ b/tests/runtime/help @@ -0,0 +1 @@ +../../help \ No newline at end of file diff --git a/tests/runtime/motd b/tests/runtime/motd new file mode 100644 index 00000000..980a0d5f --- /dev/null +++ b/tests/runtime/motd @@ -0,0 +1 @@ +Hello World! diff --git a/tests/send1.c b/tests/send1.c new file mode 100644 index 00000000..2ed74ab5 --- /dev/null +++ b/tests/send1.c @@ -0,0 +1,119 @@ +/* + * send1.c: Test sendto_* under various conditions + * Copyright 2017 Simon Arlott + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ +#include +#include +#include +#include +#include "tap/basic.h" + +#include "ircd_util.h" +#include "client_util.h" + +#include "send.h" + +#define MSG "%s:%d (%s)", __FILE__, __LINE__, __FUNCTION__ + +static void sendto_one_numeric1(void) +{ + struct Client *user = make_local_person(); + + sendto_one_numeric(user, 1, "Hello %s!", "World"); + is_client_sendq(":" TEST_ME_NAME " 001 " TEST_NICK " Hello World!" CRLF, user, MSG); + + remove_local_person(user); +} + +static void sendto_wallops_flags1(void) +{ + struct Client *user1 = make_local_person_nick("user1"); + struct Client *user2 = make_local_person_nick("user2"); + struct Client *oper1 = make_local_person_nick("oper1"); + struct Client *oper2 = make_local_person_nick("oper2"); + struct Client *oper3 = make_local_person_nick("oper3"); + struct Client *oper4 = make_local_person_nick("oper4"); + + rb_dlinkAddAlloc(oper1, &local_oper_list); + rb_dlinkAddAlloc(oper1, &oper_list); + SetOper(oper1); + + rb_dlinkAddAlloc(oper2, &local_oper_list); + rb_dlinkAddAlloc(oper2, &oper_list); + SetOper(oper2); + + rb_dlinkAddAlloc(oper3, &local_oper_list); + rb_dlinkAddAlloc(oper3, &oper_list); + SetOper(oper3); + + rb_dlinkAddAlloc(oper4, &local_oper_list); + rb_dlinkAddAlloc(oper4, &oper_list); + SetOper(oper4); + + user1->umodes |= UMODE_WALLOP; + oper1->umodes |= UMODE_WALLOP | UMODE_OPERWALL; + oper2->umodes |= UMODE_WALLOP | UMODE_OPERWALL | UMODE_ADMIN; + oper3->umodes |= UMODE_WALLOP; + oper4->umodes |= UMODE_OPERWALL; + + sendto_wallops_flags(UMODE_WALLOP, oper1, "Test to users"); + is_client_sendq(":oper1!" TEST_USERNAME "@" TEST_HOSTNAME " WALLOPS :Test to users" CRLF, user1, "User is +w; " MSG); + is_client_sendq_empty(user2, "User is -w; " MSG); + is_client_sendq(":oper1!" TEST_USERNAME "@" TEST_HOSTNAME " WALLOPS :Test to users" CRLF, oper1, "User is +w; " MSG); + is_client_sendq(":oper1!" TEST_USERNAME "@" TEST_HOSTNAME " WALLOPS :Test to users" CRLF, oper2, "User is +w; " MSG); + is_client_sendq(":oper1!" TEST_USERNAME "@" TEST_HOSTNAME " WALLOPS :Test to users" CRLF, oper3, "User is +w; " MSG); + is_client_sendq_empty(oper4, "User is -w; " MSG); + + sendto_wallops_flags(UMODE_OPERWALL, oper2, "Test to opers"); + is_client_sendq_empty(user1, "Not an oper; " MSG); + is_client_sendq_empty(user2, "Not an oper; " MSG); + is_client_sendq(":oper2!" TEST_USERNAME "@" TEST_HOSTNAME " WALLOPS :Test to opers" CRLF, oper1, "Oper is +z; " MSG); + is_client_sendq(":oper2!" TEST_USERNAME "@" TEST_HOSTNAME " WALLOPS :Test to opers" CRLF, oper2, "Oper is +z; " MSG); + is_client_sendq_empty(oper3, "Oper is -z; " MSG); + is_client_sendq(":oper2!" TEST_USERNAME "@" TEST_HOSTNAME " WALLOPS :Test to opers" CRLF, oper4, "Oper is +z; " MSG); + + sendto_wallops_flags(UMODE_ADMIN, &me, "Test to admins"); + is_client_sendq_empty(user1, "Not an admin; " MSG); + is_client_sendq_empty(user2, "Not an admin; " MSG); + is_client_sendq_empty(oper1, "Not an admin; " MSG); + is_client_sendq(":" TEST_ME_NAME " WALLOPS :Test to admins" CRLF, oper2, MSG); + is_client_sendq_empty(oper3, "Not an admin; " MSG); + is_client_sendq_empty(oper4, "Not an admin; " MSG); + + remove_local_person(user1); + remove_local_person(user2); + remove_local_person(oper1); + remove_local_person(oper2); + remove_local_person(oper3); + remove_local_person(oper4); +} + +int main(int argc, char *argv[]) +{ + plan_lazy(); + + ircd_util_init(__FILE__); + client_util_init(); + + sendto_one_numeric1(); + sendto_wallops_flags1(); + + client_util_free(); + ircd_util_free(); + return 0; +} diff --git a/tests/send1.conf b/tests/send1.conf new file mode 100644 index 00000000..3c198e27 --- /dev/null +++ b/tests/send1.conf @@ -0,0 +1,7 @@ +serverinfo { + sid = "0AA"; + name = "me.test"; + description = "Test server"; + network_name = "Test network"; +}; +