static void test_empty_tree() { tree_t *tree = alloc_tree(); ASSERT(get_child_by_index(tree->shadow_root, 0)->checksum_valid == false); update_checksums(tree); ASSERT(get_child_by_index(tree->shadow_root, 0)->checksum_valid == true); }
static convert_to_flat_code_t convert_to_flat_helper( to_flat_state_t *state, const tree_t *tree) { // get the real root. node_t *shadow_root = tree->shadow_root; if (shadow_root->num_children != 1) { return CONVERT_TO_FLAT_WTF; } node_t *real_root = get_child_by_index(shadow_root, 0); return convert_to_flat_iterator(state, real_root); }
static void sr_dup_trees_test(void **state) { int rc = SR_ERR_OK; sr_node_t *trees = NULL, *trees_dup = NULL, *node = NULL, *leaf = NULL; size_t tree_cnt = 0; char value[10] = { 0, }; trees = create_example_module_trees(&tree_cnt); assert_int_equal(SR_ERR_OK, rc); /* duplicate the array of trees */ rc = sr_dup_trees(trees, tree_cnt, &trees_dup); assert_int_equal(SR_ERR_OK, rc); /* /example_module:container */ assert_non_null(trees_dup); #ifdef USE_SR_MEM_MGMT assert_non_null(trees_dup->_sr_mem); assert_ptr_not_equal(trees->_sr_mem, trees_dup->_sr_mem); assert_int_equal(1, trees_dup->_sr_mem->obj_count); assert_true(0 < trees_dup->_sr_mem->used_total); #else assert_null(trees_dup->_sr_mem); #endif assert_string_equal("container", trees_dup->name); assert_false(trees_dup->dflt); assert_string_equal("example-module", trees_dup->module_name); assert_int_equal(SR_CONTAINER_T, trees_dup->type); assert_null(trees_dup->parent); assert_non_null(trees_dup->first_child); assert_non_null(trees_dup->last_child); assert_null(trees_dup->prev); assert_null(trees_dup->next); for (int i = 0; i < 10; ++i) { /* /example_module:container/list[key1="key1-i"][key2="key2-i"] */ node = get_child_by_index(trees_dup, i); assert_string_equal("list", node->name); assert_false(node->dflt); assert_null(node->module_name); assert_int_equal(SR_LIST_T, node->type); assert_ptr_equal(trees_dup, node->parent); assert_non_null(node->first_child); assert_non_null(node->last_child); if (0 < i) { assert_ptr_equal(get_child_by_index(trees_dup, i-1), node->prev); assert_ptr_equal(node->prev->next, node); } else { assert_null(node->prev); } if (9 > i) { assert_ptr_equal(get_child_by_index(trees_dup, i+1), node->next); assert_ptr_equal(node->next->prev, node); } else { assert_null(node->next); } /* /example_module:container/list[key1="key1-i"][key2="key2-i"]/key1 */ leaf = get_child_by_index(node, 0); assert_string_equal("key1", leaf->name); assert_false(leaf->dflt); assert_null(leaf->module_name); assert_int_equal(SR_STRING_T, leaf->type); snprintf(value, 10, "key1-%d", i); assert_string_equal(value, leaf->data.string_val); assert_ptr_equal(node, leaf->parent); assert_null(leaf->first_child); assert_null(leaf->last_child); assert_null(leaf->prev); assert_ptr_equal(get_child_by_index(node, 1), leaf->next); assert_ptr_equal(leaf->next->prev, leaf); /* /example_module:container/list[key1="key1-i"][key2="key2-i"]/key2 */ leaf = get_child_by_index(node, 1); assert_string_equal("key2", leaf->name); assert_false(leaf->dflt); assert_null(leaf->module_name); assert_int_equal(SR_STRING_T, leaf->type); snprintf(value, 10, "key2-%d", i); assert_string_equal(value, leaf->data.string_val); assert_ptr_equal(node, leaf->parent); assert_null(leaf->first_child); assert_null(leaf->last_child); assert_ptr_equal(get_child_by_index(node, 0), leaf->prev); assert_ptr_equal(leaf->prev->next, leaf); assert_ptr_equal(get_child_by_index(node, 2), leaf->next); assert_ptr_equal(leaf->next->prev, leaf); /* /example_module:container/list[key1="key1-i"][key2="key2-i"]/leaf */ leaf = get_child_by_index(node, 2); assert_string_equal("leaf", leaf->name); assert_false(leaf->dflt); assert_null(leaf->module_name); assert_int_equal(SR_STRING_T, leaf->type); snprintf(value, 10, "leaf-%d", i); assert_string_equal(value, leaf->data.string_val); assert_ptr_equal(node, leaf->parent); assert_null(leaf->first_child); assert_null(leaf->last_child); assert_ptr_equal(get_child_by_index(node, 1), leaf->prev); assert_ptr_equal(leaf->prev->next, leaf); assert_null(leaf->next); } for (int i = 1; i < tree_cnt; ++i) { /* /example_module:number[.=0] */ leaf = trees_dup + i; assert_non_null(leaf); #ifdef USE_SR_MEM_MGMT assert_non_null(leaf->_sr_mem); assert_ptr_not_equal(trees->_sr_mem, leaf->_sr_mem); assert_ptr_equal(trees_dup[i-1]._sr_mem, leaf->_sr_mem); assert_int_equal(1, leaf->_sr_mem->obj_count); assert_true(0 < leaf->_sr_mem->used_total); #else assert_null(leaf->_sr_mem); #endif assert_string_equal("number", leaf->name); assert_false(leaf->dflt); assert_string_equal("example-module", leaf->module_name); assert_int_equal(SR_UINT16_T, leaf->type); assert_int_equal(i-1, leaf->data.uint16_val); assert_null(leaf->parent); assert_null(leaf->first_child); assert_null(leaf->last_child); assert_null(leaf->prev); assert_null(leaf->next); } sr_free_trees(trees_dup, tree_cnt); sr_free_trees(trees, tree_cnt); }
static sr_node_t * create_example_module_trees(size_t *tree_cnt) { int rc = 0; sr_node_t *trees = NULL, *node = NULL, *leaf = NULL; char value[10] = { 0, }; rc = sr_new_trees(6, &trees); assert_int_equal(SR_ERR_OK, rc); /* /example_module:container */ rc = sr_node_set_name(trees, "container"); assert_int_equal(SR_ERR_OK, rc); rc = sr_node_set_module(trees, "example-module"); assert_int_equal(SR_ERR_OK, rc); trees[0].type = SR_CONTAINER_T; for (int i = 0; i < 10; ++i) { /* /example_module:container/list[key1="key1-i"][key2="key2-i"] */ rc = sr_node_add_child(trees, "list", NULL, &node); assert_int_equal(SR_ERR_OK, rc); node->type = SR_LIST_T; assert_ptr_equal(trees, node->parent); if (0 < i) { assert_ptr_equal(get_child_by_index(trees, i-1), node->prev); assert_ptr_equal(node->prev->next, node); } else { assert_null(node->prev); } assert_null(node->next); assert_null(node->first_child); assert_null(node->last_child); assert_ptr_equal(get_child_by_index(trees, i), node); /* /example_module:container/list[key1="key1-i"][key2="key2-i"]/key1 */ rc = sr_node_add_child(node, "key1", NULL, &leaf); assert_int_equal(SR_ERR_OK, rc); snprintf(value, 10, "key1-%d", i); rc = sr_node_set_str_data(leaf, SR_STRING_T, value); assert_int_equal(SR_ERR_OK, rc); assert_ptr_equal(node, leaf->parent); assert_null(leaf->prev); assert_null(leaf->next); assert_null(leaf->first_child); assert_null(leaf->last_child); assert_ptr_equal(get_child_by_index(node, 0), leaf); /* /example_module:container/list[key1="key1-i"][key2="key2-i"]/key2 */ rc = sr_node_add_child(node, "key2", NULL, &leaf); assert_int_equal(SR_ERR_OK, rc); snprintf(value, 10, "key2-%d", i); rc = sr_node_set_str_data(leaf, SR_STRING_T, value); assert_int_equal(SR_ERR_OK, rc); assert_ptr_equal(node, leaf->parent); assert_ptr_equal(get_child_by_index(node, 0), leaf->prev); assert_ptr_equal(leaf->prev->next, leaf); assert_null(leaf->next); assert_null(leaf->first_child); assert_null(leaf->last_child); assert_ptr_equal(get_child_by_index(node, 1), leaf); /* /example_module:container/list[key1="key1-i"][key2="key2-i"]/leaf (="leaf-i") */ rc = sr_node_add_child(node, "leaf", NULL, &leaf); assert_int_equal(SR_ERR_OK, rc); snprintf(value, 10, "leaf-%d", i); rc = sr_node_set_str_data(leaf, SR_STRING_T, value); assert_int_equal(SR_ERR_OK, rc); assert_ptr_equal(node, leaf->parent); assert_ptr_equal(get_child_by_index(node, 1), leaf->prev); assert_ptr_equal(leaf->prev->next, leaf); assert_null(leaf->next); assert_null(leaf->first_child); assert_null(leaf->last_child); assert_ptr_equal(get_child_by_index(node, 2), leaf); } for (int i = 0; i < 5; ++i) { /* /example_module:number[.=i] */ rc = sr_node_set_name(trees + i + 1, "number"); assert_int_equal(SR_ERR_OK, rc); rc = sr_node_set_module(trees + i + 1, "example-module"); assert_int_equal(SR_ERR_OK, rc); trees[i+1].type = SR_UINT16_T; trees[i+1].data.uint16_val = i; } assert_non_null(tree_cnt); *tree_cnt = 6; return trees; }
/** * Verify that when a path is added or removed, the affected paths have their * checksums invalidated. */ static void test_updates_reset_checksums() { uint8_t checksum[SHA1_BYTES]; for (int ix = 0; ix < SHA1_BYTES; ix++) { checksum[ix] = (uint8_t) ix; } tree_t *tree = alloc_tree(); char *paths_to_add[] = { "abc", "ab/def", "ab/defg/hi", "ab/defg/h/ij/kl", "ab/defg/h/ijk", "ab/defg/h/i/jkl/mn/op/qr", "ab/defg/h/i/jkl/mn/op/qrs", }; const size_t num_paths = sizeof(paths_to_add) / sizeof(*paths_to_add); for (size_t ix = 0; ix < num_paths; ix++) { add_update_path_result_t add_result = add_or_update_path(tree, STRPLUSLEN(paths_to_add[ix]), checksum, SHA1_BYTES, 0); ASSERT(add_result == ADD_UPDATE_PATH_OK); } update_checksums(tree); ASSERT(get_child_by_index(tree->shadow_root, 0)->checksum_valid == true); ASSERT(add_or_update_path(tree, STRPLUSLEN("ab/defg/h/ijk"), checksum, SHA1_BYTES, 0) == ADD_UPDATE_PATH_OK); path_checksum_t dirs_to_check_after_add[] = { {"abc", true}, {"ab/", false}, {"ab/defg/", false}, {"ab/defg/h/", false}, {"ab/defg/h/i/", true}, {"ab/defg/h/i/jkl/", true}, {"ab/defg/h/i/jkl/mn/", true}, {"ab/defg/h/i/jkl/mn/op/", true}, {"ab/defg/h/ij/", true}, }; size_t num_dirs = sizeof(dirs_to_check_after_add) / sizeof(*dirs_to_check_after_add); for (size_t ix = 0; ix < num_dirs; ix++) { get_path_unfiltered_result_t get_result = get_path_unfiltered(tree, STRPLUSLEN(dirs_to_check_after_add[ix].path)); ASSERT(get_result.code == GET_PATH_OK); ASSERT(get_result.node->checksum_valid == dirs_to_check_after_add[ix].expected_checksum_valid); } ASSERT(get_child_by_index(tree->shadow_root, 0)->checksum_valid == false); update_checksums(tree); ASSERT(get_child_by_index(tree->shadow_root, 0)->checksum_valid == true); ASSERT(remove_path(tree, STRPLUSLEN("ab/defg/h/i/jkl/mn/op/qrs")) == REMOVE_PATH_OK); path_checksum_t dirs_to_check_after_remove[] = { {"abc", true}, {"ab/", false}, {"ab/defg/", false}, {"ab/defg/h/", false}, {"ab/defg/h/i/", false}, {"ab/defg/h/i/jkl/", false}, {"ab/defg/h/i/jkl/mn/", false}, {"ab/defg/h/i/jkl/mn/op/", false}, {"ab/defg/h/ij/", true}, }; num_dirs = sizeof(dirs_to_check_after_remove) / sizeof(*dirs_to_check_after_remove); for (size_t ix = 0; ix < num_dirs; ix++) { get_path_unfiltered_result_t get_result = get_path_unfiltered(tree, STRPLUSLEN(dirs_to_check_after_remove[ix].path)); ASSERT(get_result.code == GET_PATH_OK); ASSERT(get_result.node->checksum_valid == dirs_to_check_after_remove[ix].expected_checksum_valid); } ASSERT(get_child_by_index(tree->shadow_root, 0)->checksum_valid == false); }
static convert_to_flat_code_t convert_to_flat_iterator( to_flat_state_t *state, const node_t *node) { assert(node->type == TYPE_IMPLICIT || node->type == TYPE_ROOT); for (uint32_t ix = 0; ix < node->num_children; ix++) { node_t *child = get_child_by_index(node, ix); if (child->type == TYPE_LEAF) { size_t space_needed = state->dirpath_build_buffer_idx + child->name_sz + 1 /* null character */ + (SHA1_BYTES * 2) + (child->flags != '\000' ? 1 : 0) + 1 /* NL */; if (CONVERT_EXPAND_TO_FIT( &state->output_buffer, state->output_buffer_idx, &state->output_buffer_sz, space_needed) == false) { return CONVERT_TO_FLAT_OOM; } // copy the dirpath over to the output buffer. memcpy(&state->output_buffer[state->output_buffer_idx], state->dirpath_build_buffer, state->dirpath_build_buffer_idx); state->output_buffer_idx += state->dirpath_build_buffer_idx; // copy the filename over to the output buffer. memcpy(&state->output_buffer[state->output_buffer_idx], child->name, child->name_sz); state->output_buffer_idx += child->name_sz; // copy the filename over to the output buffer. state->output_buffer[state->output_buffer_idx] = '\000'; state->output_buffer_idx++; // transcribe the sha over. hexlify(child->checksum, SHA1_BYTES, &state->output_buffer[state->output_buffer_idx]); state->output_buffer_idx += (SHA1_BYTES * 2); if (child->flags != '\000') { state->output_buffer[state->output_buffer_idx] = child->flags; state->output_buffer_idx++; } state->output_buffer[state->output_buffer_idx] = '\n'; state->output_buffer_idx++; assert(state->output_buffer_idx < state->output_buffer_sz); } else { // save the old value... size_t previous_dirpath_build_buffer_idx = state->dirpath_build_buffer_idx; if (PATH_APPEND( &state->dirpath_build_buffer, &state->dirpath_build_buffer_idx, &state->dirpath_build_buffer_sz, child->name, child->name_sz) == false) { return CONVERT_TO_FLAT_OOM; } convert_to_flat_iterator(state, child); state->dirpath_build_buffer_idx = previous_dirpath_build_buffer_idx; } } return CONVERT_TO_FLAT_OK; }