Subject: [PATCH/RFC 2/3] Integrate wildmatch to git

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Mon, 7 May 2012 20:01:56 +0700

- Make wildmatch.c part of libgit.a
 - Rewrite test-wildmatch.c to follow git coding style (i.e. no
   catching up with mainstream since it has turned GPL-3 anyway)
 - Put wildtest.txt into a real test case

Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 Makefile             |    3 +
 compat/wildmatch.c   |   26 +---
 t/t3070-wildmatch.sh |   27 +++++
 test-wildmatch.c     |  314 +++++++++++++++++++++-----------------------------
 4 files changed, 167 insertions(+), 203 deletions(-)
 create mode 100755 t/t3070-wildmatch.sh

diff --git a/Makefile b/Makefile
index 2fa7211..b82f8b6 100644
--- a/Makefile
+++ b/Makefile
@@ -497,6 +497,7 @@ TEST_PROGRAMS_NEED_X += test-sha1
 TEST_PROGRAMS_NEED_X += test-sigchain
 TEST_PROGRAMS_NEED_X += test-subprocess
 TEST_PROGRAMS_NEED_X += test-svn-fe
+TEST_PROGRAMS_NEED_X += test-wildmatch
 
 TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X))
 
@@ -598,6 +599,7 @@ LIB_H += compat/cygwin.h
 LIB_H += compat/mingw.h
 LIB_H += compat/obstack.h
 LIB_H += compat/terminal.h
+LIB_H += compat/wildmatch.h
 LIB_H += compat/win32/dirent.h
 LIB_H += compat/win32/poll.h
 LIB_H += compat/win32/pthread.h
@@ -693,6 +695,7 @@ LIB_OBJS += combine-diff.o
 LIB_OBJS += commit.o
 LIB_OBJS += compat/obstack.o
 LIB_OBJS += compat/terminal.o
+LIB_OBJS += compat/wildmatch.o
 LIB_OBJS += config.o
 LIB_OBJS += connect.o
 LIB_OBJS += connected.o
diff --git a/compat/wildmatch.c b/compat/wildmatch.c
index f3a1731..791b9ef 100644
--- a/compat/wildmatch.c
+++ b/compat/wildmatch.c
@@ -9,7 +9,13 @@
 **  work differently than '*', and to fix the character-class code.
 */
 
-#include "rsync.h"
+#include <stddef.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "wildmatch.h"
+
+typedef unsigned char uchar;
 
 /* What character marks an inverted character class? */
 #define NEGATE_CLASS	'!'
@@ -53,10 +59,6 @@
 #define ISUPPER(c) (ISASCII(c) && isupper(c))
 #define ISXDIGIT(c) (ISASCII(c) && isxdigit(c))
 
-#ifdef WILD_TEST_ITERATIONS
-int wildmatch_iteration_count;
-#endif
-
 static int force_lower_case = 0;
 
 /* Match pattern "p" against the a virtually-joined string consisting
@@ -65,10 +67,6 @@ static int dowild(const uchar *p, const uchar *text, const uchar*const *a)
 {
     uchar p_ch;
 
-#ifdef WILD_TEST_ITERATIONS
-    wildmatch_iteration_count++;
-#endif
-
     for ( ; (p_ch = *p) != '\0'; text++, p++) {
 	int matched, special;
 	uchar t_ch, prev_ch;
@@ -288,9 +286,6 @@ static const uchar *trailing_N_elements(const uchar*const **a_ptr, int count)
 int wildmatch(const char *pattern, const char *text)
 {
     static const uchar *nomore[1]; /* A NULL pointer. */
-#ifdef WILD_TEST_ITERATIONS
-    wildmatch_iteration_count = 0;
-#endif
     return dowild((const uchar*)pattern, (const uchar*)text, nomore) == TRUE;
 }
 
