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