diff options
Diffstat (limited to 'test/buffer.c')
| -rw-r--r-- | test/buffer.c | 193 |
1 files changed, 188 insertions, 5 deletions
diff --git a/test/buffer.c b/test/buffer.c index a4b318e..7d879b0 100644 --- a/test/buffer.c +++ b/test/buffer.c @@ -1,11 +1,21 @@ #include <string.h> #include "dged/buffer.h" +#include "dged/settings.h" #include "assert.h" #include "test.h" -void test_add() { +static uint32_t add_callback_call_count = 0; +static void add_callback(struct buffer *buffer, struct edit_location added, + void *userdata) { + (void)buffer; + (void)added; + (void)userdata; + ++add_callback_call_count; +} + +static void test_add(void) { struct buffer b = buffer_create("test-buffer"); ASSERT(buffer_num_lines(&b) == 0, "Expected buffer to have zero lines"); @@ -16,10 +26,62 @@ void test_add() { ASSERT(loc.line == 1 && loc.col == strlen(txt), "Expected buffer to have one line with characters"); + // test callback + uint32_t hook_id = buffer_add_insert_hook(&b, add_callback, NULL); + buffer_add(&b, (struct location){.line = 0, .col = 0}, (uint8_t *)"hej", 3); + ASSERT(add_callback_call_count == 1, "Expected callback to have been called"); + + // test removing the hook + buffer_remove_insert_hook(&b, hook_id, NULL); + buffer_add(&b, (struct location){.line = 0, .col = 0}, (uint8_t *)"hej", 3); + ASSERT(add_callback_call_count == 1, + "Expected callback to not have been called after it has been removed"); + buffer_destroy(&b); } -void test_word_at() { +static uint32_t delete_callback_call_count = 0; +static void delete_callback(struct buffer *buffer, struct edit_location removed, + void *userdata) { + (void)buffer; + (void)removed; + (void)userdata; + ++delete_callback_call_count; +} + +static void test_delete(void) { + struct buffer b = buffer_create("test-buffer-delete"); + const char *txt = "we are adding some text\ntwo lines to be exact"; + struct location loc = buffer_add(&b, (struct location){.line = 0, .col = 0}, + (uint8_t *)txt, strlen(txt)); + + ASSERT(buffer_line_length(&b, 0) == 23, + "Expected line 1 to be 23 chars before deletion"); + buffer_delete(&b, region_new((struct location){.line = 0, .col = 0}, + (struct location){.line = 0, .col = 2})); + ASSERT(buffer_line_length(&b, 0) == 21, + "Expected line 1 to be 21 chars after deletion"); + + // delete newline + buffer_delete(&b, region_new((struct location){.line = 0, .col = 21}, + (struct location){.line = 1, .col = 0})); + ASSERT(buffer_num_lines(&b) == 1, + "Expected buffer to have one line after new line deletion"); + ASSERT(buffer_line_length(&b, 0) == 42, + "Expected single line to be sum of both line lengths after new line " + "deletion"); + + // test that callback works + buffer_add_delete_hook(&b, delete_callback, NULL); + buffer_delete(&b, region_new((struct location){.line = 0, .col = 0}, + (struct location){.line = 0, .col = 2})); + ASSERT(delete_callback_call_count == 1, + "Expected callback to have been called"); + + buffer_destroy(&b); +} + +static void test_word_at(void) { struct buffer b = buffer_create("test-word-at-buffer"); const char *txt = "word1 (word2). Another"; buffer_add(&b, (struct location){.line = 0, .col = 0}, (uint8_t *)txt, @@ -40,8 +102,7 @@ void test_word_at() { "Expected word to span cols 7..12"); // test that clamping works correctly - struct region word3 = - buffer_word_at(&b, (struct location){.line = 0, .col = 100}); + struct region word3 = buffer_word_at(&b, buffer_clamp(&b, 0, 100)); ASSERT(region_has_size(word3), "expected 0,100 to be in the last word"); ASSERT(word3.begin.col == 15 && word3.end.col == 22, "Expected word to span cols 15..22"); @@ -49,7 +110,129 @@ void test_word_at() { buffer_destroy(&b); } -void run_buffer_tests() { +static void test_line_len(void) { + struct buffer b = buffer_create("test-line-length-buffer"); + const char *txt = "Look! Banana 🍌"; + buffer_add(&b, (struct location){.line = 0, .col = 0}, (uint8_t *)txt, + strlen(txt)); + ASSERT(buffer_line_length(&b, 0) == 15, + "Expected banana line to be 15 chars wide"); +} + +static void test_char_movement(void) { + struct buffer b = buffer_create("test-char-movement-buffer"); + const char *txt = "abcdefgh 🎯jklmn\tab"; + buffer_add(&b, buffer_end(&b), (uint8_t *)txt, strlen(txt)); + struct location next = + buffer_next_char(&b, (struct location){.line = 0, .col = 0}); + ASSERT(next.col == 1, "Expected next char to be next char"); + + next = buffer_next_char(&b, (struct location){.line = 0, .col = 9}); + ASSERT(next.col == 11, + "Expected a double width char to result in a 2 column move"); + + next = buffer_next_char(&b, (struct location){.line = 0, .col = 16}); + uint64_t tab_width = settings_get("editor.tab-width")->value.number_value; + ASSERT(next.col == 16 + tab_width, + "Expected a tab to result in a move the width of a tab"); + + struct location prev = + buffer_previous_char(&b, (struct location){.line = 0, .col = 0}); + ASSERT(prev.col == 0 && prev.line == 0, + "Expected backwards motion from 0,0 not to be possible"); + + prev = buffer_previous_char(&b, (struct location){.line = 0, .col = 11}); + ASSERT(prev.col == 9, + "Expected a double width char to result in a 2 column move"); + + prev = buffer_previous_char( + &b, (struct location){.line = 0, .col = 16 + tab_width}); + ASSERT(prev.col == 16, + "Expected a tab move backwards to step over the width of a tab"); +} + +static void test_word_movement(void) { + struct buffer b = buffer_create("test-word-movement-buffer"); + + const char *txt = " word1, word2 \"word3\" word4"; + buffer_add(&b, buffer_end(&b), (uint8_t *)txt, strlen(txt)); + struct location next = + buffer_next_word(&b, (struct location){.line = 0, .col = 0}); + ASSERT(next.col == 1, "Expected next word to start at col 1"); + + next = buffer_next_word(&b, (struct location){.line = 0, .col = 1}); + ASSERT(next.col == 8, "Expected next word to start at col 8"); + + next = buffer_next_word(&b, (struct location){.line = 0, .col = 8}); + ASSERT(next.col == 15, "Expected next word to start at col 15"); + + next = buffer_next_word(&b, (struct location){.line = 0, .col = 15}); + ASSERT(next.col == 22, "Expected next word to start at col 22"); + + struct location prev = + buffer_previous_word(&b, (struct location){.line = 0, .col = 26}); + ASSERT(prev.col == 22, "Expected previous word to start at col 22"); + + prev = buffer_previous_word(&b, (struct location){.line = 0, .col = 22}); + ASSERT(prev.col == 15, "Expected previous word to start at col 15"); + + prev = buffer_previous_word(&b, (struct location){.line = 0, .col = 0}); + ASSERT(prev.col == 0 && prev.line == 0, + "Expected previous word to not go before beginning of buffer"); +} + +void test_copy(void) { + struct buffer b = buffer_create("test-copy-buffer"); + buffer_add(&b, (struct location){.line = 0, .col = 0}, (uint8_t *)"copy", 4); + + buffer_copy(&b, region_new((struct location){.line = 0, .col = 0}, + (struct location){.line = 0, .col = 4})); + buffer_paste(&b, (struct location){.line = 0, .col = 4}); + ASSERT(buffer_line_length(&b, 0) == 8, "Expected text to be copied"); + struct text_chunk t = buffer_line(&b, 0); + ASSERT_STR_EQ((const char *)t.text, "copycopy", + "Expected copied text to match"); + if (t.allocated) { + free(t.text); + } + + buffer_cut(&b, region_new((struct location){.line = 0, .col = 2}, + (struct location){.line = 0, .col = 4})); + buffer_paste(&b, (struct location){.line = 0, .col = 0}); + ASSERT(buffer_line_length(&b, 0) == 8, "Expected line length to be the same"); + t = buffer_line(&b, 0); + ASSERT_STR_EQ((const char *)t.text, "pycocopy", + "Expected cut+pasted text to match"); + if (t.allocated) { + free(t.text); + } + + // test kill ring + buffer_paste_older(&b, (struct location){.line = 0, .col = 0}); + ASSERT(buffer_line_length(&b, 0) == 12, + "Expected line length to have increased when pasting older"); + t = buffer_line(&b, 0); + ASSERT_STR_EQ((const char *)t.text, "copypycocopy", + "Expected pasted older text to match"); + if (t.allocated) { + free(t.text); + } + + buffer_destroy(&b); +} + +void run_buffer_tests(void) { + settings_init(10); + settings_set_default( + "editor.tab-width", + (struct setting_value){.type = Setting_Number, .number_value = 4}); + run_test(test_add); + run_test(test_delete); run_test(test_word_at); + run_test(test_line_len); + run_test(test_char_movement); + run_test(test_word_movement); + run_test(test_copy); + settings_destroy(); } |
