summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAlbert Cervin <albert@acervin.com>2023-02-11 23:03:39 +0100
committerAlbert Cervin <albert@acervin.com>2023-02-15 23:41:35 +0100
commite45499816eab8abadbdd5bb6dd79b526a4ed6648 (patch)
tree3cdcb0238aaae8ed1b3578e4ad71883f0702de3c /test
parentc2976cea9bbca465712534b7e523783e2ccc6c6e (diff)
downloaddged-e45499816eab8abadbdd5bb6dd79b526a4ed6648.tar.gz
dged-e45499816eab8abadbdd5bb6dd79b526a4ed6648.tar.xz
dged-e45499816eab8abadbdd5bb6dd79b526a4ed6648.zip
Implement undo
This also fixes a bunch of valgrind errors
Diffstat (limited to 'test')
-rw-r--r--test/buffer.c2
-rw-r--r--test/command.c6
-rw-r--r--test/keyboard.c1
-rw-r--r--test/main.c3
-rw-r--r--test/minibuffer.c21
-rw-r--r--test/test.h1
-rw-r--r--test/text.c36
-rw-r--r--test/undo.c104
8 files changed, 157 insertions, 17 deletions
diff --git a/test/buffer.c b/test/buffer.c
index 9781a6d..38ce468 100644
--- a/test/buffer.c
+++ b/test/buffer.c
@@ -41,6 +41,8 @@ void test_move() {
ASSERT(
b.dot.col == 0 && b.dot.line == 0,
"Expected to not be able to move backwards when at beginning of buffer");
+
+ buffer_destroy(&b);
}
void run_buffer_tests() { run_test(test_move); }
diff --git a/test/command.c b/test/command.c
index be5fffc..09de7f4 100644
--- a/test/command.c
+++ b/test/command.c
@@ -53,6 +53,8 @@ void test_register_command() {
"Expected number of commands to be 3 after inserting two more");
ASSERT(cmds.capacity > 1,
"Expected capacity to have increased to accommodate new commands");
+
+ command_registry_destroy(&cmds);
}
void test_lookup_command() {
@@ -70,6 +72,8 @@ void test_lookup_command() {
"Expected to be able to look up inserted command by hash");
ASSERT_STR_EQ(cmd->name, "fake",
"Expected the found function to have the correct name");
+
+ command_registry_destroy(&cmds);
}
int32_t failing_command(struct command_ctx ctx, int argc, const char *argv[]) {
@@ -91,6 +95,8 @@ void test_execute_command() {
struct command *fail_cmd = lookup_command(&cmds, "fejl");
int32_t res2 = execute_command(fail_cmd, &cmds, NULL, NULL, 0, NULL);
ASSERT(res2 != 0, "Expected failing command to fail");
+
+ command_registry_destroy(&cmds);
}
void run_command_tests() {
diff --git a/test/keyboard.c b/test/keyboard.c
index b85c4ad..a76d2a7 100644
--- a/test/keyboard.c
+++ b/test/keyboard.c
@@ -68,6 +68,7 @@ void fake_keyboard_close_write(struct fake_keyboard *kbd) {
void fake_keyboard_destroy(struct fake_keyboard *kbd) {
fake_keyboard_close_write(kbd);
+ reactor_destroy(kbd->reactor);
}
void simple_key() {
diff --git a/test/main.c b/test/main.c
index 7663f8f..a999b43 100644
--- a/test/main.c
+++ b/test/main.c
@@ -21,6 +21,9 @@ int main() {
printf("\n📜 \x1b[1;36mRunning text tests...\x1b[0m\n");
run_text_tests();
+ printf("\n⏪ \x1b[1;36mRunning undo tests...\x1b[0m\n");
+ run_undo_tests();
+
printf("\n🕴️ \x1b[1;36mRunning buffer tests...\x1b[0m\n");
run_buffer_tests();
diff --git a/test/minibuffer.c b/test/minibuffer.c
index dc29648..0e41c7b 100644
--- a/test/minibuffer.c
+++ b/test/minibuffer.c
@@ -2,12 +2,17 @@
#include "stdlib.h"
#include "test.h"
+#include "allocator.h"
#include "buffer.h"
#include "display.h"
#include "minibuffer.h"
static struct buffer b = {0};
+static struct frame_allocator *g_alloc = NULL;
+
+void *alloc_fn(size_t sz) { return frame_allocator_alloc(g_alloc, sz); }
+
void init() {
if (b.name == NULL) {
b = buffer_create("minibuffer", false);
@@ -16,12 +21,21 @@ void init() {
minibuffer_init(&b);
}
+void destroy() {
+ if (b.name != NULL) {
+ buffer_destroy(&b);
+ }
+}
+
void test_minibuffer_echo() {
uint32_t relline, relcol;
// TODO: how to clear this?
+ struct frame_allocator alloc = frame_allocator_create(1024);
+ g_alloc = &alloc;
+
struct command_list *list =
- command_list_create(10, malloc, 0, 0, "minibuffer");
+ command_list_create(10, alloc_fn, 0, 0, "minibuffer");
init();
ASSERT(!minibuffer_displaying(),
@@ -38,6 +52,10 @@ void test_minibuffer_echo() {
buffer_update(&b, 100, 1, list, 0, &relline, &relcol);
ASSERT(!minibuffer_displaying(),
"A zero timeout echo should be cleared after first update");
+
+ frame_allocator_destroy(&alloc);
+ g_alloc = NULL;
+ destroy();
}
int32_t fake(struct command_ctx ctx, int argc, const char *argv[]) { return 0; }
@@ -64,6 +82,7 @@ void test_minibuffer_prompt() {
minibuffer_abort_prompt();
ASSERT(!minibuffer_focused(),
"Minibuffer must not be focused after prompt has been aborted");
+ destroy();
}
void run_minibuffer_tests() {
diff --git a/test/test.h b/test/test.h
index f777916..4dab62e 100644
--- a/test/test.h
+++ b/test/test.h
@@ -12,6 +12,7 @@
void run_buffer_tests();
void run_utf8_tests();
void run_text_tests();
+void run_undo_tests();
void run_command_tests();
void run_keyboard_tests();
void run_allocator_tests();
diff --git a/test/text.c b/test/text.c
index 9c8d825..cb18df5 100644
--- a/test/text.c
+++ b/test/text.c
@@ -8,6 +8,10 @@
#include <string.h>
#include <wchar.h>
+void assert_line_eq(struct text_chunk line, const char *txt, const char *msg) {
+ ASSERT(strncmp((const char *)line.text, txt, line.nbytes) == 0, msg);
+}
+
void assert_line_equal(struct text_chunk *line) {}
void test_add_text() {
@@ -24,16 +28,16 @@ void test_add_text() {
ASSERT(text_line_size(t, 0) == 14 && text_line_length(t, 0) == 14,
"Expected line 1 to have 14 chars and 14 bytes");
- ASSERT_STR_EQ((const char *)text_get_line(t, 0).text, "This is line 1",
- "Expected line 1 to be line 1");
+ assert_line_eq(text_get_line(t, 0), "This is line 1",
+ "Expected line 1 to be line 1");
const char *txt2 = "This is line 2\n";
text_insert_at(t, 1, 0, (uint8_t *)txt2, strlen(txt2), &lines_added,
&cols_added);
ASSERT(text_num_lines(t) == 2,
"Expected text to have two lines after second insertion");
- ASSERT_STR_EQ((const char *)text_get_line(t, 1).text, "This is line 2",
- "Expected line 2 to be line 2");
+ assert_line_eq(text_get_line(t, 1), "This is line 2",
+ "Expected line 2 to be line 2");
// simulate indentation
const char *txt3 = " ";
@@ -41,19 +45,18 @@ void test_add_text() {
&cols_added);
ASSERT(text_num_lines(t) == 2,
"Expected text to have two lines after second insertion");
- ASSERT_STR_EQ((const char *)text_get_line(t, 0).text, " This is line 1",
- "Expected line 1 to be indented");
- ASSERT_STR_EQ((const char *)text_get_line(t, 1).text, "This is line 2",
- "Expected line 2 to be line 2 still");
+ assert_line_eq(text_get_line(t, 0), " This is line 1",
+ "Expected line 1 to be indented");
+ assert_line_eq(text_get_line(t, 1), "This is line 2",
+ "Expected line 2 to be line 2 still");
// insert newline in middle of line
text_insert_at(t, 1, 4, (uint8_t *)"\n", 1, &lines_added, &cols_added);
ASSERT(text_num_lines(t) == 3,
"Expected text to have three lines after inserting a new line");
- ASSERT_STR_EQ((const char *)text_get_line(t, 1).text, "This",
- "Expected line 2 to be split");
- ASSERT_STR_EQ((const char *)text_get_line(t, 2).text, " is line 2",
- "Expected line 2 to be split");
+ assert_line_eq(text_get_line(t, 1), "This", "Expected line 2 to be split");
+ assert_line_eq(text_get_line(t, 2), " is line 2",
+ "Expected line 2 to be split");
// insert newline before line 1
text_insert_at(t, 1, 0, (uint8_t *)"\n", 1, &lines_added, &cols_added);
@@ -61,10 +64,10 @@ void test_add_text() {
text_num_lines(t) == 4,
"Expected to have four lines after adding an empty line in the middle");
ASSERT(text_line_length(t, 1) == 0, "Expected line 2 to be empty");
- ASSERT_STR_EQ((const char *)text_get_line(t, 2).text, "This",
- "Expected line 3 to be previous line 2");
- ASSERT_STR_EQ((const char *)text_get_line(t, 3).text, " is line 2",
- "Expected line 4 to be previous line 3");
+ assert_line_eq(text_get_line(t, 2), "This",
+ "Expected line 3 to be previous line 2");
+ assert_line_eq(text_get_line(t, 3), " is line 2",
+ "Expected line 4 to be previous line 3");
text_destroy(t);
}
@@ -151,6 +154,7 @@ void test_delete_text() {
text_destroy(t);
text_destroy(t2);
text_destroy(t3);
+ text_destroy(t4);
}
void run_text_tests() {
diff --git a/test/undo.c b/test/undo.c
new file mode 100644
index 0000000..d0e2fdb
--- /dev/null
+++ b/test/undo.c
@@ -0,0 +1,104 @@
+#include "assert.h"
+#include "test.h"
+
+#include "undo.h"
+#include <stdlib.h>
+
+void test_undo_insert() {
+ struct undo_stack undo;
+
+ /* small capacity on purpose to force re-sizing */
+ undo_init(&undo, 1);
+
+ undo_push_boundary(&undo, (struct undo_boundary){.save_point = true});
+ ASSERT(undo_size(&undo) == 1,
+ "Expected undo stack to have one item after inserting a save point");
+
+ undo_push_boundary(&undo, (struct undo_boundary){});
+ ASSERT(undo_size(&undo) == 2,
+ "Expected undo stack to have two items after inserting a boundary");
+
+ undo_push_add(&undo, (struct undo_add){.begin = {.col = 0, .row = 0},
+ .end = {.col = 4, .row = 0}});
+ ASSERT(undo_size(&undo) == 3,
+ "Expected undo stack to have three items after inserting an add");
+
+ undo_push_delete(&undo, (struct undo_delete){.pos = {.row = 0, .col = 3},
+ .data = NULL,
+ .nbytes = 0});
+
+ ASSERT(undo_size(&undo) == 4,
+ "Expected undo stack to have four items after inserting a delete");
+
+ ASSERT(undo_current_position(&undo) == undo_size(&undo) - 1,
+ "Undo stack position should be at the top after inserting");
+
+ undo_destroy(&undo);
+}
+
+void test_undo() {
+ struct undo_stack undo;
+ undo_init(&undo, 10);
+
+ undo_push_boundary(&undo, (struct undo_boundary){.save_point = true});
+ undo_push_add(&undo, (struct undo_add){.begin = {.row = 0, .col = 10},
+ .end = {.row = 2, .col = 3}});
+
+ struct undo_record *records = NULL;
+ uint32_t nrecords = 0;
+
+ undo_next(&undo, &records, &nrecords);
+ ASSERT(nrecords == 2, "Expected to get back two records");
+ ASSERT(records[0].type == Undo_Add,
+ "Expected first returned record to be an add");
+ free(records);
+
+ ASSERT(undo_current_position(&undo) == INVALID_TOP,
+ "Expected undo stack position to have changed after undo");
+
+ // check that undo begin causes the top of the stack to not be reset
+ undo_begin(&undo);
+ undo_push_add(&undo, (struct undo_add){.begin = {.row = 0, .col = 10},
+ .end = {.row = 0, .col = 12}});
+ undo_end(&undo);
+
+ ASSERT(undo_current_position(&undo) == INVALID_TOP,
+ "Expected undo stack position to not have changed when undo "
+ "information was added as part of an undo");
+
+ // but now it should
+ undo_push_add(&undo, (struct undo_add){.begin = {.row = 0, .col = 10},
+ .end = {.row = 0, .col = 12}});
+
+ ASSERT(undo_current_position(&undo) == 3,
+ "Expected undo stack position to have changed when undo information "
+ "was added");
+
+ // test that it gets reset to top
+ undo_begin(&undo);
+ records = NULL;
+ undo_next(&undo, &records, &nrecords);
+ free(records);
+
+ undo_push_add(&undo, (struct undo_add){.begin = {.row = 0, .col = 10},
+ .end = {.row = 0, .col = 12}});
+ undo_push_boundary(&undo, (struct undo_boundary){.save_point = false});
+ undo_push_add(&undo, (struct undo_add){.begin = {.row = 0, .col = 10},
+ .end = {.row = 0, .col = 12}});
+
+ records = NULL;
+ undo_next(&undo, &records, &nrecords);
+ free(records);
+
+ undo_end(&undo);
+ ASSERT(
+ undo_current_position(&undo) == 4,
+ "Expected undo stack position to have been reset when it reached zero");
+
+ undo_destroy(&undo);
+}
+
+void run_undo_tests() {
+ run_test(test_undo_insert);
+ run_test(test_undo);
+}