summaryrefslogtreecommitdiff
path: root/tests/snapshot_failure_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/snapshot_failure_test.c')
-rw-r--r--tests/snapshot_failure_test.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/tests/snapshot_failure_test.c b/tests/snapshot_failure_test.c
new file mode 100644
index 0000000..4133bfd
--- /dev/null
+++ b/tests/snapshot_failure_test.c
@@ -0,0 +1,91 @@
+#include "term/term.h"
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+static bool fail_next_realloc;
+static int malloc_failure_countdown = -1;
+static bool malloc_was_failed;
+void *__real_malloc(size_t);
+void *__wrap_malloc(size_t size)
+{
+ if (malloc_failure_countdown >= 0) {
+ if (malloc_failure_countdown-- == 0) {
+ malloc_failure_countdown = -1;
+ malloc_was_failed = true;
+ return NULL;
+ }
+ }
+ return __real_malloc(size);
+}
+
+void *__real_realloc(void *, size_t);
+void *__wrap_realloc(void *p, size_t size)
+{
+ if (fail_next_realloc) {
+ fail_next_realloc = false;
+ return NULL;
+ }
+ return __real_realloc(p, size);
+}
+
+int main(void)
+{
+ struct term_options options = { .size = { 8, 3 }, .scrollback = 5 };
+ struct term *term = term_new(&options);
+ struct term_snapshot *snapshot = term_snapshot_new();
+ assert(term && snapshot && term_snapshot_update(snapshot, term));
+
+ const char accented[] = "e\xcc\x81";
+ term_feed(term, accented, sizeof(accented) - 1, 0);
+ fail_next_realloc = true;
+ assert(!term_snapshot_update(snapshot, term));
+ assert(!fail_next_realloc);
+ assert(term_snapshot_view(snapshot)->size.x == 0);
+ assert(term_snapshot_view(snapshot)->size.y == 0);
+ assert(term_snapshot_row(snapshot, 0) == NULL);
+
+ assert(term_snapshot_update(snapshot, term));
+ const struct term_cell *row = term_snapshot_row(snapshot, 0);
+ assert(row);
+ uint32_t cps[4];
+ assert(term_snapshot_cluster(snapshot, row[0].text, cps, 4) == 2);
+ assert(cps[0] == 'e' && cps[1] == 0x301);
+
+ term_snapshot_free(snapshot);
+ term_free(term);
+
+ /* More than 256 rows moves both temporary arrays off the stack. */
+ options.size.y = 300;
+ term = term_new(&options);
+ snapshot = term_snapshot_new();
+ assert(term && snapshot && term_snapshot_update(snapshot, term));
+
+ /* Fail new_keys allocation, then make sure retry fills all rows. */
+ malloc_was_failed = false;
+ malloc_failure_countdown = 0;
+ assert(!term_snapshot_update(snapshot, term));
+ assert(malloc_was_failed);
+ assert(term_snapshot_view(snapshot)->size.y == 0);
+ assert(term_snapshot_row(snapshot, 0) == NULL);
+ assert(term_snapshot_update(snapshot, term));
+ assert(term_snapshot_view(snapshot)->size.y == 300);
+ assert(term_snapshot_row(snapshot, 299));
+
+ /* The first malloc is new_keys; fail the following selection-span array. */
+ malloc_was_failed = false;
+ malloc_failure_countdown = 1;
+ assert(!term_snapshot_update(snapshot, term));
+ assert(malloc_was_failed);
+ assert(term_snapshot_view(snapshot)->size.y == 0);
+ assert(term_snapshot_row(snapshot, 0) == NULL);
+ assert(term_snapshot_update(snapshot, term));
+ assert(term_snapshot_view(snapshot)->size.y == 300);
+ assert(term_snapshot_row(snapshot, 299));
+
+ term_snapshot_free(snapshot);
+ term_free(term);
+ return 0;
+}