TEST_END TEST_BEGIN(test_hooks_expand_simple) { /* "Simple" in the sense that we're not in a realloc variant. */ hooks_t hooks = {NULL, NULL, &test_expand_hook, (void *)123}; void *handle = hook_install(TSDN_NULL, &hooks); assert_ptr_ne(handle, NULL, "Hook installation failed"); void *volatile ptr; /* xallocx() */ reset(); ptr = malloc(1); size_t new_usize = xallocx(ptr, 100, 200, MALLOCX_TCACHE_NONE); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, (int)hook_expand_xallocx, "Wrong hook type"); assert_ptr_eq(ptr, arg_address, "Wrong pointer expanded"); assert_u64_eq(arg_old_usize, nallocx(1, 0), "Wrong old usize"); assert_u64_eq(arg_new_usize, sallocx(ptr, 0), "Wrong new usize"); assert_u64_eq(new_usize, arg_result_raw, "Wrong result"); assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong arg"); assert_u64_eq(100, arg_args_raw[1], "Wrong arg"); assert_u64_eq(200, arg_args_raw[2], "Wrong arg"); assert_u64_eq(MALLOCX_TCACHE_NONE, arg_args_raw[3], "Wrong arg"); hook_remove(TSDN_NULL, handle); }
TEST_END TEST_BEGIN(test_rtree_extrema) { unsigned i; extent_node_t node_a, node_b; for (i = 1; i <= (sizeof(uintptr_t) << 3); i++) { rtree_t rtree; assert_false(rtree_new(&rtree, i, node_alloc, node_dalloc), "Unexpected rtree_new() failure"); assert_false(rtree_set(&rtree, 0, &node_a), "Unexpected rtree_set() failure"); assert_ptr_eq(rtree_get(&rtree, 0, true), &node_a, "rtree_get() should return previously set value"); assert_false(rtree_set(&rtree, ~((uintptr_t)0), &node_b), "Unexpected rtree_set() failure"); assert_ptr_eq(rtree_get(&rtree, ~((uintptr_t)0), true), &node_b, "rtree_get() should return previously set value"); rtree_delete(&rtree); } }
static void test_iterate (void) { p11_dict *map; p11_dictiter iter; int key = 1; int value = 2; void *pkey; void *pvalue; int ret; map = p11_dict_new (p11_dict_direct_hash, p11_dict_direct_equal, NULL, NULL); assert_ptr_not_null (map); if (!p11_dict_set (map, &key, &value)) assert_not_reached (); p11_dict_iterate (map, &iter); ret = p11_dict_next (&iter, &pkey, &pvalue); assert_num_eq (1, ret); assert_ptr_eq (pkey, &key); assert_ptr_eq (pvalue, &value); ret = p11_dict_next (&iter, &pkey, &pvalue); assert_num_eq (0, ret); p11_dict_free (map); }
static void test_junk(size_t sz_min, size_t sz_max) { char *s; size_t sz_prev, sz, i; arena_dalloc_junk_small_orig = arena_dalloc_junk_small; arena_dalloc_junk_small = arena_dalloc_junk_small_intercept; arena_dalloc_junk_large_orig = arena_dalloc_junk_large; arena_dalloc_junk_large = arena_dalloc_junk_large_intercept; huge_dalloc_junk_orig = huge_dalloc_junk; huge_dalloc_junk = huge_dalloc_junk_intercept; sz_prev = 0; s = (char *)mallocx(sz_min, 0); assert_ptr_not_null((void *)s, "Unexpected mallocx() failure"); for (sz = sallocx(s, 0); sz <= sz_max; sz_prev = sz, sz = sallocx(s, 0)) { if (sz_prev > 0) { assert_c_eq(s[0], 'a', "Previously allocated byte %zu/%zu is corrupted", ZU(0), sz_prev); assert_c_eq(s[sz_prev-1], 'a', "Previously allocated byte %zu/%zu is corrupted", sz_prev-1, sz_prev); } for (i = sz_prev; i < sz; i++) { assert_c_eq(s[i], 0xa5, "Newly allocated byte %zu/%zu isn't junk-filled", i, sz); s[i] = 'a'; } if (xallocx(s, sz+1, 0, 0) == sz) { void *junked = (void *)s; s = (char *)rallocx(s, sz+1, 0); assert_ptr_not_null((void *)s, "Unexpected rallocx() failure"); if (!config_mremap || sz+1 <= arena_maxclass) { assert_ptr_eq(most_recently_junked, junked, "Expected region of size %zu to be " "junk-filled", sz); } } } dallocx(s, 0); assert_ptr_eq(most_recently_junked, (void *)s, "Expected region of size %zu to be junk-filled", sz); arena_dalloc_junk_small = arena_dalloc_junk_small_orig; arena_dalloc_junk_large = arena_dalloc_junk_large_orig; huge_dalloc_junk = huge_dalloc_junk_orig; }
static void test_uri_get_set_attribute (void) { CK_ATTRIBUTE attr; CK_ATTRIBUTE_PTR ptr; P11KitUri *uri; int ret; uri = p11_kit_uri_new (); assert_ptr_not_null (uri); ptr = p11_kit_uri_get_attribute (uri, CKA_LABEL); assert_ptr_eq (NULL, ptr); ret = p11_kit_uri_clear_attribute (uri, CKA_LABEL); assert_num_eq (P11_KIT_URI_OK, ret); ret = p11_kit_uri_clear_attribute (uri, CKA_COLOR); assert_num_eq (P11_KIT_URI_NOT_FOUND, ret); attr.type = CKA_LABEL; attr.pValue = "Test"; attr.ulValueLen = 4; ret = p11_kit_uri_set_attribute (uri, &attr); assert_num_eq (P11_KIT_URI_OK, ret); /* We can set other attributes */ attr.type = CKA_COLOR; ret = p11_kit_uri_set_attribute (uri, &attr); assert_num_eq (P11_KIT_URI_OK, ret); /* And get them too */ ptr = p11_kit_uri_get_attribute (uri, CKA_COLOR); assert_ptr_not_null (ptr); ptr = p11_kit_uri_get_attribute (uri, CKA_LABEL); assert_ptr_not_null (ptr); assert (ptr->type == CKA_LABEL); assert (ptr->ulValueLen == 4); assert (memcmp (ptr->pValue, "Test", 4) == 0); ret = p11_kit_uri_clear_attribute (uri, CKA_LABEL); assert_num_eq (P11_KIT_URI_OK, ret); ptr = p11_kit_uri_get_attribute (uri, CKA_LABEL); assert_ptr_eq (NULL, ptr); p11_kit_uri_free (uri); }
static void test_iterate_remove (void) { p11_dict *map; p11_dictiter iter; char *keys[] = { "111", "222", "333" }; char *values[] = { "444", "555", "666" }; void *okeys[3]; void *ovalues[3]; bool ret; int i; map = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, NULL, NULL); assert_ptr_not_null (map); for (i = 0; i < 3; i++) { if (!p11_dict_set (map, keys[i], values[i])) assert_not_reached (); } p11_dict_iterate (map, &iter); ret = p11_dict_next (&iter, &okeys[0], &ovalues[0]); assert_num_eq (true, ret); ret = p11_dict_next (&iter, &okeys[1], &ovalues[1]); assert_num_eq (true, ret); if (!p11_dict_remove (map, okeys[1])) assert_not_reached (); ret = p11_dict_next (&iter, &okeys[2], &ovalues[2]); assert_num_eq (true, ret); ret = p11_dict_next (&iter, NULL, NULL); assert_num_eq (false, ret); assert_num_eq (2, p11_dict_size (map)); p11_dict_free (map); qsort (okeys, 3, sizeof (void *), compar_strings); qsort (ovalues, 3, sizeof (void *), compar_strings); for (i = 0; i < 3; i++) { assert_str_eq (keys[i], okeys[i]); assert_ptr_eq (keys[i], okeys[i]); assert_str_eq (values[i], ovalues[i]); assert_ptr_eq (values[i], ovalues[i]); } }
TEST_END TEST_BEGIN(test_rtree_random) { unsigned i; sfmt_t *sfmt; #define NSET 16 #define SEED 42 sfmt = init_gen_rand(SEED); for (i = 1; i <= (sizeof(uintptr_t) << 3); i++) { uintptr_t keys[NSET]; extent_node_t node; unsigned j; rtree_t rtree; assert_false(rtree_new(&rtree, i, node_alloc, node_dalloc), "Unexpected rtree_new() failure"); for (j = 0; j < NSET; j++) { keys[j] = (uintptr_t)gen_rand64(sfmt); assert_false(rtree_set(&rtree, keys[j], &node), "Unexpected rtree_set() failure"); assert_ptr_eq(rtree_get(&rtree, keys[j], true), &node, "rtree_get() should return previously set value"); } for (j = 0; j < NSET; j++) { assert_ptr_eq(rtree_get(&rtree, keys[j], true), &node, "rtree_get() should return previously set value"); } for (j = 0; j < NSET; j++) { assert_false(rtree_set(&rtree, keys[j], NULL), "Unexpected rtree_set() failure"); assert_ptr_null(rtree_get(&rtree, keys[j], true), "rtree_get() should return previously set value"); } for (j = 0; j < NSET; j++) { assert_ptr_null(rtree_get(&rtree, keys[j], true), "rtree_get() should return previously set value"); } rtree_delete(&rtree); } fini_gen_rand(sfmt); #undef NSET #undef SEED }
static void test_set_get_remove (void) { char *key = "KEY"; char *value = "VALUE"; char *check; p11_dict *map; bool ret; map = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, NULL, NULL); if (!p11_dict_set (map, key, value)) assert_not_reached (); check = p11_dict_get (map, key); assert_ptr_eq (check, value); ret = p11_dict_remove (map, key); assert_num_eq (true, ret); ret = p11_dict_remove (map, key); assert_num_eq (false, ret); check = p11_dict_get (map, key); assert (check == NULL); p11_dict_free (map); }
END_TEST START_TEST (document_type) { reset_errno(); size_t c = model_size(model); assert_noerr(); assert_uint_eq(1, c); reset_errno(); Document *d = model_document(model, 0); assert_noerr(); assert_not_null(d); reset_errno(); Node *bogus = model_document(model, 1); assert_errno(EINVAL); assert_null(bogus); reset_errno(); Node *r1 = model_document_root(model, 0); assert_noerr(); assert_not_null(r1); assert_node_kind(r1, MAPPING); reset_errno(); Node *r2 = document_root(d); assert_noerr(); assert_not_null(r2); assert_ptr_eq(r1, r2); }
static void test_set_get (void) { char *key = "KEY"; char *value = "VALUE"; char *check; p11_dict *map; map = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, NULL, NULL); p11_dict_set (map, key, value); check = p11_dict_get (map, key); assert_ptr_eq (check, value); p11_dict_free (map); }
static void test_uri_parse_parse_unknown_object_type (void) { P11KitUri *uri; CK_ATTRIBUTE_PTR attr; int ret; uri = p11_kit_uri_new (); assert_ptr_not_null (uri); ret = p11_kit_uri_parse ("pkcs11:type=unknown", P11_KIT_URI_FOR_OBJECT, uri); assert_num_eq (P11_KIT_URI_OK, ret); attr = p11_kit_uri_get_attribute (uri, CKA_CLASS); assert_ptr_eq (NULL, attr); p11_kit_uri_free (uri); }
TEST_END TEST_BEGIN(test_no_move_fail) { void *p, *q; size_t sz, tsz; assert_d_eq(allocm(&p, &sz, 42, 0), ALLOCM_SUCCESS, "Unexpected allocm() error"); q = p; assert_d_eq(rallocm(&q, &tsz, sz + 5, 0, ALLOCM_NO_MOVE), ALLOCM_ERR_NOT_MOVED, "Unexpected rallocm() result"); assert_ptr_eq(q, p, "Unexpected object move"); assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz); assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS, "Unexpected dallocm() error"); }
TEST_END TEST_BEGIN(test_hooks_realloc_as_malloc_or_free) { hooks_t hooks = {&test_alloc_hook, &test_dalloc_hook, &test_expand_hook, (void *)123}; void *handle = hook_install(TSDN_NULL, &hooks); assert_ptr_ne(handle, NULL, "Hook installation failed"); void *volatile ptr; /* realloc(NULL, size) as malloc */ reset(); ptr = realloc(NULL, 1); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, (int)hook_alloc_realloc, "Wrong hook type"); assert_ptr_eq(ptr, arg_result, "Wrong result"); assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, "Wrong raw result"); assert_u64_eq((uintptr_t)NULL, arg_args_raw[0], "Wrong argument"); assert_u64_eq((uintptr_t)1, arg_args_raw[1], "Wrong argument"); free(ptr); /* realloc(ptr, 0) as free */ ptr = malloc(1); reset(); realloc(ptr, 0); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, (int)hook_dalloc_realloc, "Wrong hook type"); assert_ptr_eq(ptr, arg_address, "Wrong pointer freed"); assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong raw arg"); assert_u64_eq((uintptr_t)0, arg_args_raw[1], "Wrong raw arg"); /* realloc(NULL, 0) as malloc(0) */ reset(); ptr = realloc(NULL, 0); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, (int)hook_alloc_realloc, "Wrong hook type"); assert_ptr_eq(ptr, arg_result, "Wrong result"); assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, "Wrong raw result"); assert_u64_eq((uintptr_t)NULL, arg_args_raw[0], "Wrong argument"); assert_u64_eq((uintptr_t)0, arg_args_raw[1], "Wrong argument"); free(ptr); hook_remove(TSDN_NULL, handle); }
TEST_END TEST_BEGIN(test_hooks_dalloc_simple) { /* "Simple" in the sense that we're not in a realloc variant. */ hooks_t hooks = {NULL, &test_dalloc_hook, NULL, (void *)123}; void *handle = hook_install(TSDN_NULL, &hooks); assert_ptr_ne(handle, NULL, "Hook installation failed"); void *volatile ptr; /* free() */ reset(); ptr = malloc(1); free(ptr); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, (int)hook_dalloc_free, "Wrong hook type"); assert_ptr_eq(ptr, arg_address, "Wrong pointer freed"); assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong raw arg"); /* dallocx() */ reset(); ptr = malloc(1); dallocx(ptr, MALLOCX_TCACHE_NONE); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, (int)hook_dalloc_dallocx, "Wrong hook type"); assert_ptr_eq(ptr, arg_address, "Wrong pointer freed"); assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong raw arg"); assert_u64_eq((uintptr_t)MALLOCX_TCACHE_NONE, arg_args_raw[1], "Wrong raw arg"); /* sdallocx() */ reset(); ptr = malloc(1); sdallocx(ptr, 1, MALLOCX_TCACHE_NONE); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, (int)hook_dalloc_sdallocx, "Wrong hook type"); assert_ptr_eq(ptr, arg_address, "Wrong pointer freed"); assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong raw arg"); assert_u64_eq((uintptr_t)1, arg_args_raw[1], "Wrong raw arg"); assert_u64_eq((uintptr_t)MALLOCX_TCACHE_NONE, arg_args_raw[2], "Wrong raw arg"); hook_remove(TSDN_NULL, handle); }
TEST_END TEST_BEGIN(test_tcache_none) { test_skip_if(!opt_tcache); /* Allocate p and q. */ void *p0 = mallocx(42, 0); assert_ptr_not_null(p0, "Unexpected mallocx() failure"); void *q = mallocx(42, 0); assert_ptr_not_null(q, "Unexpected mallocx() failure"); /* Deallocate p and q, but bypass the tcache for q. */ dallocx(p0, 0); dallocx(q, MALLOCX_TCACHE_NONE); /* Make sure that tcache-based allocation returns p, not q. */ void *p1 = mallocx(42, 0); assert_ptr_not_null(p1, "Unexpected mallocx() failure"); assert_ptr_eq(p0, p1, "Expected tcache to allocate cached region"); /* Clean up. */ dallocx(p1, MALLOCX_TCACHE_NONE); }
TEST_END TEST_BEGIN(test_rtree_bits) { unsigned i, j, k; for (i = 1; i < (sizeof(uintptr_t) << 3); i++) { uintptr_t keys[] = {0, 1, (((uintptr_t)1) << (sizeof(uintptr_t)*8-i)) - 1}; extent_node_t node; rtree_t rtree; assert_false(rtree_new(&rtree, i, node_alloc, node_dalloc), "Unexpected rtree_new() failure"); for (j = 0; j < sizeof(keys)/sizeof(uintptr_t); j++) { assert_false(rtree_set(&rtree, keys[j], &node), "Unexpected rtree_set() failure"); for (k = 0; k < sizeof(keys)/sizeof(uintptr_t); k++) { assert_ptr_eq(rtree_get(&rtree, keys[k], true), &node, "rtree_get() should return " "previously set value and ignore " "insignificant key bits; i=%u, j=%u, k=%u, " "set key=%#"FMTxPTR", get key=%#"FMTxPTR, i, j, k, keys[j], keys[k]); } assert_ptr_null(rtree_get(&rtree, (((uintptr_t)1) << (sizeof(uintptr_t)*8-i)), false), "Only leftmost rtree leaf should be set; " "i=%u, j=%u", i, j); assert_false(rtree_set(&rtree, keys[j], NULL), "Unexpected rtree_set() failure"); } rtree_delete(&rtree); } }
static void test_get_function_list (void) { CK_FUNCTION_LIST_PTR module; CK_FUNCTION_LIST_PTR list; p11_virtual virt; CK_RV rv; p11_virtual_init (&virt, &p11_virtual_base, &mock_x_module_no_slots, NULL); module = p11_virtual_wrap (&virt, NULL); assert_ptr_not_null (module); rv = (module->C_GetFunctionList) (&list); assert_num_eq (CKR_OK, rv); assert_ptr_eq (module, list); rv = (module->C_GetFunctionList) (&list); assert_num_eq (CKR_OK, rv); rv = (module->C_GetFunctionList) (NULL); assert_num_eq (CKR_ARGUMENTS_BAD, rv); p11_virtual_unwrap (module); }
static void test_fall_through (void) { CK_FUNCTION_LIST_PTR module; Override over = { }; p11_virtual base; CK_RV rv; p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL); p11_virtual_init (&over.virt, &p11_virtual_stack, &base, NULL); over.virt.funcs.C_Initialize = override_initialize; over.check = "overide-arg"; module = p11_virtual_wrap (&over.virt, NULL); assert_ptr_not_null (module); rv = (module->C_Initialize) ("initialize-arg"); assert_num_eq (CKR_NEED_TO_CREATE_THREADS, rv); /* All other functiosn should have just fallen through */ assert_ptr_eq (mock_module_no_slots.C_Finalize, module->C_Finalize); p11_virtual_unwrap (module); }
void * thd_start(void *arg) { int err; void *p; uint64_t a0, a1, d0, d1; uint64_t *ap0, *ap1, *dp0, *dp1; size_t sz, usize; sz = sizeof(a0); if ((err = mallctl("thread.allocated", &a0, &sz, NULL, 0))) { if (err == ENOENT) goto label_ENOENT; test_fail("%s(): Error in mallctl(): %s", __func__, strerror(err)); } sz = sizeof(ap0); if ((err = mallctl("thread.allocatedp", &ap0, &sz, NULL, 0))) { if (err == ENOENT) goto label_ENOENT; test_fail("%s(): Error in mallctl(): %s", __func__, strerror(err)); } assert_u64_eq(*ap0, a0, "\"thread.allocatedp\" should provide a pointer to internal " "storage"); sz = sizeof(d0); if ((err = mallctl("thread.deallocated", &d0, &sz, NULL, 0))) { if (err == ENOENT) goto label_ENOENT; test_fail("%s(): Error in mallctl(): %s", __func__, strerror(err)); } sz = sizeof(dp0); if ((err = mallctl("thread.deallocatedp", &dp0, &sz, NULL, 0))) { if (err == ENOENT) goto label_ENOENT; test_fail("%s(): Error in mallctl(): %s", __func__, strerror(err)); } assert_u64_eq(*dp0, d0, "\"thread.deallocatedp\" should provide a pointer to internal " "storage"); p = malloc(1); assert_ptr_not_null(p, "Unexpected malloc() error"); sz = sizeof(a1); mallctl("thread.allocated", &a1, &sz, NULL, 0); sz = sizeof(ap1); mallctl("thread.allocatedp", &ap1, &sz, NULL, 0); assert_u64_eq(*ap1, a1, "Dereferenced \"thread.allocatedp\" value should equal " "\"thread.allocated\" value"); assert_ptr_eq(ap0, ap1, "Pointer returned by \"thread.allocatedp\" should not change"); usize = malloc_usable_size(p); assert_u64_le(a0 + usize, a1, "Allocated memory counter should increase by at least the amount " "explicitly allocated"); free(p); sz = sizeof(d1); mallctl("thread.deallocated", &d1, &sz, NULL, 0); sz = sizeof(dp1); mallctl("thread.deallocatedp", &dp1, &sz, NULL, 0); assert_u64_eq(*dp1, d1, "Dereferenced \"thread.deallocatedp\" value should equal " "\"thread.deallocated\" value"); assert_ptr_eq(dp0, dp1, "Pointer returned by \"thread.deallocatedp\" should not change"); assert_u64_le(d0 + usize, d1, "Deallocated memory counter should increase by at least the amount " "explicitly deallocated"); return (NULL); label_ENOENT: assert_false(config_stats, "ENOENT should only be returned if stats are disabled"); test_skip("\"thread.allocated\" mallctl not available"); return (NULL); }
TEST_END static void do_realloc_test(void *(*ralloc)(void *, size_t, int), int flags, int expand_type, int dalloc_type) { hooks_t hooks = {&test_alloc_hook, &test_dalloc_hook, &test_expand_hook, (void *)123}; void *handle = hook_install(TSDN_NULL, &hooks); assert_ptr_ne(handle, NULL, "Hook installation failed"); void *volatile ptr; void *volatile ptr2; /* Realloc in-place, small. */ ptr = malloc(129); reset(); ptr2 = ralloc(ptr, 130, flags); assert_ptr_eq(ptr, ptr2, "Small realloc moved"); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, expand_type, "Wrong hook type"); assert_ptr_eq(ptr, arg_address, "Wrong address"); assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, "Wrong raw result"); assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong argument"); assert_u64_eq((uintptr_t)130, arg_args_raw[1], "Wrong argument"); free(ptr); /* * Realloc in-place, large. Since we can't guarantee the large case * across all platforms, we stay resilient to moving results. */ ptr = malloc(2 * 1024 * 1024); free(ptr); ptr2 = malloc(1 * 1024 * 1024); reset(); ptr = ralloc(ptr2, 2 * 1024 * 1024, flags); /* ptr is the new address, ptr2 is the old address. */ if (ptr == ptr2) { assert_d_eq(call_count, 1, "Hook not called"); assert_d_eq(arg_type, expand_type, "Wrong hook type"); } else { assert_d_eq(call_count, 2, "Wrong hooks called"); assert_ptr_eq(ptr, arg_result, "Wrong address"); assert_d_eq(arg_type, dalloc_type, "Wrong hook type"); } assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_ptr_eq(ptr2, arg_address, "Wrong address"); assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, "Wrong raw result"); assert_u64_eq((uintptr_t)ptr2, arg_args_raw[0], "Wrong argument"); assert_u64_eq((uintptr_t)2 * 1024 * 1024, arg_args_raw[1], "Wrong argument"); free(ptr); /* Realloc with move, small. */ ptr = malloc(8); reset(); ptr2 = ralloc(ptr, 128, flags); assert_ptr_ne(ptr, ptr2, "Small realloc didn't move"); assert_d_eq(call_count, 2, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, dalloc_type, "Wrong hook type"); assert_ptr_eq(ptr, arg_address, "Wrong address"); assert_ptr_eq(ptr2, arg_result, "Wrong address"); assert_u64_eq((uintptr_t)ptr2, (uintptr_t)arg_result_raw, "Wrong raw result"); assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong argument"); assert_u64_eq((uintptr_t)128, arg_args_raw[1], "Wrong argument"); free(ptr2); /* Realloc with move, large. */ ptr = malloc(1); reset(); ptr2 = ralloc(ptr, 2 * 1024 * 1024, flags); assert_ptr_ne(ptr, ptr2, "Large realloc didn't move"); assert_d_eq(call_count, 2, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, dalloc_type, "Wrong hook type"); assert_ptr_eq(ptr, arg_address, "Wrong address"); assert_ptr_eq(ptr2, arg_result, "Wrong address"); assert_u64_eq((uintptr_t)ptr2, (uintptr_t)arg_result_raw, "Wrong raw result"); assert_u64_eq((uintptr_t)ptr, arg_args_raw[0], "Wrong argument"); assert_u64_eq((uintptr_t)2 * 1024 * 1024, arg_args_raw[1], "Wrong argument"); free(ptr2); hook_remove(TSDN_NULL, handle); }
END_TEST START_TEST (sequence_type) { reset_errno(); Node *r = model_document_root(model, 0); assert_noerr(); assert_not_null(r); assert_node_kind(r, MAPPING); reset_errno(); Node *s = mapping_get(mapping(r), (uint8_t *)"one", 3ul); assert_noerr(); assert_not_null(s); assert_node_kind(s, SEQUENCE); assert_node_size(s, 2); reset_errno(); Node *zero = sequence_get(sequence(s), 0); assert_noerr(); assert_not_null(zero); assert_node_kind(zero, SCALAR); reset_errno(); Node *one = sequence_get(sequence(s), 1); assert_noerr(); assert_not_null(one); assert_node_kind(one, SCALAR); reset_errno(); Scalar *x = make_scalar_node((uint8_t *)"x", 1, SCALAR_STRING); assert_noerr(); assert_not_null(x); reset_errno(); Scalar *y = make_scalar_node((uint8_t *)"y", 1, SCALAR_STRING); assert_noerr(); assert_not_null(y); reset_errno(); Scalar *z = make_scalar_node((uint8_t *)"z", 1, SCALAR_STRING); assert_noerr(); assert_not_null(z); reset_errno(); Sequence *xyz = make_sequence_node(); assert_noerr(); assert_not_null(xyz); reset_errno(); sequence_add(xyz, node(x)); assert_noerr(); reset_errno(); sequence_add(xyz, node(y)); assert_noerr(); reset_errno(); sequence_add(xyz, node(z)); assert_noerr(); assert_uint_eq(3, node_size(node(xyz))); assert_ptr_eq(node(x), sequence_get(xyz, 0)); assert_ptr_eq(node(y), sequence_get(xyz, 1)); assert_ptr_eq(node(z), sequence_get(xyz, 2)); node_free(node(xyz)); }
TEST_END TEST_BEGIN(test_insert_iter_remove) { #define NITEMS ZU(1000) tsd_t *tsd; ckh_t ckh; void **p[NITEMS]; void *q, *r; size_t i; tsd = tsd_fetch(); assert_false(ckh_new(tsd, &ckh, 2, ckh_pointer_hash, ckh_pointer_keycomp), "Unexpected ckh_new() error"); for (i = 0; i < NITEMS; i++) { p[i] = mallocx(i+1, 0); assert_ptr_not_null(p[i], "Unexpected mallocx() failure"); } for (i = 0; i < NITEMS; i++) { size_t j; for (j = i; j < NITEMS; j++) { assert_false(ckh_insert(tsd, &ckh, p[j], p[j]), "Unexpected ckh_insert() failure"); assert_false(ckh_search(&ckh, p[j], &q, &r), "Unexpected ckh_search() failure"); assert_ptr_eq(p[j], q, "Key pointer mismatch"); assert_ptr_eq(p[j], r, "Value pointer mismatch"); } assert_zu_eq(ckh_count(&ckh), NITEMS, "ckh_count() should return %zu, but it returned %zu", NITEMS, ckh_count(&ckh)); for (j = i + 1; j < NITEMS; j++) { assert_false(ckh_search(&ckh, p[j], NULL, NULL), "Unexpected ckh_search() failure"); assert_false(ckh_remove(tsd, &ckh, p[j], &q, &r), "Unexpected ckh_remove() failure"); assert_ptr_eq(p[j], q, "Key pointer mismatch"); assert_ptr_eq(p[j], r, "Value pointer mismatch"); assert_true(ckh_search(&ckh, p[j], NULL, NULL), "Unexpected ckh_search() success"); assert_true(ckh_remove(tsd, &ckh, p[j], &q, &r), "Unexpected ckh_remove() success"); } { bool seen[NITEMS]; size_t tabind; memset(seen, 0, sizeof(seen)); for (tabind = 0; !ckh_iter(&ckh, &tabind, &q, &r);) { size_t k; assert_ptr_eq(q, r, "Key and val not equal"); for (k = 0; k < NITEMS; k++) { if (p[k] == q) { assert_false(seen[k], "Item %zu already seen", k); seen[k] = true; break; } } } for (j = 0; j < i + 1; j++) assert_true(seen[j], "Item %zu not seen", j); for (; j < NITEMS; j++) assert_false(seen[j], "Item %zu seen", j); } } for (i = 0; i < NITEMS; i++) { assert_false(ckh_search(&ckh, p[i], NULL, NULL), "Unexpected ckh_search() failure"); assert_false(ckh_remove(tsd, &ckh, p[i], &q, &r), "Unexpected ckh_remove() failure"); assert_ptr_eq(p[i], q, "Key pointer mismatch"); assert_ptr_eq(p[i], r, "Value pointer mismatch"); assert_true(ckh_search(&ckh, p[i], NULL, NULL), "Unexpected ckh_search() success"); assert_true(ckh_remove(tsd, &ckh, p[i], &q, &r), "Unexpected ckh_remove() success"); dallocx(p[i], 0); } assert_zu_eq(ckh_count(&ckh), 0, "ckh_count() should return %zu, but it returned %zu", ZU(0), ckh_count(&ckh)); ckh_delete(tsd, &ckh); #undef NITEMS }
TEST_END TEST_BEGIN(test_hooks_alloc_simple) { /* "Simple" in the sense that we're not in a realloc variant. */ hooks_t hooks = {&test_alloc_hook, NULL, NULL, (void *)123}; void *handle = hook_install(TSDN_NULL, &hooks); assert_ptr_ne(handle, NULL, "Hook installation failed"); /* Stop malloc from being optimized away. */ volatile int err; void *volatile ptr; /* malloc */ reset(); ptr = malloc(1); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, (int)hook_alloc_malloc, "Wrong hook type"); assert_ptr_eq(ptr, arg_result, "Wrong result"); assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, "Wrong raw result"); assert_u64_eq((uintptr_t)1, arg_args_raw[0], "Wrong argument"); free(ptr); /* posix_memalign */ reset(); err = posix_memalign((void **)&ptr, 1024, 1); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, (int)hook_alloc_posix_memalign, "Wrong hook type"); assert_ptr_eq(ptr, arg_result, "Wrong result"); assert_u64_eq((uintptr_t)err, (uintptr_t)arg_result_raw, "Wrong raw result"); assert_u64_eq((uintptr_t)&ptr, arg_args_raw[0], "Wrong argument"); assert_u64_eq((uintptr_t)1024, arg_args_raw[1], "Wrong argument"); assert_u64_eq((uintptr_t)1, arg_args_raw[2], "Wrong argument"); free(ptr); /* aligned_alloc */ reset(); ptr = aligned_alloc(1024, 1); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, (int)hook_alloc_aligned_alloc, "Wrong hook type"); assert_ptr_eq(ptr, arg_result, "Wrong result"); assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, "Wrong raw result"); assert_u64_eq((uintptr_t)1024, arg_args_raw[0], "Wrong argument"); assert_u64_eq((uintptr_t)1, arg_args_raw[1], "Wrong argument"); free(ptr); /* calloc */ reset(); ptr = calloc(11, 13); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, (int)hook_alloc_calloc, "Wrong hook type"); assert_ptr_eq(ptr, arg_result, "Wrong result"); assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, "Wrong raw result"); assert_u64_eq((uintptr_t)11, arg_args_raw[0], "Wrong argument"); assert_u64_eq((uintptr_t)13, arg_args_raw[1], "Wrong argument"); free(ptr); /* memalign */ #ifdef JEMALLOC_OVERRIDE_MEMALIGN reset(); ptr = memalign(1024, 1); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, (int)hook_alloc_memalign, "Wrong hook type"); assert_ptr_eq(ptr, arg_result, "Wrong result"); assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, "Wrong raw result"); assert_u64_eq((uintptr_t)1024, arg_args_raw[0], "Wrong argument"); assert_u64_eq((uintptr_t)1, arg_args_raw[1], "Wrong argument"); free(ptr); #endif /* JEMALLOC_OVERRIDE_MEMALIGN */ /* valloc */ #ifdef JEMALLOC_OVERRIDE_VALLOC reset(); ptr = valloc(1); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, (int)hook_alloc_valloc, "Wrong hook type"); assert_ptr_eq(ptr, arg_result, "Wrong result"); assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, "Wrong raw result"); assert_u64_eq((uintptr_t)1, arg_args_raw[0], "Wrong argument"); free(ptr); #endif /* JEMALLOC_OVERRIDE_VALLOC */ /* mallocx */ reset(); ptr = mallocx(1, MALLOCX_LG_ALIGN(10)); assert_d_eq(call_count, 1, "Hook not called"); assert_ptr_eq(arg_extra, (void *)123, "Wrong extra"); assert_d_eq(arg_type, (int)hook_alloc_mallocx, "Wrong hook type"); assert_ptr_eq(ptr, arg_result, "Wrong result"); assert_u64_eq((uintptr_t)ptr, (uintptr_t)arg_result_raw, "Wrong raw result"); assert_u64_eq((uintptr_t)1, arg_args_raw[0], "Wrong argument"); assert_u64_eq((uintptr_t)MALLOCX_LG_ALIGN(10), arg_args_raw[1], "Wrong flags"); free(ptr); hook_remove(TSDN_NULL, handle); }
TEST_END TEST_BEGIN(test_count_insert_search_remove) { tsd_t *tsd; ckh_t ckh; const char *strs[] = { "a string", "A string", "a string.", "A string." }; const char *missing = "A string not in the hash table."; size_t i; tsd = tsd_fetch(); assert_false(ckh_new(tsd, &ckh, 2, ckh_string_hash, ckh_string_keycomp), "Unexpected ckh_new() error"); assert_zu_eq(ckh_count(&ckh), 0, "ckh_count() should return %zu, but it returned %zu", ZU(0), ckh_count(&ckh)); /* Insert. */ for (i = 0; i < sizeof(strs)/sizeof(const char *); i++) { ckh_insert(tsd, &ckh, strs[i], strs[i]); assert_zu_eq(ckh_count(&ckh), i+1, "ckh_count() should return %zu, but it returned %zu", i+1, ckh_count(&ckh)); } /* Search. */ for (i = 0; i < sizeof(strs)/sizeof(const char *); i++) { union { void *p; const char *s; } k, v; void **kp, **vp; const char *ks, *vs; kp = (i & 1) ? &k.p : NULL; vp = (i & 2) ? &v.p : NULL; k.p = NULL; v.p = NULL; assert_false(ckh_search(&ckh, strs[i], kp, vp), "Unexpected ckh_search() error"); ks = (i & 1) ? strs[i] : (const char *)NULL; vs = (i & 2) ? strs[i] : (const char *)NULL; assert_ptr_eq((void *)ks, (void *)k.s, "Key mismatch, i=%zu", i); assert_ptr_eq((void *)vs, (void *)v.s, "Value mismatch, i=%zu", i); } assert_true(ckh_search(&ckh, missing, NULL, NULL), "Unexpected ckh_search() success"); /* Remove. */ for (i = 0; i < sizeof(strs)/sizeof(const char *); i++) { union { void *p; const char *s; } k, v; void **kp, **vp; const char *ks, *vs; kp = (i & 1) ? &k.p : NULL; vp = (i & 2) ? &v.p : NULL; k.p = NULL; v.p = NULL; assert_false(ckh_remove(tsd, &ckh, strs[i], kp, vp), "Unexpected ckh_remove() error"); ks = (i & 1) ? strs[i] : (const char *)NULL; vs = (i & 2) ? strs[i] : (const char *)NULL; assert_ptr_eq((void *)ks, (void *)k.s, "Key mismatch, i=%zu", i); assert_ptr_eq((void *)vs, (void *)v.s, "Value mismatch, i=%zu", i); assert_zu_eq(ckh_count(&ckh), sizeof(strs)/sizeof(const char *) - i - 1, "ckh_count() should return %zu, but it returned %zu", sizeof(strs)/sizeof(const char *) - i - 1, ckh_count(&ckh)); } ckh_delete(tsd, &ckh); }
TEST_END TEST_BEGIN(test_tcache) { #define NTCACHES 10 unsigned tis[NTCACHES]; void *ps[NTCACHES]; void *qs[NTCACHES]; unsigned i; size_t sz, psz, qsz; psz = 42; qsz = nallocx(psz, 0) + 1; /* Create tcaches. */ for (i = 0; i < NTCACHES; i++) { sz = sizeof(unsigned); assert_d_eq(mallctl("tcache.create", (void *)&tis[i], &sz, NULL, 0), 0, "Unexpected mallctl() failure, i=%u", i); } /* Exercise tcache ID recycling. */ for (i = 0; i < NTCACHES; i++) { assert_d_eq(mallctl("tcache.destroy", NULL, NULL, (void *)&tis[i], sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u", i); } for (i = 0; i < NTCACHES; i++) { sz = sizeof(unsigned); assert_d_eq(mallctl("tcache.create", (void *)&tis[i], &sz, NULL, 0), 0, "Unexpected mallctl() failure, i=%u", i); } /* Flush empty tcaches. */ for (i = 0; i < NTCACHES; i++) { assert_d_eq(mallctl("tcache.flush", NULL, NULL, (void *)&tis[i], sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u", i); } /* Cache some allocations. */ for (i = 0; i < NTCACHES; i++) { ps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i])); assert_ptr_not_null(ps[i], "Unexpected mallocx() failure, i=%u", i); dallocx(ps[i], MALLOCX_TCACHE(tis[i])); qs[i] = mallocx(qsz, MALLOCX_TCACHE(tis[i])); assert_ptr_not_null(qs[i], "Unexpected mallocx() failure, i=%u", i); dallocx(qs[i], MALLOCX_TCACHE(tis[i])); } /* Verify that tcaches allocate cached regions. */ for (i = 0; i < NTCACHES; i++) { void *p0 = ps[i]; ps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i])); assert_ptr_not_null(ps[i], "Unexpected mallocx() failure, i=%u", i); assert_ptr_eq(ps[i], p0, "Expected mallocx() to allocate cached region, i=%u", i); } /* Verify that reallocation uses cached regions. */ for (i = 0; i < NTCACHES; i++) { void *q0 = qs[i]; qs[i] = rallocx(ps[i], qsz, MALLOCX_TCACHE(tis[i])); assert_ptr_not_null(qs[i], "Unexpected rallocx() failure, i=%u", i); assert_ptr_eq(qs[i], q0, "Expected rallocx() to allocate cached region, i=%u", i); /* Avoid undefined behavior in case of test failure. */ if (qs[i] == NULL) { qs[i] = ps[i]; } } for (i = 0; i < NTCACHES; i++) { dallocx(qs[i], MALLOCX_TCACHE(tis[i])); } /* Flush some non-empty tcaches. */ for (i = 0; i < NTCACHES/2; i++) { assert_d_eq(mallctl("tcache.flush", NULL, NULL, (void *)&tis[i], sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u", i); } /* Destroy tcaches. */ for (i = 0; i < NTCACHES; i++) { assert_d_eq(mallctl("tcache.destroy", NULL, NULL, (void *)&tis[i], sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u", i); } }