@@ -299,9 +294,6 @@ int iwildmatch(const char *pattern, const char *text)
 {
     static const uchar *nomore[1]; /* A NULL pointer. */
     int ret;
-#ifdef WILD_TEST_ITERATIONS
-    wildmatch_iteration_count = 0;
-#endif
     force_lower_case = 1;
     ret = dowild((const uchar*)pattern, (const uchar*)text, nomore) == TRUE;
     force_lower_case = 0;
@@ -320,10 +312,6 @@ int wildmatch_array(const char *pattern, const char*const *texts, int where)
     const uchar *text;
     int matched;
 
-#ifdef WILD_TEST_ITERATIONS
-    wildmatch_iteration_count = 0;
-#endif
-
     if (where > 0)
 	text = trailing_N_elements(&a, where);
     else
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
new file mode 100755
index 0000000..e748fc7
--- /dev/null
+++ b/t/t3070-wildmatch.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+test_description='wildmatch tests'
+
+. ./test-lib.sh
+
+test_wildmatch() {
+    test_expect_success "wildmatch $*" "
+	test-wildmatch $* ../t3070-wildmatch/wildtest.txt >actual &&
+	echo 'No wildmatch errors found.' >expected &&
+	test_cmp expected actual
+    "
+}
+
+test_wildmatch -x1
+test_wildmatch -x1 -E1
+test_wildmatch -x1 -E1 -se
+test_wildmatch -x2
+test_wildmatch -x2 -se
+test_wildmatch -x3
+test_wildmatch -x3 -E1
+test_wildmatch -x4
+test_wildmatch -x4 -E2 -e
+test_wildmatch -x5
+test_wildmatch -x5 -s
+
+test_done
diff --git a/test-wildmatch.c b/test-wildmatch.c
index 3456bac..b832dee 100644
--- a/test-wildmatch.c
+++ b/test-wildmatch.c
@@ -17,200 +17,146 @@
  * 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-/*#define COMPARE_WITH_FNMATCH*/
-
-#define WILD_TEST_ITERATIONS
-#include "lib/wildmatch.c"
-
-#include <popt.h>
-
-#ifdef COMPARE_WITH_FNMATCH
-#include <fnmatch.h>
-
-int fnmatch_errors = 0;
-#endif
-
-int wildmatch_errors = 0;
-
-typedef char bool;
-
-int output_iterations = 0;
-int explode_mod = 0;
-int empties_mod = 0;
-int empty_at_start = 0;
-int empty_at_end = 0;
-
-static struct poptOption long_options[] = {
-  /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
-  {"iterations",     'i', POPT_ARG_NONE,   &output_iterations, 0, 0, 0},
-  {"empties",        'e', POPT_ARG_STRING, 0, 'e', 0, 0},
-  {"explode",        'x', POPT_ARG_INT,    &explode_mod, 0, 0, 0},
-  {0,0,0,0, 0, 0, 0}
-};
+#include "cache.h"
+#include "parse-options.h"
+#include "compat/wildmatch.h"
+
+static int compare_fnmatch;
+static int fnmatch_errors;
+static int wildmatch_errors;
+static int explode_mod;
+static int empties_mod;
+static int empty_at_start;
+static int empty_at_end;
 
 /* match just at the start of string (anchored tests) */
-static void
-run_test(int line, bool matches, bool same_as_fnmatch,
-	 const char *text, const char *pattern)
+static void run_test(int line, int matches, int same_as_fnmatch,
+		     const char *text, const char *pattern)
 {
-    bool matched;
-#ifdef COMPARE_WITH_FNMATCH
-    bool fn_matched;
-    int flags = strstr(pattern, "**")? 0 : FNM_PATHNAME;
-#else
-    same_as_fnmatch = 0; /* Get rid of unused-variable compiler warning. */
-#endif
-
-    if (explode_mod) {
-	char buf[MAXPATHLEN*2], *texts[MAXPATHLEN];
-	int pos = 0, cnt = 0, ndx = 0, len = strlen(text);
+	int matched;
+	int fn_matched;
+	int flags = compare_fnmatch && strstr(pattern, "**") ? 0 : FNM_PATHNAME;
+
+	if (explode_mod) {
+		char buf[PATH_MAX * 2], *texts[PATH_MAX];
+		int pos = 0, cnt = 0, ndx = 0, len = strlen(text);
+
+		if (empty_at_start)
+			texts[ndx++] = "";
+		/* An empty string must turn into at least one empty array item. */
+		while (1) {
+			texts[ndx] = buf + ndx * (explode_mod + 1);
+			strlcpy(texts[ndx++], text + pos, explode_mod + 1);
+			if (pos + explode_mod >= len)
+				break;
+			pos += explode_mod;
+			if (!(++cnt % empties_mod))
+				texts[ndx++] = "";
+		}
+		if (empty_at_end)
+			texts[ndx++] = "";
+		texts[ndx] = NULL;
+		matched = wildmatch_array(pattern, (const char**)texts, 0);
+	} else
+		matched = wildmatch(pattern, text);
+	if (compare_fnmatch)
+		fn_matched = !fnmatch(pattern, text, flags);
+
+	if (matched != matches) {
+		printf("wildmatch failure on line %d:\n  %s\n  %s\n  expected %s match\n",
+		       line, text, pattern, matches ? "a" : "NO");
+		wildmatch_errors++;
+	}
 
-	if (empty_at_start)
-	    texts[ndx++] = "";
-	/* An empty string must turn into at least one empty array item. */
-	while (1) {
-	    texts[ndx] = buf + ndx * (explode_mod + 1);
-	    strlcpy(texts[ndx++], text + pos, explode_mod + 1);
-	    if (pos + explode_mod >= len)
-		break;
-	    pos += explode_mod;
-	    if (!(++cnt % empties_mod))
-		texts[ndx++] = "";
+	if (compare_fnmatch && fn_matched != (matches ^ !same_as_fnmatch)) {
+		printf("fnmatch disagreement on line %d:\n  %s\n  %s\n  expected %s match\n",
+		       line, text, pattern, matches ^ !same_as_fnmatch ? "a" : "NO");
+		fnmatch_errors++;
 	}
-	if (empty_at_end)
-	    texts[ndx++] = "";
-	texts[ndx] = NULL;
-	matched = wildmatch_array(pattern, (const char**)texts, 0);
-    } else
-	matched = wildmatch(pattern, text);
-#ifdef COMPARE_WITH_FNMATCH
-    fn_matched = !fnmatch(pattern, text, flags);
-#endif
-    if (matched != matches) {
-	printf("wildmatch failure on line %d:\n  %s\n  %s\n  expected %s match\n",
-	       line, text, pattern, matches? "a" : "NO");
-	wildmatch_errors++;
-    }
-#ifdef COMPARE_WITH_FNMATCH
-    if (fn_matched != (matches ^ !same_as_fnmatch)) {
-	printf("fnmatch disagreement on line %d:\n  %s\n  %s\n  expected %s match\n",
-	       line, text, pattern, matches ^ !same_as_fnmatch? "a" : "NO");
-	fnmatch_errors++;
-    }
-#endif
-    if (output_iterations) {
-	printf("%d: \"%s\" iterations = %d\n", line, pattern,
-	       wildmatch_iteration_count);
-    }
 }
 
-int
-main(int argc, char **argv)
+int main(int argc, const char **argv)
 {
-    char buf[2048], *s, *string[2], *end[2];
-    const char *arg;
-    FILE *fp;
-    int opt, line, i, flag[2];
-    poptContext pc = poptGetContext("wildtest", argc, (const char**)argv,
-				    long_options, 0);
-
-    while ((opt = poptGetNextOpt(pc)) != -1) {
-	switch (opt) {
-	  case 'e':
-	    arg = poptGetOptArg(pc);
-	    empties_mod = atoi(arg);
-	    if (strchr(arg, 's'))
-		empty_at_start = 1;
-	    if (strchr(arg, 'e'))
-		empty_at_end = 1;
-	    if (!explode_mod)
-		explode_mod = 1024;
-	    break;
-	  default:
-	    fprintf(stderr, "%s: %s\n",
-		    poptBadOption(pc, POPT_BADOPTION_NOALIAS),
-		    poptStrerror(opt));
-	    exit(1);
-	}
-    }
-
-    if (explode_mod && !empties_mod)
-	empties_mod = 1024;
-
-    argv = (char**)poptGetArgs(pc);
-    if (!argv || argv[1]) {
-	fprintf(stderr, "Usage: wildtest [OPTIONS] TESTFILE\n");
-	exit(1);
-    }
-
-    if ((fp = fopen(*argv, "r")) == NULL) {
-	fprintf(stderr, "Unable to open %s\n", *argv);
-	exit(1);
-    }
-
-    line = 0;
-    while (fgets(buf, sizeof buf, fp)) {
-	line++;
-	if (*buf == '#' || *buf == '\n')
-	    continue;
-	for (s = buf, i = 0; i <= 1; i++) {
-	    if (*s == '1')
-		flag[i] = 1;
-	    else if (*s == '0')
-		flag[i] = 0;
-	    else
-		flag[i] = -1;
-	    if (*++s != ' ' && *s != '\t')
-		flag[i] = -1;
-	    if (flag[i] < 0) {
-		fprintf(stderr, "Invalid flag syntax on line %d of %s:\n%s",
-			line, *argv, buf);
-		exit(1);
-	    }
-	    while (*++s == ' ' || *s == '\t') {}
-	}
-	for (i = 0; i <= 1; i++) {
-	    if (*s == '\'' || *s == '"' || *s == '`') {
-		char quote = *s++;
-		string[i] = s;
-		while (*s && *s != quote) s++;
-		if (!*s) {
-		    fprintf(stderr, "Unmatched quote on line %d of %s:\n%s",
-			    line, *argv, buf);
-		    exit(1);
+	char buf[2048];
+	FILE *fp;
+	int line;
+	const struct option opts[] = {
+		OPT_INTEGER('E', "empties", &empties_mod, ""),
+		OPT_INTEGER('x', "explode", &explode_mod, "explode mode"),
+		OPT_BOOL('s', NULL, &empty_at_start, ""),
+		OPT_BOOL('e', NULL, &empty_at_end, ""),
+		OPT_BOOL(0, "fnmatch", &compare_fnmatch, "compare with fnmatch()"),
+		OPT_END(),
+	};
+
+	argc = parse_options(argc, argv, NULL, opts, NULL, 0);
+	if (argc != 1)
+		die("unknown option");
+
+	if (explode_mod && !empties_mod)
+		empties_mod = 1024;
+
+	if ((fp = fopen(*argv, "r")) == NULL)
+		die_errno("Unable to open %s\n", *argv);
+
+	line = 0;
+	while (fgets(buf, sizeof buf, fp)) {
+		char *s, *string[2], *end[2];
+		int i, flag[2];
+
+		line++;
+		if (*buf == '#' || *buf == '\n')
+			continue;
+		for (s = buf, i = 0; i <= 1; i++) {
+			if (*s == '1')
+				flag[i] = 1;
+			else if (*s == '0')
+				flag[i] = 0;
+			else
+				flag[i] = -1;
+			if (*++s != ' ' && *s != '\t')
+				flag[i] = -1;
+			if (flag[i] < 0)
+				die("Invalid flag syntax on line %d of %s:\n%s",
+				    line, *argv, buf);
+			while (*++s == ' ' || *s == '\t') {}
 		}
-		end[i] = s;
-	    }
-	    else {
-		if (!*s || *s == '\n') {
-		    fprintf(stderr, "Not enough strings on line %d of %s:\n%s",
-			    line, *argv, buf);
-		    exit(1);
+		for (i = 0; i <= 1; i++) {
+			if (*s == '\'' || *s == '"' || *s == '`') {
+				char quote = *s++;
+				string[i] = s;
+				while (*s && *s != quote) s++;
+				if (!*s)
+					die("Unmatched quote on line %d of %s:\n%s",
+					    line, *argv, buf);
+				end[i] = s;
+			}
+			else {
+				if (!*s || *s == '\n')
+					die("Not enough strings on line %d of %s:\n%s",
+					    line, *argv, buf);
+				string[i] = s;
+				while (*++s && *s != ' ' && *s != '\t' && *s != '\n') {}
+				end[i] = s;
+			}
+			while (*++s == ' ' || *s == '\t') {}
 		}
-		string[i] = s;
-		while (*++s && *s != ' ' && *s != '\t' && *s != '\n') {}
-		end[i] = s;
-	    }
-	    while (*++s == ' ' || *s == '\t') {}
+		*end[0] = *end[1] = '\0';
+		run_test(line, flag[0], flag[1], string[0], string[1]);
 	}
-	*end[0] = *end[1] = '\0';
-	run_test(line, flag[0], flag[1], string[0], string[1]);
-    }
-
-    if (!wildmatch_errors)
-	fputs("No", stdout);
-    else
-	printf("%d", wildmatch_errors);
-    printf(" wildmatch error%s found.\n", wildmatch_errors == 1? "" : "s");
-
-#ifdef COMPARE_WITH_FNMATCH
-    if (!fnmatch_errors)
-	fputs("No", stdout);
-    else
-	printf("%d", fnmatch_errors);
-    printf(" fnmatch error%s found.\n", fnmatch_errors == 1? "" : "s");
 
-#endif
-
-    return 0;
+	if (!wildmatch_errors)
+		fputs("No", stdout);
+	else
+		printf("%d", wildmatch_errors);
+	printf(" wildmatch error%s found.\n", wildmatch_errors == 1 ? "" : "s");
+
+	if (compare_fnmatch) {
+		if (!fnmatch_errors)
+			fputs("No", stdout);
+		else
+			printf("%d", fnmatch_errors);
+		printf(" fnmatch error%s found.\n", fnmatch_errors == 1 ? "" : "s");
+	}
+	return 0;
 }
-- 
1.7.8.36.g69ee2