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 <time.h>
19 
20 #include "bson-tests.h"
21 #include "TestSuite.h"
22 
23 
24 static void *
test_bson_writer_custom_realloc_helper(void * mem,size_t num_bytes,void * ctx)25 test_bson_writer_custom_realloc_helper (void *mem, size_t num_bytes, void *ctx)
26 {
27    int *x = (int *) ctx;
28 
29    *x = *x + 1;
30    return bson_realloc (mem, num_bytes);
31 }
32 
33 static void
test_bson_writer_custom_realloc(void)34 test_bson_writer_custom_realloc (void)
35 {
36    bson_writer_t *writer;
37    uint8_t *buf = bson_malloc (0);
38    size_t buflen = 0;
39    bson_t *b;
40    int x = 0;
41 
42    writer = bson_writer_new (
43       &buf, &buflen, 0, test_bson_writer_custom_realloc_helper, &x);
44 
45    BSON_ASSERT (bson_writer_begin (writer, &b));
46 
47    BSON_ASSERT (bson_append_utf8 (b, "hello", -1, "world", -1));
48 
49    bson_writer_end (writer);
50 
51    bson_writer_destroy (writer);
52 
53    BSON_ASSERT_CMPINT (x, >, 0);
54 
55    bson_free (buf);
56 }
57 
58 
59 static void
test_bson_writer_shared_buffer(void)60 test_bson_writer_shared_buffer (void)
61 {
62    bson_writer_t *writer;
63    uint8_t *buf = bson_malloc0 (32);
64    bool rolled_back = false;
65    size_t buflen = 32;
66    size_t n_bytes;
67    bson_t *b;
68    const char *key;
69    char keystr[32];
70    int i = 0;
71    int j = 0;
72    int n_docs = 10000;
73 
74    writer = bson_writer_new (&buf, &buflen, 0, bson_realloc_ctx, NULL);
75 
76    for (i = 0; i < n_docs; i++) {
77       BSON_ASSERT (bson_writer_begin (writer, &b));
78 
79       for (j = 0; j < 1000; j++) {
80          bson_uint32_to_string (j, &key, keystr, sizeof keystr);
81          BSON_ASSERT (bson_append_int64 (b, key, -1, j));
82       }
83 
84       if (bson_writer_get_length (writer) > (48 * 1024 * 1024)) {
85          rolled_back = true;
86          bson_writer_rollback (writer);
87          break;
88       } else {
89          bson_writer_end (writer);
90       }
91    }
92 
93    n_bytes = bson_writer_get_length (writer);
94 
95    bson_writer_destroy (writer);
96 
97    BSON_ASSERT_CMPINT (n_bytes, <, (48 * 1024 * 1024));
98    BSON_ASSERT_CMPINT (rolled_back, ==, true);
99    BSON_ASSERT (rolled_back);
100 
101    bson_free (buf);
102 }
103 
104 
105 static void
test_bson_writer_empty_sequence(void)106 test_bson_writer_empty_sequence (void)
107 {
108    const uint8_t testdata[] = {5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 0,
109                                0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, 0};
110    bson_writer_t *writer;
111    uint8_t *buf = NULL;
112    bson_t *b;
113    size_t len = 0;
114    int r;
115    int i;
116 
117    writer = bson_writer_new (&buf, &len, 0, bson_realloc_ctx, NULL);
118    for (i = 0; i < 5; i++) {
119       BSON_ASSERT (bson_writer_begin (writer, &b));
120       bson_writer_end (writer);
121    }
122    r = memcmp (buf, testdata, 25);
123    BSON_ASSERT (r == 0);
124    bson_writer_destroy (writer);
125    bson_free (buf);
126 }
127 
128 
129 static void
test_bson_writer_null_realloc(void)130 test_bson_writer_null_realloc (void)
131 {
132    const uint8_t testdata[] = {5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 5,
133                                0, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0};
134    bson_writer_t *writer;
135    uint8_t *buf = bson_malloc0 (32);
136    size_t buflen = 32;
137    bson_t *b;
138    int r;
139    int i;
140 
141    writer = bson_writer_new (&buf, &buflen, 0, NULL, NULL);
142    for (i = 0; i < 6; i++) {
143       BSON_ASSERT (bson_writer_begin (writer, &b));
144       bson_writer_end (writer);
145    }
146 
147    BSON_ASSERT (!bson_writer_begin (writer, &b));
148 
149    r = memcmp (buf, testdata, 32);
150    BSON_ASSERT (r == 0);
151    bson_writer_destroy (writer);
152 
153    bson_free (buf);
154 }
155 
156 static void
test_bson_writer_null_realloc_2(void)157 test_bson_writer_null_realloc_2 (void)
158 {
159    const uint8_t testdata[] = {5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 5,
160                                0, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0};
161    bson_writer_t *writer;
162    uint8_t *buf = bson_malloc0 (32);
163    size_t buflen = 32;
164    bson_t *b;
165    int r;
166    int i;
167 
168    writer = bson_writer_new (&buf, &buflen, 0, NULL, NULL);
169    for (i = 0; i < 5; i++) {
170       BSON_ASSERT (bson_writer_begin (writer, &b));
171       bson_writer_end (writer);
172    }
173 
174    BSON_ASSERT (bson_writer_begin (writer, &b));
175    BSON_ASSERT (!bson_append_int32 (b, "a", -1, 123));
176    bson_writer_end (writer);
177 
178    r = memcmp (buf, testdata, 32);
179    BSON_ASSERT (r == 0);
180    bson_writer_destroy (writer);
181 
182    bson_free (buf);
183 }
184 
185 void
test_writer_install(TestSuite * suite)186 test_writer_install (TestSuite *suite)
187 {
188    TestSuite_Add (
189       suite, "/bson/writer/custom_realloc", test_bson_writer_custom_realloc);
190    TestSuite_Add (
191       suite, "/bson/writer/shared_buffer", test_bson_writer_shared_buffer);
192    TestSuite_Add (
193       suite, "/bson/writer/empty_sequence", test_bson_writer_empty_sequence);
194    TestSuite_Add (
195       suite, "/bson/writer/null_realloc", test_bson_writer_null_realloc);
196    TestSuite_Add (
197       suite, "/bson/writer/null_realloc_2", test_bson_writer_null_realloc_2);
198 }
199