void test_art_insert_verylong(void) { art_tree t; int res = art_tree_init(&t); unsigned char key1[300] = { 16, 0, 0, 0, 7, 10, 0, 0, 0, 2, 17, 10, 0, 0, 0, 120, 10, 0, 0, 0, 120, 10, 0, 0, 0, 216, 10, 0, 0, 0, 202, 10, 0, 0, 0, 194, 10, 0, 0, 0, 224, 10, 0, 0, 0, 230, 10, 0, 0, 0, 210, 10, 0, 0, 0, 206, 10, 0, 0, 0, 208, 10, 0, 0, 0, 232, 10, 0, 0, 0, 124, 10, 0, 0, 0, 124, 2, 16, 0, 0, 0, 2, 12, 185, 89, 44, 213, 251, 173, 202, 211, 95, 185, 89, 110, 118, 251, 173, 202, 199, 101, 0, 8, 18, 182, 92, 236, 147, 171, 101, 150, 195, 112, 185, 218, 108, 246, 139, 164, 234, 195, 58, 177, 0, 8, 16, 0, 0, 0, 2, 12, 185, 89, 44, 213, 251, 173, 202, 211, 95, 185, 89, 110, 118, 251, 173, 202, 199, 101, 0, 8, 18, 180, 93, 46, 151, 9, 212, 190, 95, 102, 178, 217, 44, 178, 235, 29, 190, 218, 8, 16, 0, 0, 0, 2, 12, 185, 89, 44, 213, 251, 173, 202, 211, 95, 185, 89, 110, 118, 251, 173, 202, 199, 101, 0, 8, 18, 180, 93, 46, 151, 9, 212, 190, 95, 102, 183, 219, 229, 214, 59, 125, 182, 71, 108, 180, 220, 238, 150, 91, 117, 150, 201, 84, 183, 128, 8, 16, 0, 0, 0, 2, 12, 185, 89, 44, 213, 251, 173, 202, 211, 95, 185, 89, 110, 118, 251, 173, 202, 199, 101, 0, 8, 18, 180, 93, 46, 151, 9, 212, 190, 95, 108, 176, 217, 47, 50, 219, 61, 134, 207, 97, 151, 88, 237, 246, 208, 8, 18, 255, 255, 255, 219, 191, 198, 134, 5, 223, 212, 72, 44, 208, 250, 180, 14, 1, 0, 0, 8, '\0'}; unsigned char key2[303] = { 16, 0, 0, 0, 7, 10, 0, 0, 0, 2, 17, 10, 0, 0, 0, 120, 10, 0, 0, 0, 120, 10, 0, 0, 0, 216, 10, 0, 0, 0, 202, 10, 0, 0, 0, 194, 10, 0, 0, 0, 224, 10, 0, 0, 0, 230, 10, 0, 0, 0, 210, 10, 0, 0, 0, 206, 10, 0, 0, 0, 208, 10, 0, 0, 0, 232, 10, 0, 0, 0, 124, 10, 0, 0, 0, 124, 2, 16, 0, 0, 0, 2, 12, 185, 89, 44, 213, 251, 173, 202, 211, 95, 185, 89, 110, 118, 251, 173, 202, 199, 101, 0, 8, 18, 182, 92, 236, 147, 171, 101, 150, 195, 112, 185, 218, 108, 246, 139, 164, 234, 195, 58, 177, 0, 8, 16, 0, 0, 0, 2, 12, 185, 89, 44, 213, 251, 173, 202, 211, 95, 185, 89, 110, 118, 251, 173, 202, 199, 101, 0, 8, 18, 180, 93, 46, 151, 9, 212, 190, 95, 102, 178, 217, 44, 178, 235, 29, 190, 218, 8, 16, 0, 0, 0, 2, 12, 185, 89, 44, 213, 251, 173, 202, 211, 95, 185, 89, 110, 118, 251, 173, 202, 199, 101, 0, 8, 18, 180, 93, 46, 151, 9, 212, 190, 95, 102, 183, 219, 229, 214, 59, 125, 182, 71, 108, 180, 220, 238, 150, 91, 117, 150, 201, 84, 183, 128, 8, 16, 0, 0, 0, 3, 12, 185, 89, 44, 213, 251, 133, 178, 195, 105, 183, 87, 237, 150, 155, 165, 150, 229, 97, 182, 0, 8, 18, 161, 91, 239, 50, 10, 61, 150, 223, 114, 179, 217, 64, 8, 12, 186, 219, 172, 150, 91, 53, 166, 221, 101, 178, 0, 8, 18, 255, 255, 255, 219, 191, 198, 134, 5, 208, 212, 72, 44, 208, 250, 180, 14, 1, 0, 0, 8, '\0'}; fail_unless(res == 0); fail_unless(NULL == art_insert(&t, key1, 299, (void *)key1)); fail_unless(NULL == art_insert(&t, key2, 302, (void *)key2)); art_insert(&t, key2, 302, (void *)key2); fail_unless(art_size(&t) == 2); res = art_tree_destroy(&t); fail_unless(res == 0); }
void test_art_long_prefix(void) { art_tree t; int res = art_tree_init(&t); uintptr_t v; const char *s; fail_unless(res == 0); s = "this:key:has:a:long:prefix:3"; v = 3; fail_unless(NULL == art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, (void *)v)); s = "this:key:has:a:long:common:prefix:2"; v = 2; fail_unless(NULL == art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, (void *)v)); s = "this:key:has:a:long:common:prefix:1"; v = 1; fail_unless(NULL == art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, (void *)v)); // Search for the keys s = "this:key:has:a:long:common:prefix:1"; fail_unless( 1 == (uintptr_t)art_search(&t, (unsigned char *)s, (int)strlen(s) + 1)); s = "this:key:has:a:long:common:prefix:2"; fail_unless( 2 == (uintptr_t)art_search(&t, (unsigned char *)s, (int)strlen(s) + 1)); s = "this:key:has:a:long:prefix:3"; fail_unless( 3 == (uintptr_t)art_search(&t, (unsigned char *)s, (int)strlen(s) + 1)); { const char *expected[] = { "this:key:has:a:long:common:prefix:1", "this:key:has:a:long:common:prefix:2", "this:key:has:a:long:prefix:3", }; prefix_data p = {0, 3, expected}; fail_unless(!art_iter_prefix(&t, (unsigned char *)"this:key:has", 12, test_prefix_cb, &p)); diag("Count: %d Max: %d", p.count, p.max_count); fail_unless(p.count == p.max_count); } res = art_tree_destroy(&t); fail_unless(res == 0); }
/** * Creates a new set and adds it to the set set. * @arg mgr The manager to add to * @arg set_name The name of the set * @arg config The configuration for the set * @arg is_hot Is the set hot. False for existing. * @arg delta Should a delta entry be added, or the primary tree updated. * This is usually 0, except during initialization when it is safe to update * the primary tree. * @return 0 on success, -1 on error */ static int add_set(hlld_setmgr *mgr, char *set_name, hlld_config *config, int is_hot, int delta) { // Create the set hlld_set_wrapper *set = calloc(1, sizeof(hlld_set_wrapper)); set->is_active = 1; set->is_hot = is_hot; set->should_delete = 0; pthread_rwlock_init(&set->rwlock, NULL); // Set the custom set if its not the same if (mgr->config != config) { set->custom = config; } // Try to create the underlying set. Only discover if it is hot. int res = init_set(config, set_name, is_hot, &set->set); if (res != 0) { free(set); return -1; } // Check if we are adding a delta value or directly updating ART tree if (delta) create_delta_update(mgr, CREATE, set); else art_insert(mgr->set_map, set_name, strlen(set_name)+1, set); return 0; }
int add_elements(struct ds_context *ctx) { PMEMobjpool *pop; int errors = 0; int i; int key_len; int val_len; unsigned char *key; unsigned char *value; if (ctx == NULL) { errors++; } else if (ctx->pop == NULL) { errors++; } if (!errors) { pop = ctx->pop; for (i = 0; i < ctx->insertions; i++) { key = NULL; value = NULL; key_len = read_key(&key); val_len = read_value(&value); art_insert(pop, key, key_len, value, val_len); if (key != NULL) free(key); if (value != NULL) free(value); } } return errors; }
/** * Creates a new filter and adds it to the filter map. * @arg mgr The manager to add to * @arg filter_name The name of the filter * @arg config The configuration for the filter * @arg is_hot Is the filter hot. False for existing. * @arg delta Is this a delta update or should the map be updated * @return 0 on success, -1 on error */ static int add_filter(bloom_filtmgr *mgr, char *filter_name, bloom_config *config, int is_hot, int delta) { // Create the filter bloom_filter_wrapper *filt = calloc(1, sizeof(bloom_filter_wrapper)); filt->is_active = 1; filt->is_hot = is_hot; filt->should_delete = 0; pthread_rwlock_init(&filt->rwlock, NULL); // Set the custom filter if its not the same if (mgr->config != config) { filt->custom = config; } // Try to create the underlying filter. Only discover if it is hot. int res = init_bloom_filter(config, filter_name, is_hot, &filt->filter); if (res != 0) { free(filt); return -1; } // Check if we are adding a delta value or directly updating ART tree if (delta) create_delta_update(mgr, CREATE, filt); else art_insert(mgr->filter_map, (unsigned char*)filter_name, strlen(filter_name)+1, filt); return 0; }
void test_art_insert_iter(void) { art_tree t; int res = art_tree_init(&t); int len; char buf[512]; FILE *f = fopen("thirdparty/libart/tests/words.txt", "r"); uint64_t xor_mask = 0; uintptr_t line = 1, nlines; fail_unless(res == 0); while (fgets(buf, sizeof buf, f)) { len = (int)strlen(buf); buf[len - 1] = '\0'; if (art_insert(&t, (unsigned char *)buf, len, (void *)line)) { fail("art_insert didn't return NULL"); } xor_mask ^= (line * (buf[0] + len)); line++; } nlines = line - 1; { uint64_t out[] = {0, 0}; fail_unless(art_iter(&t, iter_cb, &out) == 0); fail_unless(out[0] == nlines); fail_unless(out[1] == xor_mask); } res = art_tree_destroy(&t); fail_unless(res == 0); }
static ERL_NIF_TERM elibart_insert(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { art_tree* t; ErlNifBinary key, value; art_elem_struct *elem; unsigned char buffer[BUFF_SIZE]; // 256Kb buffer unsigned char *key_copy = buffer; // extract arguments atr_tree, key, value if (argc != 3) return enif_make_badarg(env); if(!enif_get_resource(env, argv[0], elibart_RESOURCE, (void**) &t)) return enif_make_badarg(env); if (!enif_inspect_binary(env, argv[1], &key)) return enif_make_badarg(env); if (!enif_inspect_binary(env, argv[2], &value)) return enif_make_badarg(env); // buffer size not enough, pay the price if (key.size > BUFF_SIZE) key_copy = malloc(key.size + 1); // TODO review -- is it possible not to copy the key just to add '\0'? memcpy(key_copy, key.data, key.size); key_copy[key.size] = '\0'; //create art element elem = malloc(sizeof(art_elem_struct)); if (elem == NULL) mk_error(env, "malloc_no_mem"); elem->data = malloc(value.size); elem->size = value.size; memcpy(elem->data, value.data, value.size); // insert the element in the art_tree art_elem_struct *old_elem = art_insert(t, key_copy, key.size + 1, elem); // buffer size not enough, pay the price if (key.size > BUFF_SIZE) free(key_copy); // the inserted key is new if (!old_elem) return enif_make_tuple2(env, mk_atom(env, "ok"), mk_atom(env, "empty")); // the inserted key already existed, return previous value ErlNifBinary res; enif_alloc_binary(old_elem->size, &res); memcpy(res.data, old_elem->data, old_elem->size); free(old_elem->data); free(old_elem); return enif_make_tuple2(env, enif_make_atom(env, "ok"), enif_make_binary(env, &res)); }
END_TEST START_TEST(test_art_insert_copy_delete) { art_tree t; int res = init_art_tree(&t); fail_unless(res == 0); int len; char buf[512]; FILE *f = fopen("tests/words.txt", "r"); uintptr_t line = 1, nlines; while (fgets(buf, sizeof buf, f)) { len = strlen(buf); buf[len-1] = '\0'; fail_unless(NULL == art_insert(&t, buf, len, (void*)line)); line++; } nlines = line - 1; // Create a new tree art_tree t2; fail_unless(art_copy(&t2, &t) == 0); // Destroy the original res = destroy_art_tree(&t); fail_unless(res == 0); // Seek back to the start fseek(f, 0, SEEK_SET); // Search for each line line = 1; while (fgets(buf, sizeof buf, f)) { len = strlen(buf); buf[len-1] = '\0'; // Search first, ensure all entries still // visible uintptr_t val = (uintptr_t)art_search(&t2, buf, len); fail_unless(line == val, "Line: %d Val: %" PRIuPTR " Str: %s\n", line, val, buf); // Delete, should get lineno back val = (uintptr_t)art_delete(&t2, buf, len); fail_unless(line == val, "Line: %d Val: %" PRIuPTR " Str: %s\n", line, val, buf); // Check the size fail_unless(art_size(&t2) == nlines - line); line++; } res = destroy_art_tree(&t2); fail_unless(res == 0); }
void test_art_insert_delete(void) { art_tree t; int res = art_tree_init(&t); int len; char buf[512]; FILE *f = fopen("thirdparty/libart/tests/words.txt", "r"); uintptr_t line = 1, nlines; fail_unless(res == 0); while (fgets(buf, sizeof buf, f)) { len = (int)strlen(buf); buf[len - 1] = '\0'; if (art_insert(&t, (unsigned char *)buf, len, (void *)line)) { fail("art_insert didn't return NULL"); } line++; } nlines = line - 1; // Seek back to the start fseek(f, 0, SEEK_SET); // Search for each line line = 1; while (fgets(buf, sizeof buf, f)) { uintptr_t val; len = (int)strlen(buf); buf[len - 1] = '\0'; // Search first, ensure all entries still // visible val = (uintptr_t)art_search(&t, (unsigned char *)buf, len); if (line != val) { fail("Line: %d Val: %" PRIuPTR " Str: %s", line, val, buf); } // Delete, should get lineno back val = (uintptr_t)art_delete(&t, (unsigned char *)buf, len); if (line != val) { fail("Line: %d Val: %" PRIuPTR " Str: %s", line, val, buf); } // Check the size if (art_size(&t) != nlines - line) { fail("bad size after delete"); } line++; } // Check the minimum and maximum fail_unless(!art_minimum(&t)); fail_unless(!art_maximum(&t)); res = art_tree_destroy(&t); fail_unless(res == 0); }
void test_art_prefix(void) { art_tree t; void *v; art_tree_init(&t); fail_unless(art_insert(&t, (const unsigned char*)"food", 4, "food") == NULL); fail_unless(art_insert(&t, (const unsigned char*)"foo", 3, "foo") == NULL); diag("size is now %d", art_size(&t)); fail_unless(art_size(&t) == 2); fail_unless((v = art_search(&t, (const unsigned char*)"food", 4)) != NULL); diag("food lookup yields %s", v); fail_unless(v && strcmp((char*)v, "food") == 0); art_iter(&t, dump_iter, NULL); fail_unless((v = art_search(&t, (const unsigned char*)"foo", 3)) != NULL); diag("foo lookup yields %s", v); fail_unless(v && strcmp((char*)v, "foo") == 0); art_tree_destroy(&t); }
void test_art_insert_search_uuid(void) { art_tree t; art_leaf *l; int res = art_tree_init(&t); int len; char buf[512]; FILE *f = fopen("thirdparty/libart/tests/uuid.txt", "r"); uintptr_t line = 1; fail_unless(res == 0); while (fgets(buf, sizeof buf, f)) { len = (int)strlen(buf); buf[len - 1] = '\0'; if (art_insert(&t, (unsigned char *)buf, len, (void *)line)) { fail("art_insert didn't return NULL"); } line++; } // Seek back to the start fseek(f, 0, SEEK_SET); // Search for each line line = 1; while (fgets(buf, sizeof buf, f)) { uintptr_t val; len = (int)strlen(buf); buf[len - 1] = '\0'; val = (uintptr_t)art_search(&t, (unsigned char *)buf, len); if (line != val) { fail("Line: %d Val: %" PRIuPTR " Str: %s\n", line, val, buf); } line++; } // Check the minimum l = art_minimum(&t); diag("minimum is %s", l->key); fail_unless( l && strcmp((char *)l->key, "00026bda-e0ea-4cda-8245-522764e9f325") == 0); // Check the maximum l = art_maximum(&t); diag("maximum is %s", l->key); fail_unless( l && strcmp((char *)l->key, "ffffcb46-a92e-4822-82af-a7190f9c1ec5") == 0); res = art_tree_destroy(&t); fail_unless(res == 0); }
void test_art_insert_search(void) { art_tree t; int res = art_tree_init(&t); int len; char buf[512]; FILE *f = fopen("thirdparty/libart/tests/words.txt", "r"); uintptr_t line = 1; art_leaf *l; fail_unless(res == 0); while (fgets(buf, sizeof buf, f)) { len = (int)strlen(buf); buf[len - 1] = '\0'; if (art_insert(&t, (unsigned char *)buf, len, (void *)line)) { fail("art_insert didn't return NULL"); } line++; } // Seek back to the start fseek(f, 0, SEEK_SET); // Search for each line line = 1; while (fgets(buf, sizeof buf, f)) { len = (int)strlen(buf); buf[len - 1] = '\0'; { uintptr_t val = (uintptr_t)art_search(&t, (unsigned char *)buf, len); if (line != val) { fail("Line: %d Val: %" PRIuPTR " Str: %s", line, val, buf); } } line++; } // Check the minimum l = art_minimum(&t); fail_unless(l && strcmp((char *)l->key, "A") == 0); // Check the maximum l = art_maximum(&t); fail_unless(l && strcmp((char *)l->key, "zythum") == 0); res = art_tree_destroy(&t); fail_unless(res == 0); }
END_TEST START_TEST(test_art_insert_search_uuid) { art_tree t; int res = art_tree_init(&t); fail_unless(res == 0); int len; char buf[512]; FILE *f = fopen("tests/uuid.txt", "r"); uintptr_t line = 1; while (fgets(buf, sizeof buf, f)) { len = strlen(buf); buf[len-1] = '\0'; fail_unless(NULL == art_insert(&t, (unsigned char*)buf, len, (void*)line)); line++; } // Seek back to the start fseek(f, 0, SEEK_SET); // Search for each line line = 1; while (fgets(buf, sizeof buf, f)) { len = strlen(buf); buf[len-1] = '\0'; uintptr_t val = (uintptr_t)art_search(&t, (unsigned char*)buf, len); fail_unless(line == val, "Line: %d Val: %" PRIuPTR " Str: %s\n", line, val, buf); line++; } // Check the minimum art_leaf *l = art_minimum(&t); fail_unless(l && strcmp((char*)l->key, "00026bda-e0ea-4cda-8245-522764e9f325") == 0); // Check the maximum l = art_maximum(&t); fail_unless(l && strcmp((char*)l->key, "ffffcb46-a92e-4822-82af-a7190f9c1ec5") == 0); res = art_tree_destroy(&t); fail_unless(res == 0); }
END_TEST START_TEST(test_art_insert_search) { art_tree t; int res = art_tree_init(&t); fail_unless(res == 0); int len; char buf[512]; FILE *f = fopen("tests/words.txt", "r"); uintptr_t line = 1; while (fgets(buf, sizeof buf, f)) { len = strlen(buf); buf[len-1] = '\0'; fail_unless(NULL == art_insert(&t, (unsigned char*)buf, len, (void*)line)); line++; } // Seek back to the start fseek(f, 0, SEEK_SET); // Search for each line line = 1; while (fgets(buf, sizeof buf, f)) { len = strlen(buf); buf[len-1] = '\0'; uintptr_t val = (uintptr_t)art_search(&t, (unsigned char*)buf, len); fail_unless(line == val, "Line: %d Val: %" PRIuPTR " Str: %s\n", line, val, buf); line++; } // Check the minimum art_leaf *l = art_minimum(&t); fail_unless(l && strcmp((char*)l->key, "A") == 0); // Check the maximum l = art_maximum(&t); fail_unless(l && strcmp((char*)l->key, "zythum") == 0); res = art_tree_destroy(&t); fail_unless(res == 0); }
int insert_element(struct ds_context *ctx) { PMEMobjpool *pop; int errors = 0; if (ctx == NULL) { errors++; } else if (ctx->pop == NULL) { errors++; } if (!errors) { pop = ctx->pop; art_insert(pop, ctx->key, ctx->key_len, ctx->value, ctx->val_len); } return errors; }
/** * Merges changes into the alternate tree from the delta lists * Safety: Safe ONLY if no other thread is using alt_filter_map */ static void merge_old_versions(bloom_filtmgr *mgr, filter_list *delta, unsigned long long min_vsn) { // Handle older delta first (bottom up) if (delta->next) merge_old_versions(mgr, delta->next, min_vsn); // Check if we should skip this update if (delta->vsn > min_vsn) return; // Handle current update bloom_filter_wrapper *s = delta->filter; switch (delta->type) { case CREATE: art_insert(mgr->alt_filter_map, (unsigned char*)s->filter->filter_name, strlen(s->filter->filter_name)+1, s); break; case DELETE: art_delete(mgr->alt_filter_map, (unsigned char*)s->filter->filter_name, strlen(s->filter->filter_name)+1); break; case BARRIER: // Ignore the barrier... break; } }
void test_art_insert(void) { art_tree t; int res = art_tree_init(&t); int len; char buf[512]; FILE *f = fopen("thirdparty/libart/tests/words.txt", "r"); uintptr_t line = 1; fail_unless(res == 0); while (fgets(buf, sizeof buf, f)) { len = (int)strlen(buf); buf[len - 1] = '\0'; if (art_insert(&t, (unsigned char *)buf, len, (void *)line)) { fail("insert should have returned NULL but did not"); } if (art_size(&t) != line) { fail("art_size didn't match current line no"); } line++; } res = art_tree_destroy(&t); fail_unless(res == 0); }
END_TEST START_TEST(test_art_insert) { art_tree t; int res = art_tree_init(&t); fail_unless(res == 0); int len; char buf[512]; FILE *f = fopen("tests/words.txt", "r"); uintptr_t line = 1; while (fgets(buf, sizeof buf, f)) { len = strlen(buf); buf[len-1] = '\0'; fail_unless(NULL == art_insert(&t, (unsigned char*)buf, len, (void*)line)); fail_unless(art_size(&t) == line); line++; } res = art_tree_destroy(&t); fail_unless(res == 0); }
void vio_dict_store(vio_dict *dict, const char *key, uint32_t klen, uint32_t val) { /* art_search() returns NULL if a value is not found. Since 0 is a valid index to store, add 1 to it. Note that this means we can actually only store 2^32-1 words. */ art_insert(&dict->words, (const unsigned char *)key, klen, (void *)(val + 1)); }
void test_art_iter_prefix(void) { art_tree t; int res = art_tree_init(&t); const char *s = "api.foo.bar"; const char *expected2[] = {"abc.123.456", "api", "api.foe.fum", "api.foo", "api.foo.bar", "api.foo.baz"}; fail_unless(res == 0); fail_unless(NULL == art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, NULL)); s = "api.foo.baz"; fail_unless(NULL == art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, NULL)); s = "api.foe.fum"; fail_unless(NULL == art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, NULL)); s = "abc.123.456"; fail_unless(NULL == art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, NULL)); s = "api.foo"; fail_unless(NULL == art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, NULL)); s = "api"; fail_unless(NULL == art_insert(&t, (unsigned char *)s, (int)strlen(s) + 1, NULL)); { // Iterate over api const char *expected[] = {"api", "api.foe.fum", "api.foo", "api.foo.bar", "api.foo.baz"}; prefix_data p = {0, 5, expected}; fail_unless( !art_iter_prefix(&t, (unsigned char *)"api", 3, test_prefix_cb, &p)); diag("Count: %d Max: %d", p.count, p.max_count); fail_unless(p.count == p.max_count); } { // Iterate over 'a' prefix_data p2 = {0, 6, expected2}; fail_unless( !art_iter_prefix(&t, (unsigned char *)"a", 1, test_prefix_cb, &p2)); fail_unless(p2.count == p2.max_count); } { // Check a failed iteration prefix_data p3 = {0, 0, NULL}; fail_unless( !art_iter_prefix(&t, (unsigned char *)"b", 1, test_prefix_cb, &p3)); fail_unless(p3.count == 0); } { // Iterate over api. const char *expected4[] = {"api.foe.fum", "api.foo", "api.foo.bar", "api.foo.baz"}; prefix_data p4 = {0, 4, expected4}; fail_unless( !art_iter_prefix(&t, (unsigned char *)"api.", 4, test_prefix_cb, &p4)); diag("Count: %d Max: %d", p4.count, p4.max_count); fail_unless(p4.count == p4.max_count); } { // Iterate over api.foo.ba const char *expected5[] = {"api.foo.bar"}; prefix_data p5 = {0, 1, expected5}; fail_unless(!art_iter_prefix(&t, (unsigned char *)"api.foo.bar", 11, test_prefix_cb, &p5)); diag("Count: %d Max: %d", p5.count, p5.max_count); fail_unless(p5.count == p5.max_count); } // Check a failed iteration on api.end { prefix_data p6 = {0, 0, NULL}; fail_unless(!art_iter_prefix(&t, (unsigned char *)"api.end", 7, test_prefix_cb, &p6)); fail_unless(p6.count == 0); } // Iterate over empty prefix { prefix_data p7 = {0, 6, expected2}; fail_unless( !art_iter_prefix(&t, (unsigned char *)"", 0, test_prefix_cb, &p7)); fail_unless(p7.count == p7.max_count); } res = art_tree_destroy(&t); fail_unless(res == 0); }