add tests for irc_cmd/irc_line, and fix handling of missing-prefix to set source to NULL in irc_line
authorTero Marttila <terom@fixme.fi>
Fri, 08 May 2009 00:13:38 +0300
changeset 190 69fd25c8484c
parent 189 f351facab1f0
child 191 031582f7b61b
add tests for irc_cmd/irc_line, and fix handling of missing-prefix to set source to NULL in irc_line
src/irc_line.c
src/irc_line.h
src/test/irc_cmd.c
src/test/irc_line.c
src/test/test_list.inc
--- a/src/irc_line.c	Fri May 08 00:12:52 2009 +0300
+++ b/src/irc_line.c	Fri May 08 00:13:38 2009 +0300
@@ -9,9 +9,9 @@
     int i;
     err_t err;
 
-    // prefix?
+    // line would start with a prefix
     if (data && *data == ':') {
-        // consume as token
+        // consume the prefix as token
         char *prefix = strsep(&data, " ") + 1;
         
         // parse as a nickmask
@@ -23,6 +23,9 @@
             // valid, store
             line->source = nm;
         }
+    } else {
+        // no prefix
+        line->source = NULL;
     }
 
     // command
--- a/src/irc_line.h	Fri May 08 00:12:52 2009 +0300
+++ b/src/irc_line.h	Fri May 08 00:13:38 2009 +0300
@@ -51,6 +51,8 @@
  * If the prefix is a valid nickmask, it will be stored in the given given irc_nm, and irc_line.nm set to this.
  *
  * The irc_line will have the first N args values set to valid values, and all the rest set to NULL.
+ *
+ * XXX: strip trailing \r\n
  */
 err_t irc_line_parse (struct irc_line *line, struct irc_nm *nm, char *data);
 
@@ -61,6 +63,8 @@
  *
  * An error is returned if a token has an invalid value (e.g. a space in the command or an argument other than the last
  * one), or if the resulting line is too long.
+ *
+ * XXX: append trailing \r\n
  */
 err_t irc_line_build (const struct irc_line *line, char *buf);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/irc_cmd.c	Fri May 08 00:13:38 2009 +0300
