summaryrefslogtreecommitdiff
path: root/tests/history_text_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/history_text_test.c')
-rw-r--r--tests/history_text_test.c135
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;
+}