diff options
| author | Berke GΓΌzel <wenekar1@gmail.com> | 2026-10-12 17:49:34 +0300 |
|---|---|---|
| committer | Berke GΓΌzel <wenekar1@gmail.com> | 2026-10-12 17:49:34 +0300 |
| commit | 4384435941b8c7658856b381d071aee2e0035e89 (patch) | |
| tree | 5ece99c3dd1decb8ec3fd404c0ece2b5865a552a /tests/history_text_test.c | |
term: move the term core to subprojects/term
The core now builds, tests, and benchmarks alone, as a Meson subproject
with no dependency on the main tree.
- include/term/ holds term.h and the header-only unicode/. src/ holds
the core and its private headers. The main tree gets only
include/term through term_dep, so it cannot reach a private header.
- The term tests, the term benchmarks, the Kitty parser suite, and
tools/amalgamate.py and tools/generate_unicode.py move with it. The
tests run as term:<name>.
- The main build passes its -march (arch_flag) and b_ndebug to the
subproject. A directory configured before this commit needs
meson configure -Dterm:arch_flag=-march=... once.
- The term tests compile with -UNDEBUG. They do work inside assert.
- The subproject exports term_test_dep with term_api.h, for the main
tree's render, thumbnail, color, and selection tests.
- The Kitty bridge used struct vector2i and has not compiled since the
public API redesign. It builds again. 2 of its 14 tests fail: REP
after a tab, and a cursor report after a resize.
- dirgraph.py drops the term and unicode layers. Its self-test uses pty.
- The symbols test ignores the __odr_asan symbols that ASan adds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests/history_text_test.c')
| -rw-r--r-- | tests/history_text_test.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/tests/history_text_test.c b/tests/history_text_test.c new file mode 100644 index 0000000..88ca6aa --- /dev/null +++ b/tests/history_text_test.c @@ -0,0 +1,135 @@ +#include "term/term.h" +#include "term_api.h" + +#include <assert.h> +#include <pthread.h> +#include <stdatomic.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static struct term *new_term(int cols) +{ + struct term *term = term_new(&(struct term_options){ + .size = { .x = cols, .y = 2 }, + .scrollback = 100, + }); + assert(term); + return term; +} + +static void feed(struct term *term, const char *text) +{ + term_feed(term, text, strlen(text), 0); +} + +static void expect_history(struct term *term, int rows, const char *expected) +{ + char *text = tt_history_text(term, rows); + assert(text); + if (strcmp(text, expected)) { + fprintf(stderr, "history: got \"%s\" want \"%s\"\n", text, expected); + assert(0); + } + free(text); +} + +static void unicode_and_selection(void) +{ + struct term *term = new_term(16); + expect_history(term, 100, ""); + feed(term, "eΜπ©βπ»η\r\nnext\r\nlast"); + expect_history(term, 100, "eΜπ©βπ»η\n"); + expect_history(term, 0, ""); + term_select_start(term, (struct term_vector2i){0}, false, TERM_SELECT_CELL); + term_select_extend(term, (struct term_vector2i){ .x = 4 }, false); + char *before = tt_selection_text(term); + assert(before); + expect_history(term, 100, "eΜπ©βπ»η\n"); + char *after = tt_selection_text(term); + assert(after && !strcmp(before, after)); + free(before); + free(after); + feed(term, "\033[?1049h"); + expect_history(term, 100, ""); + feed(term, "\033[?1049l"); + expect_history(term, 100, "eΜπ©βπ»η\n"); + term_free(term); +} + +static void limits_and_scrolled_view(void) +{ + struct term *term = new_term(8); + feed(term, "one\r\ntwo\r\nthree\r\nfour\r\nfive"); + expect_history(term, 100, "one\ntwo\nthree\n"); + expect_history(term, 2, "two\nthree\n"); + term_scroll(term, 2); + expect_history(term, 100, "one\n"); + term_scroll(term, 100); + expect_history(term, 100, ""); + term_scroll_to(term, 0); + assert(term_resize(term, (struct term_vector2i){ .x = 12, .y = 2 })); + expect_history(term, 100, "one\ntwo\nthree\n"); + term_free(term); +} + +static void wrapped_rows(void) +{ + struct term *term = new_term(4); + feed(term, "abcdefghi\r\nx\r\ny"); + expect_history(term, 100, "abcdefghi\n"); + expect_history(term, 2, "efghi\n"); + term_free(term); + + term = new_term(4); + feed(term, "abcdefghijklm"); + expect_history(term, 100, "abcdefgh"); + term_free(term); +} + +struct writer { + struct term *term; + _Atomic bool done; +}; + +static const char unicode_line[] = "eΜπ©βπ»η\r\n"; +static const char history_line[] = "eΜπ©βπ»η\n"; + +static void *write_history(void *userdata) +{ + struct writer *writer = userdata; + for (int i = 0; i < 1000; i++) + feed(writer->term, unicode_line); + atomic_store(&writer->done, true); + return NULL; +} + +static void concurrent_history(void) +{ + struct term *term = new_term(16); + struct writer writer = { .term = term }; + pthread_t thread; + assert(pthread_create(&thread, NULL, write_history, &writer) == 0); + do { + char *text = tt_history_text(term, 10); + assert(text); + size_t n = strlen(text); + size_t line_len = sizeof(history_line) - 1; + assert(n % line_len == 0 && n / line_len <= 10); + for (size_t offset = 0; offset < n; offset += line_len) + assert(!memcmp(text + offset, history_line, line_len)); + free(text); + } while (!atomic_load(&writer.done)); + assert(pthread_join(thread, NULL) == 0); + term_free(term); +} + +int main(void) +{ + unicode_and_selection(); + limits_and_scrolled_view(); + wrapped_rows(); + concurrent_history(); + puts("PASS: history text"); + return 0; +} |
