xref: /4.0.0/couchstore/tests/views/reducers.c (revision d826ffba)
1/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
3#include "view_tests.h"
4#include "../src/couch_btree.h"
5#include "../src/views/mapreduce/mapreduce.h"
6#include <string.h>
7#include <inttypes.h>
8
9#define BITMAP_SIZE 1024
10
11#define VIEW_KV_CHUNK_THRESHOLD (7 * 1024)
12#define VIEW_KP_CHUNK_THRESHOLD (6 * 1024)
13
14int view_btree_cmp(const sized_buf *key1, const sized_buf *key2);
15couchfile_modify_result *make_modres(arena* a, couchfile_modify_request *rq);
16static void free_node_list(nodelist *nl)
17{
18    nodelist *tmp;
19    tmp = nl;
20    while (tmp != NULL ){
21        nl = nl->next;
22        free(tmp->pointer);
23        free(tmp);
24        tmp = nl;
25    }
26}
27
28static void free_id_value(view_id_btree_value_t *value)
29{
30    unsigned i;
31
32    for (i = 0; i < value->num_view_keys_map; ++i) {
33        free(value->view_keys_map[i].json_keys);
34    }
35    free(value->view_keys_map);
36}
37
38static void free_view_value(view_btree_value_t *value)
39{
40    free(value->values);
41}
42
43static void free_view_reduction(view_btree_reduction_t *red)
44{
45    free(red->reduce_values);
46}
47
48static void test_view_id_btree_reducer(void)
49{
50    nodelist *nl = NULL;
51    node_pointer *np = NULL;
52    node_pointer *np2 = NULL;
53    view_id_btree_reduction_t *r;
54    char dst[MAX_REDUCTION_SIZE];
55    size_t size_r;
56    int i, count = 0;
57
58    view_id_btree_key_t key1;
59    char *key_bin1 = NULL;
60    size_t key_bin1_size = 0;
61
62    view_id_btree_value_t data1;
63    char *data_bin1 = NULL;
64    size_t data_bin1_size = 0;
65
66    view_id_btree_reduction_t reduction1;
67    char reduction_bin1[512];
68    size_t reduction_bin1_size = 0;
69    view_id_btree_reduction_t reduction2;
70    char reduction_bin2[512];
71    size_t reduction_bin2_size = 0;
72
73    nodelist *nl2 = NULL;
74
75    view_id_btree_key_t key2;
76    char *key_bin2 = NULL;
77    size_t key_bin2_size = 0;
78
79    view_id_btree_value_t data2;
80    char *data_bin2 = NULL;
81    size_t data_bin2_size = 0;
82
83    key1.partition = 67;
84    key1.doc_id.buf = "doc_00000057";
85    key1.doc_id.size = sizeof("doc_00000057") - 1;
86    cb_assert(encode_view_id_btree_key(&key1, &key_bin1, &key_bin1_size) == COUCHSTORE_SUCCESS);
87
88    data1.partition = 67;
89    data1.num_view_keys_map = 2;
90    data1.view_keys_map = (view_keys_mapping_t *) malloc(sizeof(view_keys_mapping_t) * 2);
91    cb_assert(data1.view_keys_map != NULL);
92
93    data1.view_keys_map[0].view_id = 0;
94    data1.view_keys_map[0].num_keys = 2;
95    data1.view_keys_map[0].json_keys = (sized_buf *) malloc(sizeof(sized_buf) * 2);
96    cb_assert(data1.view_keys_map[0].json_keys != NULL);
97    data1.view_keys_map[0].json_keys[0].buf = "-321";
98    data1.view_keys_map[0].json_keys[0].size = sizeof("-321") - 1;
99    data1.view_keys_map[0].json_keys[1].buf = "[123,\"foobar\"]";
100    data1.view_keys_map[0].json_keys[1].size = sizeof("[123,\"foobar\"]") - 1;
101
102    data1.view_keys_map[1].view_id = 1;
103    data1.view_keys_map[1].num_keys = 1;
104    data1.view_keys_map[1].json_keys = (sized_buf *) malloc(sizeof(sized_buf) * 1);
105    data1.view_keys_map[1].json_keys[0].buf = "[5,6,7]";
106    data1.view_keys_map[1].json_keys[0].size = sizeof("[5,6,7]") - 1;
107
108    cb_assert(encode_view_id_btree_value(&data1, &data_bin1, &data_bin1_size) == COUCHSTORE_SUCCESS);
109    free_id_value(&data1);
110
111    key2.partition = 57;
112    key2.doc_id.buf = "foobar";
113    key2.doc_id.size = sizeof("foobar") - 1;
114    cb_assert(encode_view_id_btree_key(&key2, &key_bin2, &key_bin2_size) == COUCHSTORE_SUCCESS);
115
116    data2.partition = 57;
117    data2.num_view_keys_map = 2;
118    data2.view_keys_map = (view_keys_mapping_t *) malloc(sizeof(view_keys_mapping_t) * 2);
119    cb_assert(data2.view_keys_map != NULL);
120
121    data2.view_keys_map[0].view_id = 0;
122    data2.view_keys_map[0].num_keys = 1;
123    data2.view_keys_map[0].json_keys = (sized_buf *) malloc(sizeof(sized_buf) * 1);
124    cb_assert(data2.view_keys_map[0].json_keys != NULL);
125    data2.view_keys_map[0].json_keys[0].buf = "\"abc\"";
126    data2.view_keys_map[0].json_keys[0].size = sizeof("\"abc\"") - 1;
127
128    data2.view_keys_map[1].view_id = 1;
129    data2.view_keys_map[1].num_keys = 1;
130    data2.view_keys_map[1].json_keys = (sized_buf *) malloc(sizeof(sized_buf) * 1);
131    data2.view_keys_map[1].json_keys[0].buf = "\"qwerty\"";
132    data2.view_keys_map[1].json_keys[0].size = sizeof("\"qwerty\"") - 1;
133
134    cb_assert(encode_view_id_btree_value(&data2, &data_bin2, &data_bin2_size) == COUCHSTORE_SUCCESS);
135    free_id_value(&data2);
136
137    reduction1.kv_count = 11;
138    memset(&reduction1.partitions_bitmap, 0, sizeof(reduction1.partitions_bitmap));
139    set_bit(&reduction1.partitions_bitmap, 10);
140    set_bit(&reduction1.partitions_bitmap, 1001);
141    cb_assert(encode_view_id_btree_reduction(&reduction1, reduction_bin1, &reduction_bin1_size) == COUCHSTORE_SUCCESS);
142
143    reduction2.kv_count = 22;
144    memset(&reduction2.partitions_bitmap, 0, sizeof(reduction2.partitions_bitmap));
145    set_bit(&reduction2.partitions_bitmap, 7);
146    set_bit(&reduction2.partitions_bitmap, 77);
147    cb_assert(encode_view_id_btree_reduction(&reduction2, reduction_bin2, &reduction_bin2_size) == COUCHSTORE_SUCCESS);
148
149    nl = (nodelist *) malloc(sizeof(nodelist));
150    cb_assert(nl != NULL);
151
152    count++;
153    nl->data.buf = data_bin1;
154    nl->data.size = data_bin1_size;
155    nl->key.buf = key_bin1;
156    nl->key.size = key_bin1_size;
157    nl->pointer = NULL;
158    nl->next = NULL;
159
160    np = (node_pointer *) malloc(sizeof(node_pointer));
161    cb_assert(np != NULL);
162    np->key.buf = key_bin1;
163    np->key.size = key_bin1_size;
164    np->reduce_value.buf = reduction_bin1;
165    np->reduce_value.size = reduction_bin1_size;
166    np->pointer = 0;
167    np->subtreesize = 3;
168    nl->pointer = np;
169
170    nl2 = (nodelist *) malloc(sizeof(nodelist));
171    cb_assert(nl2 != NULL);
172
173    count++;
174    nl2->data.buf = data_bin2;
175    nl2->data.size = data_bin2_size;
176    nl2->key.buf = key_bin2;
177    nl2->key.size = key_bin2_size;
178    nl2->pointer = NULL;
179    nl2->next = NULL;
180    nl->next = nl2;
181
182    cb_assert(view_id_btree_reduce(dst, &size_r, nl, count, NULL) == COUCHSTORE_SUCCESS);
183    cb_assert(decode_view_id_btree_reduction(dst, &r) == COUCHSTORE_SUCCESS);
184    cb_assert(r->kv_count == (uint64_t) count);
185
186    for (i = 0; i < BITMAP_SIZE; ++i) {
187        if ((i != 57) && (i != 67)) {
188            cb_assert(!is_bit_set(&r->partitions_bitmap, i));
189        } else {
190            cb_assert(is_bit_set(&r->partitions_bitmap, i));
191        }
192    }
193
194    free_view_id_btree_reduction(r);
195
196    np2 = (node_pointer *) malloc(sizeof(node_pointer));
197    cb_assert(np2 != NULL);
198    np2->key.buf = key_bin2;
199    np2->key.size = key_bin2_size;
200    np2->reduce_value.buf = reduction_bin2;
201    np2->reduce_value.size = reduction_bin2_size;
202    np2->pointer = 0;
203    np2->subtreesize = 3;
204    nl2->pointer = np2;
205
206    cb_assert(view_id_btree_rereduce(dst, &size_r, nl, count, NULL) == COUCHSTORE_SUCCESS);
207    cb_assert(decode_view_id_btree_reduction(dst, &r) == COUCHSTORE_SUCCESS);
208    cb_assert(r->kv_count == 33);
209
210    for (i = 0; i < BITMAP_SIZE; ++i) {
211        if ((i != 7) && (i != 77) && (i != 10) && (i != 1001)) {
212            cb_assert(!is_bit_set(&r->partitions_bitmap, i));
213        } else {
214            cb_assert(is_bit_set(&r->partitions_bitmap, i));
215        }
216    }
217
218    free_view_id_btree_reduction(r);
219    free_node_list(nl);
220    free(key_bin1);
221    free(key_bin2);
222    free(data_bin1);
223    free(data_bin2);
224}
225
226static void test_view_btree_sum_reducer(void)
227{
228    char *error_msg = NULL;
229    view_reducer_ctx_t *ctx = NULL;
230    const char *function_sources[] = { "_sum" };
231    int i;
232
233    view_btree_key_t key1, key2, key3;
234    char *key1_bin = NULL;
235    char *key2_bin = NULL;
236    char *key3_bin = NULL;
237    size_t key1_bin_size = 0;
238    size_t key2_bin_size = 0;
239    size_t key3_bin_size = 0;
240
241    view_btree_value_t value1, value2, value3;
242    char *value1_bin = NULL;
243    char *value2_bin = NULL;
244    char *value3_bin = NULL;
245    size_t value1_bin_size = 0;
246    size_t value2_bin_size = 0;
247    size_t value3_bin_size = 0;
248
249    view_btree_reduction_t reduction1;
250    char reduction1_bin[512];
251    size_t reduction1_bin_size = 0;
252    view_btree_reduction_t reduction2;
253    char reduction2_bin[512];
254    size_t reduction2_bin_size = 0;
255
256    nodelist *nl = NULL, *nl2 = NULL, *nl3 = NULL;
257    node_pointer *np = NULL, *np2 = NULL;
258
259    view_btree_reduction_t *red = NULL;
260    char red_bin[512];
261    size_t red_bin_size = 0;
262
263    ctx = make_view_reducer_ctx(function_sources, 1, &error_msg);
264    cb_assert(ctx != NULL);
265
266    key1.json_key.buf = "10";
267    key1.json_key.size = sizeof("10") - 1;
268    key1.doc_id.buf = "doc_10";
269    key1.doc_id.size = sizeof("doc_10") - 1;
270    cb_assert(encode_view_btree_key(&key1, &key1_bin, &key1_bin_size) == COUCHSTORE_SUCCESS);
271
272    key2.json_key.buf = "11";
273    key2.json_key.size = sizeof("11") - 1;
274    key2.doc_id.buf = "doc_11";
275    key2.doc_id.size = sizeof("doc_11") - 1;
276    cb_assert(encode_view_btree_key(&key2, &key2_bin, &key2_bin_size) == COUCHSTORE_SUCCESS);
277
278    key3.json_key.buf = "12";
279    key3.json_key.size = sizeof("12") - 1;
280    key3.doc_id.buf = "doc_12";
281    key3.doc_id.size = sizeof("doc_12") - 1;
282    cb_assert(encode_view_btree_key(&key3, &key3_bin, &key3_bin_size) == COUCHSTORE_SUCCESS);
283
284    value1.partition = 7;
285    value1.num_values = 2;
286    value1.values = (sized_buf *) malloc(sizeof(sized_buf) * 2);
287    value1.values[0].buf = "100";
288    value1.values[0].size = sizeof("100") - 1;
289    value1.values[1].buf = "1";
290    value1.values[1].size = sizeof("1") - 1;
291    cb_assert(encode_view_btree_value(&value1, &value1_bin, &value1_bin_size) == COUCHSTORE_SUCCESS);
292
293    value2.partition = 666;
294    value2.num_values = 1;
295    value2.values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
296    value2.values[0].buf = "1000";
297    value2.values[0].size = sizeof("1000") - 1;
298    cb_assert(encode_view_btree_value(&value2, &value2_bin, &value2_bin_size) == COUCHSTORE_SUCCESS);
299
300    value3.partition = 1023;
301    value3.num_values = 1;
302    value3.values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
303    value3.values[0].buf = "5000.33";
304    value3.values[0].size = sizeof("5000.33") - 1;
305    cb_assert(encode_view_btree_value(&value3, &value3_bin, &value3_bin_size) == COUCHSTORE_SUCCESS);
306
307    nl = (nodelist *) malloc(sizeof(nodelist));
308    cb_assert(nl != NULL);
309    nl->data.buf = value1_bin;
310    nl->data.size = value1_bin_size;
311    nl->key.buf = key1_bin;
312    nl->key.size = key1_bin_size;
313    nl->pointer = NULL;
314
315    nl2 = (nodelist *) malloc(sizeof(nodelist));
316    cb_assert(nl2 != NULL);
317    nl2->data.buf = value2_bin;
318    nl2->data.size = value2_bin_size;
319    nl2->key.buf = key2_bin;
320    nl2->key.size = key2_bin_size;
321    nl2->pointer = NULL;
322    nl->next = nl2;
323
324    nl3 = (nodelist *) malloc(sizeof(nodelist));
325    cb_assert(nl3 != NULL);
326    nl3->data.buf = value3_bin;
327    nl3->data.size = value3_bin_size;
328    nl3->key.buf = key3_bin;
329    nl3->key.size = key3_bin_size;
330    nl3->pointer = NULL;
331    nl3->next = NULL;
332    nl2->next = nl3;
333
334    cb_assert(view_btree_reduce(red_bin, &red_bin_size, nl, 3, ctx) == COUCHSTORE_SUCCESS);
335    cb_assert(decode_view_btree_reduction(red_bin, red_bin_size, &red) == COUCHSTORE_SUCCESS);
336    cb_assert(red->kv_count == 4);
337    cb_assert(red->num_values == 1);
338    cb_assert(red->reduce_values[0].size == (sizeof("6101.33") - 1));
339    cb_assert(strncmp(red->reduce_values[0].buf, "6101.33", sizeof("6101.33") - 1) == 0);
340
341    for (i = 0; i < BITMAP_SIZE; ++i) {
342        if ((i != 7) && (i != 666) && (i != 1023)) {
343            cb_assert(!is_bit_set(&red->partitions_bitmap, i));
344        } else {
345            cb_assert(is_bit_set(&red->partitions_bitmap, i));
346        }
347    }
348    free_view_btree_reduction(red);
349    red = NULL;
350
351    /* Test _sum reduce error */
352
353    value3.values[0].buf = "\"foobar\"";
354    value3.values[0].size = sizeof("\"foobar\"") - 1;
355    free(value3_bin);
356    cb_assert(encode_view_btree_value(&value3, &value3_bin, &value3_bin_size) == COUCHSTORE_SUCCESS);
357
358    nl3->data.buf = value3_bin;
359    nl3->data.size = value3_bin_size;
360
361    cb_assert(view_btree_reduce(red_bin, &red_bin_size, nl, 3, ctx) == COUCHSTORE_ERROR_REDUCER_FAILURE);
362    cb_assert(ctx->error != NULL);
363    cb_assert(strcmp(ctx->error, "Value is not a number (key 12)") == 0);
364
365    /* Test _sum rereduce */
366
367    reduction1.kv_count = 11;
368    memset(&reduction1.partitions_bitmap, 0, sizeof(reduction1.partitions_bitmap));
369    set_bit(&reduction1.partitions_bitmap, 10);
370    set_bit(&reduction1.partitions_bitmap, 1011);
371    reduction1.num_values = 1;
372    reduction1.reduce_values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
373    cb_assert(reduction1.reduce_values != NULL);
374    reduction1.reduce_values[0].buf = "4444.11";
375    reduction1.reduce_values[0].size = sizeof("4444.11") - 1;
376    cb_assert(encode_view_btree_reduction(&reduction1, reduction1_bin, &reduction1_bin_size) == COUCHSTORE_SUCCESS);
377
378    reduction2.kv_count = 44;
379    memset(&reduction2.partitions_bitmap, 0, sizeof(reduction2.partitions_bitmap));
380    set_bit(&reduction2.partitions_bitmap, 10);
381    set_bit(&reduction2.partitions_bitmap, 777);
382    set_bit(&reduction2.partitions_bitmap, 333);
383    reduction2.num_values = 1;
384    reduction2.reduce_values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
385    cb_assert(reduction2.reduce_values != NULL);
386    reduction2.reduce_values[0].buf = "-100";
387    reduction2.reduce_values[0].size = sizeof("-100") - 1;
388    cb_assert(encode_view_btree_reduction(&reduction2, reduction2_bin, &reduction2_bin_size) == COUCHSTORE_SUCCESS);
389
390    np = (node_pointer *) malloc(sizeof(node_pointer));
391    cb_assert(np != NULL);
392    np->key.buf = key1_bin;
393    np->key.size = key1_bin_size;
394    np->reduce_value.buf = reduction1_bin;
395    np->reduce_value.size = reduction1_bin_size;
396    np->pointer = 0;
397    np->subtreesize = 222;
398    nl->pointer = np;
399
400    np2 = (node_pointer *) malloc(sizeof(node_pointer));
401    cb_assert(np2 != NULL);
402    np2->key.buf = key2_bin;
403    np2->key.size = key2_bin_size;
404    np2->reduce_value.buf = reduction2_bin;
405    np2->reduce_value.size = reduction2_bin_size;
406    np2->pointer = 0;
407    np2->subtreesize = 333;
408    nl2->pointer = np2;
409
410    cb_assert(view_btree_rereduce(red_bin, &red_bin_size, nl, 2, ctx) == COUCHSTORE_SUCCESS);
411    cb_assert(decode_view_btree_reduction(red_bin, red_bin_size, &red) == COUCHSTORE_SUCCESS);
412    cb_assert(red->kv_count == 55);
413    cb_assert(red->num_values == 1);
414    cb_assert(red->reduce_values[0].size == (sizeof("4344.11") - 1));
415    cb_assert(strncmp(red->reduce_values[0].buf, "4344.11", sizeof("4344.11") - 1) == 0);
416
417    for (i = 0; i < BITMAP_SIZE; ++i) {
418        if ((i != 10) && (i != 333) && (i != 777) && (i != 1011)) {
419            cb_assert(!is_bit_set(&red->partitions_bitmap, i));
420        } else {
421            cb_assert(is_bit_set(&red->partitions_bitmap, i));
422        }
423    }
424
425    /* Test _sum rereduce error */
426
427    free_view_btree_reduction(red);
428    red = NULL;
429
430    reduction2.reduce_values[0].buf = "true";
431    reduction2.reduce_values[0].size = sizeof("true") - 1;
432    cb_assert(encode_view_btree_reduction(&reduction2, reduction2_bin, &reduction2_bin_size) == COUCHSTORE_SUCCESS);
433
434    np2->reduce_value.buf = reduction2_bin;
435    np2->reduce_value.size = reduction2_bin_size;
436
437    cb_assert(view_btree_rereduce(red_bin, &red_bin_size, nl, 2, ctx) == COUCHSTORE_ERROR_REDUCER_FAILURE);
438    cb_assert(ctx->error != NULL);
439    cb_assert(strcmp(ctx->error, "Value is not a number") == 0);
440
441    free_view_reduction(&reduction1);
442    free_view_reduction(&reduction2);
443    free_view_btree_reduction(red);
444    free_view_reducer_ctx(ctx);
445    free(key1_bin);
446    free(key2_bin);
447    free(key3_bin);
448    free_view_value(&value1);
449    free_view_value(&value2);
450    free_view_value(&value3);
451    free(value1_bin);
452    free(value2_bin);
453    free(value3_bin);
454    free_node_list(nl);
455}
456
457static void test_view_btree_count_reducer(void)
458{
459    char *error_msg = NULL;
460    view_reducer_ctx_t *ctx = NULL;
461    const char *function_sources[] = { "_count" };
462    int i;
463
464    view_btree_key_t key1, key2, key3;
465    char *key1_bin = NULL;
466    char *key2_bin = NULL;
467    char *key3_bin = NULL;
468    size_t key1_bin_size = 0;
469    size_t key2_bin_size = 0;
470    size_t key3_bin_size = 0;
471
472    view_btree_value_t value1, value2, value3;
473    char *value1_bin = NULL;
474    char *value2_bin = NULL;
475    char *value3_bin = NULL;
476    size_t value1_bin_size = 0;
477    size_t value2_bin_size = 0;
478    size_t value3_bin_size = 0;
479
480    view_btree_reduction_t reduction1;
481    char reduction1_bin[512];
482    size_t reduction1_bin_size = 0;
483    view_btree_reduction_t reduction2;
484    char reduction2_bin[512];
485    size_t reduction2_bin_size = 0;
486
487    nodelist *nl = NULL, *nl2 = NULL, *nl3 = NULL;
488    node_pointer *np = NULL, *np2 = NULL;
489
490    view_btree_reduction_t *red = NULL;
491    char red_bin[512];
492    size_t red_bin_size = 0;
493
494    ctx = make_view_reducer_ctx(function_sources, 1, &error_msg);
495    cb_assert(ctx != NULL);
496
497    key1.json_key.buf = "10";
498    key1.json_key.size = sizeof("10") - 1;
499    key1.doc_id.buf = "doc_10";
500    key1.doc_id.size = sizeof("doc_10") - 1;
501    cb_assert(encode_view_btree_key(&key1, &key1_bin, &key1_bin_size) == COUCHSTORE_SUCCESS);
502
503    key2.json_key.buf = "11";
504    key2.json_key.size = sizeof("11") - 1;
505    key2.doc_id.buf = "doc_11";
506    key2.doc_id.size = sizeof("doc_11") - 1;
507    cb_assert(encode_view_btree_key(&key2, &key2_bin, &key2_bin_size) == COUCHSTORE_SUCCESS);
508
509    key3.json_key.buf = "12";
510    key3.json_key.size = sizeof("12") - 1;
511    key3.doc_id.buf = "doc_12";
512    key3.doc_id.size = sizeof("doc_12") - 1;
513    cb_assert(encode_view_btree_key(&key3, &key3_bin, &key3_bin_size) == COUCHSTORE_SUCCESS);
514
515    value1.partition = 7;
516    value1.num_values = 2;
517    value1.values = (sized_buf *) malloc(sizeof(sized_buf) * 2);
518    value1.values[0].buf = "100";
519    value1.values[0].size = sizeof("100") - 1;
520    value1.values[1].buf = "1";
521    value1.values[1].size = sizeof("1") - 1;
522    cb_assert(encode_view_btree_value(&value1, &value1_bin, &value1_bin_size) == COUCHSTORE_SUCCESS);
523
524    value2.partition = 666;
525    value2.num_values = 1;
526    value2.values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
527    value2.values[0].buf = "1000";
528    value2.values[0].size = sizeof("1000") - 1;
529    cb_assert(encode_view_btree_value(&value2, &value2_bin, &value2_bin_size) == COUCHSTORE_SUCCESS);
530
531    value3.partition = 1023;
532    value3.num_values = 1;
533    value3.values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
534    value3.values[0].buf = "5000.33";
535    value3.values[0].size = sizeof("5000.33") - 1;
536    cb_assert(encode_view_btree_value(&value3, &value3_bin, &value3_bin_size) == COUCHSTORE_SUCCESS);
537
538    nl = (nodelist *) malloc(sizeof(nodelist));
539    cb_assert(nl != NULL);
540    nl->data.buf = value1_bin;
541    nl->data.size = value1_bin_size;
542    nl->key.buf = key1_bin;
543    nl->key.size = key1_bin_size;
544    nl->pointer = NULL;
545
546    nl2 = (nodelist *) malloc(sizeof(nodelist));
547    cb_assert(nl2 != NULL);
548    nl2->data.buf = value2_bin;
549    nl2->data.size = value2_bin_size;
550    nl2->key.buf = key2_bin;
551    nl2->key.size = key2_bin_size;
552    nl2->pointer = NULL;
553    nl->next = nl2;
554
555    nl3 = (nodelist *) malloc(sizeof(nodelist));
556    cb_assert(nl3 != NULL);
557    nl3->data.buf = value3_bin;
558    nl3->data.size = value3_bin_size;
559    nl3->key.buf = key3_bin;
560    nl3->key.size = key3_bin_size;
561    nl3->pointer = NULL;
562    nl3->next = NULL;
563    nl2->next = nl3;
564
565    cb_assert(view_btree_reduce(red_bin, &red_bin_size, nl, 3, ctx) == COUCHSTORE_SUCCESS);
566    cb_assert(decode_view_btree_reduction(red_bin, red_bin_size, &red) == COUCHSTORE_SUCCESS);
567    cb_assert(red->kv_count == 4);
568    cb_assert(red->num_values == 1);
569    cb_assert(red->reduce_values[0].size == (sizeof("4") - 1));
570    cb_assert(strncmp(red->reduce_values[0].buf, "4", sizeof("4") - 1) == 0);
571
572    for (i = 0; i < BITMAP_SIZE; ++i) {
573        if ((i != 7) && (i != 666) && (i != 1023)) {
574            cb_assert(!is_bit_set(&red->partitions_bitmap, i));
575        } else {
576            cb_assert(is_bit_set(&red->partitions_bitmap, i));
577        }
578    }
579    free_view_btree_reduction(red);
580    red = NULL;
581
582    reduction1.kv_count = 11;
583    memset(&reduction1.partitions_bitmap, 0, sizeof(reduction1.partitions_bitmap));
584    set_bit(&reduction1.partitions_bitmap, 10);
585    set_bit(&reduction1.partitions_bitmap, 1011);
586    reduction1.num_values = 1;
587    reduction1.reduce_values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
588    cb_assert(reduction1.reduce_values != NULL);
589    reduction1.reduce_values[0].buf = "4444";
590    reduction1.reduce_values[0].size = sizeof("4444") - 1;
591    cb_assert(encode_view_btree_reduction(&reduction1, reduction1_bin, &reduction1_bin_size) == COUCHSTORE_SUCCESS);
592
593    reduction2.kv_count = 44;
594    memset(&reduction2.partitions_bitmap, 0, sizeof(reduction2.partitions_bitmap));
595    set_bit(&reduction2.partitions_bitmap, 10);
596    set_bit(&reduction2.partitions_bitmap, 777);
597    set_bit(&reduction2.partitions_bitmap, 333);
598    reduction2.num_values = 1;
599    reduction2.reduce_values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
600    cb_assert(reduction2.reduce_values != NULL);
601    reduction2.reduce_values[0].buf = "100";
602    reduction2.reduce_values[0].size = sizeof("100") - 1;
603    cb_assert(encode_view_btree_reduction(&reduction2, reduction2_bin, &reduction2_bin_size) == COUCHSTORE_SUCCESS);
604
605    np = (node_pointer *) malloc(sizeof(node_pointer));
606    cb_assert(np != NULL);
607    np->key.buf = key1_bin;
608    np->key.size = key1_bin_size;
609    np->reduce_value.buf = reduction1_bin;
610    np->reduce_value.size = reduction1_bin_size;
611    np->pointer = 0;
612    np->subtreesize = 222;
613    nl->pointer = np;
614
615    np2 = (node_pointer *) malloc(sizeof(node_pointer));
616    cb_assert(np2 != NULL);
617    np2->key.buf = key2_bin;
618    np2->key.size = key2_bin_size;
619    np2->reduce_value.buf = reduction2_bin;
620    np2->reduce_value.size = reduction2_bin_size;
621    np2->pointer = 0;
622    np2->subtreesize = 333;
623    nl2->pointer = np2;
624
625    cb_assert(view_btree_rereduce(red_bin, &red_bin_size, nl, 2, ctx) == COUCHSTORE_SUCCESS);
626    cb_assert(decode_view_btree_reduction(red_bin, red_bin_size, &red) == COUCHSTORE_SUCCESS);
627    cb_assert(red->kv_count == 55);
628    cb_assert(red->num_values == 1);
629    cb_assert(red->reduce_values[0].size == (sizeof("4544") - 1));
630    cb_assert(strncmp(red->reduce_values[0].buf, "4544", sizeof("4544") - 1) == 0);
631
632    for (i = 0; i < BITMAP_SIZE; ++i) {
633        if ((i != 10) && (i != 333) && (i != 777) && (i != 1011)) {
634            cb_assert(!is_bit_set(&red->partitions_bitmap, i));
635        } else {
636            cb_assert(is_bit_set(&red->partitions_bitmap, i));
637        }
638    }
639
640    free_view_reduction(&reduction1);
641    free_view_reduction(&reduction2);
642    free_view_btree_reduction(red);
643    free_view_reducer_ctx(ctx);
644    free(key1_bin);
645    free(key2_bin);
646    free(key3_bin);
647    free_view_value(&value1);
648    free_view_value(&value2);
649    free_view_value(&value3);
650    free(value1_bin);
651    free(value2_bin);
652    free(value3_bin);
653    free_node_list(nl);
654}
655
656static void test_view_btree_stats_reducer(void)
657{
658    char *error_msg = NULL;
659    view_reducer_ctx_t *ctx = NULL;
660    const char *function_sources[] = { "_stats" };
661    int i;
662#ifdef _MSC_VER
663    const char *expected_reduction =
664        "{\"sum\":3101.5,\"count\":4,\"min\":1,\"max\":2000.5,\"sumsqr\":5.012e+006}";
665#else
666    const char *expected_reduction =
667        "{\"sum\":3101.5,\"count\":4,\"min\":1,\"max\":2000.5,\"sumsqr\":5.012e+06}";
668#endif
669    const char *expected_rereduction =
670        "{\"sum\":10203.1,\"count\":8,\"min\":1,\"max\":2000.5,\"sumsqr\":15}";
671
672    view_btree_key_t key1, key2, key3;
673    char *key1_bin = NULL;
674    char *key2_bin = NULL;
675    char *key3_bin = NULL;
676    size_t key1_bin_size = 0;
677    size_t key2_bin_size = 0;
678    size_t key3_bin_size = 0;
679
680    view_btree_value_t value1, value2, value3;
681    char *value1_bin = NULL;
682    char *value2_bin = NULL;
683    char *value3_bin = NULL;
684    size_t value1_bin_size = 0;
685    size_t value2_bin_size = 0;
686    size_t value3_bin_size = 0;
687
688    view_btree_reduction_t reduction1;
689    char reduction1_bin[512];
690    size_t reduction1_bin_size = 0;
691    view_btree_reduction_t reduction2;
692    char reduction2_bin[512];
693    size_t reduction2_bin_size = 0;
694
695    nodelist *nl = NULL, *nl2 = NULL, *nl3 = NULL;
696    node_pointer *np = NULL, *np2 = NULL;
697
698    view_btree_reduction_t *red = NULL;
699    char red_bin[512];
700    size_t red_bin_size = 0;
701
702    ctx = make_view_reducer_ctx(function_sources, 1, &error_msg);
703    cb_assert(ctx != NULL);
704
705    key1.json_key.buf = "10";
706    key1.json_key.size = sizeof("10") - 1;
707    key1.doc_id.buf = "doc_10";
708    key1.doc_id.size = sizeof("doc_10") - 1;
709    cb_assert(encode_view_btree_key(&key1, &key1_bin, &key1_bin_size) == COUCHSTORE_SUCCESS);
710
711    key2.json_key.buf = "11";
712    key2.json_key.size = sizeof("11") - 1;
713    key2.doc_id.buf = "doc_11";
714    key2.doc_id.size = sizeof("doc_11") - 1;
715    cb_assert(encode_view_btree_key(&key2, &key2_bin, &key2_bin_size) == COUCHSTORE_SUCCESS);
716
717    key3.json_key.buf = "12";
718    key3.json_key.size = sizeof("12") - 1;
719    key3.doc_id.buf = "doc_12";
720    key3.doc_id.size = sizeof("doc_12") - 1;
721    cb_assert(encode_view_btree_key(&key3, &key3_bin, &key3_bin_size) == COUCHSTORE_SUCCESS);
722
723    value1.partition = 7;
724    value1.num_values = 2;
725    value1.values = (sized_buf *) malloc(sizeof(sized_buf) * 2);
726    value1.values[0].buf = "100";
727    value1.values[0].size = sizeof("100") - 1;
728    value1.values[1].buf = "1";
729    value1.values[1].size = sizeof("1") - 1;
730    cb_assert(encode_view_btree_value(&value1, &value1_bin, &value1_bin_size) == COUCHSTORE_SUCCESS);
731
732    value2.partition = 666;
733    value2.num_values = 1;
734    value2.values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
735    value2.values[0].buf = "1000";
736    value2.values[0].size = sizeof("1000") - 1;
737    cb_assert(encode_view_btree_value(&value2, &value2_bin, &value2_bin_size) == COUCHSTORE_SUCCESS);
738
739    value3.partition = 1023;
740    value3.num_values = 1;
741    value3.values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
742    value3.values[0].buf = "2000.50";
743    value3.values[0].size = sizeof("2000.50") - 1;
744    cb_assert(encode_view_btree_value(&value3, &value3_bin, &value3_bin_size) == COUCHSTORE_SUCCESS);
745
746    nl = (nodelist *) malloc(sizeof(nodelist));
747    cb_assert(nl != NULL);
748    nl->data.buf = value1_bin;
749    nl->data.size = value1_bin_size;
750    nl->key.buf = key1_bin;
751    nl->key.size = key1_bin_size;
752    nl->pointer = NULL;
753
754    nl2 = (nodelist *) malloc(sizeof(nodelist));
755    cb_assert(nl2 != NULL);
756    nl2->data.buf = value2_bin;
757    nl2->data.size = value2_bin_size;
758    nl2->key.buf = key2_bin;
759    nl2->key.size = key2_bin_size;
760    nl2->pointer = NULL;
761    nl->next = nl2;
762
763    nl3 = (nodelist *) malloc(sizeof(nodelist));
764    cb_assert(nl3 != NULL);
765    nl3->data.buf = value3_bin;
766    nl3->data.size = value3_bin_size;
767    nl3->key.buf = key3_bin;
768    nl3->key.size = key3_bin_size;
769    nl3->pointer = NULL;
770    nl3->next = NULL;
771    nl2->next = nl3;
772
773    cb_assert(view_btree_reduce(red_bin, &red_bin_size, nl, 3, ctx) == COUCHSTORE_SUCCESS);
774    cb_assert(decode_view_btree_reduction(red_bin, red_bin_size, &red) == COUCHSTORE_SUCCESS);
775    cb_assert(red->kv_count == 4);
776    cb_assert(red->num_values == 1);
777    cb_assert(red->reduce_values[0].size == strlen(expected_reduction));
778    cb_assert(strncmp(red->reduce_values[0].buf,
779                   expected_reduction, strlen(expected_reduction)) == 0);
780
781    for (i = 0; i < BITMAP_SIZE; ++i) {
782        if ((i != 7) && (i != 666) && (i != 1023)) {
783            cb_assert(!is_bit_set(&red->partitions_bitmap, i));
784        } else {
785            cb_assert(is_bit_set(&red->partitions_bitmap, i));
786        }
787    }
788    free_view_btree_reduction(red);
789    red = NULL;
790
791    /* Test _stats reduce error */
792    value3.values[0].buf = "\"foobar\"";
793    value3.values[0].size = sizeof("\"foobar\"") - 1;
794    free(value3_bin);
795    cb_assert(encode_view_btree_value(&value3, &value3_bin, &value3_bin_size) == COUCHSTORE_SUCCESS);
796
797    nl3->data.buf = value3_bin;
798    nl3->data.size = value3_bin_size;
799
800    cb_assert(view_btree_reduce(red_bin, &red_bin_size, nl, 3, ctx) == COUCHSTORE_ERROR_REDUCER_FAILURE);
801    cb_assert(ctx->error != NULL);
802    cb_assert(strcmp(ctx->error, "Value is not a number (key 12)") == 0);
803
804    /* Test successful rereduce */
805
806    reduction1.kv_count = 11;
807    memset(&reduction1.partitions_bitmap, 0, sizeof(reduction1.partitions_bitmap));
808    set_bit(&reduction1.partitions_bitmap, 10);
809    set_bit(&reduction1.partitions_bitmap, 1011);
810    reduction1.num_values = 1;
811    reduction1.reduce_values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
812    cb_assert(reduction1.reduce_values != NULL);
813    reduction1.reduce_values[0].buf = "{\"sum\":3101.5,\"count\":4,\"min\":1,\"max\":2000.5,\"sumsqr\":5}";
814    reduction1.reduce_values[0].size = strlen(reduction1.reduce_values[0].buf);
815    cb_assert(encode_view_btree_reduction(&reduction1, reduction1_bin, &reduction1_bin_size) == COUCHSTORE_SUCCESS);
816
817    reduction2.kv_count = 44;
818    memset(&reduction2.partitions_bitmap, 0, sizeof(reduction2.partitions_bitmap));
819    set_bit(&reduction2.partitions_bitmap, 10);
820    set_bit(&reduction2.partitions_bitmap, 777);
821    set_bit(&reduction2.partitions_bitmap, 333);
822    reduction2.num_values = 1;
823    reduction2.reduce_values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
824    cb_assert(reduction2.reduce_values != NULL);
825    reduction2.reduce_values[0].buf = "{\"sum\":7101.6,\"count\":4,\"min\":3,\"max\":1000.5,\"sumsqr\":10}";
826    reduction2.reduce_values[0].size = strlen(reduction2.reduce_values[0].buf);
827    cb_assert(encode_view_btree_reduction(&reduction2, reduction2_bin, &reduction2_bin_size) == COUCHSTORE_SUCCESS);
828
829    np = (node_pointer *) malloc(sizeof(node_pointer));
830    cb_assert(np != NULL);
831    np->key.buf = key1_bin;
832    np->key.size = key1_bin_size;
833    np->reduce_value.buf = reduction1_bin;
834    np->reduce_value.size = reduction1_bin_size;
835    np->pointer = 0;
836    np->subtreesize = 222;
837    nl->pointer = np;
838
839    np2 = (node_pointer *) malloc(sizeof(node_pointer));
840    cb_assert(np2 != NULL);
841    np2->key.buf = key2_bin;
842    np2->key.size = key2_bin_size;
843    np2->reduce_value.buf = reduction2_bin;
844    np2->reduce_value.size = reduction2_bin_size;
845    np2->pointer = 0;
846    np2->subtreesize = 333;
847    nl2->pointer = np2;
848
849    cb_assert(view_btree_rereduce(red_bin, &red_bin_size, nl, 2, ctx) == COUCHSTORE_SUCCESS);
850    cb_assert(decode_view_btree_reduction(red_bin, red_bin_size, &red) == COUCHSTORE_SUCCESS);
851    cb_assert(red->kv_count == 55);
852    cb_assert(red->num_values == 1);
853    cb_assert(red->reduce_values[0].size == strlen(expected_rereduction));
854    cb_assert(strncmp(red->reduce_values[0].buf, expected_rereduction, red->reduce_values[0].size) == 0);
855
856    for (i = 0; i < BITMAP_SIZE; ++i) {
857        if ((i != 10) && (i != 333) && (i != 777) && (i != 1011)) {
858            cb_assert(!is_bit_set(&red->partitions_bitmap, i));
859        } else {
860            cb_assert(is_bit_set(&red->partitions_bitmap, i));
861        }
862    }
863
864    free_view_reduction(&reduction1);
865    free_view_reduction(&reduction2);
866    free_view_btree_reduction(red);
867    free_view_reducer_ctx(ctx);
868    free(key1_bin);
869    free(key2_bin);
870    free(key3_bin);
871    free_view_value(&value1);
872    free_view_value(&value2);
873    free_view_value(&value3);
874    free(value1_bin);
875    free(value2_bin);
876    free(value3_bin);
877    free_node_list(nl);
878}
879
880static void test_view_btree_js_reducer(void)
881{
882    char *error_msg = NULL;
883    view_reducer_ctx_t *ctx = NULL;
884    const char *function_sources[] = {
885        "function(key, values, rereduce) {"
886        "  if (values[3] == 'foobar') throw('foobar');"
887        "  if (rereduce) return sum(values);"
888        "  return values.length;"
889        "}"
890    };
891    int i;
892
893    view_btree_key_t key1, key2, key3;
894    char *key1_bin = NULL;
895    char *key2_bin = NULL;
896    char *key3_bin = NULL;
897    size_t key1_bin_size = 0;
898    size_t key2_bin_size = 0;
899    size_t key3_bin_size = 0;
900
901    view_btree_value_t value1, value2, value3;
902    char *value1_bin = NULL;
903    char *value2_bin = NULL;
904    char *value3_bin = NULL;
905    size_t value1_bin_size = 0;
906    size_t value2_bin_size = 0;
907    size_t value3_bin_size = 0;
908
909    view_btree_reduction_t reduction1;
910    char reduction1_bin[512];
911    size_t reduction1_bin_size = 0;
912    view_btree_reduction_t reduction2;
913    char reduction2_bin[512];
914    size_t reduction2_bin_size = 0;
915
916    nodelist *nl = NULL, *nl2 = NULL, *nl3 = NULL;
917    node_pointer *np = NULL, *np2 = NULL;
918
919    view_btree_reduction_t *red = NULL;
920    char red_bin[512];
921    size_t red_bin_size = 0;
922
923    ctx = make_view_reducer_ctx(function_sources, 1, &error_msg);
924    cb_assert(ctx != NULL);
925
926    key1.json_key.buf = "10";
927    key1.json_key.size = sizeof("10") - 1;
928    key1.doc_id.buf = "doc_10";
929    key1.doc_id.size = sizeof("doc_10") - 1;
930    cb_assert(encode_view_btree_key(&key1, &key1_bin, &key1_bin_size) == COUCHSTORE_SUCCESS);
931
932    key2.json_key.buf = "11";
933    key2.json_key.size = sizeof("11") - 1;
934    key2.doc_id.buf = "doc_11";
935    key2.doc_id.size = sizeof("doc_11") - 1;
936    cb_assert(encode_view_btree_key(&key2, &key2_bin, &key2_bin_size) == COUCHSTORE_SUCCESS);
937
938    key3.json_key.buf = "12";
939    key3.json_key.size = sizeof("12") - 1;
940    key3.doc_id.buf = "doc_12";
941    key3.doc_id.size = sizeof("doc_12") - 1;
942    cb_assert(encode_view_btree_key(&key3, &key3_bin, &key3_bin_size) == COUCHSTORE_SUCCESS);
943
944    value1.partition = 7;
945    value1.num_values = 2;
946    value1.values = (sized_buf *) malloc(sizeof(sized_buf) * 2);
947    value1.values[0].buf = "100";
948    value1.values[0].size = sizeof("100") - 1;
949    value1.values[1].buf = "1";
950    value1.values[1].size = sizeof("1") - 1;
951    cb_assert(encode_view_btree_value(&value1, &value1_bin, &value1_bin_size) == COUCHSTORE_SUCCESS);
952
953    value2.partition = 666;
954    value2.num_values = 1;
955    value2.values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
956    value2.values[0].buf = "1000";
957    value2.values[0].size = sizeof("1000") - 1;
958    cb_assert(encode_view_btree_value(&value2, &value2_bin, &value2_bin_size) == COUCHSTORE_SUCCESS);
959
960    value3.partition = 1023;
961    value3.num_values = 1;
962    value3.values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
963    value3.values[0].buf = "5000.33";
964    value3.values[0].size = sizeof("5000.33") - 1;
965    cb_assert(encode_view_btree_value(&value3, &value3_bin, &value3_bin_size) == COUCHSTORE_SUCCESS);
966
967    nl = (nodelist *) malloc(sizeof(nodelist));
968    cb_assert(nl != NULL);
969    nl->data.buf = value1_bin;
970    nl->data.size = value1_bin_size;
971    nl->key.buf = key1_bin;
972    nl->key.size = key1_bin_size;
973    nl->pointer = NULL;
974
975    nl2 = (nodelist *) malloc(sizeof(nodelist));
976    cb_assert(nl2 != NULL);
977    nl2->data.buf = value2_bin;
978    nl2->data.size = value2_bin_size;
979    nl2->key.buf = key2_bin;
980    nl2->key.size = key2_bin_size;
981    nl2->pointer = NULL;
982    nl->next = nl2;
983
984    nl3 = (nodelist *) malloc(sizeof(nodelist));
985    cb_assert(nl3 != NULL);
986    nl3->data.buf = value3_bin;
987    nl3->data.size = value3_bin_size;
988    nl3->key.buf = key3_bin;
989    nl3->key.size = key3_bin_size;
990    nl3->pointer = NULL;
991    nl3->next = NULL;
992    nl2->next = nl3;
993
994    cb_assert(view_btree_reduce(red_bin, &red_bin_size, nl, 3, ctx) == COUCHSTORE_SUCCESS);
995    cb_assert(decode_view_btree_reduction(red_bin, red_bin_size, &red) == COUCHSTORE_SUCCESS);
996    cb_assert(red->kv_count == 4);
997    cb_assert(red->num_values == 1);
998    cb_assert(red->reduce_values[0].size == (sizeof("4") - 1));
999    cb_assert(strncmp(red->reduce_values[0].buf, "4", sizeof("4") - 1) == 0);
1000
1001    for (i = 0; i < BITMAP_SIZE; ++i) {
1002        if ((i != 7) && (i != 666) && (i != 1023)) {
1003            cb_assert(!is_bit_set(&red->partitions_bitmap, i));
1004        } else {
1005            cb_assert(is_bit_set(&red->partitions_bitmap, i));
1006        }
1007    }
1008    free_view_btree_reduction(red);
1009    red = NULL;
1010
1011    /* Test JS reduce error */
1012
1013    free(value3_bin);
1014    value3.values[0].buf = "\"foobar\"";
1015    value3.values[0].size = sizeof("\"foobar\"") - 1;
1016    cb_assert(encode_view_btree_value(&value3, &value3_bin, &value3_bin_size) == COUCHSTORE_SUCCESS);
1017
1018    nl3->data.buf = value3_bin;
1019    nl3->data.size = value3_bin_size;
1020
1021    cb_assert(view_btree_reduce(red_bin, &red_bin_size, nl, 3, ctx) == COUCHSTORE_ERROR_REDUCER_FAILURE);
1022    cb_assert(ctx->error != NULL);
1023    cb_assert(strcmp(ctx->error, "foobar") == 0);
1024
1025    /* Test JS rereduce */
1026
1027    reduction1.kv_count = 11;
1028    memset(&reduction1.partitions_bitmap, 0, sizeof(reduction1.partitions_bitmap));
1029    set_bit(&reduction1.partitions_bitmap, 10);
1030    set_bit(&reduction1.partitions_bitmap, 1011);
1031    reduction1.num_values = 1;
1032    reduction1.reduce_values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
1033    cb_assert(reduction1.reduce_values != NULL);
1034    reduction1.reduce_values[0].buf = "4444";
1035    reduction1.reduce_values[0].size = sizeof("4444") - 1;
1036    cb_assert(encode_view_btree_reduction(&reduction1, reduction1_bin, &reduction1_bin_size) == COUCHSTORE_SUCCESS);
1037
1038    reduction2.kv_count = 44;
1039    memset(&reduction2.partitions_bitmap, 0, sizeof(reduction2.partitions_bitmap));
1040    set_bit(&reduction2.partitions_bitmap, 10);
1041    set_bit(&reduction2.partitions_bitmap, 777);
1042    set_bit(&reduction2.partitions_bitmap, 333);
1043    reduction2.num_values = 1;
1044    reduction2.reduce_values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
1045    cb_assert(reduction2.reduce_values != NULL);
1046    reduction2.reduce_values[0].buf = "100";
1047    reduction2.reduce_values[0].size = sizeof("100") - 1;
1048    cb_assert(encode_view_btree_reduction(&reduction2, reduction2_bin, &reduction2_bin_size) == COUCHSTORE_SUCCESS);
1049
1050    np = (node_pointer *) malloc(sizeof(node_pointer));
1051    cb_assert(np != NULL);
1052    np->key.buf = key1_bin;
1053    np->key.size = key1_bin_size;
1054    np->reduce_value.buf = reduction1_bin;
1055    np->reduce_value.size = reduction1_bin_size;
1056    np->pointer = 0;
1057    np->subtreesize = 222;
1058    nl->pointer = np;
1059
1060    np2 = (node_pointer *) malloc(sizeof(node_pointer));
1061    cb_assert(np2 != NULL);
1062    np2->key.buf = key2_bin;
1063    np2->key.size = key2_bin_size;
1064    np2->reduce_value.buf = reduction2_bin;
1065    np2->reduce_value.size = reduction2_bin_size;
1066    np2->pointer = 0;
1067    np2->subtreesize = 333;
1068    nl2->pointer = np2;
1069
1070    cb_assert(view_btree_rereduce(red_bin, &red_bin_size, nl, 2, ctx) == COUCHSTORE_SUCCESS);
1071    cb_assert(decode_view_btree_reduction(red_bin, red_bin_size, &red) == COUCHSTORE_SUCCESS);
1072    cb_assert(red->kv_count == 55);
1073    cb_assert(red->num_values == 1);
1074    cb_assert(red->reduce_values[0].size == (sizeof("4544") - 1));
1075    cb_assert(strncmp(red->reduce_values[0].buf, "4544", sizeof("4544") - 1) == 0);
1076
1077    for (i = 0; i < BITMAP_SIZE; ++i) {
1078        if ((i != 10) && (i != 333) && (i != 777) && (i != 1011)) {
1079            cb_assert(!is_bit_set(&red->partitions_bitmap, i));
1080        } else {
1081            cb_assert(is_bit_set(&red->partitions_bitmap, i));
1082        }
1083    }
1084
1085    free_view_reduction(&reduction1);
1086    free_view_reduction(&reduction2);
1087    free_view_btree_reduction(red);
1088    free_view_reducer_ctx(ctx);
1089    free(key1_bin);
1090    free(key2_bin);
1091    free(key3_bin);
1092    free_view_value(&value1);
1093    free_view_value(&value2);
1094    free_view_value(&value3);
1095    free(value1_bin);
1096    free(value2_bin);
1097    free(value3_bin);
1098    free_node_list(nl);
1099}
1100
1101static void test_view_btree_multiple_reducers(void)
1102{
1103    char *error_msg = NULL;
1104    view_reducer_ctx_t *ctx = NULL;
1105    const char *function_sources[] = {
1106        "_count",
1107        "function(key, values, rereduce) {"
1108        "  if (values[3] == 'foobar') throw('foobar');"
1109        "  if (rereduce) return sum(values);"
1110        "  return values.length;"
1111        "}",
1112        "_sum"
1113    };
1114    int i;
1115
1116    view_btree_key_t key1, key2, key3;
1117    char *key1_bin = NULL;
1118    char *key2_bin = NULL;
1119    char *key3_bin = NULL;
1120    size_t key1_bin_size = 0;
1121    size_t key2_bin_size = 0;
1122    size_t key3_bin_size = 0;
1123
1124    view_btree_value_t value1, value2, value3;
1125    char *value1_bin = NULL;
1126    char *value2_bin = NULL;
1127    char *value3_bin = NULL;
1128    size_t value1_bin_size = 0;
1129    size_t value2_bin_size = 0;
1130    size_t value3_bin_size = 0;
1131
1132    view_btree_reduction_t reduction1;
1133    char reduction1_bin[512];
1134    size_t reduction1_bin_size = 0;
1135    view_btree_reduction_t reduction2;
1136    char reduction2_bin[512];
1137    size_t reduction2_bin_size = 0;
1138
1139    nodelist *nl = NULL, *nl2 = NULL, *nl3 = NULL;
1140    node_pointer *np = NULL, *np2 = NULL;
1141
1142    view_btree_reduction_t *red = NULL;
1143    char red_bin[512];
1144    size_t red_bin_size = 0;
1145
1146    ctx = make_view_reducer_ctx(function_sources, 3, &error_msg);
1147    cb_assert(ctx != NULL);
1148
1149    key1.json_key.buf = "10";
1150    key1.json_key.size = sizeof("10") - 1;
1151    key1.doc_id.buf = "doc_10";
1152    key1.doc_id.size = sizeof("doc_10") - 1;
1153    cb_assert(encode_view_btree_key(&key1, &key1_bin, &key1_bin_size) == COUCHSTORE_SUCCESS);
1154
1155    key2.json_key.buf = "11";
1156    key2.json_key.size = sizeof("11") - 1;
1157    key2.doc_id.buf = "doc_11";
1158    key2.doc_id.size = sizeof("doc_11") - 1;
1159    cb_assert(encode_view_btree_key(&key2, &key2_bin, &key2_bin_size) == COUCHSTORE_SUCCESS);
1160
1161    key3.json_key.buf = "12";
1162    key3.json_key.size = sizeof("12") - 1;
1163    key3.doc_id.buf = "doc_12";
1164    key3.doc_id.size = sizeof("doc_12") - 1;
1165    cb_assert(encode_view_btree_key(&key3, &key3_bin, &key3_bin_size) == COUCHSTORE_SUCCESS);
1166
1167    value1.partition = 7;
1168    value1.num_values = 2;
1169    value1.values = (sized_buf *) malloc(sizeof(sized_buf) * 2);
1170    value1.values[0].buf = "100";
1171    value1.values[0].size = sizeof("100") - 1;
1172    value1.values[1].buf = "1";
1173    value1.values[1].size = sizeof("1") - 1;
1174    cb_assert(encode_view_btree_value(&value1, &value1_bin, &value1_bin_size) == COUCHSTORE_SUCCESS);
1175
1176    value2.partition = 666;
1177    value2.num_values = 1;
1178    value2.values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
1179    value2.values[0].buf = "1000";
1180    value2.values[0].size = sizeof("1000") - 1;
1181    cb_assert(encode_view_btree_value(&value2, &value2_bin, &value2_bin_size) == COUCHSTORE_SUCCESS);
1182
1183    value3.partition = 1023;
1184    value3.num_values = 1;
1185    value3.values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
1186    value3.values[0].buf = "5000.33";
1187    value3.values[0].size = sizeof("5000.33") - 1;
1188    cb_assert(encode_view_btree_value(&value3, &value3_bin, &value3_bin_size) == COUCHSTORE_SUCCESS);
1189
1190    nl = (nodelist *) malloc(sizeof(nodelist));
1191    cb_assert(nl != NULL);
1192    nl->data.buf = value1_bin;
1193    nl->data.size = value1_bin_size;
1194    nl->key.buf = key1_bin;
1195    nl->key.size = key1_bin_size;
1196    nl->pointer = NULL;
1197
1198    nl2 = (nodelist *) malloc(sizeof(nodelist));
1199    cb_assert(nl2 != NULL);
1200    nl2->data.buf = value2_bin;
1201    nl2->data.size = value2_bin_size;
1202    nl2->key.buf = key2_bin;
1203    nl2->key.size = key2_bin_size;
1204    nl2->pointer = NULL;
1205    nl->next = nl2;
1206
1207    nl3 = (nodelist *) malloc(sizeof(nodelist));
1208    cb_assert(nl3 != NULL);
1209    nl3->data.buf = value3_bin;
1210    nl3->data.size = value3_bin_size;
1211    nl3->key.buf = key3_bin;
1212    nl3->key.size = key3_bin_size;
1213    nl3->pointer = NULL;
1214    nl3->next = NULL;
1215    nl2->next = nl3;
1216
1217    cb_assert(view_btree_reduce(red_bin, &red_bin_size, nl, 3, ctx) == COUCHSTORE_SUCCESS);
1218    cb_assert(decode_view_btree_reduction(red_bin, red_bin_size, &red) == COUCHSTORE_SUCCESS);
1219    cb_assert(red->kv_count == 4);
1220    cb_assert(red->num_values == 3);
1221    cb_assert(red->reduce_values[0].size == (sizeof("4") - 1));
1222    cb_assert(strncmp(red->reduce_values[0].buf, "4", sizeof("4") - 1) == 0);
1223    cb_assert(red->reduce_values[1].size == (sizeof("4") - 1));
1224    cb_assert(strncmp(red->reduce_values[1].buf, "4", sizeof("4") - 1) == 0);
1225    cb_assert(red->reduce_values[2].size == (sizeof("6101.33") - 1));
1226    cb_assert(strncmp(red->reduce_values[2].buf, "6101.33", sizeof("6101.33") - 1) == 0);
1227
1228    for (i = 0; i < BITMAP_SIZE; ++i) {
1229        if ((i != 7) && (i != 666) && (i != 1023)) {
1230            cb_assert(!is_bit_set(&red->partitions_bitmap, i));
1231        } else {
1232            cb_assert(is_bit_set(&red->partitions_bitmap, i));
1233        }
1234    }
1235    free_view_btree_reduction(red);
1236    red = NULL;
1237
1238    /* Test JS reduce error */
1239
1240    free(value3_bin);
1241    value3.values[0].buf = "\"foobar\"";
1242    value3.values[0].size = sizeof("\"foobar\"") - 1;
1243    cb_assert(encode_view_btree_value(&value3, &value3_bin, &value3_bin_size) == COUCHSTORE_SUCCESS);
1244
1245    nl3->data.buf = value3_bin;
1246    nl3->data.size = value3_bin_size;
1247
1248    cb_assert(view_btree_reduce(red_bin, &red_bin_size, nl, 3, ctx) == COUCHSTORE_ERROR_REDUCER_FAILURE);
1249    cb_assert(ctx->error != NULL);
1250    cb_assert(strcmp(ctx->error, "foobar") == 0);
1251
1252    /* Test JS rereduce */
1253
1254    reduction1.kv_count = 11;
1255    memset(&reduction1.partitions_bitmap, 0, sizeof(reduction1.partitions_bitmap));
1256    set_bit(&reduction1.partitions_bitmap, 10);
1257    set_bit(&reduction1.partitions_bitmap, 1011);
1258    reduction1.num_values = 3;
1259    reduction1.reduce_values = (sized_buf *) malloc(sizeof(sized_buf) * 3);
1260    cb_assert(reduction1.reduce_values != NULL);
1261    reduction1.reduce_values[0].buf = "4444";
1262    reduction1.reduce_values[0].size = sizeof("4444") - 1;
1263    reduction1.reduce_values[1].buf = "44";
1264    reduction1.reduce_values[1].size = sizeof("44") - 1;
1265    reduction1.reduce_values[2].buf = "4000";
1266    reduction1.reduce_values[2].size = sizeof("4000") - 1;
1267    cb_assert(encode_view_btree_reduction(&reduction1, reduction1_bin, &reduction1_bin_size) == COUCHSTORE_SUCCESS);
1268
1269    reduction2.kv_count = 44;
1270    memset(&reduction2.partitions_bitmap, 0, sizeof(reduction2.partitions_bitmap));
1271    set_bit(&reduction2.partitions_bitmap, 10);
1272    set_bit(&reduction2.partitions_bitmap, 777);
1273    set_bit(&reduction2.partitions_bitmap, 333);
1274    reduction2.num_values = 3;
1275    reduction2.reduce_values = (sized_buf *) malloc(sizeof(sized_buf) * 3);
1276    cb_assert(reduction2.reduce_values != NULL);
1277    reduction2.reduce_values[0].buf = "100";
1278    reduction2.reduce_values[0].size = sizeof("100") - 1;
1279    reduction2.reduce_values[1].buf = "100";
1280    reduction2.reduce_values[1].size = sizeof("100") - 1;
1281    reduction2.reduce_values[2].buf = "100";
1282    reduction2.reduce_values[2].size = sizeof("100") - 1;
1283    cb_assert(encode_view_btree_reduction(&reduction2, reduction2_bin, &reduction2_bin_size) == COUCHSTORE_SUCCESS);
1284
1285    np = (node_pointer *) malloc(sizeof(node_pointer));
1286    cb_assert(np != NULL);
1287    np->key.buf = key1_bin;
1288    np->key.size = key1_bin_size;
1289    np->reduce_value.buf = reduction1_bin;
1290    np->reduce_value.size = reduction1_bin_size;
1291    np->pointer = 0;
1292    np->subtreesize = 222;
1293    nl->pointer = np;
1294
1295    np2 = (node_pointer *) malloc(sizeof(node_pointer));
1296    cb_assert(np2 != NULL);
1297    np2->key.buf = key2_bin;
1298    np2->key.size = key2_bin_size;
1299    np2->reduce_value.buf = reduction2_bin;
1300    np2->reduce_value.size = reduction2_bin_size;
1301    np2->pointer = 0;
1302    np2->subtreesize = 333;
1303    nl2->pointer = np2;
1304
1305    cb_assert(view_btree_rereduce(red_bin, &red_bin_size, nl, 2, ctx) == COUCHSTORE_SUCCESS);
1306    cb_assert(decode_view_btree_reduction(red_bin, red_bin_size, &red) == COUCHSTORE_SUCCESS);
1307    cb_assert(red->kv_count == 55);
1308    cb_assert(red->num_values == 3);
1309    cb_assert(red->reduce_values[0].size == (sizeof("4544") - 1));
1310    cb_assert(strncmp(red->reduce_values[0].buf, "4544", sizeof("4544") - 1) == 0);
1311    cb_assert(red->reduce_values[1].size == (sizeof("144") - 1));
1312    cb_assert(strncmp(red->reduce_values[1].buf, "144", sizeof("144") - 1) == 0);
1313    cb_assert(red->reduce_values[2].size == (sizeof("4100") - 1));
1314    cb_assert(strncmp(red->reduce_values[2].buf, "4100", sizeof("4100") - 1) == 0);
1315
1316    for (i = 0; i < BITMAP_SIZE; ++i) {
1317        if ((i != 10) && (i != 333) && (i != 777) && (i != 1011)) {
1318            cb_assert(!is_bit_set(&red->partitions_bitmap, i));
1319        } else {
1320            cb_assert(is_bit_set(&red->partitions_bitmap, i));
1321        }
1322    }
1323
1324    free_view_reduction(&reduction1);
1325    free_view_reduction(&reduction2);
1326    free_view_btree_reduction(red);
1327    free_view_reducer_ctx(ctx);
1328    free(key1_bin);
1329    free(key2_bin);
1330    free(key3_bin);
1331    free_view_value(&value1);
1332    free_view_value(&value2);
1333    free_view_value(&value3);
1334    free(value1_bin);
1335    free(value2_bin);
1336    free(value3_bin);
1337    free_node_list(nl);
1338}
1339
1340static void test_view_btree_no_reducers(void)
1341{
1342    char *error_msg = NULL;
1343    view_reducer_ctx_t *ctx = NULL;
1344    int i;
1345
1346    view_btree_key_t key1, key2, key3;
1347    char *key1_bin = NULL;
1348    char *key2_bin = NULL;
1349    char *key3_bin = NULL;
1350    size_t key1_bin_size = 0;
1351    size_t key2_bin_size = 0;
1352    size_t key3_bin_size = 0;
1353
1354    view_btree_value_t value1, value2, value3;
1355    char *value1_bin = NULL;
1356    char *value2_bin = NULL;
1357    char *value3_bin = NULL;
1358    size_t value1_bin_size = 0;
1359    size_t value2_bin_size = 0;
1360    size_t value3_bin_size = 0;
1361
1362    view_btree_reduction_t reduction1;
1363    char reduction1_bin[512];
1364    size_t reduction1_bin_size = 0;
1365    view_btree_reduction_t reduction2;
1366    char reduction2_bin[512];
1367    size_t reduction2_bin_size = 0;
1368
1369    nodelist *nl = NULL, *nl2 = NULL, *nl3 = NULL;
1370    node_pointer *np = NULL, *np2 = NULL;
1371
1372    view_btree_reduction_t *red = NULL;
1373    char red_bin[512];
1374    size_t red_bin_size = 0;
1375
1376    ctx = make_view_reducer_ctx(NULL, 0, &error_msg);
1377    cb_assert(ctx != NULL);
1378
1379    key1.json_key.buf = "10";
1380    key1.json_key.size = sizeof("10") - 1;
1381    key1.doc_id.buf = "doc_10";
1382    key1.doc_id.size = sizeof("doc_10") - 1;
1383    cb_assert(encode_view_btree_key(&key1, &key1_bin, &key1_bin_size) == COUCHSTORE_SUCCESS);
1384
1385    key2.json_key.buf = "11";
1386    key2.json_key.size = sizeof("11") - 1;
1387    key2.doc_id.buf = "doc_11";
1388    key2.doc_id.size = sizeof("doc_11") - 1;
1389    cb_assert(encode_view_btree_key(&key2, &key2_bin, &key2_bin_size) == COUCHSTORE_SUCCESS);
1390
1391    key3.json_key.buf = "12";
1392    key3.json_key.size = sizeof("12") - 1;
1393    key3.doc_id.buf = "doc_12";
1394    key3.doc_id.size = sizeof("doc_12") - 1;
1395    cb_assert(encode_view_btree_key(&key3, &key3_bin, &key3_bin_size) == COUCHSTORE_SUCCESS);
1396
1397    value1.partition = 7;
1398    value1.num_values = 2;
1399    value1.values = (sized_buf *) malloc(sizeof(sized_buf) * 2);
1400    value1.values[0].buf = "100";
1401    value1.values[0].size = sizeof("100") - 1;
1402    value1.values[1].buf = "1";
1403    value1.values[1].size = sizeof("1") - 1;
1404    cb_assert(encode_view_btree_value(&value1, &value1_bin, &value1_bin_size) == COUCHSTORE_SUCCESS);
1405
1406    value2.partition = 666;
1407    value2.num_values = 1;
1408    value2.values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
1409    value2.values[0].buf = "1000";
1410    value2.values[0].size = sizeof("1000") - 1;
1411    cb_assert(encode_view_btree_value(&value2, &value2_bin, &value2_bin_size) == COUCHSTORE_SUCCESS);
1412
1413    value3.partition = 1023;
1414    value3.num_values = 1;
1415    value3.values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
1416    value3.values[0].buf = "5000.33";
1417    value3.values[0].size = sizeof("5000.33") - 1;
1418    cb_assert(encode_view_btree_value(&value3, &value3_bin, &value3_bin_size) == COUCHSTORE_SUCCESS);
1419
1420    nl = (nodelist *) malloc(sizeof(nodelist));
1421    cb_assert(nl != NULL);
1422    nl->data.buf = value1_bin;
1423    nl->data.size = value1_bin_size;
1424    nl->key.buf = key1_bin;
1425    nl->key.size = key1_bin_size;
1426    nl->pointer = NULL;
1427
1428    nl2 = (nodelist *) malloc(sizeof(nodelist));
1429    cb_assert(nl2 != NULL);
1430    nl2->data.buf = value2_bin;
1431    nl2->data.size = value2_bin_size;
1432    nl2->key.buf = key2_bin;
1433    nl2->key.size = key2_bin_size;
1434    nl2->pointer = NULL;
1435    nl->next = nl2;
1436
1437    nl3 = (nodelist *) malloc(sizeof(nodelist));
1438    cb_assert(nl3 != NULL);
1439    nl3->data.buf = value3_bin;
1440    nl3->data.size = value3_bin_size;
1441    nl3->key.buf = key3_bin;
1442    nl3->key.size = key3_bin_size;
1443    nl3->pointer = NULL;
1444    nl3->next = NULL;
1445    nl2->next = nl3;
1446
1447    cb_assert(view_btree_reduce(red_bin, &red_bin_size, nl, 3, ctx) == COUCHSTORE_SUCCESS);
1448    cb_assert(decode_view_btree_reduction(red_bin, red_bin_size, &red) == COUCHSTORE_SUCCESS);
1449    cb_assert(red->kv_count == 4);
1450    cb_assert(red->num_values == 0);
1451    cb_assert(red->reduce_values == NULL);
1452
1453    for (i = 0; i < BITMAP_SIZE; ++i) {
1454        if ((i != 7) && (i != 666) && (i != 1023)) {
1455            cb_assert(!is_bit_set(&red->partitions_bitmap, i));
1456        } else {
1457            cb_assert(is_bit_set(&red->partitions_bitmap, i));
1458        }
1459    }
1460    free_view_btree_reduction(red);
1461    red = NULL;
1462
1463    /* Test rereduce */
1464
1465    reduction1.kv_count = 11;
1466    memset(&reduction1.partitions_bitmap, 0, sizeof(reduction1.partitions_bitmap));
1467    set_bit(&reduction1.partitions_bitmap, 10);
1468    set_bit(&reduction1.partitions_bitmap, 1011);
1469    reduction1.num_values = 0;
1470    reduction1.reduce_values = NULL;
1471    cb_assert(encode_view_btree_reduction(&reduction1, reduction1_bin, &reduction1_bin_size) == COUCHSTORE_SUCCESS);
1472
1473    reduction2.kv_count = 44;
1474    memset(&reduction2.partitions_bitmap, 0, sizeof(reduction2.partitions_bitmap));
1475    set_bit(&reduction2.partitions_bitmap, 10);
1476    set_bit(&reduction2.partitions_bitmap, 777);
1477    set_bit(&reduction2.partitions_bitmap, 333);
1478    reduction2.num_values = 0;
1479    reduction2.reduce_values = NULL;
1480    cb_assert(encode_view_btree_reduction(&reduction2, reduction2_bin, &reduction2_bin_size) == COUCHSTORE_SUCCESS);
1481
1482    np = (node_pointer *) malloc(sizeof(node_pointer));
1483    cb_assert(np != NULL);
1484    np->key.buf = key1_bin;
1485    np->key.size = key1_bin_size;
1486    np->reduce_value.buf = reduction1_bin;
1487    np->reduce_value.size = reduction1_bin_size;
1488    np->pointer = 0;
1489    np->subtreesize = 222;
1490    nl->pointer = np;
1491
1492    np2 = (node_pointer *) malloc(sizeof(node_pointer));
1493    cb_assert(np2 != NULL);
1494    np2->key.buf = key2_bin;
1495    np2->key.size = key2_bin_size;
1496    np2->reduce_value.buf = reduction2_bin;
1497    np2->reduce_value.size = reduction2_bin_size;
1498    np2->pointer = 0;
1499    np2->subtreesize = 333;
1500    nl2->pointer = np2;
1501
1502    cb_assert(view_btree_rereduce(red_bin, &red_bin_size, nl, 2, ctx) == COUCHSTORE_SUCCESS);
1503    cb_assert(decode_view_btree_reduction(red_bin, red_bin_size, &red) == COUCHSTORE_SUCCESS);
1504    cb_assert(red->kv_count == 55);
1505    cb_assert(red->num_values == 0);
1506    cb_assert(red->reduce_values == NULL);
1507
1508    for (i = 0; i < BITMAP_SIZE; ++i) {
1509        if ((i != 10) && (i != 333) && (i != 777) && (i != 1011)) {
1510            cb_assert(!is_bit_set(&red->partitions_bitmap, i));
1511        } else {
1512            cb_assert(is_bit_set(&red->partitions_bitmap, i));
1513        }
1514    }
1515
1516    free_view_reduction(&reduction1);
1517    free_view_reduction(&reduction2);
1518    free_view_btree_reduction(red);
1519    free_view_reducer_ctx(ctx);
1520    free(key1_bin);
1521    free(key2_bin);
1522    free(key3_bin);
1523    free_view_value(&value1);
1524    free_view_value(&value2);
1525    free_view_value(&value3);
1526    free(value1_bin);
1527    free(value2_bin);
1528    free(value3_bin);
1529    free_node_list(nl);
1530}
1531
1532static void test_view_btree_large_reducer(void)
1533{
1534    char *error_msg = NULL;
1535    view_reducer_ctx_t *ctx = NULL;
1536    const char *function_sources[] = {
1537        "function(key, values, rereduce) {"
1538        "   if (rereduce) {"
1539        "       var a = \"a\";"
1540        "       for(i=0;i<6000;i++) {"
1541        "           a = a + \"a\";"
1542        "       }"
1543        "       return a;"
1544        "   }"
1545        "   return 1;"
1546        "}"
1547    };
1548
1549    view_btree_key_t key1, key2;
1550    char *key1_bin = NULL;
1551    char *key2_bin = NULL;
1552    size_t key1_bin_size = 0;
1553    size_t key2_bin_size = 0;
1554
1555    view_btree_value_t value1, value2;
1556    char *value1_bin = NULL;
1557    char *value2_bin = NULL;
1558    char *value3_bin = NULL;
1559    size_t value1_bin_size = 0;
1560    size_t value2_bin_size = 0;
1561
1562    view_btree_reduction_t reduction1;
1563    char reduction1_bin[7000];
1564    size_t reduction1_bin_size = 0;
1565    view_btree_reduction_t reduction2;
1566    char reduction2_bin[7000];
1567    size_t reduction2_bin_size = 0;
1568
1569    nodelist *nl = NULL, *nl2 = NULL, *nl0 = NULL;
1570    node_pointer *np = NULL, *np2 = NULL;
1571
1572    view_btree_reduction_t *red = NULL;
1573
1574    ctx = make_view_reducer_ctx(function_sources, 1, &error_msg);
1575    cb_assert(ctx != NULL);
1576
1577    key1.json_key.buf = "10";
1578    key1.json_key.size = sizeof("10") - 1;
1579    key1.doc_id.buf = "doc_10";
1580    key1.doc_id.size = sizeof("doc_10") - 1;
1581    cb_assert(encode_view_btree_key(&key1, &key1_bin, &key1_bin_size)
1582        == COUCHSTORE_SUCCESS);
1583
1584    key2.json_key.buf = "11";
1585    key2.json_key.size = sizeof("11") - 1;
1586    key2.doc_id.buf = "doc_11";
1587    key2.doc_id.size = sizeof("doc_11") - 1;
1588    cb_assert(encode_view_btree_key(&key2, &key2_bin, &key2_bin_size)
1589        == COUCHSTORE_SUCCESS);
1590
1591    value1.partition = 7;
1592    value1.num_values = 1;
1593    value1.values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
1594    value1.values[0].buf = malloc(6000);
1595    value1.values[0].size = 6000;
1596    cb_assert(encode_view_btree_value(&value1, &value1_bin, &value1_bin_size)
1597        == COUCHSTORE_SUCCESS);
1598
1599    value2.partition = 666;
1600    value2.num_values = 1;
1601    value2.values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
1602    value2.values[0].buf = malloc(6000);
1603    value2.values[0].size = 6000;
1604    cb_assert(encode_view_btree_value(&value2, &value2_bin, &value2_bin_size)
1605        == COUCHSTORE_SUCCESS);
1606
1607    nl0 = (nodelist *) malloc(sizeof(nodelist));
1608    cb_assert(nl0 != NULL);
1609    nl0->pointer = NULL;
1610
1611    nl = (nodelist *) malloc(sizeof(nodelist));
1612    cb_assert(nl != NULL);
1613    nl->data.buf = value1_bin;
1614    nl->data.size = value1_bin_size;
1615    nl->key.buf = key1_bin;
1616    nl->key.size = key1_bin_size;
1617    nl->pointer = NULL;
1618    nl0->next = nl;
1619
1620    nl2 = (nodelist *) malloc(sizeof(nodelist));
1621    cb_assert(nl2 != NULL);
1622    nl2->data.buf = value2_bin;
1623    nl2->data.size = value2_bin_size;
1624    nl2->key.buf = key2_bin;
1625    nl2->key.size = key2_bin_size;
1626    nl2->pointer = NULL;
1627    nl->next = nl2;
1628    nl2->next = NULL;
1629
1630    reduction1.kv_count = 11;
1631    memset(&reduction1.partitions_bitmap, 0, sizeof(reduction1.partitions_bitmap));
1632    set_bit(&reduction1.partitions_bitmap, 10);
1633    set_bit(&reduction1.partitions_bitmap, 1011);
1634    reduction1.num_values = 1;
1635    reduction1.reduce_values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
1636    cb_assert(reduction1.reduce_values != NULL);
1637    reduction1.reduce_values[0].buf = "100";
1638    reduction1.reduce_values[0].size = 3;
1639    cb_assert(encode_view_btree_reduction(&reduction1, reduction1_bin, &reduction1_bin_size)
1640        == COUCHSTORE_SUCCESS);
1641
1642    reduction2.kv_count = 44;
1643    memset(&reduction2.partitions_bitmap, 0, sizeof(reduction2.partitions_bitmap));
1644    set_bit(&reduction2.partitions_bitmap, 10);
1645    set_bit(&reduction2.partitions_bitmap, 777);
1646    set_bit(&reduction2.partitions_bitmap, 333);
1647    reduction2.num_values = 1;
1648    reduction2.reduce_values = (sized_buf *) malloc(sizeof(sized_buf) * 1);
1649    cb_assert(reduction2.reduce_values != NULL);
1650    reduction2.reduce_values[0].buf = "100";
1651    reduction2.reduce_values[0].size = 3;
1652    cb_assert(encode_view_btree_reduction(&reduction2, reduction2_bin, &reduction2_bin_size)
1653        == COUCHSTORE_SUCCESS);
1654
1655    np = (node_pointer *) malloc(sizeof(node_pointer));
1656    cb_assert(np != NULL);
1657    np->key.buf = key1_bin;
1658    np->key.size = key1_bin_size;
1659    np->reduce_value.buf = reduction1_bin;
1660    np->reduce_value.size = reduction1_bin_size;
1661    np->pointer = 0;
1662    np->subtreesize = 222;
1663    nl->pointer = np;
1664
1665    np2 = (node_pointer *) malloc(sizeof(node_pointer));
1666    cb_assert(np2 != NULL);
1667    np2->key.buf = key2_bin;
1668    np2->key.size = key2_bin_size;
1669    np2->reduce_value.buf = reduction2_bin;
1670    np2->reduce_value.size = reduction2_bin_size;
1671    np2->pointer = 0;
1672    np2->subtreesize = 333;
1673    nl2->pointer = np2;
1674
1675    couchstore_error_t ret = COUCHSTORE_SUCCESS;
1676    arena *transient_arena = new_arena(0);
1677    arena *persistent_arena = new_arena(0);
1678    couchfile_modify_result *mr;
1679    tree_file index_file;
1680
1681    compare_info cmp = {
1682        .compare = view_btree_cmp
1683    };
1684    char *dst_file = "dst_file";
1685    cb_assert(transient_arena != NULL && persistent_arena != NULL);
1686    ret = tree_file_open(&index_file, dst_file, O_CREAT | O_RDWR,
1687        couchstore_get_default_file_ops());
1688    cb_assert(ret == COUCHSTORE_SUCCESS);
1689    mr = new_btree_modres(persistent_arena,
1690            transient_arena,
1691            &index_file,
1692            &cmp,
1693            view_btree_reduce,
1694            view_btree_rereduce,
1695            ctx,
1696            VIEW_KV_CHUNK_THRESHOLD + (VIEW_KV_CHUNK_THRESHOLD / 3),
1697            VIEW_KP_CHUNK_THRESHOLD + (VIEW_KP_CHUNK_THRESHOLD / 3));
1698
1699    cb_assert(mr != NULL);
1700    couchfile_modify_result* targ_mr = make_modres(mr->arena, mr->rq);
1701    cb_assert(targ_mr != NULL);
1702    targ_mr->modified = 1;
1703    targ_mr->node_type = KP_NODE;
1704    targ_mr->pointers = nl0;
1705    targ_mr->pointers_end = nl2;
1706    finish_root(mr->rq, targ_mr, &ret);
1707    cb_assert(ret == COUCHSTORE_SUCCESS);
1708
1709    tree_file_close(&index_file);
1710    remove(dst_file);
1711    free_view_reduction(&reduction1);
1712    free_view_reduction(&reduction2);
1713    free_view_btree_reduction(red);
1714    free_view_reducer_ctx(ctx);
1715    free(key1_bin);
1716    free(key2_bin);
1717    free(value1.values[0].buf);
1718    free(value2.values[0].buf);
1719    free_view_value(&value1);
1720    free_view_value(&value2);
1721    free(value1_bin);
1722    free(value2_bin);
1723    free(value3_bin);
1724    free_node_list(nl0);
1725    delete_arena(persistent_arena);
1726    delete_arena(transient_arena);
1727}
1728
1729void reducer_tests(void)
1730{
1731    fprintf(stderr, "Running built-in reducer tests ... \n");
1732    test_view_id_btree_reducer();
1733    fprintf(stderr, "End of built-in view id btree reducer tests\n");
1734    test_view_btree_sum_reducer();
1735    fprintf(stderr, "End of built-in view btree sum reducer tests\n");
1736    test_view_btree_count_reducer();
1737    fprintf(stderr, "End of built-in view btree count reducer tests\n");
1738    test_view_btree_stats_reducer();
1739    fprintf(stderr, "End of built-in view btree stats reducer tests\n");
1740    test_view_btree_js_reducer();
1741    fprintf(stderr, "End of view btree js reducer tests\n");
1742    test_view_btree_multiple_reducers();
1743    fprintf(stderr, "End of view btree multiple reducer tests\n");
1744    test_view_btree_no_reducers();
1745    fprintf(stderr, "End of view btree no reducer tests\n");
1746    test_view_btree_large_reducer();
1747    fprintf(stderr, "End of view btree large reducer tests\n");
1748}
1749