--- /dev/null
+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