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