1 /*
2  * Copyright 2013 MongoDB, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 
18 #include <bson.h>
19 #include <fcntl.h>
20 #include <time.h>
21 
22 #include "bson-tests.h"
23 #include "TestSuite.h"
24 
25 
26 static void
test_bson_string_new(void)27 test_bson_string_new (void)
28 {
29    bson_string_t *str;
30    char *s;
31 
32    str = bson_string_new (NULL);
33    s = bson_string_free (str, false);
34    BSON_ASSERT (s);
35    BSON_ASSERT (!strcmp (s, ""));
36    bson_free (s);
37 
38    str = bson_string_new ("");
39    s = bson_string_free (str, false);
40    BSON_ASSERT (s);
41    BSON_ASSERT (!*s);
42    BSON_ASSERT (0 == strcmp (s, ""));
43    bson_free (s);
44 
45    str = bson_string_new ("abcdef");
46    s = bson_string_free (str, false);
47    BSON_ASSERT (s);
48    BSON_ASSERT (!strcmp (s, "abcdef"));
49    bson_free (s);
50 
51    str = bson_string_new ("");
52    s = bson_string_free (str, true);
53    BSON_ASSERT (!s);
54 }
55 
56 
57 static void
test_bson_string_append(void)58 test_bson_string_append (void)
59 {
60    bson_string_t *str;
61    char *s;
62 
63    str = bson_string_new (NULL);
64    bson_string_append (str, "christian was here");
65    bson_string_append (str, "\n");
66    s = bson_string_free (str, false);
67    BSON_ASSERT (s);
68    BSON_ASSERT (!strcmp (s, "christian was here\n"));
69    bson_free (s);
70 
71    str = bson_string_new (">>>");
72    bson_string_append (str, "^^^");
73    bson_string_append (str, "<<<");
74    s = bson_string_free (str, false);
75    BSON_ASSERT (s);
76    BSON_ASSERT (!strcmp (s, ">>>^^^<<<"));
77    bson_free (s);
78 }
79 
80 
81 static void
test_bson_string_append_c(void)82 test_bson_string_append_c (void)
83 {
84    bson_string_t *str;
85    char *s;
86 
87    str = bson_string_new (NULL);
88    bson_string_append_c (str, 'c');
89    bson_string_append_c (str, 'h');
90    bson_string_append_c (str, 'r');
91    bson_string_append_c (str, 'i');
92    bson_string_append_c (str, 's');
93    s = bson_string_free (str, false);
94    BSON_ASSERT (s);
95    BSON_ASSERT (!strcmp (s, "chris"));
96    bson_free (s);
97 }
98 
99 
100 static void
test_bson_string_append_printf(void)101 test_bson_string_append_printf (void)
102 {
103    bson_string_t *str;
104 
105    str = bson_string_new ("abcd ");
106    bson_string_append_printf (str, "%d %d %d", 1, 2, 3);
107    BSON_ASSERT (!strcmp (str->str, "abcd 1 2 3"));
108    bson_string_truncate (str, 2);
109    BSON_ASSERT (!strcmp (str->str, "ab"));
110    bson_string_free (str, true);
111 }
112 
113 
114 static void
test_bson_string_append_unichar(void)115 test_bson_string_append_unichar (void)
116 {
117    static const unsigned char test1[] = {0xe2, 0x82, 0xac, 0};
118    bson_string_t *str;
119    char *s;
120 
121    str = bson_string_new (NULL);
122    bson_string_append_unichar (str, 0x20AC);
123    s = bson_string_free (str, false);
124    BSON_ASSERT (s);
125    BSON_ASSERT (!strcmp (s, (const char *) test1));
126    bson_free (s);
127 }
128 
129 
130 static void
test_bson_strdup_printf(void)131 test_bson_strdup_printf (void)
132 {
133    char *s;
134 
135    s = bson_strdup_printf ("%s:%u", "localhost", 27017);
136    BSON_ASSERT (!strcmp (s, "localhost:27017"));
137    bson_free (s);
138 }
139 
140 
141 static void
test_bson_strdup(void)142 test_bson_strdup (void)
143 {
144    char *s;
145 
146    s = bson_strdup ("localhost:27017");
147    BSON_ASSERT (!strcmp (s, "localhost:27017"));
148    bson_free (s);
149 }
150 
151 
152 static void
test_bson_strndup(void)153 test_bson_strndup (void)
154 {
155    char *s;
156 
157    s = bson_strndup ("asdf", 2);
158    BSON_ASSERT (!strcmp (s, "as"));
159    bson_free (s);
160 
161    s = bson_strndup ("asdf", 10);
162    BSON_ASSERT (!strcmp (s, "asdf"));
163    bson_free (s);
164 
165    /* Some tests where we truncate to size n-1, n, n+1 */
166    s = bson_strndup ("asdf", 3);
167    BSON_ASSERT (!strcmp (s, "asd"));
168    bson_free (s);
169 
170    s = bson_strndup ("asdf", 4);
171    BSON_ASSERT (!strcmp (s, "asdf"));
172    bson_free (s);
173 
174    s = bson_strndup ("asdf", 5);
175    BSON_ASSERT (!strcmp (s, "asdf"));
176    bson_free (s);
177 }
178 
179 
180 static void
test_bson_strnlen(void)181 test_bson_strnlen (void)
182 {
183    char *s = "test";
184 
185    ASSERT_CMPINT ((int) strlen (s), ==, (int) bson_strnlen (s, 100));
186 }
187 
188 
189 typedef struct {
190    const char *str;
191    int base;
192    int64_t rv;
193    const char *remaining;
194    int _errno;
195 } strtoll_test;
196 
197 
198 static void
test_bson_ascii_strtoll(void)199 test_bson_ascii_strtoll (void)
200 {
201 #ifdef END
202 #undef END
203 #endif
204 #define END ""
205    int64_t rv;
206    int i;
207    char *endptr;
208    strtoll_test tests[] = {
209       /* input, base, expected output, # of chars parsed, expected errno */
210       {"1", 10, 1, END, 0},
211       {"+1", 10, 1, END, 0},
212       {"-1", 10, -1, END, 0},
213       {"0", 10, 0, END, 0},
214       {"0 ", 10, 0, " ", 0},
215       {" 0 ", 10, 0, " ", 0},
216       {" 0", 10, 0, END, 0},
217       {" 0\"", 10, 0, "\"", 0},
218       {"0l", 10, 0, "l", 0},
219       {"0l ", 10, 0, "l ", 0},
220       {"0u", 10, 0, "u", 0},
221       {"0u ", 10, 0, "u ", 0},
222       {"0L", 10, 0, "L", 0},
223       {"0L ", 10, 0, "L ", 0},
224       {"0U", 10, 0, "U", 0},
225       {"0U ", 10, 0, "U ", 0},
226       {"-0", 10, 0, END, 0},
227       {"+0", 10, 0, END, 0},
228       {"010", 8, 8, END, 0},
229       /* stroll "takes as many characters as possible to form a valid base-n
230        * integer", so it ignores "8" and returns 0 */
231       {"08", 0, 0, "8", 0},
232       {"010", 10, 10, END, 0},
233       {"010", 8, 8, END, 0},
234       {"010", 0, 8, END, 0},
235       {"68719476736", 10, 68719476736, END, 0},
236       {"-68719476736", 10, -68719476736, END, 0},
237       {"+68719476736", 10, 68719476736, END, 0},
238       {"   68719476736  ", 10, 68719476736, "  ", 0},
239       {"   68719476736  ", 0, 68719476736, "  ", 0},
240       {"   -68719476736  ", 10, -68719476736, "  ", 0},
241       {"   -68719476736  ", 0, -68719476736, "  ", 0},
242       {"   4611686018427387904LL", 10, 4611686018427387904LL, "LL", 0},
243       {" -4611686018427387904LL ", 10, -4611686018427387904LL, "LL ", 0},
244       {"0x1000000000", 16, 68719476736, END, 0},
245       {"0x1000000000", 0, 68719476736, END, 0},
246       {"-0x1000000000", 16, -68719476736, END, 0},
247       {"-0x1000000000", 0, -68719476736, END, 0},
248       {"+0x1000000000", 16, 68719476736, END, 0},
249       {"+0x1000000000", 0, 68719476736, END, 0},
250       {"01234", 8, 668, END, 0},
251       {"01234", 0, 668, END, 0},
252       {"-01234", 8, -668, END, 0},
253       {"-01234", 0, -668, END, 0},
254       {"+01234", 8, 668, END, 0},
255       {"+01234", 0, 668, END, 0},
256       {"9223372036854775807", 10, INT64_MAX, END, 0},
257       {"-9223372036854775808", 10, INT64_MIN, END, 0},
258       {"9223372036854775808", 10, INT64_MAX, "8", ERANGE},   /* LLONG_MAX+1   */
259       {"-9223372036854775809", 10, INT64_MIN, "9", ERANGE},  /* LLONG_MIN-1   */
260       {"18446744073709551615", 10, INT64_MAX, "5", ERANGE},  /* 2*LLONG_MAX+1 */
261       {"-18446744073709551618", 10, INT64_MIN, "8", ERANGE}, /* 2*LLONG_MIN-1 */
262       {NULL}};
263 
264    for (i = 0; tests[i].str; i++) {
265       errno = 0;
266 
267       rv = bson_ascii_strtoll (tests[i].str, &endptr, tests[i].base);
268       BSON_ASSERT_CMPINT (rv, ==, tests[i].rv);
269       BSON_ASSERT_CMPINT (errno, ==, tests[i]._errno);
270       BSON_ASSERT_CMPSTR (endptr, tests[i].remaining);
271    }
272 #undef END
273 }
274 
275 
276 static void
test_bson_strncpy(void)277 test_bson_strncpy (void)
278 {
279    char buf[5];
280 
281    bson_strncpy (buf, "foo", sizeof buf);
282    BSON_ASSERT_CMPSTR ("foo", buf);
283    bson_strncpy (buf, "foobar", sizeof buf);
284    BSON_ASSERT_CMPSTR ("foob", buf);
285 }
286 
287 
288 static void
test_bson_strcasecmp(void)289 test_bson_strcasecmp (void)
290 {
291    BSON_ASSERT (!bson_strcasecmp ("FoO", "foo"));
292    BSON_ASSERT (bson_strcasecmp ("Foa", "foo") < 0);
293    BSON_ASSERT (bson_strcasecmp ("FoZ", "foo") > 0);
294 }
295 
296 
297 void
test_string_install(TestSuite * suite)298 test_string_install (TestSuite *suite)
299 {
300    TestSuite_Add (suite, "/bson/string/new", test_bson_string_new);
301    TestSuite_Add (suite, "/bson/string/append", test_bson_string_append);
302    TestSuite_Add (suite, "/bson/string/append_c", test_bson_string_append_c);
303    TestSuite_Add (
304       suite, "/bson/string/append_printf", test_bson_string_append_printf);
305    TestSuite_Add (
306       suite, "/bson/string/append_unichar", test_bson_string_append_unichar);
307    TestSuite_Add (suite, "/bson/string/strdup", test_bson_strdup);
308    TestSuite_Add (suite, "/bson/string/strdup_printf", test_bson_strdup_printf);
309    TestSuite_Add (suite, "/bson/string/strndup", test_bson_strndup);
310    TestSuite_Add (suite, "/bson/string/ascii_strtoll", test_bson_ascii_strtoll);
311    TestSuite_Add (suite, "/bson/string/strncpy", test_bson_strncpy);
312    TestSuite_Add (suite, "/bson/string/strnlen", test_bson_strnlen);
313    TestSuite_Add (suite, "/bson/string/strcasecmp", test_bson_strcasecmp);
314 }
315