test(PageList): add failing test for reflow hyperlink OOM

pull/8277/head
Qwerasd 2025-08-18 18:24:57 -06:00
parent 6fdaf21b82
commit 61fc290ad1
2 changed files with 96 additions and 1 deletions

View File

@ -7029,6 +7029,7 @@ test "PageList resize reflow less cols wrap across page boundary cursor in secon
try testing.expect(!cells[3].hasText());
}
}
test "PageList resize reflow more cols cursor in wrapped row" {
const testing = std.testing;
const alloc = testing.allocator;
@ -7222,6 +7223,100 @@ test "PageList resize reflow more cols no reflow preserves semantic prompt" {
}
}
test "PageList resize reflow exceeds hyperlink memory forcing capacity increase" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, 2, 10, 0);
defer s.deinit();
try testing.expectEqual(@as(usize, 1), s.totalPages());
// Grow to the capacity of the first page and add
// one more row so that we have two pages total.
{
const page = &s.pages.first.?.data;
page.pauseIntegrityChecks(true);
for (page.size.rows..page.capacity.rows) |_| {
_ = try s.grow();
}
page.pauseIntegrityChecks(false);
try testing.expectEqual(@as(usize, 1), s.totalPages());
try s.growRows(1);
try testing.expectEqual(@as(usize, 2), s.totalPages());
// We now have two pages.
try std.testing.expect(s.pages.first.? != s.pages.last.?);
try std.testing.expectEqual(s.pages.last.?, s.pages.first.?.next);
}
// We use almost all string alloc capacity with a hyperlink in the final
// row of the first page, and do the same on the first row of the second
// page. We also mark the row as wrapped so that when we resize with more
// cols the row unwraps and we have a single row that requires almost two
// times the base string alloc capacity.
//
// This forces the reflow to increase capacity.
//
// +--+ = PAGE 0
// : :
// | X <- where X is hyperlinked with almost all string cap.
// +--+
// +--+ = PAGE 1
// X | <- X here also almost hits string cap with a hyperlink.
// +--+
// Almost hit string alloc cap in bottom right of first page.
// Mark the final row as wrapped.
{
const page = &s.pages.first.?.data;
const id = try page.insertHyperlink(.{
.id = .{ .implicit = 0 },
.uri = "a" ** (pagepkg.string_bytes_default - 1),
});
const rac = page.getRowAndCell(page.size.cols - 1, page.size.rows - 1);
rac.row.wrap = true;
rac.cell.* = .{
.content_tag = .codepoint,
.content = .{ .codepoint = 'X' },
};
try page.setHyperlink(rac.row, rac.cell, id);
try std.testing.expectError(
error.StringsOutOfMemory,
page.insertHyperlink(.{
.id = .{ .implicit = 1 },
.uri = "AAAAAAAAAAAAAAAAAAAAAAAAAA",
}),
);
}
// Almost hit string alloc cap in top left of second page.
// Mark the first row as a wrap continuation.
{
const page = &s.pages.last.?.data;
const id = try page.insertHyperlink(.{
.id = .{ .implicit = 1 },
.uri = "a" ** (pagepkg.string_bytes_default - 1),
});
const rac = page.getRowAndCell(0, 0);
rac.row.wrap_continuation = true;
rac.cell.* = .{
.content_tag = .codepoint,
.content = .{ .codepoint = 'X' },
};
try page.setHyperlink(rac.row, rac.cell, id);
try std.testing.expectError(
error.StringsOutOfMemory,
page.insertHyperlink(.{
.id = .{ .implicit = 2 },
.uri = "AAAAAAAAAAAAAAAAAAAAAAAAAA",
}),
);
}
// Resize to 1 column wider, unwrapping the row.
try s.resize(.{ .cols = s.cols + 1, .reflow = true });
}
test "PageList resize reflow more cols unwrap wide spacer head" {
const testing = std.testing;
const alloc = testing.allocator;

View File

@ -53,7 +53,7 @@ const string_chunk_len = 32;
const string_chunk = string_chunk_len * @sizeOf(u8);
const StringAlloc = BitmapAllocator(string_chunk);
const string_count_default = StringAlloc.bitmap_bit_size;
const string_bytes_default = string_count_default * string_chunk;
pub const string_bytes_default = string_count_default * string_chunk;
/// Default number of hyperlinks we support.
///