|
20 | 20 | #include "py/binary.h" |
21 | 21 | #include "py/bc.h" |
22 | 22 |
|
| 23 | +// Forward declaration for tracked allocation testing |
| 24 | +typedef struct _m_tracked_node_t { |
| 25 | + struct _m_tracked_node_t *prev; |
| 26 | + struct _m_tracked_node_t *next; |
| 27 | + #if !MICROPY_ENABLE_GC |
| 28 | + uintptr_t size; |
| 29 | + #endif |
| 30 | + uint8_t data[]; |
| 31 | +} m_tracked_node_t; |
| 32 | + |
23 | 33 | // expected output of this file is found in extra_coverage.py.exp |
24 | 34 |
|
25 | 35 | #if defined(MICROPY_UNIX_COVERAGE) |
@@ -368,6 +378,87 @@ static mp_obj_t extra_coverage(void) { |
368 | 378 | } |
369 | 379 |
|
370 | 380 | mp_printf(&mp_plat_print, "m_tracked_head = %p\n", MP_STATE_VM(m_tracked_head)); |
| 381 | + |
| 382 | + // Test realloc at head/tail of list (exercises NULL prev/next handling) |
| 383 | + mp_printf(&mp_plat_print, "# tracked realloc list positions\n"); |
| 384 | + |
| 385 | + // Allocate 3 nodes to create a list |
| 386 | + uint8_t *nodes[3]; |
| 387 | + for (int i = 0; i < 3; ++i) { |
| 388 | + nodes[i] = m_tracked_calloc(1, 32); |
| 389 | + nodes[i][0] = 'A' + i; // Mark each with A, B, C |
| 390 | + } |
| 391 | + |
| 392 | + // Verify initial list has 3 items (head should be nodes[2], the last allocated) |
| 393 | + int count = 0; |
| 394 | + for (m_tracked_node_t *n = MP_STATE_VM(m_tracked_head); n != NULL; n = n->next) { |
| 395 | + ++count; |
| 396 | + } |
| 397 | + mp_printf(&mp_plat_print, "list count: %d\n", count); |
| 398 | + |
| 399 | + // Realloc the tail (first allocated, nodes[0]) - tests next==NULL case |
| 400 | + nodes[0] = m_tracked_realloc(nodes[0], 64); |
| 401 | + mp_printf(&mp_plat_print, "tail realloc marker: %c\n", nodes[0][0]); |
| 402 | + |
| 403 | + // Realloc the head (last allocated, nodes[2]) - tests prev==NULL case |
| 404 | + nodes[2] = m_tracked_realloc(nodes[2], 64); |
| 405 | + mp_printf(&mp_plat_print, "head realloc marker: %c\n", nodes[2][0]); |
| 406 | + |
| 407 | + // Realloc middle node - tests both prev and next non-NULL |
| 408 | + nodes[1] = m_tracked_realloc(nodes[1], 64); |
| 409 | + mp_printf(&mp_plat_print, "middle realloc marker: %c\n", nodes[1][0]); |
| 410 | + |
| 411 | + // Verify list still has 3 items and is traversable |
| 412 | + count = 0; |
| 413 | + for (m_tracked_node_t *n = MP_STATE_VM(m_tracked_head); n != NULL; n = n->next) { |
| 414 | + ++count; |
| 415 | + } |
| 416 | + mp_printf(&mp_plat_print, "list count after reallocs: %d\n", count); |
| 417 | + |
| 418 | + // Verify backward traversal (prev pointers correct) |
| 419 | + // Find tail by walking forward |
| 420 | + m_tracked_node_t *tail = MP_STATE_VM(m_tracked_head); |
| 421 | + while (tail != NULL && tail->next != NULL) { |
| 422 | + tail = tail->next; |
| 423 | + } |
| 424 | + // Walk backward and count |
| 425 | + count = 0; |
| 426 | + for (m_tracked_node_t *n = tail; n != NULL; n = n->prev) { |
| 427 | + ++count; |
| 428 | + } |
| 429 | + mp_printf(&mp_plat_print, "backward traversal count: %d\n", count); |
| 430 | + |
| 431 | + // Test pure allocation via realloc (NULL ptr) |
| 432 | + uint8_t *new_alloc = m_tracked_realloc(NULL, 32); |
| 433 | + new_alloc[0] = 'X'; |
| 434 | + mp_printf(&mp_plat_print, "realloc(NULL) marker: %c\n", new_alloc[0]); |
| 435 | + |
| 436 | + // Test pure free via realloc (size 0) |
| 437 | + void *result = m_tracked_realloc(new_alloc, 0); |
| 438 | + mp_printf(&mp_plat_print, "realloc(ptr, 0) result: %d\n", result == NULL ? 1 : 0); |
| 439 | + |
| 440 | + // Test shrinking realloc (64->32) - may return same pointer |
| 441 | + nodes[1] = m_tracked_realloc(nodes[1], 32); |
| 442 | + mp_printf(&mp_plat_print, "shrink realloc marker: %c\n", nodes[1][0]); |
| 443 | + |
| 444 | + // Clean up - free in reverse order to stress list operations |
| 445 | + for (int i = 2; i >= 0; --i) { |
| 446 | + m_tracked_free(nodes[i]); |
| 447 | + } |
| 448 | + |
| 449 | + // Test single-node list realloc (prev==NULL && next==NULL simultaneously) |
| 450 | + uint8_t *single = m_tracked_calloc(1, 32); |
| 451 | + single[0] = 'S'; |
| 452 | + single = m_tracked_realloc(single, 64); |
| 453 | + mp_printf(&mp_plat_print, "single node realloc marker: %c\n", single[0]); |
| 454 | + count = 0; |
| 455 | + for (m_tracked_node_t *n = MP_STATE_VM(m_tracked_head); n != NULL; n = n->next) { |
| 456 | + ++count; |
| 457 | + } |
| 458 | + mp_printf(&mp_plat_print, "single node list count: %d\n", count); |
| 459 | + m_tracked_free(single); |
| 460 | + |
| 461 | + mp_printf(&mp_plat_print, "m_tracked_head after cleanup: %p\n", MP_STATE_VM(m_tracked_head)); |
371 | 462 | } |
372 | 463 |
|
373 | 464 | // vstr |
|
0 commit comments