>From f419f9d151107fadd9e8f977a2966fee5302b6d6 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Thu, 14 Jan 2016 09:31:34 -0800
Subject: [PROPOSED PATCH 2/2] Cleanup of test suite

Pacify "make CFLAGS='$(GCC_DEBUG_FLAGS)'" and fix some other
minor problems found while trying the test procedure.
* Makefile (TESTOBJS): New macro.
(testsuite): Use it.
(tests): Don't assume . is in PATH.
(clean_misc): Remove testsuite.
* NEWS: Mention test suite.
* testsuite.c: Make all extern symbols static, except for 'main'.
(TM_ZONE, TM_GMTOFF): Make consistent with privatet.h.
(ATTRIBUTE_CONST, ATTRIBUTE_PURE, _Noreturn):
New macros, copied from private.h.
(catchsig): Now _Noreturn.
(isleap, nleapsbetween, monthlens, progname): Now const.
(tmcmp): Now pure.
(progname): Now just an array, not a pointer to it.
(main): Use const pointers to literals, since the literals cannot
be changed.
(runtests): Omit unused locals.
(getargs): Mention return type on definition.
---
 Makefile    | 11 +++----
 NEWS        |  3 ++
 testsuite.c | 98 ++++++++++++++++++++++++++++++++++++++++---------------------
 3 files changed, 74 insertions(+), 38 deletions(-)

diff --git a/Makefile b/Makefile
index 744995c..16c472d 100644
--- a/Makefile
+++ b/Makefile
@@ -346,6 +346,7 @@ RANLIB=		:
 TZCOBJS=	zic.o
 TZDOBJS=	zdump.o localtime.o asctime.o
 DATEOBJS=	date.o localtime.o strftime.o asctime.o
+TESTOBJS=	testsuite.o localtime.o
 LIBSRCS=	localtime.c asctime.c difftime.c
 LIBOBJS=	localtime.o asctime.o difftime.o
 HEADERS=	tzfile.h private.h
@@ -405,9 +406,9 @@ INSTALL:	ALL install date.1
 		cp -f date.1 $(DESTDIR)$(MANDIR)/man1/.
 
 tests:		testsuite testcases
-		testsuite testcases
+		./testsuite testcases
 		@ echo "scripted tests succeeded; trying exhaustive tests (this may take a minute or two)"
-		testsuite -x -f 1901-12-14 -t 2038-01-19 -i 1753
+		./testsuite -x -f 1901-12-14 -t 2038-01-19 -i 1753
 		@ # uncomment the following lines if you have 64-bit time_t's
 		@ # testsuite testcases64
 		@ # echo "semiexhaustive 64-bit tests (this may take several minutes)"
@@ -429,8 +430,8 @@ zdump:		$(TZDOBJS)
 zic:		$(TZCOBJS)
 		$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(TZCOBJS) $(LDLIBS)
 
-testsuite:	testsuite.o localtime.o
-		$(CC) -o $@ $(CFLAGS) $(LDFLAGS) testsuite.o localtime.o $(LDLIBS)
+testsuite:	$(TESTOBJS)
+		$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(TESTOBJS) $(LDLIBS)
 
 yearistype:	yearistype.sh
 		cp yearistype.sh yearistype
@@ -550,7 +551,7 @@ check_web:	$(WEB_PAGES)
 
 clean_misc:
 		rm -f core *.o *.out \
-		  date tzselect version.h zdump zic yearistype libtz.a
+		  date testsuite tzselect version.h zdump zic yearistype libtz.a
 clean:		clean_misc
 		rm -fr tzpublic
 
diff --git a/NEWS b/NEWS
index 14a87ac..35a593d 100644
--- a/NEWS
+++ b/NEWS
@@ -30,6 +30,9 @@ Unreleased, experimental changes
 
   Changes affecting build procedure
 
+    A test suite is now available.  Run 'make tests' to use it.
+    (Thanks to Steve Summit.)
+
     An installer can now combine leap seconds with use of the backzone file,
     e.g., with 'make PACKRATDATA=backzone REDO=posix_right zones'.
     The old 'make posix_packrat' rule is now marked as obsolescent.
diff --git a/testsuite.c b/testsuite.c
index 5984867..f835ef4 100644
--- a/testsuite.c
+++ b/testsuite.c
@@ -156,49 +156,74 @@
 #include <setjmp.h>
 #include <errno.h>
 
-/* temporarily hardwired (could get these from private.h) */
-#define TM_ZONE tm_zone
-#define TM_GMTOFF tm_gmtoff
-
+/* Duplicated from tzfile.h.  */
 #define EPOCH_WDAY 4	/* Thursday */
 
+/* Duplicated from private.h.  In theory, test programs should not
+   rely on internals of programs being tested.  This section is pretty
+   long, though, so perhaps we should just include private.h instead.  */
+#if 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
+# define ATTRIBUTE_CONST __attribute__ ((const))
+# define ATTRIBUTE_PURE __attribute__ ((__pure__))
+#else
+# define ATTRIBUTE_CONST /* empty */
+# define ATTRIBUTE_PURE /* empty */
+#endif
+#if (defined __GLIBC__ \
+     || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
+     || (defined __APPLE__ && defined __MACH__))
+# if !defined TM_GMTOFF && !defined NO_TM_GMTOFF
+#  define TM_GMTOFF tm_gmtoff
+# endif
+# if !defined TM_ZONE && !defined NO_TM_ZONE
+#  define TM_ZONE tm_zone
+# endif
+#endif
+#if !defined _Noreturn && __STDC_VERSION__ < 201112
+# if 2 < __GNUC__ + (8 <= __GNUC_MINOR__)
+#  define _Noreturn __attribute__ ((__noreturn__))
+# else
+#  define _Noreturn
+# endif
+#endif
+
 #define Streq(s1, s2) (strcmp(s1, s2) == 0)
 
