tests: add signature checks
[gnulib.git] / tests / test-strcasestr.c
1 /* Test of case-insensitive searching in a string.
2    Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
18
19 #include <config.h>
20
21 #include <string.h>
22
23 #include "signature.h"
24 SIGNATURE_CHECK (strcasestr, char *, (char const *, char const *));
25
26 #include <signal.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30
31 #define ASSERT(expr) \
32   do                                                                         \
33     {                                                                        \
34       if (!(expr))                                                           \
35         {                                                                    \
36           fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
37           fflush (stderr);                                                   \
38           abort ();                                                          \
39         }                                                                    \
40     }                                                                        \
41   while (0)
42
43 int
44 main ()
45 {
46 #if HAVE_DECL_ALARM
47   /* Declare failure if test takes too long, by using default abort
48      caused by SIGALRM.  All known platforms that lack alarm also lack
49      strcasestr, and the replacement strcasestr is known to not take too
50      long.  */
51   signal (SIGALRM, SIG_DFL);
52   alarm (50);
53 #endif
54
55   {
56     const char input[] = "foo";
57     const char *result = strcasestr (input, "");
58     ASSERT (result == input);
59   }
60
61   {
62     const char input[] = "foo";
63     const char *result = strcasestr (input, "O");
64     ASSERT (result == input + 1);
65   }
66
67   {
68     const char input[] = "ABC ABCDAB ABCDABCDABDE";
69     const char *result = strcasestr (input, "ABCDaBD");
70     ASSERT (result == input + 15);
71   }
72
73   {
74     const char input[] = "ABC ABCDAB ABCDABCDABDE";
75     const char *result = strcasestr (input, "ABCDaBE");
76     ASSERT (result == NULL);
77   }
78
79   {
80     const char input[] = "ABC ABCDAB ABCDABCDABDE";
81     const char *result = strcasestr (input, "ABCDaBCD");
82     ASSERT (result == input + 11);
83   }
84
85   /* Check that a very long haystack is handled quickly if the needle is
86      short and occurs near the beginning.  */
87   {
88     size_t repeat = 10000;
89     size_t m = 1000000;
90     char *needle =
91       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
92       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaAaaaaaaAAAAaaaaaaa"
93       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
94     char *haystack = (char *) malloc (m + 1);
95     if (haystack != NULL)
96       {
97         memset (haystack, 'A', m);
98         haystack[0] = 'B';
99         haystack[m] = '\0';
100
101         for (; repeat > 0; repeat--)
102           {
103             ASSERT (strcasestr (haystack, needle) == haystack + 1);
104           }
105
106         free (haystack);
107       }
108   }
109
110   /* Check that a very long needle is discarded quickly if the haystack is
111      short.  */
112   {
113     size_t repeat = 10000;
114     size_t m = 1000000;
115     char *haystack =
116       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
117       "ABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB";
118     char *needle = (char *) malloc (m + 1);
119     if (needle != NULL)
120       {
121         memset (needle, 'A', m);
122         needle[m] = '\0';
123
124         for (; repeat > 0; repeat--)
125           {
126             ASSERT (strcasestr (haystack, needle) == NULL);
127           }
128
129         free (needle);
130       }
131   }
132
133   /* Check that the asymptotic worst-case complexity is not quadratic.  */
134   {
135     size_t m = 1000000;
136     char *haystack = (char *) malloc (2 * m + 2);
137     char *needle = (char *) malloc (m + 2);
138     if (haystack != NULL && needle != NULL)
139       {
140         const char *result;
141
142         memset (haystack, 'A', 2 * m);
143         haystack[2 * m] = 'B';
144         haystack[2 * m + 1] = '\0';
145
146         memset (needle, 'a', m);
147         needle[m] = 'B';
148         needle[m + 1] = '\0';
149
150         result = strcasestr (haystack, needle);
151         ASSERT (result == haystack + m);
152       }
153     free (needle);
154     free (haystack);
155   }
156
157   return 0;
158 }