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 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 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 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 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 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