[PATCH] test: Improve tests for the date/time parser module
authorMichal Sojka <sojkam1@fel.cvut.cz>
Tue, 25 Sep 2012 12:05:27 +0000 (14:05 +0200)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:49:37 +0000 (09:49 -0800)
80/4ab7afcc59a8296a7ddf16a9ab46f15f84746e [new file with mode: 0644]

diff --git a/80/4ab7afcc59a8296a7ddf16a9ab46f15f84746e b/80/4ab7afcc59a8296a7ddf16a9ab46f15f84746e
new file mode 100644 (file)
index 0000000..1ed9e56
--- /dev/null
@@ -0,0 +1,346 @@
+Return-Path: <sojkam1@fel.cvut.cz>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+       by olra.theworths.org (Postfix) with ESMTP id 09F44431FC0\r
+       for <notmuch@notmuchmail.org>; Tue, 25 Sep 2012 05:22:36 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -2.3\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-2.3 tagged_above=-999 required=5\r
+       tests=[RCVD_IN_DNSWL_MED=-2.3] autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+       by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+       with ESMTP id xyvE91thvojF for <notmuch@notmuchmail.org>;\r
+       Tue, 25 Sep 2012 05:22:34 -0700 (PDT)\r
+Received: from max.feld.cvut.cz (max.feld.cvut.cz [147.32.192.36])\r
+       by olra.theworths.org (Postfix) with ESMTP id 911A4431FAF\r
+       for <notmuch@notmuchmail.org>; Tue, 25 Sep 2012 05:22:34 -0700 (PDT)\r
+Received: from localhost (unknown [192.168.200.4])\r
+       by max.feld.cvut.cz (Postfix) with ESMTP id 816F03CFF23;\r
+       Tue, 25 Sep 2012 14:21:40 +0200 (CEST)\r
+X-Virus-Scanned: IMAP AMAVIS\r
+Received: from max.feld.cvut.cz ([192.168.200.1])\r
+       by localhost (styx.feld.cvut.cz [192.168.200.4]) (amavisd-new,\r
+       port 10044)\r
+       with ESMTP id i3GAJ3IoEsxP; Tue, 25 Sep 2012 14:21:38 +0200 (CEST)\r
+Received: from imap.feld.cvut.cz (imap.feld.cvut.cz [147.32.192.34])\r
+       by max.feld.cvut.cz (Postfix) with ESMTP id 011023CFEE7;\r
+       Tue, 25 Sep 2012 14:05:43 +0200 (CEST)\r
+Received: from steelpick.2x.cz (unknown [213.29.198.144])\r
+       (Authenticated sender: sojkam1)\r
+       by imap.feld.cvut.cz (Postfix) with ESMTPSA id 1F9F6660969;\r
+       Tue, 25 Sep 2012 14:05:33 +0200 (CEST)\r
+Received: from wsh by steelpick.2x.cz with local (Exim 4.80)\r
+       (envelope-from <sojkam1@fel.cvut.cz>)\r
+       id 1TGTtH-0001WN-Nb; Tue, 25 Sep 2012 14:05:27 +0200\r
+From: Michal Sojka <sojkam1@fel.cvut.cz>\r
+To: Jani Nikula <jani@nikula.org>, notmuch@notmuchmail.org,\r
+       David Bremner <david@tethera.net>\r
+Subject: [PATCH] test: Improve tests for the date/time parser module\r
+In-Reply-To:\r
+ <24186aafbdcb967b8f66c2390c928f3788ab6cbf.1347484177.git.jani@nikula.org>\r
+References: <cover.1347484177.git.jani@nikula.org>\r
+       <24186aafbdcb967b8f66c2390c928f3788ab6cbf.1347484177.git.jani@nikula.org>\r
+User-Agent: Notmuch/0.14+23~g9d68aca (http://notmuchmail.org) Emacs/24.2.1\r
+       (x86_64-pc-linux-gnu)\r
+Date: Tue, 25 Sep 2012 14:05:27 +0200\r
+Message-ID: <87zk4e1f5k.fsf@steelpick.2x.cz>\r
+MIME-Version: 1.0\r
+Content-Type: text/plain\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+       <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Tue, 25 Sep 2012 12:22:36 -0000\r
+\r
+This patch reworks date/time parser library test program to make it\r
+easier to to write the actual tests. It also modifies the notmuch test\r
+script and adds several new tests to it.\r
+\r
+The INPUT file for the test contains both the dates to be parsed as well\r
+as the "expected" results. The test program outputs the results in the\r
+same format and replaces expected results with real results. Currently,\r
+the "expected" results in the INPUT file correspond to the real results,\r
+so the test passes. Some results are, however, different from what I\r
+would expect - this is mentioned in the comments after '#'.\r
+\r
+This patch applies on top of Jani's patchset.\r
+---\r
+It can be seen that there are several errors and unexpected results.\r
+As I've already written, I'm not sure that the approach taken by this\r
+library is the right one. I tend to agree with mina86, that using a\r
+more systematic approach (such as bison) would be beneficial.\r
+\r
+This is however not to say to throw this patchset away. Either Jani\r
+will be able to fix all the corner cases. Or we can work together to\r
+develop a better solution - add support for ranges to the bison\r
+parser.\r
+\r
+-Michal\r
+\r
+diff --git a/test/Makefile.local b/test/Makefile.local\r
+index 9ae130a..b9105c7 100644\r
+--- a/test/Makefile.local\r
++++ b/test/Makefile.local\r
+@@ -20,7 +20,7 @@ $(dir)/symbol-test: $(dir)/symbol-test.o\r
+       $(call quiet,CXX) $^ -o $@ -Llib -lnotmuch $(XAPIAN_LDFLAGS)\r
+ \r
+ $(dir)/parse-time: $(dir)/parse-time.o parse-time-string/parse-time-string.o\r
+-      $(call quiet,CC) $^ -o $@\r
++      $(call quiet,CC) $^ -o $@ -lrt\r
+ \r
+ .PHONY: test check\r
+ \r
+diff --git a/test/parse-time-string b/test/parse-time-string\r
+index 34b80d7..265437c 100755\r
+--- a/test/parse-time-string\r
++++ b/test/parse-time-string\r
+@@ -14,13 +14,48 @@ _parse_time ()\r
+     ${TEST_DIRECTORY}/parse-time --format=%s "$*"\r
+ }\r
+ \r
+-test_begin_subtest "date(1) default format without TZ code"\r
+-test_expect_equal "$(_parse_time Fri Aug 3 23:06:06 2012)" "$(_date Fri Aug 3 23:06:06 2012)"\r
++test_begin_subtest "Date parser tests"\r
++cat <<EOF > INPUT\r
++now          -> Tue Jan 11 11:11:00 +0000 2011\r
++2010-1-1     -> parse_time_string() error: 5\r
++Jan 2        -> Sat Jan 02 11:11:00 +0000 2010   # Why 2010?\r
++Mon          -> Mon Jan 10 11:11:00 +0000 2011\r
++last Friday  -> parse_time_string() error: 4\r
++2 hours ago  -> parse_time_string() error: 1\r
++last month   -> Sat Dec 11 11:11:00 +0000 2010\r
++month ago    -> parse_time_string() error: 1\r
++8am          -> Tue Jan 11 08:00:00 +0000 2011\r
++9:15         -> Tue Jan 11 09:15:00 +0000 2011\r
++12:34        -> Tue Jan 11 12:34:00 +0000 2011\r
++monday       -> Mon Jan 10 11:11:00 +0000 2011\r
++yesterday    -> Mon Jan 10 11:11:00 +0000 2011\r
++tomorrow     -> parse_time_string() error: 1\r
++             -> Tue Jan 11 11:11:00 +0000 2011 # Shouldn't empty string return an error???\r
+ \r
+-test_begin_subtest "date(1) --rfc-2822 format"\r
+-test_expect_equal "$(_parse_time Fri, 03 Aug 2012 23:07:46 +0100)" "$(_date Fri, 03 Aug 2012 23:07:46 +0100)"\r
++Aug 3 23:06:06 2012             -> Fri Aug 03 23:06:06 +0000 2012 # date(1) default format without TZ code\r
++Fri, 03 Aug 2012 23:07:46 +0100 -> Fri Aug 03 22:07:46 +0000 2012 # rfc-2822\r
++2012-08-03 23:09:37+03:00       -> Fri Aug 03 20:09:37 +0000 2012 # rfc-3339 seconds\r
+ \r
+-test_begin_subtest "date(1) --rfc=3339=seconds format"\r
+-test_expect_equal "$(_parse_time 2012-08-03 23:09:37+03:00)" "$(_date 2012-08-03 23:09:37+03:00)"\r
++10s           -> Tue Jan 11 11:10:50 +0000 2011\r
++19701223s     -> Wed Dec 23 11:10:59 +0000 1970 # Surprising - number is parsed as date and 's' as '1 second'\r
++19701223      -> Wed Dec 23 11:11:00 +0000 1970\r
++\r
++19701223 +0100 -> Wed Dec 23 11:11:00 +0000 1970 # Timezone is ignored without an error\r
++\r
++today ^-> Wed Jan 12 00:00:00 +0000 2011 # This should be 11 23:59:59\r
++today v-> Tue Jan 11 00:00:00 +0000 2011\r
++\r
++thisweek ^-> Sun Jan 16 00:00:00 +0000 2011  # This should be Sunday 23:59:59\r
++thisweek v-> Sun Jan 09 00:00:00 +0000 2011  # This should be Monday 00:00:00\r
++\r
++two months ago-> parse_time_string() error: 1 # Comments in the code suggest that this is supported\r
++two months -> Thu Nov 11 11:11:00 +0000 2010\r
++\r
++1348569850 -> parse_time_string() error: 4 # Seconds since epoch not yet supported? Backward compatibility in notmuch???\r
++10 -> parse_time_string() error: 4 # Seconds since epoch?\r
++EOF\r
++\r
++${TEST_DIRECTORY}/parse-time --now="Tue Jan 11 11:11:00 +0000 2011" < INPUT > OUTPUT\r
++test_expect_equal_file INPUT OUTPUT\r
+ \r
+ test_done\r
+diff --git a/test/parse-time.c b/test/parse-time.c\r
+index b4de76b..0415f49 100644\r
+--- a/test/parse-time.c\r
++++ b/test/parse-time.c\r
+@@ -18,59 +18,47 @@\r
+  * Author: Jani Nikula <jani@nikula.org>\r
+  */\r
+ \r
++\r
++#define _XOPEN_SOURCE 500       /* for strptime() and snprintf() */\r
+ #include <getopt.h>\r
+ #include <stdio.h>\r
+ #include <stdlib.h>\r
+ #include <string.h>\r
++#include <time.h>\r
+ \r
+ #include "parse-time-string.h"\r
+ \r
+-/*\r
+- * concat argv[start]...argv[end - 1], separating them by a single\r
+- * space, to a malloced string\r
+- */\r
+-static char *\r
+-concat_args (int start, int end, char *argv[])\r
+-{\r
+-    int i;\r
+-    size_t len = 1;\r
+-    char *p;\r
+-\r
+-    for (i = start; i < end; i++)\r
+-      len += strlen (argv[i]) + 1;\r
+-\r
+-    p = malloc (len);\r
+-    if (!p)\r
+-      return NULL;\r
+-\r
+-    *p = 0;\r
+-\r
+-    for (i = start; i < end; i++) {\r
+-      if (i != start)\r
+-          strcat (p, " ");\r
+-      strcat (p, argv[i]);\r
+-    }\r
+-\r
+-    return p;\r
+-}\r
+-\r
+ #define DEFAULT_FORMAT "%a %b %d %T %z %Y"\r
+ \r
+ static void\r
+ usage (const char *name)\r
+ {\r
+-    printf ("Usage: %s [options ...] <date/time>\n\n", name);\r
++    printf ("Usage: %s [options ...]\n\n", name);\r
+     printf (\r
+-      "Parse <date/time> and display it in given format.\n\n"\r
+-      "  -f, --format=FMT output format, FMT according to strftime(3)\n"\r
+-      "                   (default: \"%s\")\n"\r
+-      "  -n, --now=N      use N seconds since epoch as now (default: now)\n"\r
+-      "  -u, --up         round result up (default: no rounding)\n"\r
+-      "  -d, --down       round result down (default: no rounding)\n"\r
+-      "  -h, --help       print this help\n",\r
++      "Parse date/time read from stdin and display it in given format.\n\n"\r
++      "  -f, --format=FMT output format for dates and input format for --now,\n"\r
++        "                   FMT according to strftime(3) (default: \"%s\")\n"\r
++      "  -n, --now=N      reference date in FMT (default: now)\n"\r
++      "  -h, --help       print this help\n"\r
++      "\n"\r
++      "stdin should contain one date/time per line in the following format:\n"\r
++      "  <date/time> [ <arrow> [ comment ] ]\n"\r
++      "where <arrow> determines the operation performed on the <date/time>.\n"\r
++      "It can be one of '->', '^->', 'v->' meaning convert, convert and round\n"\r
++      "up, convert and round down, respectively.\n",\r
+       DEFAULT_FORMAT);\r
+ }\r
+ \r
++static const char *\r
++get_round_str (int round)\r
++{\r
++    switch (round) {\r
++    case PARSE_TIME_ROUND_UP:   return "^";\r
++    case PARSE_TIME_ROUND_DOWN: return "v";\r
++    default:                  return "";\r
++    }\r
++}\r
++\r
+ int\r
+ main (int argc, char *argv[])\r
+ {\r
+@@ -79,14 +67,10 @@ main (int argc, char *argv[])\r
+     time_t result;\r
+     time_t now;\r
+     time_t *nowp = NULL;\r
+-    char *argstr;\r
+     int round = PARSE_TIME_NO_ROUND;\r
+-    char buf[1024];\r
+     const char *format = DEFAULT_FORMAT;\r
+     struct option options[] = {\r
+       { "help",       no_argument,            NULL,   'h' },\r
+-      { "up",         no_argument,            NULL,   'u' },\r
+-      { "down",       no_argument,            NULL,   'd' },\r
+       { "format",     required_argument,      NULL,   'f' },\r
+       { "now",        required_argument,      NULL,   'n' },\r
+       { NULL, 0, NULL, 0 },\r
+@@ -111,8 +95,13 @@ main (int argc, char *argv[])\r
+           round = PARSE_TIME_ROUND_DOWN;\r
+           break;\r
+       case 'n':\r
+-          /* specify now in seconds since epoch */\r
+-          now = (time_t) strtol (optarg, NULL, 10);\r
++          memset (&tm, 0, sizeof (tm));\r
++          char *parsed = strptime (optarg, format, &tm);\r
++          if (!parsed) {\r
++              fprintf (stderr, "Cannot parse reference date: %s\n", optarg);\r
++              return 1;\r
++          }\r
++          now = mktime (&tm);\r
+           if (now >= (time_t) 0)\r
+               nowp = &now;\r
+           break;\r
+@@ -124,22 +113,47 @@ main (int argc, char *argv[])\r
+       }\r
+     }\r
+ \r
+-    argstr = concat_args (optind, argc, argv);\r
+-    if (!argstr)\r
+-      return 1;\r
+-\r
+-    r = parse_time_string (argstr, &result, nowp, round);\r
+-\r
+-    free (argstr);\r
+-\r
+-    if (r)\r
+-      return 1;\r
+-\r
+-    if (!localtime_r (&result, &tm))\r
+-      return 1;\r
+-\r
+-    strftime (buf, sizeof (buf), format, &tm);\r
+-    printf ("%s\n", buf);\r
++    char input[BUFSIZ];\r
++    while (fgets (input, BUFSIZ, stdin) && input[0]) {\r
++      if (input[0] == '\n') {\r
++          printf ("\n");\r
++          continue;\r
++      }\r
++      char *arrow;\r
++      char *comment = strrchr (input, '#');\r
++      arrow = strstr (input, "->");\r
++      round = PARSE_TIME_NO_ROUND;\r
++      if (arrow > input) {\r
++          switch (arrow[-1]) {\r
++          case '^': round = PARSE_TIME_ROUND_UP; arrow--; break;\r
++          case 'v': round = PARSE_TIME_ROUND_DOWN; arrow--; break;\r
++          default: break;\r
++          }\r
++      }\r
++      if (arrow)\r
++          *arrow = 0;\r
++      else\r
++          arrow = input + strlen (input); /* XXX: comment is not handled */\r
++      while (arrow > input && arrow[-1] == '\n')\r
++          arrow--;\r
++      *arrow-- = 0;\r
++\r
++      r = parse_time_string (input, &result, nowp, round);\r
++      char resstr[BUFSIZ];\r
++      if (r)\r
++          snprintf (resstr, sizeof(resstr), "parse_time_string() error: %d", r);\r
++      else if (!localtime_r (&result, &tm))\r
++          snprintf (resstr, sizeof(resstr), "localtime(result) error");\r
++      else\r
++          strftime (resstr, sizeof (resstr), format, &tm);\r
++\r
++      char buf[BUFSIZ];\r
++      snprintf (buf, sizeof(buf), "%s%s-> %s", input, get_round_str (round), resstr);\r
++      if (!comment)\r
++          printf ("%s\n", buf);\r
++      else\r
++          printf ("%-*s%s", (int)(comment - input), buf, comment);\r
++    }\r
+ \r
+     return 0;\r
+ }\r