1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3 #ident "$Id$"
4 /*======
5 This file is part of PerconaFT.
6
7
8 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9
10 PerconaFT is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License, version 2,
12 as published by the Free Software Foundation.
13
14 PerconaFT is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
21
22 ----------------------------------------
23
24 PerconaFT is free software: you can redistribute it and/or modify
25 it under the terms of the GNU Affero General Public License, version 3,
26 as published by the Free Software Foundation.
27
28 PerconaFT is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU Affero General Public License for more details.
32
33 You should have received a copy of the GNU Affero General Public License
34 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
35 ======= */
36
37 #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38
39 #include "test.h"
40
41 #include "loader/loader-internal.h"
42 #include "loader/pqueue.h"
43
44 int found_dup = -1;
45
46 // simple compare func
test_compare(DB * UU (db),const DBT * dbta,const DBT * dbtb)47 static int test_compare(DB * UU(db), const DBT *dbta, const DBT *dbtb)
48 {
49 int a = *((int*)dbta->data);
50 int b = *((int*)dbtb->data);
51 if ( a<b ) return -1;
52 if ( a>b ) return 1;
53 return 0;
54 }
55
dbt_init(DBT * dbt,void * data,uint32_t size)56 static inline DBT *dbt_init(DBT *dbt, void *data, uint32_t size) {
57 memset(dbt, 0, sizeof *dbt);
58 dbt->data = data;
59 dbt->size = size;
60 return dbt;
61 }
62
err_cb(DB * db,int which_db,int err,DBT * key,DBT * val,void * extra)63 static void err_cb(DB *db, int which_db, int err, DBT *key, DBT *val, void *extra) {
64 (void) db; (void) which_db; (void) err; (void) extra;
65 (void) val;
66 found_dup = *(int *)key->data;
67 if (verbose) printf("err_cb : key <%d> val <%d>\n", *(int *)key->data, *(int *)val->data);
68 }
69
run_test(void)70 static int run_test(void)
71 {
72 const int n_sources=10;
73 pqueue_t *pq;
74 pqueue_node_t *pq_nodes = (pqueue_node_t *) toku_malloc( n_sources * sizeof(pqueue_node_t));
75 pqueue_node_t *node;
76 DB *dest_db = NULL;
77 ft_compare_func compare = test_compare;
78 int r;
79 struct error_callback_s error_callback;
80 ft_loader_init_error_callback(&error_callback);
81 ft_loader_set_error_function(&error_callback, err_cb, NULL);
82
83 r = pqueue_init(&pq, n_sources, 0, dest_db, compare, &error_callback);
84 if (r) return r;
85
86 DBT keys[n_sources];
87 DBT vals[n_sources];
88 DBT zero;
89 toku_init_dbt_flags(&zero, DB_DBT_REALLOC);
90 int key_data[10] = {0, 4, 8, 9, 5, 1, 2, 6, 7, 3};
91
92 for (int i=0;i<n_sources; i++) {
93 if (verbose) printf("%d ", key_data[i]);
94 keys[i] = zero;
95 vals[i] = zero;
96 dbt_init(&keys[i], &key_data[i], sizeof(int));
97 }
98 if (verbose) printf("\n");
99
100 // test 1 : fill it up, then empty it out
101 for (int i=0; i<n_sources; i++) {
102 pq_nodes[i].key = &keys[i];
103 pq_nodes[i].val = &vals[i];
104 pq_nodes[i].i = i;
105 pqueue_insert(pq, &pq_nodes[i]);
106 }
107
108 for (int i=0; i<n_sources; i++) {
109 r = pqueue_pop(pq, &node); assert(r==0);
110 if (verbose) printf("%d : %d\n", i, *(int*)(node->key->data));
111 if ( *(int*)(node->key->data) != i ) {
112 if (verbose)
113 printf("FAIL\n");
114 return -1;
115 }
116 }
117 pqueue_free(pq);
118 if (verbose) printf("test1 : PASS\n");
119
120 // test 2 : fill it, then empty and reload, then empty
121 {
122 r = pqueue_init(&pq, n_sources, 0, dest_db, compare, &error_callback);
123 if (r) return r;
124 }
125
126 DBT more_keys[20];
127 DBT more_vals[20];
128 int more_key_data[20] = {0, 4, 8, 9, 5, 1, 2, 6, 7, 3, 10, 11, 14, 13, 12, 17, 19, 15, 18, 16};
129 for (int i=0; i<20; i++) {
130 more_keys[i] = zero;
131 more_vals[i] = zero;
132 dbt_init(&more_keys[i], &more_key_data[i], sizeof(int));
133 }
134
135 for (int i=0; i<10; i++) {
136 pq_nodes[i].key = &more_keys[i];
137 pq_nodes[i].val = &more_vals[i];
138 pq_nodes[i].i = i;
139 pqueue_insert(pq, &pq_nodes[i]);
140 }
141
142 for (int i=0; i<5; i++) {
143 r = pqueue_pop(pq, &node); assert(r==0);
144 if ( *(int *)node->key->data != i ) { printf("FAIL\n"); return -1; }
145 if (verbose) printf("%d : %d\n", i, *(int*)node->key->data);
146 }
147
148 int n;
149 for (int i=5; i<15; i++) {
150 r = pqueue_pop(pq, &node); assert(r==0);
151 if ( *(int *)node->key->data != i ) { printf("FAIL\n"); return -1; }
152 if (verbose) printf("%d : %d\n", i, *(int*)node->key->data);
153 n = node->i;
154 pq_nodes[n].key = &more_keys[i+5];
155 pq_nodes[n].val = &more_vals[i+5];
156 pqueue_insert(pq, &pq_nodes[n]);
157 }
158
159 for (int i=15; i<20; i++) {
160 r = pqueue_pop(pq, &node); assert(r==0);
161 if ( *(int*)node->key->data != i ) { printf("FAIL\n"); return -1; }
162 if (verbose) printf("%d : %d\n", i, *(int*)node->key->data);
163 }
164 if (verbose) printf("test2 : PASS\n");
165 pqueue_free(pq);
166
167 // test 3 : put in a dup
168 {
169 r = pqueue_init(&pq, 10, 0, dest_db, compare, &error_callback);
170 if (r) return r;
171 }
172
173 DBT keys3[10];
174 DBT vals3[10];
175 int key_data3[10] = {0, 1, 2, 3, 4, 5, 6, 6, 8, 9}; // dup is 6
176 int val_data3[10];
177
178 for (int i=0; i<10; i++) {
179 keys3[i] = zero;
180 vals3[i] = zero;
181 val_data3[i] = i;
182 dbt_init(&keys3[i], &key_data3[i], sizeof(int));
183 dbt_init(&vals3[i], &val_data3[i], sizeof(int));
184 }
185 int ii;
186 for (ii=0; ii<10; ii++) {
187 pq_nodes[ii].key = &keys3[ii];
188 pq_nodes[ii].val = &vals3[ii];
189 pq_nodes[ii].i = ii;
190 r = pqueue_insert(pq, &pq_nodes[ii]);
191 if ( r != 0 ) goto found_duplicate6;
192 }
193 for (ii=0; ii<10; ii++) {
194 r = pqueue_pop(pq, &node);
195 // if (verbose) printf("%d : %d\n", ii, *(int*)node->key->data);
196 if ( r != 0 ) goto found_duplicate6;
197 }
198 found_duplicate6:
199 // if (verbose) printf("%d : %d\n", ii, *(int*)node->key->data);
200 if ( found_dup != 6 ) { printf("FAIL\n"); return -1; }
201 if (verbose) printf("test3 : PASS\n");
202 pqueue_free(pq);
203 ft_loader_destroy_error_callback(&error_callback);
204
205 // test 4 - find duplicate when inserting
206 ft_loader_init_error_callback(&error_callback);
207 ft_loader_set_error_function(&error_callback, err_cb, NULL);
208 r = pqueue_init(&pq, 10, 0, dest_db, compare, &error_callback); if (r) return r;
209
210 found_dup = -1;
211 DBT keys4[10];
212 DBT vals4[10];
213 int key_data4[10] = {0, 0, 2, 3, 4, 5, 6, 7, 8, 9}; // dup is 0
214 int val_data4[10];
215
216 for (int i=0; i<10; i++) {
217 keys4[i] = zero;
218 vals4[i] = zero;
219 val_data4[i] = i;
220 dbt_init(&keys4[i], &key_data4[i], sizeof(int));
221 dbt_init(&vals4[i], &val_data4[i], sizeof(int));
222 }
223
224 for (ii=0; ii<10; ii++) {
225 pq_nodes[ii].key = &keys4[ii];
226 pq_nodes[ii].val = &vals4[ii];
227 pq_nodes[ii].i = ii;
228 r = pqueue_insert(pq, &pq_nodes[ii]);
229 if ( r != 0 ) {
230 // if (verbose) printf("%d : %d\n", ii, *(int*)pq_nodes[ii].key->data);
231 goto found_duplicate0;
232 }
233 }
234 for (ii=0; ii<10; ii++) {
235 r = pqueue_pop(pq, &node);
236 // if (verbose) printf("%d : %d\n", ii, *(int*)node->key->data);
237 if ( r != 0 ) goto found_duplicate0;
238 }
239 found_duplicate0:
240 if ( found_dup != 0 ) { printf("FAIL - found_dup : %d\n", found_dup); return -1; }
241 if (verbose) printf("test4 : PASS\n");
242 if (verbose) printf("PASS\n");
243 pqueue_free(pq);
244 toku_free(pq_nodes);
245 ft_loader_destroy_error_callback(&error_callback);
246
247 return 0;
248 }
249
250
251
252 int
test_main(int argc,const char * argv[])253 test_main (int argc, const char *argv[]) {
254 argc--; argv++;
255 while (argc>0) {
256 if (strcmp(argv[0], "-v")==0) {
257 verbose++;
258 }
259 argc--;
260 argv++;
261 }
262 return run_test();
263 }
264