976f293137e2f7edd883425845a83a18d86672fa
[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   /* Check that length 0 does not dereference NULL.  */
73   {
74     const char *result = memmem (NULL, 0, "foo", 3);
75     ASSERT (result == NULL);
76   }
77
78   {
79     const char input[] = "foo";
80     const char *result = memmem (input, strlen (input), NULL, 0);
81     ASSERT (result == input);
82   }
83
84   /* Check that a very long haystack is handled quickly if the needle is
85      short and occurs near the beginning.  */
86   {
87     size_t repeat = 10000;
88     size_t m = 1000000;
89     char *needle =
90       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
91       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
92     size_t n = strlen (needle);
93     char *haystack = (char *) malloc (m + 1);
94     if (haystack != NULL)
95       {
96         memset (haystack, 'A', m);
97         haystack[0] = 'B';
98
99         for (; repeat > 0; repeat--)
100           {
101             ASSERT (memmem (haystack, m, needle, n) == haystack + 1);
102           }
103
104         free (haystack);
105       }
106   }
107
108   /* Check that a very long needle is discarded quickly if the haystack is
109      short.  */
110   {
111     size_t repeat = 10000;
112     size_t m = 1000000;
113     char *haystack =
114       "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
115       "ABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB";
116     size_t n = strlen (haystack);
117     char *needle = (char *) malloc (m + 1);
118     if (needle != NULL)
119       {
120         memset (needle, 'A', m);
121
122         for (; repeat > 0; repeat--)
123           {
124             ASSERT (memmem (haystack, n, needle, m) == NULL);
125           }
126
127         free (needle);
128       }
129   }
130
131   /* Check that the asymptotic worst-case complexity is not quadratic.  */
132   {
133     size_t m = 1000000;
134     char *haystack = (char *) malloc (2 * m + 1);
135     char *needle = (char *) malloc (m + 1);
136     if (haystack != NULL && needle != NULL)
137       {
138         const char *result;
139
140         memset (haystack, 'A', 2 * m);
141         haystack[2 * m] = 'B';
142
143         memset (needle, 'A', m);
144         needle[m] = 'B';
145
146         result = memmem (haystack, 2 * m + 1, needle, m + 1);
147         ASSERT (result == haystack + m);
148       }
149     if (needle != NULL)
150       free (needle);
151     if (haystack != NULL)
152       free (haystack);
153   }
154
155   return 0;
156 }