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 #define BSON_INSIDE
20 #include "bson-thread-private.h"
21 #undef BSON_INSIDE
22 #include <ctype.h>
23 #include <fcntl.h>
24 #include <time.h>
25
26 #ifdef HAVE_STRINGS_H
27 #include <strings.h>
28 #endif
29
30 #include "bson-tests.h"
31 #include "TestSuite.h"
32
33 #define N_THREADS 4
34
35 static const char *gTestOids[] = {"000000000000000000000000",
36 "010101010101010101010101",
37 "0123456789abcdefafcdef03",
38 "fcdeab182763817236817236",
39 "ffffffffffffffffffffffff",
40 "eeeeeeeeeeeeeeeeeeeeeeee",
41 "999999999999999999999999",
42 "111111111111111111111111",
43 NULL};
44
45 static const char *gTestOidsCase[] = {"0123456789ABCDEFAFCDEF03",
46 "FCDEAB182763817236817236",
47 "FFFFFFFFFFFFFFFFFFFFFFFF",
48 "EEEEEEEEEEEEEEEEEEEEEEEE",
49 "01234567890ACBCDEFabcdef",
50 NULL};
51
52 static const char *gTestOidsFail[] = {" ",
53 "abasdf ",
54 "asdfasdfasdfasdfasdf ",
55 "00000000000000000000000z",
56 "00187263123ghh21382812a8",
57 NULL};
58
59 static void *
oid_worker(void * data)60 oid_worker (void *data)
61 {
62 bson_context_t *context = data;
63 bson_oid_t oid;
64 bson_oid_t oid2;
65 int i;
66
67 bson_oid_init (&oid2, context);
68 for (i = 0; i < 500000; i++) {
69 bson_oid_init (&oid, context);
70 BSON_ASSERT (false == bson_oid_equal (&oid, &oid2));
71 BSON_ASSERT (0 < bson_oid_compare (&oid, &oid2));
72 bson_oid_copy (&oid, &oid2);
73 }
74
75 return NULL;
76 }
77
78 static void
test_bson_oid_init_from_string(void)79 test_bson_oid_init_from_string (void)
80 {
81 bson_context_t *context;
82 bson_oid_t oid;
83 char str[25];
84 int i;
85
86 context = bson_context_new (BSON_CONTEXT_NONE);
87
88 /*
89 * Test successfully parsed oids.
90 */
91
92 for (i = 0; gTestOids[i]; i++) {
93 bson_oid_init_from_string (&oid, gTestOids[i]);
94 bson_oid_to_string (&oid, str);
95 BSON_ASSERT (!strcmp (str, gTestOids[i]));
96 }
97
98 /*
99 * Test successfully parsed oids (case-insensitive).
100 */
101 for (i = 0; gTestOidsCase[i]; i++) {
102 char oid_lower[25];
103 int j;
104
105 bson_oid_init_from_string (&oid, gTestOidsCase[i]);
106 bson_oid_to_string (&oid, str);
107 BSON_ASSERT (!bson_strcasecmp (str, gTestOidsCase[i]));
108
109 for (j = 0; gTestOidsCase[i][j]; j++) {
110 oid_lower[j] = tolower (gTestOidsCase[i][j]);
111 }
112
113 oid_lower[24] = '\0';
114 BSON_ASSERT (!strcmp (str, oid_lower));
115 }
116
117 /*
118 * Test that sizeof(str) works (len of 25 with \0 instead of 24).
119 */
120 BSON_ASSERT (bson_oid_is_valid ("ffffffffffffffffffffffff", 24));
121 bson_oid_init_from_string (&oid, "ffffffffffffffffffffffff");
122 bson_oid_to_string (&oid, str);
123 BSON_ASSERT (bson_oid_is_valid (str, sizeof str));
124
125 /*
126 * Test the failures.
127 */
128
129 for (i = 0; gTestOidsFail[i]; i++) {
130 bson_oid_init_from_string (&oid, gTestOidsFail[i]);
131 bson_oid_to_string (&oid, str);
132 BSON_ASSERT (strcmp (str, gTestOidsFail[i]));
133 }
134
135 bson_context_destroy (context);
136 }
137
138
139 static void
test_bson_oid_hash(void)140 test_bson_oid_hash (void)
141 {
142 bson_oid_t oid;
143
144 bson_oid_init_from_string (&oid, "000000000000000000000000");
145 BSON_ASSERT (bson_oid_hash (&oid) == 1487062149);
146 }
147
148
149 static void
test_bson_oid_compare(void)150 test_bson_oid_compare (void)
151 {
152 bson_oid_t oid;
153 bson_oid_t oid2;
154
155 bson_oid_init_from_string (&oid, "000000000000000000001234");
156 bson_oid_init_from_string (&oid2, "000000000000000000001234");
157 BSON_ASSERT (0 == bson_oid_compare (&oid, &oid2));
158 BSON_ASSERT (true == bson_oid_equal (&oid, &oid2));
159
160 bson_oid_init_from_string (&oid, "000000000000000000001234");
161 bson_oid_init_from_string (&oid2, "000000000000000000004321");
162 BSON_ASSERT (bson_oid_compare (&oid, &oid2) < 0);
163 BSON_ASSERT (bson_oid_compare (&oid2, &oid) > 0);
164 BSON_ASSERT (false == bson_oid_equal (&oid, &oid2));
165 }
166
167
168 static void
test_bson_oid_copy(void)169 test_bson_oid_copy (void)
170 {
171 bson_oid_t oid;
172 bson_oid_t oid2;
173
174 bson_oid_init_from_string (&oid, "000000000000000000001234");
175 bson_oid_init_from_string (&oid2, "000000000000000000004321");
176 bson_oid_copy (&oid, &oid2);
177 BSON_ASSERT (true == bson_oid_equal (&oid, &oid2));
178 }
179
180
181 static void
test_bson_oid_init(void)182 test_bson_oid_init (void)
183 {
184 bson_context_t *context;
185 bson_oid_t oid;
186 bson_oid_t oid2;
187 int i;
188
189 context = bson_context_new (BSON_CONTEXT_NONE);
190 bson_oid_init (&oid, context);
191 for (i = 0; i < 10000; i++) {
192 bson_oid_init (&oid2, context);
193 BSON_ASSERT (false == bson_oid_equal (&oid, &oid2));
194 BSON_ASSERT (0 > bson_oid_compare (&oid, &oid2));
195 bson_oid_copy (&oid2, &oid);
196 }
197 bson_context_destroy (context);
198
199 /*
200 * Test that the shared context works.
201 */
202 bson_oid_init (&oid, NULL);
203 BSON_ASSERT (bson_context_get_default ());
204 }
205
206
207 static void
test_bson_oid_init_sequence(void)208 test_bson_oid_init_sequence (void)
209 {
210 bson_context_t *context;
211 bson_oid_t oid;
212 bson_oid_t oid2;
213 int i;
214
215 context = bson_context_new (BSON_CONTEXT_NONE);
216 bson_oid_init_sequence (&oid, context);
217 for (i = 0; i < 10000; i++) {
218 bson_oid_init_sequence (&oid2, context);
219 BSON_ASSERT (false == bson_oid_equal (&oid, &oid2));
220 BSON_ASSERT (0 > bson_oid_compare (&oid, &oid2));
221 bson_oid_copy (&oid2, &oid);
222 }
223 bson_context_destroy (context);
224 }
225
226
227 static void
test_bson_oid_init_sequence_thread_safe(void)228 test_bson_oid_init_sequence_thread_safe (void)
229 {
230 bson_context_t *context;
231 bson_oid_t oid;
232 bson_oid_t oid2;
233 int i;
234
235 context = bson_context_new (BSON_CONTEXT_THREAD_SAFE);
236 bson_oid_init_sequence (&oid, context);
237 for (i = 0; i < 10000; i++) {
238 bson_oid_init_sequence (&oid2, context);
239 BSON_ASSERT (false == bson_oid_equal (&oid, &oid2));
240 BSON_ASSERT (0 > bson_oid_compare (&oid, &oid2));
241 bson_oid_copy (&oid2, &oid);
242 }
243 bson_context_destroy (context);
244 }
245
246
247 #ifdef BSON_HAVE_SYSCALL_TID
248 static void
test_bson_oid_init_sequence_with_tid(void)249 test_bson_oid_init_sequence_with_tid (void)
250 {
251 bson_context_t *context;
252 bson_oid_t oid;
253 bson_oid_t oid2;
254 int i;
255
256 context = bson_context_new (BSON_CONTEXT_USE_TASK_ID);
257 bson_oid_init_sequence (&oid, context);
258 for (i = 0; i < 10000; i++) {
259 bson_oid_init_sequence (&oid2, context);
260 BSON_ASSERT (false == bson_oid_equal (&oid, &oid2));
261 BSON_ASSERT (0 > bson_oid_compare (&oid, &oid2));
262 bson_oid_copy (&oid2, &oid);
263 }
264 bson_context_destroy (context);
265 }
266 #endif
267
268
269 static void
test_bson_oid_get_time_t(void)270 test_bson_oid_get_time_t (void)
271 {
272 bson_context_t *context;
273 bson_oid_t oid;
274 bson_oid_t oid2;
275
276 /*
277 * Test that the bson time_t matches the current time. This can race, but
278 * i dont think that matters much.
279 */
280 context = bson_context_new (BSON_CONTEXT_NONE);
281 bson_oid_init (&oid, context);
282 bson_oid_init (&oid2, context);
283 BSON_ASSERT (bson_oid_get_time_t (&oid) == bson_oid_get_time_t (&oid2));
284 BSON_ASSERT (time (NULL) == bson_oid_get_time_t (&oid2));
285 bson_context_destroy (context);
286 }
287
288
289 static void
test_bson_oid_init_with_threads(void)290 test_bson_oid_init_with_threads (void)
291 {
292 bson_context_t *context;
293 int i;
294
295 {
296 bson_context_flags_t flags = 0;
297 bson_context_t *contexts[N_THREADS];
298 bson_thread_t threads[N_THREADS];
299
300 #ifdef BSON_HAVE_SYSCALL_TID
301 flags |= BSON_CONTEXT_USE_TASK_ID;
302 #endif
303
304 for (i = 0; i < N_THREADS; i++) {
305 contexts[i] = bson_context_new (flags);
306 bson_thread_create (&threads[i], oid_worker, contexts[i]);
307 }
308
309 for (i = 0; i < N_THREADS; i++) {
310 bson_thread_join (threads[i]);
311 }
312
313 for (i = 0; i < N_THREADS; i++) {
314 bson_context_destroy (contexts[i]);
315 }
316 }
317
318 /*
319 * Test threaded generation of oids using a single context;
320 */
321 {
322 bson_thread_t threads[N_THREADS];
323
324 context = bson_context_new (BSON_CONTEXT_THREAD_SAFE);
325
326 for (i = 0; i < N_THREADS; i++) {
327 bson_thread_create (&threads[i], oid_worker, context);
328 }
329
330 for (i = 0; i < N_THREADS; i++) {
331 bson_thread_join (threads[i]);
332 }
333
334 bson_context_destroy (context);
335 }
336 }
337
338 void
test_oid_install(TestSuite * suite)339 test_oid_install (TestSuite *suite)
340 {
341 TestSuite_Add (suite, "/bson/oid/init", test_bson_oid_init);
342 TestSuite_Add (
343 suite, "/bson/oid/init_from_string", test_bson_oid_init_from_string);
344 TestSuite_Add (
345 suite, "/bson/oid/init_sequence", test_bson_oid_init_sequence);
346 TestSuite_Add (suite,
347 "/bson/oid/init_sequence_thread_safe",
348 test_bson_oid_init_sequence_thread_safe);
349 #ifdef BSON_HAVE_SYSCALL_TID
350 TestSuite_Add (suite,
351 "/bson/oid/init_sequence_with_tid",
352 test_bson_oid_init_sequence_with_tid);
353 #endif
354 TestSuite_Add (
355 suite, "/bson/oid/init_with_threads", test_bson_oid_init_with_threads);
356 TestSuite_Add (suite, "/bson/oid/hash", test_bson_oid_hash);
357 TestSuite_Add (suite, "/bson/oid/compare", test_bson_oid_compare);
358 TestSuite_Add (suite, "/bson/oid/copy", test_bson_oid_copy);
359 TestSuite_Add (suite, "/bson/oid/get_time_t", test_bson_oid_get_time_t);
360 }
361