mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-11-14 10:10:11 -08:00
msf: update msf_header_matches_saved_extent
* changed test to apply full page allocation pattern in a stream * added new test cases for the page allocation pattern * bugfix stream growth logic
This commit is contained in:
1 parent
1603bcf11e
commit
da23fa1607
2 files changed
+62
-21
No files matched your search
@@ -490,14 +490,17 @@ msf_alloc_pn_arr(Arena *arena, MSF_Context *msf, MSF_UInt alloc_count)
|
||||
{
|
||||
// make sure FPM has enough space for new page numbers
|
||||
//
|
||||
// we grow FPM at correct intervals here because we pre-alloc unused FPM pages ahead of time
|
||||
// grow FPM at correct intervals here because we pre-alloc unused FPM pages ahead of time
|
||||
MSF_UInt curr_page_cap = msf_get_page_count_cap(msf->page_data_list, msf->page_size);
|
||||
MSF_UInt new_page_count = msf->page_count + alloc_count;
|
||||
if (new_page_count > curr_page_cap) {
|
||||
B32 is_fpm_alloced = msf_grow(msf, new_page_count);
|
||||
if (!is_fpm_alloced) {
|
||||
for (;;) {
|
||||
U64 new_page_count = (U64)msf->page_count + alloc_count;
|
||||
if (new_page_count <= curr_page_cap) {
|
||||
break;
|
||||
}
|
||||
if (new_page_count > MSF_PN_MAX || !msf_grow(msf, (MSF_PageNumber)new_page_count)) {
|
||||
return 0;
|
||||
}
|
||||
curr_page_cap = msf_get_page_count_cap(msf->page_data_list, msf->page_size);
|
||||
}
|
||||
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
@@ -7123,58 +7123,96 @@ TEST(get_msf_stream_pages)
|
||||
|
||||
TEST(msf_header_matches_saved_extent)
|
||||
{
|
||||
MSF_UInt page_sizes[] = {512, 4096};
|
||||
MSF_UInt page_sizes[] = {512, KB(4)};
|
||||
MSF_UInt fpms[] = {MSF_FPM0, MSF_FPM1};
|
||||
|
||||
for EachIndex(size_idx, ArrayCount(page_sizes)) {
|
||||
MSF_UInt page_size = page_sizes[size_idx];
|
||||
MSF_PageNumber last_pages[] = {68, page_size - 1, page_size, page_size + 3,
|
||||
page_size * 8 - 1, page_size * 8, page_size * 8 + 3};
|
||||
// Cover an entire FPM's bitmap with small pages, and the default page size's
|
||||
// first interval without making this a large-memory test.
|
||||
U64 case_count = page_size == 512 ? ArrayCount(last_pages) : 4;
|
||||
MSF_UInt P = page_sizes[size_idx];
|
||||
|
||||
// Exercise physical FPM-slot boundaries and transitions between bitmap intervals.
|
||||
//
|
||||
// P * 2 and P * 7: intermediate valid slot-zero pages.
|
||||
// P * 16 - 1: end of the second bitmap interval.
|
||||
// P * 16: first page in the third interval.
|
||||
// P * 16 + 3: first ordinary page after reserved FPM slots.
|
||||
//
|
||||
// Both active FPM choices.
|
||||
//
|
||||
MSF_PageNumber last_pages[] = {
|
||||
68,
|
||||
P - 1,
|
||||
P,
|
||||
P + 3,
|
||||
P * 2,
|
||||
P * 7,
|
||||
P * 8 - 1,
|
||||
P * 8,
|
||||
P * 8 + 3,
|
||||
P * 16 - 1,
|
||||
P * 16,
|
||||
P * 16 + 3,
|
||||
};
|
||||
// Full bitmap coverage is inexpensive with 512-byte pages. With 4 KiB
|
||||
// pages, stop after the first physical FPM-slot boundary.
|
||||
U64 case_count = P == 512 ? ArrayCount(last_pages) : 4;
|
||||
for EachIndex(fpm_idx, ArrayCount(fpms)) {
|
||||
for EachIndex(case_idx, case_count) {
|
||||
Temp temp = temp_begin(arena);
|
||||
MSF_Context *msf = msf_alloc(page_size, fpms[fpm_idx]);
|
||||
MSF_Context *msf = msf_alloc(P, fpms[fpm_idx]);
|
||||
|
||||
// Leave low pages for the stream table and root so that the final data
|
||||
// page, not metadata, determines EOF. This also exercises a sparse file.
|
||||
MSF_PageList gap = msf_alloc_pages(msf, 64);
|
||||
T_Ok(gap.first->pn == 4 && gap.last->pn == 67);
|
||||
MSF_PageNumber last_pn = last_pages[case_idx];
|
||||
MSF_UInt data_page_count = 0;
|
||||
|
||||
// Cover an entire FPM's bitmap with small pages, and the default page size's
|
||||
// first interval without making this a large-memory test.
|
||||
MSF_PageNumber last_pn = last_pages[case_idx];
|
||||
MSF_UInt data_page_count = 0;
|
||||
for (MSF_PageNumber pn = 68; pn <= last_pn; ++pn) {
|
||||
MSF_UInt slot = pn % page_size;
|
||||
MSF_UInt slot = pn % P;
|
||||
data_page_count += slot != MSF_FPM0 && slot != MSF_FPM1;
|
||||
}
|
||||
String8 payload = str8(push_array_no_zero(arena, U8, (U64)data_page_count * page_size),
|
||||
(U64)data_page_count * page_size);
|
||||
String8 payload = str8(push_array_no_zero(arena, U8, (U64)data_page_count * P),
|
||||
(U64)data_page_count * P);
|
||||
MemorySet(payload.str, 0xA5, payload.size);
|
||||
|
||||
MSF_StreamNumber sn = msf_stream_alloc(msf);
|
||||
T_Ok(msf_stream_write(msf, sn, payload.str, (MSF_UInt)payload.size));
|
||||
T_Ok(msf_find_stream(msf, sn)->page_list.last->pn == last_pn);
|
||||
|
||||
// Free the low pages so metadata can reuse them while the payload remains at
|
||||
// high page numbers. Unused pages below EOF exercise sparse MSF page layouts.
|
||||
msf_free_pages(msf, &gap);
|
||||
T_Ok(msf_build(msf) == MSF_Error_OK);
|
||||
T_Ok(msf->root_page_list.last->pn < last_pn);
|
||||
T_Ok(msf->st_page_list.last->pn < last_pn);
|
||||
|
||||
// validate that last page was assigned to the payload
|
||||
U64 save_size = msf_get_save_size(msf);
|
||||
T_Ok(save_size == ((U64)last_pn + 1) * page_size);
|
||||
T_Ok(save_size == ((U64)last_pn + 1) * P);
|
||||
|
||||
// allocate buffer for the serialized MSF file
|
||||
String8 saved = str8(push_array_no_zero(arena, U8, save_size), save_size);
|
||||
T_Ok(msf_save(msf, saved.str, saved.size));
|
||||
|
||||
// validate 'page_count' field matches the serialized file size
|
||||
MSF_Header70 *header = (MSF_Header70 *)saved.str;
|
||||
T_Ok((U64)header->page_count * header->page_size == saved.size);
|
||||
|
||||
// match internal page data list to the serialized file bytes
|
||||
String8List pages = msf_get_page_data_nodes(arena, msf);
|
||||
T_Ok(str8_match(saved, str8_list_join(arena, &pages, 0), 0));
|
||||
|
||||
// Size agreement alone must not conceal a truncated final stream page.
|
||||
MSF_Parsed *parsed = msf_parsed_from_data(arena, saved);
|
||||
T_Ok(parsed != 0);
|
||||
|
||||
// validate parsed stream against the expected payload
|
||||
if (parsed != 0 && sn < parsed->stream_count) {
|
||||
T_Ok(str8_match(parsed->streams[sn], payload, 0));
|
||||
} else {
|
||||
T_Ok(0);
|
||||
}
|
||||
|
||||
msf_release(msf);
|
||||
temp_end(temp);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user