@@ -0,0 +1,91 @@
+#include "../irc_cmd.h"
+#include "test.h"
+
+struct test_irc_cmd_ctx {
+    const struct irc_line *line;
+
+    int test;
+};
+
+static void on_TEST_1 (const struct irc_line *line, void *arg)
+{
+    struct test_irc_cmd_ctx *ctx = arg;
+    
+    log_debug("%s: %s", line->command, line->args[0]);
+
+    assert(line == ctx->line);
+    assert(ctx->test = 1);
+
+    ctx->test = 0;
+}
+
+static void on_TEST_2 (const struct irc_line *line, void *arg)
+{
+    struct test_irc_cmd_ctx *ctx = arg;
+    
+    log_debug("%s: %s", line->command, line->args[0]);
+
+    assert(line == ctx->line);
+    assert(ctx->test = 2);
+
+    ctx->test = 0;
+}
+
+static const struct irc_cmd_handler _handlers[] = {
+    {   "TEST_1",   on_TEST_1   },
+    {   "TEST_2",   on_TEST_2   },
+    {   NULL,       NULL        }
+};
+
+void assert_cmd_invoke (struct irc_cmd_handlers *handlers, struct test_irc_cmd_ctx *ctx, const char *command, int test)
+{
+    struct irc_line line;
+ 
+    // setup line
+    ctx->line = &line;
+    line.source = NULL;
+    line.command = command;
+    line.args[0] = "this is a test";
+    ctx->test = test;
+    
+    irc_cmd_invoke(handlers, &line);
+
+    if (test < 0)
+        assert(ctx->test == -1);
+    else
+        assert(!ctx->test);
+}
+
+void test_irc_cmd (void)
+{
+    struct test_irc_cmd_ctx ctx;
+    struct irc_cmd_handlers handlers;
+
+    // setup our handlers
+    irc_cmd_init(&handlers);
+    irc_cmd_add(&handlers, _handlers, &ctx);
+
+    // test first command
+    assert_cmd_invoke(&handlers, &ctx, "TEST_1", 1);
+    
+    // test second command
+    assert_cmd_invoke(&handlers, &ctx, "TEST_2", 2);
+    
+    // test unknown command
+    assert_cmd_invoke(&handlers, &ctx, "TEST_3", -1);
+
+    // remove unknown handler (wrong ctx arg)
+    irc_cmd_remove(&handlers, _handlers, &handlers);
+
+    // ensure it still works
+    assert_cmd_invoke(&handlers, &ctx, "TEST_1", 1);
+    
+    // remove the right handler
+    irc_cmd_remove(&handlers, _handlers, &ctx);
+
+    // ensure it doesn't work anymore
+    assert_cmd_invoke(&handlers, &ctx, "TEST_1", -1);
+    
+    // do clear, although this will be empty...
+    irc_cmd_clear(&handlers);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/irc_line.c	Fri May 08 00:13:38 2009 +0300
@@ -0,0 +1,131 @@
+#include "../irc_line.h"
+#include "test.h"
+
+
+void assert_irc_line_cmp (const struct irc_line *is, const struct irc_line *should_be)
+{
+    if (should_be->source) {
+        assert(is->source);
+        assert_strcmp(is->source->nickname, should_be->source->nickname);
+        assert_strcmp(is->source->username, should_be->source->username);
+        assert_strcmp(is->source->hostname, should_be->source->hostname);
+
+    } else {
+        assert_null(is->source);
+    }
+    
+    assert_strcmp(is->command, should_be->command);
+    
+    for (size_t idx = 0; idx < IRC_ARG_MAX; idx++) {
+        if (!should_be->args[idx])
+            break;
+
+        assert_strcmp(is->args[idx], should_be->args[idx]);
+    }
+}
+
+void assert_irc_line_parse (const char *data, const struct irc_line *line)
+{
+    struct irc_line out_line;
+    struct irc_nm nm;
+    char buf[1024];
+
+    assert(strlen(data) < 1024);
+    strcpy(buf, data);
+
+    assert_success(irc_line_parse(&out_line, &nm, buf));
+    assert_irc_line_cmp(&out_line, line);
+}
+
+void assert_irc_line_build (const struct irc_line *line, const char *data)
+{
+    char buf[IRC_LINE_MAX];
+
+    assert_success(irc_line_build(line, buf));
+    assert_strcmp(buf, data);
+}
+
+void assert_irc_line_build_err (const struct irc_line *line, err_t err)
+{
+    char buf[IRC_LINE_MAX];
+
+    assert_err(irc_line_build(line, buf), err);
+}
+
+#define TEST_IRC_LINE_PARSE(in, source, command, ...) \
+    do {    \
+        struct irc_line line = { source, command, { __VA_ARGS__, NULL } };  \
+        assert_irc_line_parse(in, &line);   \
+    } while (0)
+
+void test_irc_line_parse (void)
+{
+    struct irc_nm source = { "nick", "user", "host" };
+    struct irc_nm source_server = { NULL, NULL, "server" };
+
+    TEST_IRC_LINE_PARSE("CMD_1",
+            NULL, "CMD_1", NULL);
+    
+    TEST_IRC_LINE_PARSE(":nick!user@host CMD_2 arg1 arg2 :trailing arg",
+            &source, "CMD_2", "arg1", "arg2", "trailing arg");
+    
+    TEST_IRC_LINE_PARSE(":nick!user@host CMD_3 :arg0",
+            &source, "CMD_3", "arg0");
+    
+    TEST_IRC_LINE_PARSE(":server CMD_4 arg0",
+            &source_server, "CMD_4", "arg0");
+    
+    TEST_IRC_LINE_PARSE(":foo!bar CMD_5 :arg0",
+            NULL, "CMD_5", "arg0");
+}
+
+
+#define TEST_IRC_LINE_BUILD(out, command, ...) \
+    do {    \
+        struct irc_line line = { NULL, command, { __VA_ARGS__, NULL } };    \
+        assert_irc_line_build(&line, out); \
+    } while (0)
+
+#define TEST_IRC_LINE_BUILD_ERR(err, command, ...) \
+    do {    \
+        struct irc_line line = { NULL, command, { __VA_ARGS__, NULL } };    \
+        assert_irc_line_build_err(&line, err);   \
+    } while (0)
+
+void test_irc_line_build (void)
+{
+    TEST_IRC_LINE_BUILD("CMD_1",            
+            "CMD_1", NULL);
+
+    TEST_IRC_LINE_BUILD("CMD_2 arg0",       
+            "CMD_2", "arg0");
+
+    TEST_IRC_LINE_BUILD("CMD_3 arg0 arg1",
+            "CMD_3", "arg0", "arg1");
+
+    TEST_IRC_LINE_BUILD("CMD_4 :argX argX",
+            "CMD_4", "argX argX");
+
+    TEST_IRC_LINE_BUILD("CMD_5 arg0 :argX argX",
+            "CMD_5", "arg0", "argX argX");
+    
+    TEST_IRC_LINE_BUILD_ERR(ERR_LINE_TOO_LONG,
+              "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+              "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+              "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+              "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+              "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+              NULL);
+
+    TEST_IRC_LINE_BUILD_ERR(ERR_LINE_INVALID_TOKEN,
+            "XXX", "foo bar", "quux");
+
+    TEST_IRC_LINE_BUILD_ERR(ERR_LINE_INVALID_TOKEN,
+            "XXX", "foo\r\n");
+
+    TEST_IRC_LINE_BUILD_ERR(ERR_LINE_INVALID_TOKEN,
+            "XXX", "foo", "bar quux\r\n");
+
+}
+
+
--- a/src/test/test_list.inc	Fri May 08 00:12:52 2009 +0300
+++ b/src/test/test_list.inc	Fri May 08 00:13:38 2009 +0300
@@ -36,6 +36,10 @@
 
 TEST ( line_proto                   )
 
+TEST ( irc_cmd                      )
+TEST ( irc_line_parse               )
+TEST ( irc_line_build               )
+
 TEST ( irc_queue                    )
 TEST ( irc_conn                     )
 TEST ( irc_conn_self_nick           )