From 497808ddeb197266fb878f930ed33e4703e2dd4a Mon Sep 17 00:00:00 2001 From: Andreew Gregory Date: Sat, 1 Nov 2025 15:26:27 +0300 Subject: [PATCH] Fixed hella lot of bugs in rb tree. Wrote tests for BuffRBTreeBy***_SetU64Segment (they work) --- CMakeLists.txt | 1 + src/l1/anne/util_temp_very_base.h | 9 + src/l1/core/uint_segments.h | 3 + src/l1_5/anne/l1_5_templ_very_base.h | 19 +- .../codegen/rb_tree_set_map_template_inst.h | 22 +- src/l2/tests/data_structures/t0.c | 2 + src/l2/tests/data_structures/t0_2.c | 378 ++++++++++++++++++ 7 files changed, 420 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 32761a8..4a554fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ target_link_libraries(0_render_test -lvulkan -lwayland-client -lm -lxkbcommon -l #add_executable(3_render_test src/l2/tests/r3/r3.c gen/l_wl_protocols/xdg-shell-private.c) #target_link_libraries(3_render_test -lwayland-client -lm -lvulkan -lxkbcommon) +add_executable(l2t0_2 src/l2/tests/data_structures/t0_2.c) add_executable(l2t2 src/l2/tests/data_structures/t2.c) #add_executable(l2t0 src/l2/tests/data_structures/t0.c) diff --git a/src/l1/anne/util_temp_very_base.h b/src/l1/anne/util_temp_very_base.h index ba32db6..b9bb910 100644 --- a/src/l1/anne/util_temp_very_base.h +++ b/src/l1/anne/util_temp_very_base.h @@ -50,6 +50,15 @@ void generate_util_temp_very_base_headers() { } generate_guarded_span_company_for_primitive(cstr("l1"), cstr(""), cstr("CSTR"), cstr(""), true, false); + + generate_util_templ_inst_guarded_header(l, ns, cstr("#include \"../../src/l1/core/uint_segments.h\""), + (util_templates_instantiation_options){.T = cstr("U64Segment"), .t_primitive = true, .vec_extended = true}); + generate_Option_templ_inst_guarded_header(l, ns, cstr("#include \"../../src/l1/core/uint_segments.h\""), + (option_template_instantiation_op){.T = cstr("U64Segment"), .t_primitive = true}); + /* Required by BuffRBTree_Set */ + generate_Option_templ_inst_guarded_header(l, ns, cstr("#include \"../../src/l1/core/uint_segments.h\""), + (option_template_instantiation_op){.T = cstr("RefU64Segment"), .t_primitive = true}); + generate_guarded_header_of_result_type_instantiation(cstr("l1"), cstr(""), cstr(""), cstr("VecU8"), cstr("#include \"VecAndSpan_U8.h\""), true, false); generate_guarded_header_of_result_type_instantiation(cstr("l1"), cstr(""), diff --git a/src/l1/core/uint_segments.h b/src/l1/core/uint_segments.h index 12c23e4..6d56c40 100644 --- a/src/l1/core/uint_segments.h +++ b/src/l1/core/uint_segments.h @@ -48,4 +48,7 @@ bool U64Segment_less_by_len_and_start_resp_align(const U64Segment* A, const U64S return len_A < len_B; } +/* Required by BuffRBTree_Set. That was a really tough decision */ +typedef const U64Segment* RefU64Segment; + #endif diff --git a/src/l1_5/anne/l1_5_templ_very_base.h b/src/l1_5/anne/l1_5_templ_very_base.h index b5f89c1..14b8ea7 100644 --- a/src/l1_5/anne/l1_5_templ_very_base.h +++ b/src/l1_5/anne/l1_5_templ_very_base.h @@ -10,7 +10,10 @@ void generate_l1_5_template_instantiation_for_base_types(){ generate_rb_tree_Set_templ_inst_guarded_header(l, ns, cstr("#include \"../l1/VecAndSpan_S64.h\""), (set_instantiation_op){.T = cstr("S64"), .t_integer = true}); - generate_rb_tree_Set_templ_inst_guarded_header(l, ns, cstr("#include \"../../src/l1/core/uint_segments.h\""), + SpanU8 u64seg_dep = cstr("#include \"../l1/VecU64Segment.h\"\n" + "#include \"../l1/OptionU64Segment.h\"\n" + "#include \"../l1/OptionRefU64Segment.h\""); + generate_rb_tree_Set_templ_inst_guarded_header(l, ns, u64seg_dep, (set_instantiation_op){ .T = cstr("U64Segment"), .t_primitive = true, @@ -18,12 +21,22 @@ void generate_l1_5_template_instantiation_for_base_types(){ .alternative_less = cstr("U64Segment_less_by_start"), .alternative_comp_set_name_embed = cstr("Start") }); - generate_rb_tree_Set_templ_inst_guarded_header(l, ns, cstr("#include \"../../src/l1/core/uint_segments.h\""), + generate_rb_tree_Set_templ_inst_guarded_header(l, ns, u64seg_dep, (set_instantiation_op){ .T = cstr("U64Segment"), .t_primitive = true, .alternative_less = cstr("U64Segment_less_by_len_and_start"), - .alternative_comp_set_name_embed = cstr("LenAndStart") + .alternative_comp_set_name_embed = cstr("Len") + }); + generate_rb_tree_Set_templ_inst_guarded_header(l, ns, u64seg_dep, + (set_instantiation_op){ + .T = cstr("U64Segment"), + .t_primitive = true, + /* comparison takes additional U8 parameter */ + .alternative_less = cstr("U64Segment_less_by_len_and_start_resp_align"), + .alternative_equal = cstr("U64Segment_equal_U64Segment_resp_align"), + .alternative_comp_set_name_embed = cstr("LenRespAlign"), + .guest_data_T = cstr("U8") }); } diff --git a/src/l1_5/codegen/rb_tree_set_map_template_inst.h b/src/l1_5/codegen/rb_tree_set_map_template_inst.h index 4e6485f..c95e6e1 100644 --- a/src/l1_5/codegen/rb_tree_set_map_template_inst.h +++ b/src/l1_5/codegen/rb_tree_set_map_template_inst.h @@ -73,7 +73,7 @@ NODISCARD VecU8 codegen_rb_tree_set_key_ref_EQUAL_element(set_instantiation_op o } if (op.t_integer) return VecU8_fmt("key == self->el.buf[cur - 1]"); - return VecU8_fmt("%s_equal_%s(ref, &self->el.buf[cur - 1])", op.T, op.T); + return VecU8_fmt("%s_equal_%s(key, &self->el.buf[cur - 1])", op.T, op.T); } /* When key is given by a pointer into some method of Buff_RBTreeSet */ @@ -106,15 +106,15 @@ NODISCARD VecU8 codegen_rb_tree_set_option_returned_ref_t(set_instantiation_op o * we return it from self->el array */ NODISCARD VecU8 codegen_rb_tree_set_some_ref_t(set_instantiation_op op, SpanU8 index_var_name){ if (op.t_integer) - return VecU8_fmt("Some_%s(self->el[%s - 1])", op.T, index_var_name); - return VecU8_fmt("Some_Ref%s(&self->el[%s - 1])", op.T, index_var_name); + return VecU8_fmt("Some_%s(self->el.buf[%s - 1])", op.T, index_var_name); + return VecU8_fmt("Some_Ref%s(&self->el.buf[%s - 1])", op.T, index_var_name); } /* Suppose some method returns pointer to key (ofc wrapped in option). But this time we found nothing */ NODISCARD VecU8 codegen_rb_tree_set_none_ref_t(set_instantiation_op op){ if (op.t_integer) - return VecU8_fmt("Some_%s()", op.T); - return VecU8_fmt("Some_Ref%s()", op.T); + return VecU8_fmt("None_%s()", op.T); + return VecU8_fmt("None_Ref%s()", op.T); } NODISCARD VecU8 codegen_rb_tree_set_option_returned_value_t(set_instantiation_op op){ @@ -272,7 +272,7 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op VecU8_append_vec(&res, VecU8_fmt( "NODISCARD %s %s_new(%s guest) {\n" /* set, set, op.guest_data_T */ SPACE "return (%s){.tree = VecRBTreeNode_new_zeroinit(1), .root = 0, .el = Vec%s_new(), .guest = guest};\n" /* set, op.T */ - "}\n\n", set, set, set, op.T)); + "}\n\n", set, set, op.guest_data_T, set, op.T)); VecU8_append_vec(&res, VecU8_fmt( "NODISCARD %s %s_new_reserved(%s guest, size_t size) {\n" /* set, set, op.guest_data_T */ SPACE "return (%s){.tree = (VecRBTreeNode){\n" @@ -302,7 +302,7 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op * it returns true if insertion was done, false if collision happened and key was not inserted */ codegen_append_rb_tree_set_insert_kind_method(&res, op, set, cstr("insert"), vcstr("bool"), vcstr("return true;\n"), - op.t_integer ? + op.t_primitive ? vcstr("return false;\n") : VecU8_fmt( "%s_drop(key);\n" /* op.T */ @@ -314,13 +314,13 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op * previous element with equal key it it was found. It still returns true if no conflict has happened, though */ codegen_append_rb_tree_set_insert_kind_method(&res, op, set, cstr("erase_substitute"), vcstr("bool"), vcstr("return true;\n"), - op.t_integer ? + op.t_primitive ? vcstr("return false;\n") : VecU8_fmt( "%s_drop(self->el.buf[cur - 1]);\n" "self->el.buf[cur - 1] = key;\n" - "return false;\n" - )); + "return false;\n", + op.T)); /* Method _pop_substitute() is just like _erase_substitute(), but it returns a previous key * that was overthrown after collision. Wrapped in option, ofcourse */ @@ -383,7 +383,7 @@ NODISCARD VecU8 generate_rb_tree_Set_template_instantiation(set_instantiation_op codegen_append_rb_tree_set_erase_kind_method(&res, op, set, cstr("pop"), codegen_rb_tree_set_option_returned_value_t(op), VecU8_fmt("return %v;\n", codegen_rb_tree_set_none_t(op)), - VecU8_fmt("%s saved = self->el[cur - 1];\n", op.T), + VecU8_fmt("%s saved = self->el.buf[cur - 1];\n", op.T), VecU8_fmt("return %v;\n", codegen_rb_tree_set_some_t(op, cstr("saved"))) ); } diff --git a/src/l2/tests/data_structures/t0.c b/src/l2/tests/data_structures/t0.c index 072afa8..5631c4f 100644 --- a/src/l2/tests/data_structures/t0.c +++ b/src/l2/tests/data_structures/t0.c @@ -487,12 +487,14 @@ void stress(){ S64 v = VecS64_unordered_pop(&complementary_set, j); VecS64_append(&real_set, v); check(BuffRBTree_SetS64_insert(&set, v)); + check_correctness(&set); } else { assert(real_set.len > 0); size_t j = rand() % real_set.len; S64 v = VecS64_unordered_pop(&real_set, j); VecS64_append(&complementary_set, v); check(BuffRBTree_SetS64_erase(&set, v)); + check_correctness(&set); } /* We did something */ check(real_set.len == set.el.len); diff --git a/src/l2/tests/data_structures/t0_2.c b/src/l2/tests/data_structures/t0_2.c index e69de29..1ce0364 100644 --- a/src/l2/tests/data_structures/t0_2.c +++ b/src/l2/tests/data_structures/t0_2.c @@ -0,0 +1,378 @@ +#include "../../../../gen/l1_5/BuffRBTreeByLen_SetU64Segment.h" +#include "../../../../gen/l1_5/BuffRBTreeByStart_SetU64Segment.h" +#include "../../../../gen/l1_5/BuffRBTreeByLenRespAlign_SetU64Segment.h" +#include "../../../l1/core/VecU8_as_str.h" + +U32 check_structure_h_dfs(const RBTreeNode* tree, U64 x, VecU8* f){ + if (x == 0) + return 0; + if (*VecU8_at(f, x - 1) != 0) + check(false); + *VecU8_mat(f, x - 1) = 1; + U32 a = check_structure_h_dfs(tree, tree[x].left, f); + U32 b = check_structure_h_dfs(tree, tree[x].right, f); + check(a == b); + return a + (tree[x].color == RBTree_black ? 1 : 0); +} + +void check_correctness_ByStart(const BuffRBTreeByStart_SetU64Segment* self){ + check(self->tree.len == self->el.len + 1); + check(self->root < self->tree.len); + if (self->tree.len > 1) { + check(self->root != 0); + } + VecU8 f = VecU8_new_zeroinit(self->tree.len - 1); + check_structure_h_dfs(self->tree.buf, self->root, &f); + for (size_t i = 0; i < self->tree.len - 1; i++) { + check(*VecU8_at(&f, i)); + } + VecU8_drop(f); /* f invalidated */ + for (size_t v = 1; v < self->tree.len; v++) { + if (v == self->root) { + check(self->tree.buf[v].parent == 0); + } else { + check(self->tree.buf[v].parent != 0); + } + check(self->tree.buf[v].parent < self->tree.len); + check(self->tree.buf[v].left < self->tree.len); + check(self->tree.buf[v].right < self->tree.len); + if (self->tree.buf[v].left != 0) { + check(self->tree.buf[self->tree.buf[v].left].parent == v); + } + if (self->tree.buf[v].right != 0) { + check(self->tree.buf[self->tree.buf[v].right].parent == v); + } + } + + /* Checking coloring */ + check(self->tree.buf[0].color == RBTree_black); + if (self->root != 0) + check(self->tree.buf[self->root].color == RBTree_black); + for (size_t v = 1; v < self->tree.len; v++) { + if (self->tree.buf[v].color == RBTree_red) { + check(self->tree.buf[self->tree.buf[v].left].color == RBTree_black); + check(self->tree.buf[self->tree.buf[v].right].color == RBTree_black); + } + } + + /* checking keys, but better */ + for (size_t v = 1; v < self->tree.len; v++) { + if (self->tree.buf[v].left != 0) { + check(U64Segment_less_by_start(&self->el.buf[self->tree.buf[v].left - 1], &self->el.buf[v - 1])); + } + if (self->tree.buf[v].right != 0) { + check(U64Segment_less_by_start(&self->el.buf[v - 1], &self->el.buf[self->tree.buf[v].right - 1])); + } + } + for (size_t v = 1; v < self->tree.len; v++) { + if (self->tree.buf[v].left != 0) { + size_t cur = self->tree.buf[v].left; + while (self->tree.buf[cur].right != 0) + cur = self->tree.buf[cur].right; + check(U64Segment_less_by_start(&self->el.buf[cur - 1], &self->el.buf[v - 1])); + } + if (self->tree.buf[v].right != 0) { + size_t cur = self->tree.buf[v].right; + while (self->tree.buf[cur].left != 0) + cur = self->tree.buf[cur].left; + check(U64Segment_less_by_start(&self->el.buf[v - 1], &self->el.buf[cur - 1])); + } + } +} + +void stress_ByStart(){ + printf("Prepare for some real stress\n"); + for (int s = 2; s < 800; s++) { + srand(s); + BuffRBTreeByStart_SetU64Segment set = BuffRBTreeByStart_SetU64Segment_new(); + VecU64Segment real_set = VecU64Segment_new(); + U32 n = (U32)s; + VecU64Segment complementary_set = VecU64Segment_new_reserved(n); + for (size_t i = 0; i < n; i++) { + U64Segment value = {i, (U64)rand()}; + VecU64Segment_append(&complementary_set, value); + } + for (int t = 0; t < 1000; t++) { + /* Do something */ + int do_insertion = rand() % 2; + if (real_set.len == 0) + do_insertion = 1; + if (complementary_set.len == 0) + do_insertion = 0; + if (do_insertion) { + assert(complementary_set.len > 0); + size_t j = rand() % complementary_set.len; + U64Segment v = VecU64Segment_unordered_pop(&complementary_set, j); + VecU64Segment_append(&real_set, v); + check(BuffRBTreeByStart_SetU64Segment_insert(&set, v)); + check_correctness_ByStart(&set); + } else { + assert(real_set.len > 0); + size_t j = rand() % real_set.len; + U64Segment v = VecU64Segment_unordered_pop(&real_set, j); + VecU64Segment_append(&complementary_set, v); + check(BuffRBTreeByStart_SetU64Segment_erase(&set, &v)); + check_correctness_ByStart(&set); + } + /* We did something */ + check(real_set.len == set.el.len); + for (size_t j = 0; j < real_set.len; j++) { + check(BuffRBTreeByStart_SetU64Segment_find(&set, &real_set.buf[j]) != 0); + check(BuffRBTreeByStart_SetU64Segment_at(&set, &real_set.buf[j]).variant == Option_Some); + } + for (size_t j = 0; j < complementary_set.len; j++) { + check(BuffRBTreeByStart_SetU64Segment_find(&set, &complementary_set.buf[j]) == 0); + check(BuffRBTreeByStart_SetU64Segment_at(&set, &complementary_set.buf[j]).variant == Option_None); + } + } + VecU64Segment_drop(real_set); + VecU64Segment_drop(complementary_set); + BuffRBTreeByStart_SetU64Segment_drop(set); + printf("Seed s=%d passed test\n", s); + } +} + +void check_correctness_ByLen(const BuffRBTreeByLen_SetU64Segment* self){ + check(self->tree.len == self->el.len + 1); + check(self->root < self->tree.len); + if (self->tree.len > 1) { + check(self->root != 0); + } + VecU8 f = VecU8_new_zeroinit(self->tree.len - 1); + check_structure_h_dfs(self->tree.buf, self->root, &f); + for (size_t i = 0; i < self->tree.len - 1; i++) { + check(*VecU8_at(&f, i)); + } + VecU8_drop(f); /* f invalidated */ + for (size_t v = 1; v < self->tree.len; v++) { + if (v == self->root) { + check(self->tree.buf[v].parent == 0); + } else { + check(self->tree.buf[v].parent != 0); + } + check(self->tree.buf[v].parent < self->tree.len); + check(self->tree.buf[v].left < self->tree.len); + check(self->tree.buf[v].right < self->tree.len); + if (self->tree.buf[v].left != 0) { + check(self->tree.buf[self->tree.buf[v].left].parent == v); + } + if (self->tree.buf[v].right != 0) { + check(self->tree.buf[self->tree.buf[v].right].parent == v); + } + } + + /* Checking coloring */ + check(self->tree.buf[0].color == RBTree_black); + if (self->root != 0) + check(self->tree.buf[self->root].color == RBTree_black); + for (size_t v = 1; v < self->tree.len; v++) { + if (self->tree.buf[v].color == RBTree_red) { + check(self->tree.buf[self->tree.buf[v].left].color == RBTree_black); + check(self->tree.buf[self->tree.buf[v].right].color == RBTree_black); + } + } + + /* checking keys, but better */ + for (size_t v = 1; v < self->tree.len; v++) { + if (self->tree.buf[v].left != 0) { + check(U64Segment_less_by_len_and_start(&self->el.buf[self->tree.buf[v].left - 1], &self->el.buf[v - 1])); + } + if (self->tree.buf[v].right != 0) { + check(U64Segment_less_by_len_and_start(&self->el.buf[v - 1], &self->el.buf[self->tree.buf[v].right - 1])); + } + } + for (size_t v = 1; v < self->tree.len; v++) { + if (self->tree.buf[v].left != 0) { + size_t cur = self->tree.buf[v].left; + while (self->tree.buf[cur].right != 0) + cur = self->tree.buf[cur].right; + check(U64Segment_less_by_len_and_start(&self->el.buf[cur - 1], &self->el.buf[v - 1])); + } + if (self->tree.buf[v].right != 0) { + size_t cur = self->tree.buf[v].right; + while (self->tree.buf[cur].left != 0) + cur = self->tree.buf[cur].left; + check(U64Segment_less_by_len_and_start(&self->el.buf[v - 1], &self->el.buf[cur - 1])); + } + } +} + +void stress_ByLen(){ + printf("Prepare for some real stress\n"); + for (int s = 2; s < 400; s++) { + srand(s); + BuffRBTreeByLen_SetU64Segment set = BuffRBTreeByLen_SetU64Segment_new(); + VecU64Segment real_set = VecU64Segment_new(); + U32 n = (U32)s; + VecU64Segment complementary_set = VecU64Segment_new_reserved(n); + for (size_t i = 0; i < n; i++) { + U64Segment value = {i, (U64)rand()}; + VecU64Segment_append(&complementary_set, value); + } + for (int t = 0; t < 1000; t++) { + /* Do something */ + int do_insertion = rand() % 2; + if (real_set.len == 0) + do_insertion = 1; + if (complementary_set.len == 0) + do_insertion = 0; + if (do_insertion) { + assert(complementary_set.len > 0); + size_t j = rand() % complementary_set.len; + U64Segment v = VecU64Segment_unordered_pop(&complementary_set, j); + VecU64Segment_append(&real_set, v); + check(BuffRBTreeByLen_SetU64Segment_insert(&set, v)); + check_correctness_ByLen(&set); + } else { + assert(real_set.len > 0); + size_t j = rand() % real_set.len; + U64Segment v = VecU64Segment_unordered_pop(&real_set, j); + VecU64Segment_append(&complementary_set, v); + check(BuffRBTreeByLen_SetU64Segment_erase(&set, &v)); + check_correctness_ByLen(&set); + } + /* We did something */ + check(real_set.len == set.el.len); + for (size_t j = 0; j < real_set.len; j++) { + check(BuffRBTreeByLen_SetU64Segment_find(&set, &real_set.buf[j]) != 0); + check(BuffRBTreeByLen_SetU64Segment_at(&set, &real_set.buf[j]).variant == Option_Some); + } + for (size_t j = 0; j < complementary_set.len; j++) { + check(BuffRBTreeByLen_SetU64Segment_find(&set, &complementary_set.buf[j]) == 0); + check(BuffRBTreeByLen_SetU64Segment_at(&set, &complementary_set.buf[j]).variant == Option_None); + } + } + VecU64Segment_drop(real_set); + VecU64Segment_drop(complementary_set); + BuffRBTreeByLen_SetU64Segment_drop(set); + printf("Seed s=%d passed test\n", s); + } +} + +void check_correctness_ByLenRespAlign(const BuffRBTreeByLenRespAlign_SetU64Segment* self, U8 alignment_exp){ + check(self->guest == alignment_exp) + check(self->tree.len == self->el.len + 1); + check(self->root < self->tree.len); + if (self->tree.len > 1) { + check(self->root != 0); + } + VecU8 f = VecU8_new_zeroinit(self->tree.len - 1); + check_structure_h_dfs(self->tree.buf, self->root, &f); + for (size_t i = 0; i < self->tree.len - 1; i++) { + check(*VecU8_at(&f, i)); + } + VecU8_drop(f); /* f invalidated */ + for (size_t v = 1; v < self->tree.len; v++) { + if (v == self->root) { + check(self->tree.buf[v].parent == 0); + } else { + check(self->tree.buf[v].parent != 0); + } + check(self->tree.buf[v].parent < self->tree.len); + check(self->tree.buf[v].left < self->tree.len); + check(self->tree.buf[v].right < self->tree.len); + if (self->tree.buf[v].left != 0) { + check(self->tree.buf[self->tree.buf[v].left].parent == v); + } + if (self->tree.buf[v].right != 0) { + check(self->tree.buf[self->tree.buf[v].right].parent == v); + } + } + + /* Checking coloring */ + check(self->tree.buf[0].color == RBTree_black); + if (self->root != 0) + check(self->tree.buf[self->root].color == RBTree_black); + for (size_t v = 1; v < self->tree.len; v++) { + if (self->tree.buf[v].color == RBTree_red) { + check(self->tree.buf[self->tree.buf[v].left].color == RBTree_black); + check(self->tree.buf[self->tree.buf[v].right].color == RBTree_black); + } + } + + /* checking keys, but better */ + for (size_t v = 1; v < self->tree.len; v++) { + if (self->tree.buf[v].left != 0) { + check(U64Segment_less_by_len_and_start_resp_align(&self->el.buf[self->tree.buf[v].left - 1], &self->el.buf[v - 1], alignment_exp)); + } + if (self->tree.buf[v].right != 0) { + check(U64Segment_less_by_len_and_start_resp_align(&self->el.buf[v - 1], &self->el.buf[self->tree.buf[v].right - 1], alignment_exp)); + } + } + for (size_t v = 1; v < self->tree.len; v++) { + if (self->tree.buf[v].left != 0) { + size_t cur = self->tree.buf[v].left; + while (self->tree.buf[cur].right != 0) + cur = self->tree.buf[cur].right; + check(U64Segment_less_by_len_and_start_resp_align(&self->el.buf[cur - 1], &self->el.buf[v - 1], alignment_exp)); + } + if (self->tree.buf[v].right != 0) { + size_t cur = self->tree.buf[v].right; + while (self->tree.buf[cur].left != 0) + cur = self->tree.buf[cur].left; + check(U64Segment_less_by_len_and_start_resp_align(&self->el.buf[v - 1], &self->el.buf[cur - 1], alignment_exp)); + } + } +} + +void stress_ByLenRespAlign(U8 alignment_exp){ + printf("Prepare for some real stress\n"); + for (int s = 2; s < 400; s++) { + srand(s + 232323); + BuffRBTreeByLenRespAlign_SetU64Segment set = BuffRBTreeByLenRespAlign_SetU64Segment_new(alignment_exp); + VecU64Segment real_set = VecU64Segment_new(); + U32 n = (U32)s; + VecU64Segment complementary_set = VecU64Segment_new_reserved(n); + for (size_t i = 0; i < n; i++) { + U64Segment value = {i, (U64)rand()}; + VecU64Segment_append(&complementary_set, value); + } + for (int t = 0; t < 1000; t++) { + /* Do something */ + int do_insertion = rand() % 2; + if (real_set.len == 0) + do_insertion = 1; + if (complementary_set.len == 0) + do_insertion = 0; + if (do_insertion) { + assert(complementary_set.len > 0); + size_t j = rand() % complementary_set.len; + U64Segment v = VecU64Segment_unordered_pop(&complementary_set, j); + VecU64Segment_append(&real_set, v); + check(BuffRBTreeByLenRespAlign_SetU64Segment_insert(&set, v)); + check_correctness_ByLenRespAlign(&set, alignment_exp); + } else { + assert(real_set.len > 0); + size_t j = rand() % real_set.len; + U64Segment v = VecU64Segment_unordered_pop(&real_set, j); + VecU64Segment_append(&complementary_set, v); + check(BuffRBTreeByLenRespAlign_SetU64Segment_erase(&set, &v)); + check_correctness_ByLenRespAlign(&set, alignment_exp); + } + /* We did something */ + check(real_set.len == set.el.len); + for (size_t j = 0; j < real_set.len; j++) { + check(BuffRBTreeByLenRespAlign_SetU64Segment_find(&set, &real_set.buf[j]) != 0); + check(BuffRBTreeByLenRespAlign_SetU64Segment_at(&set, &real_set.buf[j]).variant == Option_Some); + } + for (size_t j = 0; j < complementary_set.len; j++) { + check(BuffRBTreeByLenRespAlign_SetU64Segment_find(&set, &complementary_set.buf[j]) == 0); + check(BuffRBTreeByLenRespAlign_SetU64Segment_at(&set, &complementary_set.buf[j]).variant == Option_None); + } + } + VecU64Segment_drop(real_set); + VecU64Segment_drop(complementary_set); + BuffRBTreeByLenRespAlign_SetU64Segment_drop(set); + printf("Seed s=%d passed test\n", s); + } +} + +int main(){ + stress_ByStart(); + stress_ByLen(); + stress_ByLenRespAlign(0); // 1 + stress_ByLenRespAlign(3); // 8 + stress_ByLenRespAlign(10); // 1024 + stress_ByLenRespAlign(12); // 4096 + return 0; +}