diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-15 11:25:24 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-15 11:25:24 +0300 |
| commit | f97c3a585e2efc1d0a4bc10e6ac04b96ee6428ea (patch) | |
| tree | e97edea243d3fbabc4eee054746e743f63ac6913 /tests/correctness_probe.c | |
| parent | 13bf7edad251df9943bd75665a3510535849b0ac (diff) | |
Document correctness findings and save reproduction probe
Diffstat (limited to 'tests/correctness_probe.c')
| -rw-r--r-- | tests/correctness_probe.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/tests/correctness_probe.c b/tests/correctness_probe.c new file mode 100644 index 0000000..0b55211 --- /dev/null +++ b/tests/correctness_probe.c @@ -0,0 +1,80 @@ +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +/* Include the implementation to inspect snapshot arena accounting. Link + * against the static library so snapshot.c is compiled only here. */ +#include "../src/snapshot.c" + +static int fail_realloc; +static int fail_resize_calloc; +void *__real_realloc(void *, size_t); +void *__real_calloc(size_t, size_t); +void *__wrap_calloc(size_t n, size_t size) +{ + if (fail_resize_calloc && n == 2 && size == sizeof(struct srow)) { + fail_resize_calloc = 0; + return NULL; + } + return __real_calloc(n, size); +} +void *__wrap_realloc(void *ptr, size_t size) +{ + if (fail_realloc) { fail_realloc = 0; return NULL; } + return __real_realloc(ptr, size); +} + +int main(void) +{ + struct term_options options = { .size = { 8, 3 }, .scrollback = 5 }; + struct term *t = term_new(&options); + struct term_snapshot *s = term_snapshot_new(); + assert(t && s && term_snapshot_update(s, t)); + const char accented[] = "e\xcc\x81"; + term_feed(t, accented, sizeof(accented) - 1, 0); + fail_realloc = 1; + bool ok = term_snapshot_update(s, t); + uint32_t cps[16]; + int n = term_snapshot_cluster(s, term_snapshot_row(s, 0)[0].text, cps, 16); + printf("snapshot arena allocation failure: update=%d cluster_length=%d (expected false, or length 2)\n", ok, n); + assert(term_snapshot_update(s, t)); + n = term_snapshot_cluster(s, term_snapshot_row(s, 0)[0].text, cps, 16); + printf("retry after allocation recovers: cluster_length=%d (expected 2)\n", n); + term_snapshot_free(s); + term_free(t); + + options.size.y = 24; + t = term_new(&options); + s = term_snapshot_new(); + assert(t && s); + const char line[] = "e\xcc\x81\r\n"; + for (int i = 1; i <= 10000; i++) { + term_feed(t, line, sizeof(line) - 1, 0); + assert(term_snapshot_update(s, t)); + if (i == 1000 || i == 10000) + printf("after %d lines: arena_words=%u dead_words=%u history_rows=%d\n", + i, s->arena_len, s->arena_dead, term_history_rows(t)); + } + term_snapshot_free(s); + term_free(t); + + options.size = (struct term_vector2i){ 8, 4 }; + t = term_new(&options); + s = term_snapshot_new(); + assert(t && s); + const char rows[] = "A\r\nB\r\nC\r\nD"; + term_feed(t, rows, sizeof(rows) - 1, 0); + assert(term_snapshot_update(s, t)); + printf("before failed height shrink: top=%c cursor_y=%d history=%d\n", + (char)term_snapshot_row(s, 0)[0].text, term_cursor(t).pos.y, term_history_rows(t)); + fail_resize_calloc = 1; + ok = term_resize(t, (struct term_vector2i){ 8, 2 }); + assert(!fail_resize_calloc); + assert(term_snapshot_update(s, t)); + printf("after failed height shrink: resize=%d height=%d top=%c cursor_y=%d history=%d\n", + ok, term_size(t).y, (char)term_snapshot_row(s, 0)[0].text, + term_cursor(t).pos.y, term_history_rows(t)); + term_snapshot_free(s); + term_free(t); + return 0; +} |
