1 /* psx-interf.c: test POSIX interface. */
2
3 #include <string.h>
4 #include <assert.h>
5
6 #include "test.h"
7
8 #define ERROR_CODE_LENGTH 20
9 #define TEST_ERRBUF_SIZE 15
10
11
12 void test_compile ();
13
14
15 /* ANSWER should be at least ERROR_CODE_LENGTH long. */
16
17 static char *
get_error_string(error_code,answer)18 get_error_string (error_code, answer)
19 int error_code;
20 char answer[];
21 {
22 switch (error_code)
23 {
24 case 0: strcpy (answer, "No error"); break;
25 case REG_NOMATCH: strcpy (answer, "REG_NOMATCH"); break;
26 case REG_BADPAT: strcpy (answer, "REG_BADPAT"); break;
27 case REG_EPAREN: strcpy (answer, "REG_EPAREN"); break;
28 case REG_ESPACE: strcpy (answer, "REG_ESPACE"); break;
29 case REG_ECOLLATE: strcpy (answer, "REG_ECOLLATE"); break;
30 case REG_ECTYPE: strcpy (answer, "REG_ECTYPE"); break;
31 case REG_EESCAPE: strcpy (answer, "REG_EESCAPE"); break;
32 case REG_ESUBREG: strcpy (answer, "REG_ESUBREG"); break;
33 case REG_EBRACK: strcpy (answer, "REG_EBRACK"); break;
34 case REG_EBRACE: strcpy (answer, "REG_EBRACE"); break;
35 case REG_BADBR: strcpy (answer, "REG_BADBR"); break;
36 case REG_ERANGE: strcpy (answer, "REG_ERANGE"); break;
37 case REG_BADRPT: strcpy (answer, "REG_BADRPT"); break;
38 case REG_EEND: strcpy (answer, "REG_EEND"); break;
39 default: strcpy (answer, "Bad error code");
40 }
41 return answer;
42 }
43
44
45 /* I don't think we actually need to initialize all these things.
46 --karl */
47
48 void
init_pattern_buffer(pattern_buffer_ptr)49 init_pattern_buffer (pattern_buffer_ptr)
50 regex_t *pattern_buffer_ptr;
51 {
52 pattern_buffer_ptr->buffer = NULL;
53 pattern_buffer_ptr->allocated = 0;
54 pattern_buffer_ptr->used = 0;
55 pattern_buffer_ptr->fastmap = NULL;
56 pattern_buffer_ptr->fastmap_accurate = 0;
57 pattern_buffer_ptr->translate = NULL;
58 pattern_buffer_ptr->can_be_null = 0;
59 pattern_buffer_ptr->re_nsub = 0;
60 pattern_buffer_ptr->no_sub = 0;
61 pattern_buffer_ptr->not_bol = 0;
62 pattern_buffer_ptr->not_eol = 0;
63 }
64
65
66 void
test_compile(valid_pattern,error_code_expected,pattern,pattern_buffer_ptr,cflags)67 test_compile (valid_pattern, error_code_expected, pattern,
68 pattern_buffer_ptr, cflags)
69 unsigned valid_pattern;
70 int error_code_expected;
71 const char *pattern;
72 regex_t *pattern_buffer_ptr;
73 int cflags;
74 {
75 int error_code_returned;
76 boolean error = false;
77 char errbuf[TEST_ERRBUF_SIZE];
78
79 init_pattern_buffer (pattern_buffer_ptr);
80 error_code_returned = regcomp (pattern_buffer_ptr, pattern, cflags);
81
82 if (valid_pattern && error_code_returned)
83 {
84 printf ("\nShould have been a valid pattern but wasn't.\n");
85 regerror (error_code_returned, pattern_buffer_ptr, errbuf,
86 TEST_ERRBUF_SIZE);
87 printf ("%s", errbuf);
88 error = true;
89 }
90
91 if (!valid_pattern && !error_code_returned)
92 {
93 printf ("\n\nInvalid pattern compiled as valid:\n");
94 error = true;
95 }
96
97 if (error_code_returned != error_code_expected)
98 {
99 char expected_error_string[ERROR_CODE_LENGTH];
100 char returned_error_string[ERROR_CODE_LENGTH];
101
102 get_error_string (error_code_expected, expected_error_string),
103 get_error_string (error_code_returned, returned_error_string);
104
105 printf (" Expected error code %s but got `%s'.\n",
106 expected_error_string, returned_error_string);
107
108 error = true;
109 }
110
111 if (error)
112 print_pattern_info (pattern, pattern_buffer_ptr);
113 }
114
115
116 static void
test_nsub(sub_count,pattern,cflags)117 test_nsub (sub_count, pattern, cflags)
118 unsigned sub_count;
119 char *pattern;
120 int cflags;
121
122 {
123 regex_t pattern_buffer;
124
125 test_compile (1, 0, pattern, &pattern_buffer, cflags);
126
127 if (pattern_buffer.re_nsub != sub_count)
128 {
129 printf ("\nShould have counted %d subexpressions but counted %d \
130 instead.\n", sub_count, pattern_buffer.re_nsub);
131 }
132
133 regfree (&pattern_buffer);
134 }
135
136
137 static void
test_regcomp()138 test_regcomp ()
139 {
140 regex_t pattern_buffer;
141 int cflags = 0;
142
143
144 printf ("\nStarting regcomp tests.\n");
145
146 cflags = 0;
147 test_compile (0, REG_ESUBREG, "\\(a\\)\\2", &pattern_buffer, cflags);
148 test_compile (0, REG_EBRACE, "a\\{", &pattern_buffer, cflags);
149 test_compile (0, REG_BADBR, "a\\{-1\\}", &pattern_buffer, cflags);
150 test_compile (0, REG_EBRACE, "a\\{", &pattern_buffer, cflags);
151 test_compile (0, REG_EBRACE, "a\\{1", &pattern_buffer, cflags);
152
153 cflags = REG_EXTENDED;
154 test_compile (0, REG_ECTYPE, "[[:alpo:]]", &pattern_buffer, cflags);
155 test_compile (0, REG_EESCAPE, "\\", &pattern_buffer, cflags);
156 test_compile (0, REG_EBRACK, "[a", &pattern_buffer, cflags);
157 test_compile (0, REG_EPAREN, "(", &pattern_buffer, cflags);
158 test_compile (0, REG_ERANGE, "[z-a]", &pattern_buffer, cflags);
159
160 test_nsub (1, "(a)", cflags);
161 test_nsub (2, "((a))", cflags);
162 test_nsub (2, "(a)(b)", cflags);
163
164 cflags = REG_EXTENDED | REG_NOSUB;
165 test_nsub (1, "(a)", cflags);
166
167 regfree (&pattern_buffer);
168
169 printf ("\nFinished regcomp tests.\n");
170 }
171
172
173 static void
fill_pmatch(pmatch,start0,end0,start1,end1,start2,end2)174 fill_pmatch (pmatch, start0, end0, start1, end1, start2, end2)
175 regmatch_t pmatch[];
176 regoff_t start0, end0, start1, end1, start2, end2;
177 {
178 pmatch[0].rm_so = start0;
179 pmatch[0].rm_eo = end0;
180 pmatch[1].rm_so = start1;
181 pmatch[1].rm_eo = end1;
182 pmatch[2].rm_so = start2;
183 pmatch[2].rm_eo = end2;
184 }
185
186
187 static void
test_pmatch(pattern,string,nmatch,pmatch,correct_pmatch,cflags)188 test_pmatch (pattern, string, nmatch, pmatch, correct_pmatch, cflags)
189 char *pattern;
190 char *string;
191 unsigned nmatch;
192 regmatch_t pmatch[];
193 regmatch_t correct_pmatch[];
194 int cflags;
195 {
196 regex_t pattern_buffer;
197 unsigned this_match;
198 int error_code_returned;
199 boolean found_nonmatch = false;
200
201 test_compile (1, 0, pattern, &pattern_buffer, cflags);
202 error_code_returned = regexec (&pattern_buffer, string, nmatch, pmatch, 0);
203
204 if (error_code_returned == REG_NOMATCH)
205 printf ("Matching failed in test_pmatch.\n");
206 else
207 {
208 for (this_match = 0; this_match < nmatch; this_match++)
209 {
210 if (pmatch[this_match].rm_so != correct_pmatch[this_match].rm_so)
211 {
212 if (found_nonmatch == false)
213 printf ("\n");
214
215 printf ("Pmatch start %d wrong: was %d when should have \
216 been %d.\n", this_match, pmatch[this_match].rm_so,
217 correct_pmatch[this_match].rm_so);
218 found_nonmatch = true;
219 }
220 if (pmatch[this_match].rm_eo != correct_pmatch[this_match].rm_eo)
221 {
222 if (found_nonmatch == false)
223 printf ("\n");
224
225 printf ("Pmatch end %d wrong: was %d when should have been \
226 %d.\n", this_match, pmatch[this_match].rm_eo,
227 correct_pmatch[this_match].rm_eo);
228 found_nonmatch = true;
229 }
230 }
231
232 if (found_nonmatch)
233 {
234 printf (" The number of pmatches requested was: %d.\n", nmatch);
235 printf (" The string to match was: `%s'.\n", string);
236 print_pattern_info (pattern, &pattern_buffer);
237 }
238 } /* error_code_returned == REG_NOMATCH */
239
240 regfree (&pattern_buffer);
241 }
242
243
244 static void
test_eflags(must_match_bol,must_match_eol,pattern,string,cflags,eflags)245 test_eflags (must_match_bol, must_match_eol, pattern, string, cflags, eflags)
246 boolean must_match_bol;
247 boolean must_match_eol;
248 char *pattern;
249 char *string;
250 int cflags;
251 int eflags;
252 {
253 regex_t pattern_buffer;
254 int error_code_returned;
255 boolean was_error = false;
256
257 test_compile (1, 0, pattern, &pattern_buffer, cflags);
258 error_code_returned = regexec (&pattern_buffer, string, 0, 0, eflags);
259
260 if (error_code_returned == REG_NOMATCH)
261 {
262 /* If wasn't true that both 1) the anchored part of the pattern
263 had to match this string and 2) this string was a proper
264 substring... */
265
266 if (!( (must_match_bol && (eflags & REG_NOTBOL))
267 || (must_match_eol && (eflags & REG_NOTEOL)) ))
268 {
269 printf ("\nEflags test failed: didn't match when should have.\n");
270 was_error = true;
271 }
272 }
273 else /* We got a match. */
274 {
275 /* If wasn't true that either 1) the anchored part of the pattern
276 didn't have to match this string or 2) this string wasn't a
277 proper substring... */
278
279 if ((must_match_bol == (eflags & REG_NOTBOL))
280 || (must_match_eol == (eflags & REG_NOTEOL)))
281 {
282 printf ("\nEflags test failed: matched when shouldn't have.\n");
283 was_error = true;
284 }
285 }
286
287 if (was_error)
288 {
289 printf (" The string to match was: `%s'.\n", string);
290 print_pattern_info (pattern, &pattern_buffer);
291
292 if (eflags & REG_NOTBOL)
293 printf (" The eflag REG_BOL was set.\n");
294 if (eflags & REG_NOTEOL)
295 printf (" The eflag REG_EOL was set.\n");
296 }
297
298 regfree (&pattern_buffer);
299 }
300
301
302 static void
test_ignore_case(should_match,pattern,string,cflags)303 test_ignore_case (should_match, pattern, string, cflags)
304 boolean should_match;
305 char *pattern;
306 char *string;
307 int cflags;
308 {
309 regex_t pattern_buffer;
310 int error_code_returned;
311
312 test_compile (1, 0, pattern, &pattern_buffer, cflags);
313 error_code_returned = regexec (&pattern_buffer, string, 0, 0, 0);
314
315 if (should_match && error_code_returned == REG_NOMATCH)
316 {
317 printf ("\nIgnore-case test failed:\n");
318 printf (" The string to match was: `%s'.\n", string);
319 print_pattern_info (pattern, &pattern_buffer);
320
321 if (cflags & REG_ICASE)
322 printf (" The cflag REG_ICASE was set.\n");
323 }
324
325 regfree (&pattern_buffer);
326 }
327
328
329 static void
test_newline(should_match,pattern,string,cflags)330 test_newline (should_match, pattern, string, cflags)
331 boolean should_match;
332 char *pattern;
333 char *string;
334 int cflags;
335 {
336 regex_t pattern_buffer;
337 int error_code_returned;
338
339 test_compile (1, 0, pattern, &pattern_buffer, cflags);
340 error_code_returned = regexec (&pattern_buffer, string, 0, 0, 0);
341
342 if (should_match && error_code_returned == REG_NOMATCH)
343 {
344 printf ("\nNewline test failed:\n");
345 printf (" The string to match was: `%s'.\n", string);
346 print_pattern_info (pattern, &pattern_buffer);
347
348 if (cflags & REG_NEWLINE)
349 printf (" The cflag REG_NEWLINE was set.\n");
350 else
351 printf (" The cflag REG_NEWLINE wasn't set.\n");
352 }
353
354 regfree (&pattern_buffer);
355 }
356
357
358 static void
test_posix_match(should_match,pattern,string,cflags)359 test_posix_match (should_match, pattern, string, cflags)
360 boolean should_match;
361 char *pattern;
362 char *string;
363 int cflags;
364 {
365 regex_t pattern_buffer;
366 int error_code_returned;
367 boolean was_error = false;
368
369 test_compile (1, 0, pattern, &pattern_buffer, cflags);
370 error_code_returned = regexec (&pattern_buffer, string, 0, 0, 0);
371
372 if (should_match && error_code_returned == REG_NOMATCH)
373 {
374 printf ("\nShould have matched but didn't:\n");
375 was_error = true;
376 }
377 else if (!should_match && error_code_returned != REG_NOMATCH)
378 {
379 printf ("\nShould not have matched but did:\n");
380 was_error = true;
381 }
382
383 if (was_error)
384 {
385 printf (" The string to match was: `%s'.\n", string);
386 print_pattern_info (pattern, &pattern_buffer);
387 }
388
389 regfree (&pattern_buffer);
390 }
391
392
393 static void
test_regexec()394 test_regexec ()
395 {
396 regmatch_t pmatch[3];
397 regmatch_t correct_pmatch[3];
398 int cflags = 0;
399 int eflags = 0;
400
401 printf ("\nStarting regexec tests.\n");
402
403 cflags = REG_NOSUB; /* shouldn't look at any of pmatch. */
404 test_pmatch ("a", "a", 0, pmatch, correct_pmatch, cflags);
405
406 /* Ask for less `pmatch'es than there are pattern subexpressions.
407 (Shouldn't look at pmatch[2]. */
408 cflags = REG_EXTENDED;
409 fill_pmatch (correct_pmatch, 0, 1, 0, 1, 100, 101);
410 test_pmatch ("((a))", "a", 2, pmatch, correct_pmatch, cflags);
411
412 /* Ask for same number of `pmatch'es as there are pattern subexpressions. */
413 cflags = REG_EXTENDED;
414 fill_pmatch(correct_pmatch, 0, 1, 0, 1, -1, -1);
415 test_pmatch ("(a)", "a", 2, pmatch, correct_pmatch, cflags);
416
417 /* Ask for more `pmatch'es than there are pattern subexpressions. */
418 cflags = REG_EXTENDED;
419 fill_pmatch (correct_pmatch, 0, 1, -1, -1, -1, -1);
420 test_pmatch ("a", "a", 2, pmatch, correct_pmatch, cflags);
421
422 eflags = REG_NOTBOL;
423 test_eflags (true, false, "^a", "a", cflags, eflags);
424 test_eflags (true, false, "(^a)", "a", cflags, eflags);
425 test_eflags (true, false, "a|^b", "b", cflags, eflags);
426 test_eflags (true, false, "^b|a", "b", cflags, eflags);
427
428 eflags = REG_NOTEOL;
429 test_eflags (false, true, "a$", "a", cflags, eflags);
430 test_eflags (false, true, "(a$)", "a", cflags, eflags);
431 test_eflags (false, true, "a|b$", "b", cflags, eflags);
432 test_eflags (false, true, "b$|a", "b", cflags, eflags);
433
434 eflags = REG_NOTBOL | REG_NOTEOL;
435 test_eflags (true, true, "^a$", "a", cflags, eflags);
436 test_eflags (true, true, "(^a$)", "a", cflags, eflags);
437 test_eflags (true, true, "a|(^b$)", "b", cflags, eflags);
438 test_eflags (true, true, "(^b$)|a", "b", cflags, eflags);
439
440 cflags = REG_ICASE;
441 test_ignore_case (true, "a", "a", cflags);
442 test_ignore_case (true, "A", "A", cflags);
443 test_ignore_case (true, "A", "a", cflags);
444 test_ignore_case (true, "a", "A", cflags);
445
446 test_ignore_case (true, "@", "@", cflags);
447 test_ignore_case (true, "\\[", "[", cflags);
448 test_ignore_case (true, "`", "`", cflags);
449 test_ignore_case (true, "{", "{", cflags);
450
451 test_ignore_case (true, "[!-`]", "A", cflags);
452 test_ignore_case (true, "[!-`]", "a", cflags);
453
454 cflags = 0;
455 test_ignore_case (false, "a", "a", cflags);
456 test_ignore_case (false, "A", "A", cflags);
457 test_ignore_case (false, "A", "a", cflags);
458 test_ignore_case (false, "a", "A", cflags);
459
460 test_ignore_case (true, "@", "@", cflags);
461 test_ignore_case (true, "\\[", "[", cflags);
462 test_ignore_case (true, "`", "`", cflags);
463 test_ignore_case (true, "{", "{", cflags);
464
465 test_ignore_case (true, "[!-`]", "A", cflags);
466 test_ignore_case (false, "[!-`]", "a", cflags);
467
468
469 /* Test newline stuff. */
470 cflags = REG_EXTENDED | REG_NEWLINE;
471 test_newline (true, "\n", "\n", cflags);
472 test_newline (true, "a\n", "a\n", cflags);
473 test_newline (true, "\nb", "\nb", cflags);
474 test_newline (true, "a\nb", "a\nb", cflags);
475
476 test_newline (false, ".", "\n", cflags);
477 test_newline (false, "[^a]", "\n", cflags);
478
479 test_newline (true, "\n^a", "\na", cflags);
480 test_newline (true, "\n(^a|b)", "\na", cflags);
481 test_newline (true, "a$\n", "a\n", cflags);
482 test_newline (true, "(a$|b)\n", "a\n", cflags);
483 test_newline (true, "(a$|b|c)\n", "a\n", cflags);
484 test_newline (true, "((a$|b|c)$)\n", "a\n", cflags);
485 test_newline (true, "((a$|b|c)$)\n", "b\n", cflags);
486 test_newline (true, "(a$|b)\n|a\n", "a\n", cflags);
487
488 test_newline (true, "^a", "\na", cflags);
489 test_newline (true, "a$", "a\n", cflags);
490
491 /* Now test normal behavior. */
492 cflags = REG_EXTENDED;
493 test_newline (true, "\n", "\n", cflags);
494 test_newline (true, "a\n", "a\n", cflags);
495 test_newline (true, "\nb", "\nb", cflags);
496 test_newline (true, "a\nb", "a\nb", cflags);
497
498 test_newline (true, ".", "\n", cflags);
499 test_newline (true, "[^a]", "\n", cflags);
500
501 test_newline (false, "\n^a", "\na", cflags);
502 test_newline (false, "a$\n", "a\n", cflags);
503
504 test_newline (false, "^a", "\na", cflags);
505 test_newline (false, "a$", "a\n", cflags);
506
507
508 /* Test that matches whole string only. */
509 cflags = 0;
510 test_posix_match (true, "a", "a", cflags);
511
512 /* Tests that match substrings. */
513 test_posix_match (true, "a", "ab", cflags);
514 test_posix_match (true, "b", "ab", cflags);
515
516 /* Test that doesn't match. */
517 test_posix_match (false, "a", "b", cflags);
518
519 printf ("\nFinished regexec tests.\n");
520 }
521
522
523 static void
test_error_code_message(error_code,expected_error_message)524 test_error_code_message (error_code, expected_error_message)
525 int error_code;
526 char *expected_error_message;
527 {
528 char returned_error_message[TEST_ERRBUF_SIZE];
529 char error_code_string[ERROR_CODE_LENGTH];
530 size_t expected_error_message_length = strlen (expected_error_message) + 1;
531 size_t returned_error_message_length = regerror (error_code, 0,
532 returned_error_message,
533 TEST_ERRBUF_SIZE);
534
535 if (returned_error_message_length != expected_error_message_length)
536 {
537 printf ("\n\n Testing returned error codes, with expected error \
538 message `%s':\n", expected_error_message);
539
540 printf ("\n\n and returned error message `%s':\n",
541 returned_error_message);
542 printf (" should have returned a length of %d but returned %d.\n",
543 expected_error_message_length, returned_error_message_length);
544 }
545
546 if (strncmp (expected_error_message, returned_error_message,
547 TEST_ERRBUF_SIZE - 1) != 0)
548 {
549
550 get_error_string (error_code, error_code_string),
551 printf ("\n\n With error code %s (%d), expected error message:\n",
552 error_code_string, error_code);
553
554 printf (" `%s'\n", expected_error_message);
555 printf (" but got:\n");
556 printf (" `%s'\n", returned_error_message);
557 }
558 }
559
560
561 static void
test_error_code_allocation(error_code,expected_error_message)562 test_error_code_allocation (error_code, expected_error_message)
563 int error_code;
564 char *expected_error_message;
565 {
566 char *returned_error_message = NULL;
567 char error_code_string[ERROR_CODE_LENGTH];
568 size_t returned_error_message_length = regerror (error_code, 0,
569 returned_error_message,
570 (size_t)0);
571
572 returned_error_message = xmalloc (returned_error_message_length + 1);
573
574 regerror (error_code, 0, returned_error_message,
575 returned_error_message_length);
576
577 if (strcmp (expected_error_message, returned_error_message) != 0)
578 {
579 get_error_string (error_code, error_code_string),
580
581 printf ("\n\n Testing error code allocation,\n");
582 printf ("with error code %s (%d), expected error message:\n",
583 error_code_string, error_code);
584 printf (" `%s'\n", expected_error_message);
585 printf (" but got:\n");
586 printf (" `%s'\n", returned_error_message);
587 }
588 }
589
590
591 static void
test_regerror()592 test_regerror ()
593 {
594 test_error_code_message (REG_NOMATCH, "No match");
595 test_error_code_message (REG_BADPAT, "Invalid regular expression");
596 test_error_code_message (REG_ECOLLATE, "Invalid collation character");
597 test_error_code_message (REG_ECTYPE, "Invalid character class name");
598 test_error_code_message (REG_EESCAPE, "Trailing backslash");
599 test_error_code_message (REG_ESUBREG, "Invalid back reference");
600 test_error_code_message (REG_EBRACK, "Unmatched [ or [^");
601 test_error_code_message (REG_EPAREN, "Unmatched ( or \\(");
602 test_error_code_message (REG_EBRACE, "Unmatched \\{");
603 test_error_code_message (REG_BADBR, "Invalid content of \\{\\}");
604 test_error_code_message (REG_ERANGE, "Invalid range end");
605 test_error_code_message (REG_ESPACE, "Memory exhausted");
606 test_error_code_message (REG_BADRPT, "Invalid preceding regular expression");
607 test_error_code_message (REG_EEND, "Premature end of regular expression");
608 test_error_code_message (REG_ESIZE, "Regular expression too big");
609 test_error_code_allocation (REG_ERPAREN, "Unmatched ) or \\)");
610 }
611
612
613 void
test_posix_interface()614 test_posix_interface ()
615 {
616 printf ("\nStarting POSIX interface tests.\n");
617 t = posix_interface_test;
618
619 test_regcomp ();
620 test_regexec ();
621 test_regerror ();
622
623 printf ("\nFinished POSIX interface tests.\n");
624 }
625