-int getargs(char **, char *, int);
+static int getargs(char **, char *, int);
 
-void runtests(FILE *, const char *);
-void run_exhaustive(const struct tm *, const struct tm *, time_t);
+static void runtests(FILE *, char const *);
+static void run_exhaustive(struct tm const *, struct tm const *, time_t);
 
-time_t quick_timegm(const struct tm *);
-int isleap(int);
-int nleapsbetween(int, int);
+static time_t quick_timegm(struct tm const *);
+static int isleap(int) ATTRIBUTE_CONST;
+static int nleapsbetween(int, int) ATTRIBUTE_CONST;
 
-int tmcmp(const struct tm *, const struct tm *);
+static int tmcmp(struct tm const *, struct tm const *) ATTRIBUTE_PURE;
 
-void catchsig(int);
+static void _Noreturn catchsig(int);
 
 /* our own copy of this time-honored array (would be nice to share) */
-int monthlens[2][12] = {
+static int const monthlens[2][12] = {
 	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
 	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
 };
 
-int errs = 0;
+static int errs = 0;
 
-jmp_buf jmpbuf;
+static jmp_buf jmpbuf;
 
-const char *progname = "testsuite";
+static char const progname[] = "testsuite";
 
-int main(int argc, char *argv[])
+int
+main(int argc, char *argv[])
 {
 	int ferrs = 0;
 	int exhaustive = 0;
 	int argi = 1;
 	int calltzset = 0;
-	char *fromstr = "1901-12-14";
-	char *tostr = "2038-01-19";
-	char *incstr = "997";	/* rather arbitrary, but useful if prime */
-	struct tm tm;
+	char const *fromstr = "1901-12-14";
+	char const *tostr = "2038-01-19";
+	char const *incstr = "997"; /* rather arbitrary, but useful if prime */
 
 	for(; argi < argc && argv[argi][0] == '-'; argi++) {
 		char *p;
@@ -308,7 +333,8 @@ int main(int argc, char *argv[])
 #define NOINV 02
 #define DENORM 04
 
-void basictest(time_t t, const struct tm *itmp, int flags, const char *tag)
+static void
+basictest(time_t t, struct tm const *itmp, int flags, char const *tag)
 {
 	int sig;
 	time_t t2;
@@ -424,17 +450,16 @@ void basictest(time_t t, const struct tm *itmp, int flags, const char *tag)
 #define MAXLINE 512
 #define MAXARGS 10
 
-void runtests(FILE *fp, const char *name)
+static void
+runtests(FILE *fp, char const *name)
 {
 	int lineno = 0;
 	char line[MAXLINE];
 	char *p;
 	char *av[MAXARGS];
 	int ac;
-	int sig;
-	time_t t, t2;
-	struct tm tm, tm2;
-	struct tm *tmp;
+	time_t t;
+	struct tm tm;
 	char tag[100];
 	int i;
 	int flags;
@@ -538,7 +563,8 @@ void runtests(FILE *fp, const char *name)
 	}
 }
 
-void run_exhaustive(const struct tm *from, const struct tm *to, time_t inc)
+static void
+run_exhaustive(struct tm const *from, struct tm const *to, time_t inc)
 {
 	time_t t, t2;
 	struct tm tm, *tmp, tmcopy;
@@ -693,7 +719,8 @@ void run_exhaustive(const struct tm *from, const struct tm *to, time_t inc)
 	printf("%ld tests completed\n", ntests);
 }
 
-int tmcmp(const struct tm *tm1, const struct tm *tm2)
+static int
+tmcmp(struct tm const *tm1, struct tm const *tm2)
 {
 	if(tm1->tm_year != tm2->tm_year)
 		return (tm1->tm_year < tm2->tm_year) ? -1 : 1;
@@ -710,7 +737,8 @@ int tmcmp(const struct tm *tm1, const struct tm *tm2)
 	else return 0;
 }
 
-time_t quick_timegm(const struct tm *tmp)
+static time_t
+quick_timegm(struct tm const *tmp)
 {
 	int m;
 	time_t r = (time_t)(1900 + tmp->tm_year - 1970) * 365 * 86400;
@@ -731,12 +759,14 @@ time_t quick_timegm(const struct tm *tmp)
 	return r;
 }
 
-int isleap(int y)
+static int
+isleap(int y)
 {
 	return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
 }
 
-int nleapsbetween(y1, y2)
+static int
+nleapsbetween(int y1, int y2)
 {
 	if(y1 == y2) {
 		return 0;	/* unnecessary optimization */
@@ -760,7 +790,8 @@ int nleapsbetween(y1, y2)
 	}
 }
 
-void catchsig(int sig)
+static void
+catchsig(int sig)
 {
 	longjmp(jmpbuf, sig);
 }
@@ -777,6 +808,7 @@ void catchsig(int sig)
 
 #define iswhite(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
 
+static int
 getargs(char *argv[], char *line, int maxargs)
 {
 	int nargs;
-- 
2.5.0

