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