@@ -236,4 +236,89 @@ TEST_SUITE("node 16") {
236236 REQUIRE_THROWS_AS (n.prev_partial_key (0 ), std::out_of_range);
237237 }
238238 }
239+
240+ TEST_CASE (" grow to node_48 preserves offset (PR #20)" ) {
241+ // This test reproduces the bug reported in PR #20:
242+ // When node_16 grows to node_48, the indexes_ array must use 128 offset
243+
244+ SUBCASE (" next_partial_key after grow" ) {
245+ leaf_node<void *>* dummy_children[17 ];
246+ for (int i = 0 ; i < 17 ; ++i) {
247+ dummy_children[i] = new leaf_node<void *>(nullptr );
248+ }
249+ node_16<void *>* n16 = new node_16<void *>();
250+ char test_keys[17 ];
251+ for (int i = 0 ; i < 17 ; ++i) {
252+ test_keys[i] = ' a' + i; // a, b, c, ..., q
253+ }
254+ for (int i = 0 ; i < 16 ; ++i) {
255+ n16->set_child (test_keys[i], dummy_children[i]);
256+ }
257+ REQUIRE (n16->is_full ());
258+ auto * n48 = static_cast <node_48<void *>*>(n16->grow ());
259+ REQUIRE (n48 != nullptr );
260+ for (int i = 0 ; i < 16 ; ++i) {
261+ auto ** child_ptr = n48->find_child (test_keys[i]);
262+ REQUIRE (child_ptr != nullptr );
263+ REQUIRE (*child_ptr == dummy_children[i]);
264+ }
265+ n48->set_child (test_keys[16 ], dummy_children[16 ]);
266+ for (int i = 0 ; i < 17 ; ++i) {
267+ auto ** child_ptr = n48->find_child (test_keys[i]);
268+ REQUIRE (child_ptr != nullptr );
269+ REQUIRE (*child_ptr == dummy_children[i]);
270+ }
271+ // Starting from first key 'a', we should find all keys in order
272+ char current = n48->next_partial_key (' a' );
273+ REQUIRE_EQ (' a' , current);
274+ for (int i = 1 ; i < 17 ; ++i) {
275+ current = n48->next_partial_key (current + 1 );
276+ REQUIRE_EQ (test_keys[i], current);
277+ }
278+ delete n48;
279+ for (int i = 0 ; i < 17 ; ++i) {
280+ delete dummy_children[i];
281+ }
282+ }
283+
284+ SUBCASE (" prev_partial_key after grow" ) {
285+ leaf_node<void *>* dummy_children[17 ];
286+ for (int i = 0 ; i < 17 ; ++i) {
287+ dummy_children[i] = new leaf_node<void *>(nullptr );
288+ }
289+ node_16<void *>* n16 = new node_16<void *>();
290+ char test_keys[17 ];
291+ for (int i = 0 ; i < 17 ; ++i) {
292+ test_keys[i] = ' a' + i; // a, b, c, ..., q
293+ }
294+ for (int i = 0 ; i < 16 ; ++i) {
295+ n16->set_child (test_keys[i], dummy_children[i]);
296+ }
297+ REQUIRE (n16->is_full ());
298+ auto * n48 = static_cast <node_48<void *>*>(n16->grow ());
299+ REQUIRE (n48 != nullptr );
300+ for (int i = 0 ; i < 16 ; ++i) {
301+ auto ** child_ptr = n48->find_child (test_keys[i]);
302+ REQUIRE (child_ptr != nullptr );
303+ REQUIRE (*child_ptr == dummy_children[i]);
304+ }
305+ n48->set_child (test_keys[16 ], dummy_children[16 ]);
306+ for (int i = 0 ; i < 17 ; ++i) {
307+ auto ** child_ptr = n48->find_child (test_keys[i]);
308+ REQUIRE (child_ptr != nullptr );
309+ REQUIRE (*child_ptr == dummy_children[i]);
310+ }
311+ // Starting from last key 'q', we should find all keys in reverse order
312+ char current = n48->prev_partial_key (' q' );
313+ REQUIRE_EQ (' q' , current);
314+ for (int i = 15 ; i >= 0 ; --i) {
315+ current = n48->prev_partial_key (current - 1 );
316+ REQUIRE_EQ (test_keys[i], current);
317+ }
318+ delete n48;
319+ for (int i = 0 ; i < 17 ; ++i) {
320+ delete dummy_children[i];
321+ }
322+ }
323+ }
239324}
0 commit comments