1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
24 #include "apr_general.h"
25 #include "apr_strings.h"
26 #include "apr_errno.h"
28 /* I haven't bothered to check for APR_ENOTIMPL here, AFAIK, all string
29 * functions exist on all platforms.
32 static void test_strtok(CuTest *tc)
44 " asdf jkl; 77889909 \r\n\1\2\3Z",
48 NULL, /* but who cares if apr_strtok() segfaults? */
51 #if 0 /* don't do this... you deserve to segfault */
68 for (curtc = 0; curtc < sizeof cases / sizeof cases[0]; curtc++) {
69 char *retval1, *retval2;
73 str1 = apr_pstrdup(p, cases[curtc].input);
74 str2 = apr_pstrdup(p, cases[curtc].input);
77 retval1 = apr_strtok(str1, cases[curtc].sep, &state);
78 retval2 = strtok(str2, cases[curtc].sep);
81 CuAssertTrue(tc, retval2 == NULL);
84 CuAssertTrue(tc, retval2 != NULL);
85 CuAssertStrEquals(tc, retval2, retval1);
88 str1 = str2 = NULL; /* make sure we pass NULL on subsequent calls */
93 static void snprintf_noNULL(CuTest *tc)
96 char *testing = apr_palloc(p, 10);
106 /* If this test fails, we are going to seg fault. */
107 apr_snprintf(buff, sizeof(buff), "%.*s", 7, testing);
108 CuAssertStrNEquals(tc, buff, testing, 7);
111 static void snprintf_0NULL(CuTest *tc)
115 rv = apr_snprintf(NULL, 0, "%sBAR", "FOO");
116 CuAssertIntEquals(tc, 6, rv);
119 static void snprintf_0nonNULL(CuTest *tc)
122 char *buff = "testing";
124 rv = apr_snprintf(buff, 0, "%sBAR", "FOO");
125 CuAssertIntEquals(tc, 6, rv);
126 CuAssert(tc, "buff unmangled", strcmp(buff, "FOOBAR") != 0);
129 static void snprintf_int64(CuTest *tc)
132 apr_int64_t i = APR_INT64_C(-42);
133 apr_uint64_t ui = APR_INT64_C(42); /* no APR_UINT64_C */
134 apr_uint64_t big = APR_INT64_C(3141592653589793238);
136 apr_snprintf(buf, sizeof buf, "%" APR_INT64_T_FMT, i);
137 CuAssertStrEquals(tc, buf, "-42");
139 apr_snprintf(buf, sizeof buf, "%" APR_UINT64_T_FMT, ui);
140 CuAssertStrEquals(tc, buf, "42");
142 apr_snprintf(buf, sizeof buf, "%" APR_UINT64_T_FMT, big);
143 CuAssertStrEquals(tc, buf, "3141592653589793238");
146 static void snprintf_underflow(CuTest *tc)
151 rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.0001);
152 CuAssertIntEquals(tc, 4, rv);
153 CuAssertStrEquals(tc, "0.00", buf);
155 rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.001);
156 CuAssertIntEquals(tc, 4, rv);
157 CuAssertStrEquals(tc, "0.00", buf);
159 rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.01);
160 CuAssertIntEquals(tc, 4, rv);
161 CuAssertStrEquals(tc, "0.01", buf);
164 static void string_error(CuTest *tc)
170 rv = apr_strerror(APR_ENOENT, buf, sizeof buf);
171 CuAssertPtrEquals(tc, buf, rv);
172 CuAssertTrue(tc, strlen(buf) > 0);
174 rv = apr_strerror(APR_TIMEUP, buf, sizeof buf);
175 CuAssertPtrEquals(tc, buf, rv);
176 CuAssertStrEquals(tc, "The timeout specified has expired", buf);
178 /* throw some randomish numbers at it to check for robustness */
179 for (n = 1; n < 1000000; n *= 2) {
180 apr_strerror(n, buf, sizeof buf);
185 static void string_long(CuTest *tc)
189 memset(s, 'A', SIZE);
192 apr_psprintf(p, "%s", s);
195 /* ### FIXME: apr.h/apr_strings.h should provide these! */
196 #define MY_LLONG_MAX (APR_INT64_C(9223372036854775807))
197 #define MY_LLONG_MIN (-MY_LLONG_MAX - APR_INT64_C(1))
199 static void string_strtoi64(CuTest *tc)
201 static const struct {
203 const char *in, *end;
208 { 0, 10, "123545", NULL, APR_INT64_C(123545) },
209 { 0, 10, " 123545", NULL, APR_INT64_C(123545) },
210 { 0, 10, " +123545", NULL, APR_INT64_C(123545) },
211 { 0, 10, "-123545", NULL, APR_INT64_C(-123545) },
212 { 0, 10, " 00000123545", NULL, APR_INT64_C(123545) },
213 { 0, 10, "123545ZZZ", "ZZZ", APR_INT64_C(123545) },
214 { 0, 10, " 123545 ", " ", APR_INT64_C(123545) },
217 { 0, 16, "1E299", NULL, APR_INT64_C(123545) },
218 { 0, 16, "1e299", NULL, APR_INT64_C(123545) },
219 { 0, 16, "0x1e299", NULL, APR_INT64_C(123545) },
220 { 0, 16, "0X1E299", NULL, APR_INT64_C(123545) },
221 { 0, 16, "+1e299", NULL, APR_INT64_C(123545) },
222 { 0, 16, "-1e299", NULL, APR_INT64_C(-123545) },
223 { 0, 16, " -1e299", NULL, APR_INT64_C(-123545) },
225 /* automatic base detection tests */
226 { 0, 0, "123545", NULL, APR_INT64_C(123545) },
227 { 0, 0, "0x1e299", NULL, APR_INT64_C(123545) },
228 { 0, 0, " 0x1e299", NULL, APR_INT64_C(123545) },
229 { 0, 0, "+0x1e299", NULL, APR_INT64_C(123545) },
230 { 0, 0, "-0x1e299", NULL, APR_INT64_C(-123545) },
232 /* large number tests */
233 { 0, 10, "8589934605", NULL, APR_INT64_C(8589934605) },
234 { 0, 10, "-8589934605", NULL, APR_INT64_C(-8589934605) },
235 { 0, 16, "0x20000000D", NULL, APR_INT64_C(8589934605) },
236 { 0, 16, "-0x20000000D", NULL, APR_INT64_C(-8589934605) },
237 { 0, 16, " 0x20000000D", NULL, APR_INT64_C(8589934605) },
238 { 0, 16, " 0x20000000D", NULL, APR_INT64_C(8589934605) },
241 { ERANGE, 10, "999999999999999999999999999999999", "", MY_LLONG_MAX },
242 { ERANGE, 10, "-999999999999999999999999999999999", "", MY_LLONG_MIN },
245 /* C99 doesn't require EINVAL for an invalid range. */
246 { EINVAL, 99, "", (void *)-1 /* don't care */, 0 },
249 /* some strtoll implementations give EINVAL when no conversion
251 { -1 /* don't care */, 10, "zzz", "zzz", APR_INT64_C(0) },
252 { -1 /* don't care */, 10, "", NULL, APR_INT64_C(0) }
257 for (n = 0; n < sizeof(ts)/sizeof(ts[0]); n++) {
258 char *end = "end ptr not changed";
263 result = apr_strtoi64(ts[n].in, &end, ts[n].base);
267 apr_psprintf(p, "for '%s': result was %" APR_INT64_T_FMT
268 " not %" APR_INT64_T_FMT, ts[n].in,
269 result, ts[n].result),
270 result == ts[n].result);
272 if (ts[n].errnum != -1) {
274 apr_psprintf(p, "for '%s': errno was %d not %d", ts[n].in,
275 errnum, ts[n].errnum),
276 ts[n].errnum == errnum);
279 if (ts[n].end == NULL) {
280 /* end must point to NUL terminator of .in */
281 CuAssertPtrEquals(tc, ts[n].in + strlen(ts[n].in), end);
282 } else if (ts[n].end != (void *)-1) {
284 apr_psprintf(p, "for '%s', end was '%s' not '%s'",
285 ts[n].in, end, ts[n].end),
286 strcmp(ts[n].end, end) == 0);
291 CuSuite *teststr(void)
293 CuSuite *suite = CuSuiteNew("Strings");
295 SUITE_ADD_TEST(suite, snprintf_0NULL);
296 SUITE_ADD_TEST(suite, snprintf_0nonNULL);
297 SUITE_ADD_TEST(suite, snprintf_noNULL);
298 SUITE_ADD_TEST(suite, snprintf_int64);
299 SUITE_ADD_TEST(suite, snprintf_underflow);
300 SUITE_ADD_TEST(suite, test_strtok);
301 SUITE_ADD_TEST(suite, string_error);
302 SUITE_ADD_TEST(suite, string_long);
303 SUITE_ADD_TEST(suite, string_strtoi64);