1/*
2 * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
3 *
4 * Jansson is free software; you can redistribute it and/or modify
5 * it under the terms of the MIT license. See LICENSE for details.
6 */
7
8#include <string.h>
9#include <jansson.h>
10#include "util.h"
11
12static void test_copy_simple(void)
13{
14    json_t *value, *copy;
15
16    if(json_copy(NULL))
17        fail("copying NULL doesn't return NULL");
18
19    /* true */
20    value = json_true();
21    copy = json_copy(value);
22    if(value != copy)
23        fail("copying true failed");
24    json_decref(value);
25    json_decref(copy);
26
27    /* false */
28    value = json_false();
29    copy = json_copy(value);
30    if(value != copy)
31        fail("copying false failed");
32    json_decref(value);
33    json_decref(copy);
34
35    /* null */
36    value = json_null();
37    copy = json_copy(value);
38    if(value != copy)
39        fail("copying null failed");
40    json_decref(value);
41    json_decref(copy);
42
43    /* string */
44    value = json_string("foo");
45    if(!value)
46        fail("unable to create a string");
47    copy = json_copy(value);
48    if(!copy)
49        fail("unable to copy a string");
50    if(copy == value)
51        fail("copying a string doesn't copy");
52    if(!json_equal(copy, value))
53        fail("copying a string produces an inequal copy");
54    if(value->refcount != 1 || copy->refcount != 1)
55        fail("invalid refcounts");
56    json_decref(value);
57    json_decref(copy);
58
59    /* integer */
60    value = json_integer(543);
61    if(!value)
62        fail("unable to create an integer");
63    copy = json_copy(value);
64    if(!copy)
65        fail("unable to copy an integer");
66    if(copy == value)
67        fail("copying an integer doesn't copy");
68    if(!json_equal(copy, value))
69        fail("copying an integer produces an inequal copy");
70    if(value->refcount != 1 || copy->refcount != 1)
71        fail("invalid refcounts");
72    json_decref(value);
73    json_decref(copy);
74
75    /* real */
76    value = json_real(123e9);
77    if(!value)
78        fail("unable to create a real");
79    copy = json_copy(value);
80    if(!copy)
81        fail("unable to copy a real");
82    if(copy == value)
83        fail("copying a real doesn't copy");
84    if(!json_equal(copy, value))
85        fail("copying a real produces an inequal copy");
86    if(value->refcount != 1 || copy->refcount != 1)
87        fail("invalid refcounts");
88    json_decref(value);
89    json_decref(copy);
90}
91
92static void test_deep_copy_simple(void)
93{
94    json_t *value, *copy;
95
96    if(json_deep_copy(NULL))
97        fail("deep copying NULL doesn't return NULL");
98
99    /* true */
100    value = json_true();
101    copy = json_deep_copy(value);
102    if(value != copy)
103        fail("deep copying true failed");
104    json_decref(value);
105    json_decref(copy);
106
107    /* false */
108    value = json_false();
109    copy = json_deep_copy(value);
110    if(value != copy)
111        fail("deep copying false failed");
112    json_decref(value);
113    json_decref(copy);
114
115    /* null */
116    value = json_null();
117    copy = json_deep_copy(value);
118    if(value != copy)
119        fail("deep copying null failed");
120    json_decref(value);
121    json_decref(copy);
122
123    /* string */
124    value = json_string("foo");
125    if(!value)
126        fail("unable to create a string");
127    copy = json_deep_copy(value);
128    if(!copy)
129        fail("unable to deep copy a string");
130    if(copy == value)
131        fail("deep copying a string doesn't copy");
132    if(!json_equal(copy, value))
133        fail("deep copying a string produces an inequal copy");
134    if(value->refcount != 1 || copy->refcount != 1)
135        fail("invalid refcounts");
136    json_decref(value);
137    json_decref(copy);
138
139    /* integer */
140    value = json_integer(543);
141    if(!value)
142        fail("unable to create an integer");
143    copy = json_deep_copy(value);
144    if(!copy)
145        fail("unable to deep copy an integer");
146    if(copy == value)
147        fail("deep copying an integer doesn't copy");
148    if(!json_equal(copy, value))
149        fail("deep copying an integer produces an inequal copy");
150    if(value->refcount != 1 || copy->refcount != 1)
151        fail("invalid refcounts");
152    json_decref(value);
153    json_decref(copy);
154
155    /* real */
156    value = json_real(123e9);
157    if(!value)
158        fail("unable to create a real");
159    copy = json_deep_copy(value);
160    if(!copy)
161        fail("unable to deep copy a real");
162    if(copy == value)
163        fail("deep copying a real doesn't copy");
164    if(!json_equal(copy, value))
165        fail("deep copying a real produces an inequal copy");
166    if(value->refcount != 1 || copy->refcount != 1)
167        fail("invalid refcounts");
168    json_decref(value);
169    json_decref(copy);
170}
171
172static void test_copy_array(void)
173{
174    const char *json_array_text = "[1, \"foo\", 3.141592, {\"foo\": \"bar\"}]";
175
176    json_t *array, *copy;
177    size_t i;
178
179    array = json_loads(json_array_text, 0, NULL);
180    if(!array)
181        fail("unable to parse an array");
182
183    copy = json_copy(array);
184    if(!copy)
185        fail("unable to copy an array");
186    if(copy == array)
187        fail("copying an array doesn't copy");
188    if(!json_equal(copy, array))
189        fail("copying an array produces an inequal copy");
190
191    for(i = 0; i < json_array_size(copy); i++)
192    {
193        if(json_array_get(array, i) != json_array_get(copy, i))
194            fail("copying an array modifies its elements");
195    }
196
197    json_decref(array);
198    json_decref(copy);
199}
200
201static void test_deep_copy_array(void)
202{
203    const char *json_array_text = "[1, \"foo\", 3.141592, {\"foo\": \"bar\"}]";
204
205    json_t *array, *copy;
206    size_t i;
207
208    array = json_loads(json_array_text, 0, NULL);
209    if(!array)
210        fail("unable to parse an array");
211
212    copy = json_deep_copy(array);
213    if(!copy)
214        fail("unable to deep copy an array");
215    if(copy == array)
216        fail("deep copying an array doesn't copy");
217    if(!json_equal(copy, array))
218        fail("deep copying an array produces an inequal copy");
219
220    for(i = 0; i < json_array_size(copy); i++)
221    {
222        if(json_array_get(array, i) == json_array_get(copy, i))
223            fail("deep copying an array doesn't copy its elements");
224    }
225
226    json_decref(array);
227    json_decref(copy);
228}
229
230static void test_copy_object(void)
231{
232    const char *json_object_text =
233        "{\"foo\": \"bar\", \"a\": 1, \"b\": 3.141592, \"c\": [1,2,3,4]}";
234
235    json_t *object, *copy;
236    void *iter;
237
238    object = json_loads(json_object_text, 0, NULL);
239    if(!object)
240        fail("unable to parse an object");
241
242    copy = json_copy(object);
243    if(!copy)
244        fail("unable to copy an object");
245    if(copy == object)
246        fail("copying an object doesn't copy");
247    if(!json_equal(copy, object))
248        fail("copying an object produces an inequal copy");
249
250    iter = json_object_iter(object);
251    while(iter)
252    {
253        const char *key;
254        json_t *value1, *value2;
255
256        key = json_object_iter_key(iter);
257        value1 = json_object_iter_value(iter);
258        value2 = json_object_get(copy, key);
259
260        if(value1 != value2)
261            fail("deep copying an object modifies its items");
262
263        iter = json_object_iter_next(object, iter);
264    }
265
266    json_decref(object);
267    json_decref(copy);
268}
269
270static void test_deep_copy_object(void)
271{
272    const char *json_object_text =
273        "{\"foo\": \"bar\", \"a\": 1, \"b\": 3.141592, \"c\": [1,2,3,4]}";
274
275    json_t *object, *copy;
276    void *iter;
277
278    object = json_loads(json_object_text, 0, NULL);
279    if(!object)
280        fail("unable to parse an object");
281
282    copy = json_deep_copy(object);
283    if(!copy)
284        fail("unable to deep copy an object");
285    if(copy == object)
286        fail("deep copying an object doesn't copy");
287    if(!json_equal(copy, object))
288        fail("deep copying an object produces an inequal copy");
289
290    iter = json_object_iter(object);
291    while(iter)
292    {
293        const char *key;
294        json_t *value1, *value2;
295
296        key = json_object_iter_key(iter);
297        value1 = json_object_iter_value(iter);
298        value2 = json_object_get(copy, key);
299
300        if(value1 == value2)
301            fail("deep copying an object doesn't copy its items");
302
303        iter = json_object_iter_next(object, iter);
304    }
305
306    json_decref(object);
307    json_decref(copy);
308}
309
310static void run_tests()
311{
312    test_copy_simple();
313    test_deep_copy_simple();
314    test_copy_array();
315    test_deep_copy_array();
316    test_copy_object();
317    test_deep_copy_object();
318}
319