From cee9ecb4ab97ed8670d2477d191ab0e46cdc2548 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Mon, 6 Feb 2017 12:30:06 -0500 Subject: [PATCH] majority of unit tests for xedit.c back up and running with the hidden X11 window --- .gitignore | 3 + TODO.md | 1 + inc/atf.h | 2 +- lib/buf.c | 8 ++- lib/filetype.c | 18 +----- lib/utils.c | 4 +- tests/xedit.c | 165 ++++++++++++++++++++++++++++++------------------- 7 files changed, 116 insertions(+), 85 deletions(-) diff --git a/.gitignore b/.gitignore index 1f2c0fe..2ef3a10 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ tags xedit xpick DELETEME +tests/libedit +tests/term +term diff --git a/TODO.md b/TODO.md index f2da016..e6f8dff 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,7 @@ Up Next: +* reverse selections passed to commands do not have results highlighted properly * check for file changes on save * check for file changes when window regains focus * Right click in tags region should search edit region diff --git a/inc/atf.h b/inc/atf.h index c895568..465ac44 100644 --- a/inc/atf.h +++ b/inc/atf.h @@ -72,7 +72,7 @@ static void handle_signal(int sig) { fprintf(stderr,"%s:%d:0:%s:CRASH (signal: %d - %s)\n", Curr_File, Curr_Line, Curr_Test, sig, sig_name); Failed++; (void)atf_print_results(); - exit(1); + _Exit(1); } #endif diff --git a/lib/buf.c b/lib/buf.c index b5fca4f..58f06df 100644 --- a/lib/buf.c +++ b/lib/buf.c @@ -172,8 +172,11 @@ static void swaplog(Buf* buf, Log** from, Log** to, Sel* sel) { void buf_init(Buf* buf) { /* cleanup old data if there is any */ - if (buf->bufstart) free(buf->bufstart); - buf_logclear(buf); + if (buf->bufstart) { + free(buf->bufstart); + buf->bufstart = NULL; + buf_logclear(buf); + } /* reset the state to defaults */ buf->modified = false; @@ -188,6 +191,7 @@ void buf_init(Buf* buf) { buf->gapend = buf->bufend; buf->undo = NULL; buf->redo = NULL; + assert(buf->bufstart); } unsigned buf_load(Buf* buf, char* path) { diff --git a/lib/filetype.c b/lib/filetype.c index 173d120..57e14ce 100644 --- a/lib/filetype.c +++ b/lib/filetype.c @@ -2,18 +2,6 @@ #include #include -static const struct { - int type; - int len; - uchar* seq; -} BOMS[] = { - { .type = UTF_8, .len = 3, .seq = (uchar[]){ 0xEFu, 0xBBu, 0xBFu }}, - { .type = UTF_16BE, .len = 2, .seq = (uchar[]){ 0xFEu, 0xFFu }}, - { .type = UTF_16LE, .len = 2, .seq = (uchar[]){ 0xFFu, 0xFEu }}, - { .type = UTF_32BE, .len = 4, .seq = (uchar[]){ 0x00u, 0x00u, 0xFEu, 0xFFu }}, - { .type = UTF_32LE, .len = 4, .seq = (uchar[]){ 0xFFu, 0xFEu, 0x00u, 0x00u }}, -}; - static const char Utf8Valid[256] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -27,10 +15,7 @@ static const char Utf8Valid[256] = { void filetype(Buf* buf, FMap file) { size_t crs = 0, lfs = 0, tabs = 0; - /* look for a BOM and parse it */ - for (size_t i = 0; i < (sizeof(BOMS)/sizeof(BOMS[0])); i++) - if (!strncmp((char*)buf, (char*)BOMS[i].seq, BOMS[i].len)) - buf->charset = BOMS[i].type; + /* look for bytes that are invalid in utf-8 and count tabs, carriage returns, and line feeds */ int type = buf->charset; @@ -43,6 +28,7 @@ void filetype(Buf* buf, FMap file) { case '\t': tabs++; break; } } + /* setup filetype attributes in the buffer */ buf->crlf = (crs == lfs); buf->charset = type; diff --git a/lib/utils.c b/lib/utils.c index f2b3444..35fb8a8 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -42,8 +42,9 @@ FMap mmap_readonly(char* path) { struct stat sb; if (((fd = open(path, O_RDONLY, 0)) < 0) || (fstat(fd, &sb) < 0) || - (sb.st_size == 0)) + (sb.st_size == 0)) { return file; + } file.buf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); file.len = sb.st_size; if (file.buf == MAP_FAILED) @@ -72,6 +73,7 @@ void mmap_close(FMap file) { char* stringdup(const char* s) { char* ns = (char*)malloc(strlen(s) + 1); + assert(ns); strcpy(ns,s); return ns; } diff --git a/tests/xedit.c b/tests/xedit.c index 8cc6a6a..9515963 100644 --- a/tests/xedit.c +++ b/tests/xedit.c @@ -13,6 +13,7 @@ enum { }; // Test Globals +bool ExitExpected = false; int ExitCode = 0; jmp_buf ExitPad; Display* XDisplay; @@ -30,6 +31,12 @@ static void initialize(void) { /* Helper Functions *****************************************************************************/ +#define EXPECT_EXIT \ + ExitCode = -1; \ + ExitExpected = true; \ + if (0 == setjmp(ExitPad)) + + void setup_view(WinRegion id, char* text, int crlf, unsigned cursor) { win_setregion(id); win_buf(id)->crlf = crlf; @@ -39,6 +46,10 @@ void setup_view(WinRegion id, char* text, int crlf, unsigned cursor) { win_sel(id)->col = buf_getcol(win_buf(id), win_sel(id)->end); } +void insert(WinRegion id, char* text) { + view_putstr(win_view(id), text); +} + void send_keys(uint mods, uint key) { XEvent e; e.xkey.display = XDisplay, @@ -297,7 +308,6 @@ TEST_SUITE(UnitTests) { CHECK(win_sel(EDIT)->end == 2); } - /* Key Handling - Unix Editing Shortcuts *************************************************************************/ TEST(ctrl+u should do nothing for empty buffer) { @@ -447,28 +457,30 @@ TEST_SUITE(UnitTests) { /* Key Handling - Standard Text Editing Shortcuts *************************************************************************/ -// TEST(cut and paste should delete selection and transfer it to+from the system clipboard) { -// setup_view(EDIT, "foo\nbar\nbaz\n", CRLF, 0); -// win_view(EDIT)->selection = (Sel){ 0, 8, 0 }; -// send_keys(ModCtrl, XK_x); -// win_view(EDIT)->selection = (Sel){ 4, 4, 0 }; -// send_keys(ModCtrl, XK_v); -// CHECK(win_sel(EDIT)->beg == 4); -// CHECK(win_sel(EDIT)->end == 12); -// CHECK(verify_text(EDIT, "baz\r\nfoo\r\nbar\r\n")); -// } -// -// TEST(copy and paste should copy selection and transfer it to+from the system clipboard) { -// win_buf(EDIT)->crlf = 1; -// setup_view(EDIT, "foo\nbar\nbaz\n", CRLF, 0); -// win_view(EDIT)->selection = (Sel){ 0, 8, 0 }; -// send_keys(ModCtrl, XK_c); -// win_view(EDIT)->selection = (Sel){ 12, 12, 0 }; -// send_keys(ModCtrl, XK_v); -// CHECK(win_sel(EDIT)->beg == 12); -// CHECK(win_sel(EDIT)->end == 20); -// CHECK(verify_text(EDIT, "foo\r\nbar\r\nbaz\r\nfoo\r\nbar\r\n")); -// } + TEST(cut and paste should delete selection and transfer it to+from the system clipboard) { + IGNORE("paste callback isn't happening"); + setup_view(EDIT, "foo\nbar\nbaz\n", CRLF, 0); + win_view(EDIT)->selection = (Sel){ 0, 8, 0 }; + send_keys(ModCtrl, XK_x); + win_view(EDIT)->selection = (Sel){ 4, 4, 0 }; + send_keys(ModCtrl, XK_v); + CHECK(win_sel(EDIT)->beg == 4); + CHECK(win_sel(EDIT)->end == 12); + CHECK(verify_text(EDIT, "baz\r\nfoo\r\nbar\r\n")); + } + + TEST(copy and paste should copy selection and transfer it to+from the system clipboard) { + IGNORE("paste callback isn't happening"); + win_buf(EDIT)->crlf = 1; + setup_view(EDIT, "foo\nbar\nbaz\n", CRLF, 0); + win_view(EDIT)->selection = (Sel){ 0, 8, 0 }; + send_keys(ModCtrl, XK_c); + win_view(EDIT)->selection = (Sel){ 12, 12, 0 }; + send_keys(ModCtrl, XK_v); + CHECK(win_sel(EDIT)->beg == 12); + CHECK(win_sel(EDIT)->end == 20); + CHECK(verify_text(EDIT, "foo\r\nbar\r\nbaz\r\nfoo\r\nbar\r\n")); + } /* Key Handling - Block Indent *************************************************************************/ @@ -588,9 +600,10 @@ TEST_SUITE(UnitTests) { setup_view(EDIT, "", CRLF, 0); win_buf(EDIT)->modified = false; ExitCode = 42; - //if (0 == setjmp(ExitPad)) - // send_keys(ModCtrl, XK_q); - puts("sendkey3"); + EXPECT_EXIT { + send_keys(ModCtrl, XK_q); + } + ExitExpected = false; CHECK(ExitCode == 0); CHECK(verify_text(TAGS, "")); } @@ -628,8 +641,9 @@ TEST_SUITE(UnitTests) { CHECK(verify_text(EDIT, "bar")); #endif } - - TEST(Commands starting with | should be take selection as input and replace it with output) { + +#if 0 + TEST(Commands starting with | should take selection as input and replace it with output) { setup_view(EDIT, "foo", CRLF, 0); win_view(EDIT)->selection = (Sel){ .beg = 0, .end = 3 }; setup_view(TAGS, "|sed -e 's/foo/bar/'", CRLF, 0); @@ -641,6 +655,7 @@ TEST_SUITE(UnitTests) { CHECK(verify_text(EDIT, "bar")); #endif } +#endif TEST(Commands starting with ! should execute in the background with no input or output) { setup_view(EDIT, "foo", CRLF, 0); @@ -660,7 +675,6 @@ TEST_SUITE(UnitTests) { send_keys(ModCtrl, XK_d); CHECK(verify_text(EDIT, "foo")); } -#endif TEST(Commands starting with < should replace selection with output) { setup_view(EDIT, "foo", CRLF, 0); @@ -670,26 +684,30 @@ TEST_SUITE(UnitTests) { send_keys(ModCtrl, XK_d); CHECK(verify_text(EDIT, "bar\r\n")); } - + TEST(Commands not starting with a sigil should replace themselves with their output) { setup_view(EDIT, "echo foo", CRLF, 0); win_view(EDIT)->selection = (Sel){ .beg = 0, .end = 8 }; send_keys(ModCtrl, XK_d); CHECK(verify_text(EDIT, "foo\r\n")); } +#endif /* Tag Handling *************************************************************************/ - TEST(Quit should quit immediately if buffer is unmodified) { + TEST(Quit should quit immediately if buffer is unmodified) { setup_view(TAGS, "", CRLF, 0); setup_view(EDIT, "", CRLF, 0); win_buf(EDIT)->modified = false; ExitCode = 42; - exec("Quit"); + EXPECT_EXIT { + exec("Quit"); + } + ExitExpected = false; CHECK(ExitCode == 0); CHECK(verify_text(TAGS, "")); } - + TEST(Quit should display error message when quit called with unsaved changes) { setup_view(TAGS, "", CRLF, 0); setup_view(EDIT, "", CRLF, 0); @@ -702,15 +720,19 @@ TEST_SUITE(UnitTests) { } TEST(Quit should discard changes if quit executed twice in less than 250 ms) { + IGNORE("Failing on the first quit call"); setup_view(TAGS, "", CRLF, 0); setup_view(EDIT, "", CRLF, 0); win_buf(EDIT)->modified = true; ExitCode = 42; - usleep(251 * 1000); - exec("Quit"); - CHECK(ExitCode == 42); - CHECK(verify_text(TAGS, "File is modified. Repeat action twice in < 250ms to quit.")); - exec("Quit"); + EXPECT_EXIT { + usleep(252 * 1000); + exec("Quit"); + CHECK(ExitCode == 42); + CHECK(verify_text(TAGS, "File is modified. Repeat action twice in < 250ms to quit.")); + exec("Quit"); + } + ExitExpected = false; CHECK(ExitCode == 0); CHECK(verify_text(TAGS, "File is modified. Repeat action twice in < 250ms to quit.")); } @@ -733,30 +755,35 @@ TEST_SUITE(UnitTests) { CHECK(verify_text(EDIT, "this file\nuses\nunix\nline\nendings\n")); } -// TEST(Cut and Paste tags should move selection to new location) { -// setup_view(EDIT, "foo\nbar\nbaz\n", CRLF, 0); -// win_view(EDIT)->selection = (Sel){ 0, 8, 0 }; -// exec("Cut"); -// win_view(EDIT)->selection = (Sel){ 4, 4, 0 }; -// exec("Paste"); -// CHECK(win_sel(EDIT)->beg == 4); -// CHECK(win_sel(EDIT)->end == 12); -// CHECK(verify_text(EDIT, "baz\r\nfoo\r\nbar\r\n")); -// } -// -// TEST(Copy and Paste tags should copy selection to new location) { -// setup_view(EDIT, "foo\nbar\nbaz\n", CRLF, 0); -// win_view(EDIT)->selection = (Sel){ 0, 8, 0 }; -// exec("Copy"); -// win_view(EDIT)->selection = (Sel){ 12, 12, 0 }; -// exec("Paste"); -// CHECK(win_sel(EDIT)->beg == 12); -// CHECK(win_sel(EDIT)->end == 20); -// CHECK(verify_text(EDIT, "foo\r\nbar\r\nbaz\r\nfoo\r\nbar\r\n")); -// } + TEST(Cut and Paste tags should move selection to new location) { + IGNORE("paste callback isn't happening"); + setup_view(EDIT, "", CRLF, 0); + insert(EDIT, "foo\nbar\nbaz\n"); + win_view(EDIT)->selection = (Sel){ 0, 8, 0 }; + exec("Cut"); + win_view(EDIT)->selection = (Sel){ 4, 4, 0 }; + exec("Paste"); + CHECK(win_sel(EDIT)->beg == 4); + CHECK(win_sel(EDIT)->end == 12); + CHECK(verify_text(EDIT, "baz\r\nfoo\r\nbar\r\n")); + } + + TEST(Copy and Paste tags should copy selection to new location) { + IGNORE("paste callback isn't happening"); + setup_view(EDIT, "", CRLF, 0); + insert(EDIT, "foo\nbar\nbaz\n"); + win_view(EDIT)->selection = (Sel){ 0, 8, 0 }; + exec("Copy"); + win_view(EDIT)->selection = (Sel){ 12, 12, 0 }; + exec("Paste"); + CHECK(win_sel(EDIT)->beg == 12); + CHECK(win_sel(EDIT)->end == 20); + CHECK(verify_text(EDIT, "foo\r\nbar\r\nbaz\r\nfoo\r\nbar\r\n")); + } TEST(Undo+Redo should undo+redo the previous insert) { - setup_view(EDIT, "foo", CRLF, 0); + setup_view(EDIT, "", CRLF, 0); + insert(EDIT, "foo"); exec("Undo"); CHECK(verify_text(EDIT, "")); exec("Redo"); @@ -831,13 +858,15 @@ TEST_SUITE(UnitTests) { CHECK(win_view(EDIT)->selection.end == 6); } -#if 0 TEST(Find should do nothing if nothing selected) { + setup_view(EDIT, "foo bar baz", CRLF, 0); setup_view(TAGS, "Find", CRLF, 0); win_view(TAGS)->selection = (Sel){ 0, 4, 0 }; + win_view(EDIT)->selection = (Sel){ 0, 0, 0 }; send_keys(ModCtrl, 'f'); + CHECK(win_view(EDIT)->selection.beg == 0); + CHECK(win_view(EDIT)->selection.end == 0); } -#endif TEST(Tabs should set indent style to tabs) { setup_view(TAGS, "Tabs", CRLF, 0); @@ -882,13 +911,19 @@ TEST_SUITE(UnitTests) { // fake out the exit routine void exit(int code) { - ExitCode = code; - longjmp(ExitPad, 1); + if (ExitExpected) { + ExitCode = code; + ExitExpected = false; + longjmp(ExitPad, 1); + } else { + assert(!"Unexpected exit. Something went wrong"); + } } int main(int argc, char** argv) { initialize(); atf_init(argc,argv); RUN_TEST_SUITE(UnitTests); - return atf_print_results(); + _Exit(atf_print_results()); + return 0; } -- 2.51.0