summaryrefslogtreecommitdiff
path: root/test/test_regex.c
blob: db4fb77b6a7921c421b8a0b85dd3d3b7a4705dd6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <usual/regex.h>
#include <usual/string.h>

#include "test_common.h"

#define NMATCH 20

/*
 * quick regex sanity check
 */

/* execute basic regex and return result as string */
static const char *b_rx(const char *regex, const char *str, int flags)
{
	static char buf[512];
	regex_t rx;
	regmatch_t matches[NMATCH];
	int nmatch, err, i;
	char *dst = buf;

	memset(&rx, 0, sizeof(rx));
	memset(matches, -1, sizeof(&matches));

	/* compile */
	err = regcomp(&rx, regex, flags);
	if (err)
		goto fail;
	nmatch = rx.re_nsub;

	/* match */
	err = regexec(&rx, str, NMATCH, matches, 0);
	if (err)
		goto fail;

	/* format result */
	for (i = 0; i < nmatch + 1; i++) {
		regmatch_t *m = &matches[i];
		*dst++ = '(';
		if (m->rm_so >= 0)
			dst += sprintf(dst, "%d", (int)m->rm_so);
		else
			*dst++ = '?';
		*dst++ = ',';
		if (m->rm_eo >= 0)
			dst += sprintf(dst, "%d", (int)m->rm_eo);
		else
			*dst++ = '?';
		*dst++ = ')';
	}
	regfree(&rx);
	return buf;

fail:
	/* format error */
	regfree(&rx);
	switch (err) {
	case REG_NOMATCH: return "NOMATCH";
	case REG_BADBR: return "BADBR";
	case REG_BADPAT: return "BADPAT";
	case REG_BADRPT: return "BADRPT";
	case REG_EBRACE: return "EBRACE";
	case REG_EBRACK: return "EBRACK";
	case REG_ECOLLATE: return "ECOLLATE";
	case REG_ECTYPE: return "ECTYPE";
#ifdef REG_EEND
	case REG_EEND: return "EEND";
#endif
	case REG_EESCAPE: return "EESCAPE";
	case REG_EPAREN: return "EPAREN";
	case REG_ERANGE: return "ERANGE";
#ifdef REG_ESIZE
	case REG_ESIZE: return "ESIZE";
#endif
	case REG_ESPACE: return "ESPACE";
	case REG_ESUBREG: return "ESUBREG";
#ifdef REG_ENOSYS
	case REG_ENOSYS: return "ENOSYS";
#endif
#ifdef REG_EMPTY
	case REG_EMPTY: return "EMPTY";
#endif
	default: return "UNKNOWN_ERROR";
	}
}

/* execute extended regex and return result as string */
static const char *e_rx(const char *regex, const char *str, int flags)
{
	return b_rx(regex, str, flags | REG_EXTENDED);
}

static void test_regex(void *ptr)
{
	str_check(e_rx("foo*", "foobar", 0), "(0,3)");
	str_check(e_rx("foo(x)?.*", "foobar", 0), "(0,6)(?,?)");
	str_check(e_rx("foo", "bar", 0), "NOMATCH");
	str_check(e_rx("foo{5,1}", "bar", 0), "BADBR");
	/* str_check(e_rx("(|)", "bar", 0), "BADPAT"); */
	str_check(e_rx("*", "bar", 0), "BADRPT");
	str_check(e_rx("foo{", "bar", 0), "EBRACE");
	str_check(e_rx("fo[o", "bar", 0), "EBRACK");
	str_check(e_rx("[[:foo:]]", "bar", 0), "ECTYPE");
	str_check(e_rx("foo\\", "foobar", 0), "EESCAPE");
	str_check(e_rx("fo(o", "bar", 0), "EPAREN");
	str_check(e_rx("[a-b-c]", "bar", 0), "ERANGE");
	str_check(b_rx("(\\1)", "bar", 0), "ESUBREG");
	str_check(e_rx("[[:random:]]", "bar", 0), "ECTYPE");
end:;
}

/*
 * Describe
 */

struct testcase_t regex_tests[] = {
	{ "minimal", test_regex },
	END_OF_TESTCASES
};