From: Michael D. Lowis Date: Fri, 3 Feb 2017 19:01:38 +0000 (-0500) Subject: Reworked unit tests to have one test executable per real executable and one catch... X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=aa78ed9253f766c911438ac39ee5b37620979759;p=projs%2Ftide.git Reworked unit tests to have one test executable per real executable and one catch-all for the library --- diff --git a/Makefile b/Makefile index f69808a..31a3bbc 100644 --- a/Makefile +++ b/Makefile @@ -10,22 +10,19 @@ LIBEDIT_OBJS = \ lib/x11.o \ lib/win.o -TEST_OBJS = \ - unittests.o \ - tests/buf.o \ - tests/utf8.o \ - tests/xedit.o +TEST_BINS = \ + tests/xedit \ + tests/xpick \ + tests/libedit include config.mk -all: xedit xpick term +all: xedit xpick term test clean: - $(RM) *.o lib*/*.o tests/*.o *.a xpick xedit term unittests - $(RM) *.d lib*/*.d tests/*.d - $(RM) *.gcno lib*/*.gcno tests/*.gcno - $(RM) *.gcda lib*/*.gcda tests/*.gcda - $(RM) *.gcov lib*/*.gcov tests/*.gcov + find . -name '*.[oad]' -delete + $(RM) xpick xedit term tests/libedit + $(RM) $(TEST_BINS) install: all mkdir -p $(PREFIX)/bin @@ -44,8 +41,8 @@ uninstall: rm -f $(PREFIX)/bin/xman rm -f $(PREFIX)/bin/edit -test: unittests - ./unittests +test: $(TEST_BINS) + for t in $(TEST_BINS); do ./$$t; done xedit: xedit.o libedit.a $(LD) -o $@ $^ $(LDFLAGS) @@ -59,7 +56,11 @@ term: term.o libedit.a libedit.a: $(LIBEDIT_OBJS) $(AR) $(ARFLAGS) $@ $^ -unittests: $(TEST_OBJS) libedit.a +#unittests: $(TEST_OBJS) libedit.a + +tests/libedit: tests/lib/buf.o tests/lib/utf8.o libedit.a +tests/xedit: tests/xedit.o libedit.a +tests/xpick: tests/xpick.o libedit.a -include *.d lib/*.d tests/*.d diff --git a/TODO.md b/TODO.md index 2d6e7ba..f2da016 100644 --- a/TODO.md +++ b/TODO.md @@ -10,7 +10,7 @@ Up Next: * ctrl+alt+f should find next occurence of previous search term * Add keyboard shortcut to highlight the thing under the cursor -The Rest: +Tomorrow-ish: * Selection bug when selecting text with tabs * off by one error on scrolling up with wrapped lines diff --git a/inc/atf.h b/inc/atf.h old mode 100755 new mode 100644 diff --git a/inc/edit.h b/inc/edit.h index ec851e4..3240ab9 100644 --- a/inc/edit.h +++ b/inc/edit.h @@ -58,19 +58,15 @@ typedef struct { void buf_init(Buf* buf); unsigned buf_load(Buf* buf, char* path); void buf_save(Buf* buf); - Rune buf_get(Buf* buf, unsigned pos); unsigned buf_end(Buf* buf); - unsigned buf_insert(Buf* buf, bool indent, unsigned off, Rune rune); unsigned buf_delete(Buf* buf, unsigned beg, unsigned end); unsigned buf_change(Buf* buf, unsigned beg, unsigned end); - void buf_undo(Buf* buf, Sel* sel); void buf_redo(Buf* buf, Sel* sel); void buf_loglock(Buf* buf); void buf_logclear(Buf* buf); - bool buf_iseol(Buf* buf, unsigned pos); unsigned buf_bol(Buf* buf, unsigned pos); unsigned buf_eol(Buf* buf, unsigned pos); @@ -78,17 +74,13 @@ unsigned buf_bow(Buf* buf, unsigned pos); unsigned buf_eow(Buf* buf, unsigned pos); unsigned buf_lscan(Buf* buf, unsigned pos, Rune r); unsigned buf_rscan(Buf* buf, unsigned pos, Rune r); - void buf_getword(Buf* buf, bool (*isword)(Rune), Sel* sel); void buf_getblock(Buf* buf, Rune beg, Rune end, Sel* sel); - unsigned buf_byrune(Buf* buf, unsigned pos, int count); unsigned buf_byword(Buf* buf, unsigned pos, int count); unsigned buf_byline(Buf* buf, unsigned pos, int count); - void buf_find(Buf* buf, int dir, size_t* beg, size_t* end); void buf_findstr(Buf* buf, int dir, char* str, size_t* beg, size_t* end); - unsigned buf_setln(Buf* buf, unsigned line); unsigned buf_getcol(Buf* buf, unsigned pos); unsigned buf_setcol(Buf* buf, unsigned pos, unsigned col); @@ -150,7 +142,6 @@ Row* view_getrow(View* view, size_t row); void view_byrune(View* view, int move, bool extsel); void view_byword(View* view, int move, bool extsel); void view_byline(View* view, int move, bool extsel); - char* view_fetchcmd(View* view, size_t row, size_t col); void view_find(View* view, int dir, size_t row, size_t col); void view_findstr(View* view, int dir, char* str); @@ -171,7 +162,6 @@ void view_scroll(View* view, int move); void view_scrollpage(View* view, int move); void view_setln(View* view, size_t line); void view_indent(View* view, int dir); - size_t view_selsize(View* view); void view_selprev(View* view); void view_setcursor(View* view, size_t row, size_t col); @@ -211,40 +201,6 @@ enum ColorId { CLR_COUNT = 16 }; -/* Global State - *****************************************************************************/ -typedef struct { - int mods; - Rune key; - void (*action)(void); -} KeyBinding; - -typedef struct { - uint64_t time; - uint8_t count; - bool pressed; - int region; -} ButtonState; - -typedef struct { - size_t x; - size_t y; - size_t height; - size_t width; - size_t csrx; - size_t csry; - bool warp_ptr; - View view; -} Region; - -typedef struct { - char* tag; - union { - void (*noarg)(void); - void (*arg)(char* arg); - } action; -} Tag; - /* Configuration *****************************************************************************/ enum { diff --git a/inc/win.h b/inc/win.h index 684cbf0..5139d77 100644 --- a/inc/win.h +++ b/inc/win.h @@ -7,7 +7,12 @@ typedef enum { FOCUSED = 4 } WinRegion; -#if 0 +typedef struct { + int mods; + Rune key; + void (*action)(void); +} KeyBinding; + typedef struct { size_t x; size_t y; @@ -18,7 +23,6 @@ typedef struct { bool warp_ptr; View view; } Region; -#endif typedef void (*MouseFunc)(WinRegion id, size_t count, size_t row, size_t col); diff --git a/lib/win.c b/lib/win.c index 24309b7..2d0170f 100644 --- a/lib/win.c +++ b/lib/win.c @@ -3,6 +3,14 @@ #include #include #include +#include + +typedef struct { + uint64_t time; + uint8_t count; + bool pressed; + int region; +} ButtonState; static void draw_glyphs(size_t x, size_t y, UGlyph* glyphs, size_t rlen, size_t ncols); static WinRegion getregion(size_t x, size_t y); diff --git a/tests/buf.c b/tests/lib/buf.c similarity index 100% rename from tests/buf.c rename to tests/lib/buf.c diff --git a/tests/utf8.c b/tests/lib/utf8.c similarity index 100% rename from tests/utf8.c rename to tests/lib/utf8.c diff --git a/unittests.c b/tests/libedit.c similarity index 91% rename from unittests.c rename to tests/libedit.c index 06c6dfd..bbe0552 100644 --- a/unittests.c +++ b/tests/libedit.c @@ -17,7 +17,6 @@ void move_pointer(unsigned x, unsigned y) { int main(int argc, char** argv) { atf_init(argc,argv); - RUN_EXTERN_TEST_SUITE(XeditTests); RUN_EXTERN_TEST_SUITE(BufferTests); RUN_EXTERN_TEST_SUITE(Utf8Tests); return atf_print_results(); diff --git a/tests/xedit.c b/tests/xedit.c index 13d67ff..4158741 100644 --- a/tests/xedit.c +++ b/tests/xedit.c @@ -1,3 +1,4 @@ +#define INCLUDE_DEFS #include #include @@ -22,880 +23,886 @@ void mockexit(int code) { /* Helper Functions *****************************************************************************/ -void setup_view(enum RegionId id, char* text, int crlf, unsigned cursor) { - ShellCmd[0] = "/bin/sh"; - Focused = id; - view_init(getview(id), NULL); - getbuf(id)->crlf = crlf; - view_putstr(getview(id), text); - getsel(id)->beg = cursor; - getsel(id)->end = cursor; - getsel(id)->col = buf_getcol(getbuf(id), getsel(id)->end); -} - -void send_keys(int mods, Rune key) { - Mods = mods; - key_handler(mods, key); -} - -bool verify_text(enum RegionId id, char* text) { - Sel sel = { .beg = 0, .end = buf_end(getbuf(id)) }; - char* buftext = view_getstr(getview(id), &sel); - //printf("buftext: '%s'\n", buftext); - bool result; - if (buftext == NULL) - result = (*text == '\0'); - else - result = (0 == strcmp(buftext, text)); - free(buftext); - return result; -} +//void setup_view(enum RegionId id, char* text, int crlf, unsigned cursor) { +// ShellCmd[0] = "/bin/sh"; +// Focused = id; +// view_init(getview(id), NULL); +// getbuf(id)->crlf = crlf; +// view_putstr(getview(id), text); +// getsel(id)->beg = cursor; +// getsel(id)->end = cursor; +// getsel(id)->col = buf_getcol(getbuf(id), getsel(id)->end); +//} +// +//void send_keys(int mods, Rune key) { +// Mods = mods; +// key_handler(mods, key); +//} +// +//bool verify_text(enum RegionId id, char* text) { +// Sel sel = { .beg = 0, .end = buf_end(getbuf(id)) }; +// char* buftext = view_getstr(getview(id), &sel); +// //printf("buftext: '%s'\n", buftext); +// bool result; +// if (buftext == NULL) +// result = (*text == '\0'); +// else +// result = (0 == strcmp(buftext, text)); +// free(buftext); +// return result; +//} /* Stubbed Functions *****************************************************************************/ -bool x11_keymodsset(int mask) { - return ((Mods & mask) == mask); -} - -size_t x11_font_height(XFont fnt) { - return 10; -} - -size_t x11_font_width(XFont fnt) { - return 10; -} - -static void redraw(int width, int height) { - /* do nothing for unit testing */ -} - -void x11_deinit(void) { - mockexit(0); -} - -bool x11_getsel(int selid, void(*cbfn)(char*)) { - cbfn(selid == PRIMARY ? PrimaryText : ClipboardText); - return true; -} - -bool x11_setsel(int selid, char* str) { - if (selid == PRIMARY) { - free(PrimaryText); - PrimaryText = str; - } else { - free(ClipboardText); - ClipboardText = str; - } - return true; -} +//bool x11_keymodsset(int mask) { +// return ((Mods & mask) == mask); +//} +// +//size_t x11_font_height(XFont fnt) { +// return 10; +//} +// +//size_t x11_font_width(XFont fnt) { +// return 10; +//} +// +//static void redraw(int width, int height) { +// /* do nothing for unit testing */ +//} +// +//void x11_deinit(void) { +// mockexit(0); +//} +// +//bool x11_getsel(int selid, void(*cbfn)(char*)) { +// cbfn(selid == PRIMARY ? PrimaryText : ClipboardText); +// return true; +//} +// +//bool x11_setsel(int selid, char* str) { +// if (selid == PRIMARY) { +// free(PrimaryText); +// PrimaryText = str; +// } else { +// free(ClipboardText); +// ClipboardText = str; +// } +// return true; +//} /* Unit Tests *****************************************************************************/ -TEST_SUITE(XeditTests) { - /* Key Handling - Normal Input - *************************************************************************/ - TEST(input not matching a shortcut should be inserted as text) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModNone, 'e'); - CHECK(getsel(EDIT)->beg == 1); - CHECK(getsel(EDIT)->end == 1); - } - - TEST(input \n chould result in RUNE_CRLF if in crlf mode) { - setup_view(EDIT, "", CRLF, 0); - getbuf(EDIT)->crlf = 1; - send_keys(ModNone, '\n'); - CHECK(getsel(EDIT)->beg == 1); - CHECK(getsel(EDIT)->end == 1); - CHECK(RUNE_CRLF == buf_get(getbuf(EDIT), 0)); - } - - TEST(input \n chould result in \n if not in crlf mode) { - setup_view(EDIT, "", CRLF, 0); - getbuf(EDIT)->crlf = 0; - send_keys(ModNone, '\n'); - CHECK(getsel(EDIT)->beg == 1); - CHECK(getsel(EDIT)->end == 1); - CHECK('\n' == buf_get(getbuf(EDIT), 0)); - } - - /* Key Handling - Cursor Movement - Basic - *************************************************************************/ - TEST(left should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModNone, KEY_LEFT); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(ctrl+left should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModCtrl, KEY_LEFT); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(left should do nothing at beginning of buffer) { - setup_view(EDIT, "AB", CRLF, 0); - send_keys(ModNone, KEY_LEFT); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(ctrl+left should do nothing at beginning of buffer) { - setup_view(EDIT, "AB", CRLF, 0); - send_keys(ModCtrl, KEY_LEFT); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(ctrl+left should move left by one word) { - setup_view(EDIT, "AB CD", CRLF, 3); - send_keys(ModCtrl, KEY_LEFT); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(left should move left by one rune) { - setup_view(EDIT, "AB", CRLF, 1); - send_keys(ModNone, KEY_LEFT); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(right should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModNone, KEY_RIGHT); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(right should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModCtrl, KEY_RIGHT); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(ctrl+right should do nothing at end of buffer) { - setup_view(EDIT, "AB", CRLF, 2); - send_keys(ModNone, KEY_RIGHT); - CHECK(getsel(EDIT)->beg == 2); - CHECK(getsel(EDIT)->end == 2); - } - - TEST(ctrl+right should do nothing at end of buffer) { - setup_view(EDIT, "AB", CRLF, 2); - send_keys(ModCtrl, KEY_RIGHT); - CHECK(getsel(EDIT)->beg == 2); - CHECK(getsel(EDIT)->end == 2); - } - - TEST(ctrl+right should move right by one word) { - setup_view(EDIT, "AB CD", CRLF, 0); - send_keys(ModCtrl, KEY_RIGHT); - CHECK(getsel(EDIT)->beg == 3); - CHECK(getsel(EDIT)->end == 3); - } - - TEST(right should move right by one rune) { - setup_view(EDIT, "AB", CRLF, 1); - send_keys(ModNone, KEY_RIGHT); - CHECK(getsel(EDIT)->beg == 2); - CHECK(getsel(EDIT)->end == 2); - } - - TEST(up should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModNone, KEY_UP); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(up should move cursor up one line) { - setup_view(EDIT, "AB\nCD", CRLF, 4); - send_keys(ModNone, KEY_UP); - CHECK(getsel(EDIT)->beg == 1); - CHECK(getsel(EDIT)->end == 1); - } - - TEST(up should do nothing for first line) { - setup_view(EDIT, "AB\nCD", CRLF, 1); - send_keys(ModNone, KEY_UP); - CHECK(getsel(EDIT)->beg == 1); - CHECK(getsel(EDIT)->end == 1); - } - - TEST(down should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModNone, KEY_DOWN); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(down should move down one line) { - setup_view(EDIT, "AB\nCD", CRLF, 1); - send_keys(ModNone, KEY_DOWN); - CHECK(getsel(EDIT)->beg == 4); - CHECK(getsel(EDIT)->end == 4); - } - - TEST(down should do nothing on last line) { - setup_view(EDIT, "AB\nCD", CRLF, 4); - send_keys(ModNone, KEY_DOWN); - CHECK(getsel(EDIT)->beg == 4); - CHECK(getsel(EDIT)->end == 4); - } - - TEST(home should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModNone, KEY_HOME); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(ctrl+home should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModCtrl, KEY_HOME); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(ctrl+home should move to beginning of buffer) { - setup_view(EDIT, "ABCD", CRLF, 4); - send_keys(ModCtrl, KEY_HOME); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(home should move to beginning of indented content) { - setup_view(EDIT, " ABCD", CRLF, 7); - send_keys(ModNone, KEY_HOME); - CHECK(getsel(EDIT)->beg == 4); - CHECK(getsel(EDIT)->end == 4); - } - - TEST(home should move to beginning of line if at beginning of indented content) { - setup_view(EDIT, " ABCD", CRLF, 7); - send_keys(ModNone, KEY_HOME); - CHECK(getsel(EDIT)->beg == 4); - CHECK(getsel(EDIT)->end == 4); - } - - TEST(home should move to beginning of indented content when at beginning of line) { - setup_view(EDIT, " ABCD", CRLF, 0); - send_keys(ModNone, KEY_HOME); - CHECK(getsel(EDIT)->beg == 4); - CHECK(getsel(EDIT)->end == 4); - } - - TEST(end should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModNone, KEY_END); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(ctrl+end should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModCtrl, KEY_END); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(ctrl+end should move to end of buffer) { - setup_view(EDIT, "ABCD", CRLF, 0); - send_keys(ModCtrl, KEY_END); - CHECK(getsel(EDIT)->beg == 4); - CHECK(getsel(EDIT)->end == 4); - } - - TEST(end should do nothing at end of line) { - setup_view(EDIT, "AB\nCD", CRLF, 2); - send_keys(ModNone, KEY_END); - CHECK(getsel(EDIT)->beg == 2); - CHECK(getsel(EDIT)->end == 2); - } - - TEST(end should move to end of line) { - setup_view(EDIT, "AB\nCD", CRLF, 0); - send_keys(ModNone, KEY_END); - CHECK(getsel(EDIT)->beg == 2); - CHECK(getsel(EDIT)->end == 2); - } - - /* Key Handling - Unix Editing Shortcuts - *************************************************************************/ - TEST(ctrl+u should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModCtrl, 'u'); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(ctrl+u should delete to beginning of line) { - setup_view(EDIT, "\nABC\n", CRLF, 2); - send_keys(ModCtrl, 'u'); - CHECK(getsel(EDIT)->beg == 1); - CHECK(getsel(EDIT)->end == 1); - CHECK(buf_end(getbuf(EDIT)) == 4); - } - - TEST(ctrl+u should delete entire lines contents) { - setup_view(EDIT, "\nABC\n", CRLF, 3); - send_keys(ModCtrl, 'u'); - CHECK(getsel(EDIT)->beg == 1); - CHECK(getsel(EDIT)->end == 1); - CHECK(buf_end(getbuf(EDIT)) == 3); - } - - TEST(ctrl+k should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModCtrl, 'k'); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - CHECK(buf_end(getbuf(EDIT)) == 0); - } - - TEST(ctrl+k should delete to end of line) { - setup_view(EDIT, "\nABC\n", CRLF, 2); - send_keys(ModCtrl, 'k'); - CHECK(getsel(EDIT)->beg == 2); - CHECK(getsel(EDIT)->end == 2); - CHECK(buf_end(getbuf(EDIT)) == 3); - } - - TEST(ctrl+k should delete entire lines contents) { - setup_view(EDIT, "\nABC\n", CRLF, 1); - send_keys(ModCtrl, 'k'); - CHECK(getsel(EDIT)->beg == 1); - CHECK(getsel(EDIT)->end == 1); - CHECK(buf_end(getbuf(EDIT)) == 2); - } - - TEST(ctrl+w should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModCtrl, 'w'); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - CHECK(buf_end(getbuf(EDIT)) == 0); - } - - TEST(ctrl+w should delete previous word) { - setup_view(EDIT, "abc def", CRLF, 4); - send_keys(ModCtrl, 'w'); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - CHECK(buf_end(getbuf(EDIT)) == 3); - } - - TEST(ctrl+h should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModCtrl, 'h'); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(ctrl+h should delete previous character) { - setup_view(EDIT, "AB", CRLF, 1); - send_keys(ModCtrl, 'h'); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - CHECK(buf_end(getbuf(EDIT)) == 1); - } - - TEST(ctrl+a should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModCtrl, 'a'); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(ctrl+a should move to beginning of indented content) { - setup_view(EDIT, " ABCD", CRLF, 7); - send_keys(ModCtrl, 'a'); - CHECK(getsel(EDIT)->beg == 4); - CHECK(getsel(EDIT)->end == 4); - } - - TEST(ctrl+a should move to beginning of line if at beginning of indented content) { - setup_view(EDIT, " ABCD", CRLF, 7); - send_keys(ModCtrl, 'a'); - CHECK(getsel(EDIT)->beg == 4); - CHECK(getsel(EDIT)->end == 4); - } - - TEST(ctrl+a should move to beginning of indented content when at beginning of line) { - setup_view(EDIT, " ABCD", CRLF, 0); - send_keys(ModCtrl, 'a'); - CHECK(getsel(EDIT)->beg == 4); - CHECK(getsel(EDIT)->end == 4); - } - - TEST(ctrl+e should do nothing for empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModCtrl, 'e'); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(ctrl+e should do nothing at end of line) { - setup_view(EDIT, "AB\nCD", CRLF, 2); - send_keys(ModCtrl, 'e'); - CHECK(getsel(EDIT)->beg == 2); - CHECK(getsel(EDIT)->end == 2); - } - - TEST(ctrl+e should move to end of line) { - setup_view(EDIT, "AB\nCD", CRLF, 0); - send_keys(ModCtrl, 'e'); - CHECK(getsel(EDIT)->beg == 2); - CHECK(getsel(EDIT)->end == 2); - } - - TEST(esc should select previously inserted text) { - setup_view(EDIT, "foo", CRLF, 0); - send_keys(ModNone, KEY_ESCAPE); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 3); - } - - TEST(esc should select previously edited text) { - setup_view(EDIT, "foob", CRLF, 4); - send_keys(ModNone, KEY_BACKSPACE); - send_keys(ModNone, KEY_ESCAPE); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 3); - } - - /* 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); - getview(EDIT)->selection = (Sel){ 0, 8, 0 }; - send_keys(ModCtrl, 'x'); - getview(EDIT)->selection = (Sel){ 4, 4, 0 }; - send_keys(ModCtrl, 'v'); - CHECK(getsel(EDIT)->beg == 4); - CHECK(getsel(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) { - getbuf(EDIT)->crlf = 1; - setup_view(EDIT, "foo\nbar\nbaz\n", CRLF, 0); - getview(EDIT)->selection = (Sel){ 0, 8, 0 }; - send_keys(ModCtrl, 'c'); - getview(EDIT)->selection = (Sel){ 12, 12, 0 }; - send_keys(ModCtrl, 'v'); - CHECK(getsel(EDIT)->beg == 12); - CHECK(getsel(EDIT)->end == 20); - CHECK(verify_text(EDIT, "foo\r\nbar\r\nbaz\r\nfoo\r\nbar\r\n")); - } - - /* Key Handling - Block Indent - *************************************************************************/ - TEST(ctrl+[ should do nothing on empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModCtrl, '['); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(ctrl+[ should do nothing at beginning of buffer) { - setup_view(EDIT, "a", CRLF, 0); - send_keys(ModCtrl, '['); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 1); - } - - TEST(ctrl+] should do nothing on empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModCtrl, ']'); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - } - - TEST(ctrl+] should indent the first line) { - setup_view(EDIT, "a", CRLF, 0); - send_keys(ModCtrl, ']'); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 5); - CHECK(verify_text(EDIT, " a")); - } - - /* Key Handling - Special - *************************************************************************/ - TEST(backspace should do nothing on empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModNone, KEY_BACKSPACE); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - CHECK(verify_text(EDIT, "")); - } - - TEST(backspace should do nothing at beginning of buffer) { - setup_view(EDIT, "abc", CRLF, 0); - send_keys(ModNone, KEY_BACKSPACE); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - CHECK(verify_text(EDIT, "abc")); - } - - TEST(backspace should delete previous character) { - setup_view(EDIT, "abc", CRLF, 1); - send_keys(ModNone, KEY_BACKSPACE); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - CHECK(verify_text(EDIT, "bc")); - } - - TEST(backspace should delete selection) { - setup_view(EDIT, "abcde", CRLF, 0); - getview(EDIT)->selection = (Sel){ .beg = 1, .end = 4 }; - send_keys(ModNone, KEY_BACKSPACE); - CHECK(getsel(EDIT)->beg == 1); - CHECK(getsel(EDIT)->end == 1); - CHECK(verify_text(EDIT, "ae")); - } - - TEST(delete should do nothing on empty buffer) { - setup_view(EDIT, "", CRLF, 0); - send_keys(ModNone, KEY_DELETE); - CHECK(getsel(EDIT)->beg == 0); - CHECK(getsel(EDIT)->end == 0); - CHECK(verify_text(EDIT, "")); - } - - TEST(delete should do nothing at end of buffer) { - setup_view(EDIT, "abc", CRLF, 3); - send_keys(ModNone, KEY_DELETE); - CHECK(getsel(EDIT)->beg == 3); - CHECK(getsel(EDIT)->end == 3); - CHECK(verify_text(EDIT, "abc")); - } - - TEST(delete should delete next character) { - setup_view(EDIT, "abc", CRLF, 2); - send_keys(ModNone, KEY_DELETE); - CHECK(getsel(EDIT)->beg == 2); - CHECK(getsel(EDIT)->end == 2); - CHECK(verify_text(EDIT, "ab")); - } - - TEST(delete should delete selection) { - setup_view(EDIT, "abcde", CRLF, 0); - getview(EDIT)->selection = (Sel){ .beg = 1, .end = 4 }; - send_keys(ModNone, KEY_DELETE); - CHECK(getsel(EDIT)->beg == 1); - CHECK(getsel(EDIT)->end == 1); - CHECK(verify_text(EDIT, "ae")); - } - - /* Key Handling - Implementation Specific - *************************************************************************/ - TEST(ctrl+t should switch focus to EDIT view) { - Focused = TAGS; - send_keys(ModCtrl, 't'); - CHECK(Focused == EDIT); - } - - TEST(ctrl+t should switch focus to TAGs view) { - Focused = EDIT; - send_keys(ModCtrl, 't'); - CHECK(Focused == TAGS); - } - - TEST(ctrl+q should quit) { - setup_view(TAGS, "", CRLF, 0); - setup_view(EDIT, "", CRLF, 0); - getbuf(EDIT)->modified = false; - ExitCode = 42; - send_keys(ModCtrl, 'q'); - CHECK(ExitCode == 0); - CHECK(verify_text(TAGS, "")); - } - - TEST(ctrl+f should find next occurrence of selected text) { - setup_view(EDIT, "foobarfoo", CRLF, 0); - getview(EDIT)->selection = (Sel){ 0, 3, 0 }; - send_keys(ModCtrl, 'f'); - CHECK(getview(EDIT)->selection.beg == 6); - CHECK(getview(EDIT)->selection.end == 9); - } - - TEST(ctrl+f should wrap around to beginning of buffer) { - setup_view(EDIT, "foobarbazfoo", CRLF, 0); - getview(EDIT)->selection = (Sel){ 9, 12, 0 }; - send_keys(ModCtrl, 'f'); - CHECK(getview(EDIT)->selection.beg == 0); - CHECK(getview(EDIT)->selection.end == 3); - } - - /* Mouse Input Handling - *************************************************************************/ - - /* Command Execution - *************************************************************************/ - TEST(Commands starting with : should be executed as sed scripts) { - setup_view(EDIT, "foo", CRLF, 0); - getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 }; - setup_view(TAGS, ":s/foo/bar/", CRLF, 0); - getview(TAGS)->selection = (Sel){ .beg = 0, .end = 11 }; - send_keys(ModCtrl, 'd'); - #ifdef __MACH__ - CHECK(verify_text(EDIT, "bar\r\n")); - #else - CHECK(verify_text(EDIT, "bar")); - #endif - } - - TEST(Commands starting with | should be take selection as input and replace it with output) { - setup_view(EDIT, "foo", CRLF, 0); - getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 }; - setup_view(TAGS, "|sed -e 's/foo/bar/'", CRLF, 0); - getview(TAGS)->selection = (Sel){ .beg = 0, .end = 20 }; - send_keys(ModCtrl, 'd'); - #ifdef __MACH__ - CHECK(verify_text(EDIT, "bar\r\n")); - #else - CHECK(verify_text(EDIT, "bar")); - #endif - } - - TEST(Commands starting with ! should execute in the background with no input or output) { - setup_view(EDIT, "foo", CRLF, 0); - getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 }; - setup_view(TAGS, "!ls", CRLF, 0); - getview(TAGS)->selection = (Sel){ .beg = 0, .end = 3 }; - send_keys(ModCtrl, 'd'); - CHECK(verify_text(EDIT, "foo")); - } - -#if 0 - TEST(Commands starting with > should execute in the background with selection as input) { - setup_view(EDIT, "foo", CRLF, 0); - getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 }; - setup_view(TAGS, ">cat", CRLF, 0); - getview(TAGS)->selection = (Sel){ .beg = 0, .end = 4 }; - send_keys(ModCtrl, 'd'); - CHECK(verify_text(EDIT, "foo")); - } -#endif - - TEST(Commands starting with < should replace selection with output) { - setup_view(EDIT, "foo", CRLF, 0); - getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 }; - setup_view(TAGS, "selection = (Sel){ .beg = 0, .end = 9 }; - send_keys(ModCtrl, '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); - getview(EDIT)->selection = (Sel){ .beg = 0, .end = 8 }; - send_keys(ModCtrl, 'd'); - CHECK(verify_text(EDIT, "foo\r\n")); - } - - /* Tag Handling - *************************************************************************/ - TEST(Quit should quit immediately if buffer is unmodified) { - setup_view(TAGS, "", CRLF, 0); - setup_view(EDIT, "", CRLF, 0); - getbuf(EDIT)->modified = false; - ExitCode = 42; - exec("Quit"); - 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); - getbuf(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.")); - } - - TEST(Quit should discard changes if quit executed twice in less than 250 ms) { - setup_view(TAGS, "", CRLF, 0); - setup_view(EDIT, "", CRLF, 0); - getbuf(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"); - CHECK(ExitCode == 0); - CHECK(verify_text(TAGS, "File is modified. Repeat action twice in < 250ms to quit.")); - } - - TEST(Save should save changes to disk with crlf line endings) { - setup_view(TAGS, "", CRLF, 0); - view_init(getview(EDIT), "docs/crlf.txt"); - CHECK(verify_text(EDIT, "this file\r\nuses\r\ndos\r\nline\r\nendings\r\n")); - exec("Save"); - view_init(getview(EDIT), "docs/crlf.txt"); - CHECK(verify_text(EDIT, "this file\r\nuses\r\ndos\r\nline\r\nendings\r\n")); - } - - TEST(Save should save changes to disk with lf line endings) { - setup_view(TAGS, "", CRLF, 0); - view_init(getview(EDIT), "docs/lf.txt"); - CHECK(verify_text(EDIT, "this file\nuses\nunix\nline\nendings\n")); - exec("Save"); - view_init(getview(EDIT), "docs/lf.txt"); - 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); - getview(EDIT)->selection = (Sel){ 0, 8, 0 }; - exec("Cut"); - getview(EDIT)->selection = (Sel){ 4, 4, 0 }; - exec("Paste"); - CHECK(getsel(EDIT)->beg == 4); - CHECK(getsel(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); - getview(EDIT)->selection = (Sel){ 0, 8, 0 }; - exec("Copy"); - getview(EDIT)->selection = (Sel){ 12, 12, 0 }; - exec("Paste"); - CHECK(getsel(EDIT)->beg == 12); - CHECK(getsel(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); - exec("Undo"); - CHECK(verify_text(EDIT, "")); - exec("Redo"); - CHECK(verify_text(EDIT, "foo")); - } - - TEST(Undo+Redo should undo+redo the previous delete) { - setup_view(EDIT, "foo", CRLF, 0); - getview(EDIT)->selection = (Sel){ 0, 3, 0 }; - send_keys(ModNone, KEY_DELETE); - exec("Undo"); - CHECK(verify_text(EDIT, "foo")); - exec("Redo"); - CHECK(verify_text(EDIT, "")); - } - - TEST(Undo+Redo should undo+redo the previous delete with two non-contiguous deletes logged) { - setup_view(EDIT, "foobarbaz", CRLF, 0); - getview(EDIT)->selection = (Sel){ 0, 3, 0 }; - send_keys(ModNone, KEY_DELETE); - getview(EDIT)->selection = (Sel){ 3, 6, 0 }; - send_keys(ModNone, KEY_DELETE); - CHECK(verify_text(EDIT, "bar")); - exec("Undo"); - CHECK(verify_text(EDIT, "barbaz")); - exec("Redo"); - CHECK(verify_text(EDIT, "bar")); - } - - TEST(Undo+Redo should undo+redo the previous delete performed with backspace) { - setup_view(EDIT, "foo", CRLF, 0); - getview(EDIT)->selection = (Sel){ 3, 3, 0 }; - for(int i = 0; i < 3; i++) - send_keys(ModNone, KEY_BACKSPACE); - CHECK(verify_text(EDIT, "")); - exec("Undo"); - CHECK(verify_text(EDIT, "foo")); - exec("Redo"); - CHECK(verify_text(EDIT, "")); - } - - TEST(Find should find next occurrence of text selected in EDIT view) { - setup_view(EDIT, "foobarfoo", CRLF, 0); - getview(EDIT)->selection = (Sel){ 0, 3, 0 }; - exec("Find"); - CHECK(getview(EDIT)->selection.beg == 6); - CHECK(getview(EDIT)->selection.end == 9); - } - - TEST(Find should find wrap around to beginning of EDIT buffer) { - setup_view(EDIT, "foobarbazfoo", CRLF, 0); - getview(EDIT)->selection = (Sel){ 9, 12, 0 }; - exec("Find"); - CHECK(getview(EDIT)->selection.beg == 0); - CHECK(getview(EDIT)->selection.end == 3); - } - - TEST(Find should find next occurrence of text selected in TAGS view) { - setup_view(TAGS, "foo", CRLF, 0); - getview(TAGS)->selection = (Sel){ 0, 3, 0 }; - setup_view(EDIT, "barfoo", CRLF, 0); - exec("Find"); - CHECK(getview(EDIT)->selection.beg == 3); - CHECK(getview(EDIT)->selection.end == 6); - } - - TEST(Find should find next occurrence of text selected after tag) { - setup_view(EDIT, "barfoo", CRLF, 0); - exec("Find foo"); - CHECK(getview(EDIT)->selection.beg == 3); - CHECK(getview(EDIT)->selection.end == 6); - } - -#if 0 - TEST(Find should do nothing if nothing selected) { - setup_view(TAGS, "Find", CRLF, 0); - getview(TAGS)->selection = (Sel){ 0, 4, 0 }; - send_keys(ModCtrl, 'f'); - } -#endif +TEST_SUITE(UnitTests) { +// /* Key Handling - Normal Input +// *************************************************************************/ +// TEST(input not matching a shortcut should be inserted as text) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModNone, 'e'); +// CHECK(getsel(EDIT)->beg == 1); +// CHECK(getsel(EDIT)->end == 1); +// } +// +// TEST(input \n chould result in RUNE_CRLF if in crlf mode) { +// setup_view(EDIT, "", CRLF, 0); +// getbuf(EDIT)->crlf = 1; +// send_keys(ModNone, '\n'); +// CHECK(getsel(EDIT)->beg == 1); +// CHECK(getsel(EDIT)->end == 1); +// CHECK(RUNE_CRLF == buf_get(getbuf(EDIT), 0)); +// } +// +// TEST(input \n chould result in \n if not in crlf mode) { +// setup_view(EDIT, "", CRLF, 0); +// getbuf(EDIT)->crlf = 0; +// send_keys(ModNone, '\n'); +// CHECK(getsel(EDIT)->beg == 1); +// CHECK(getsel(EDIT)->end == 1); +// CHECK('\n' == buf_get(getbuf(EDIT), 0)); +// } +// +// /* Key Handling - Cursor Movement - Basic +// *************************************************************************/ +// TEST(left should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModNone, KEY_LEFT); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(ctrl+left should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModCtrl, KEY_LEFT); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(left should do nothing at beginning of buffer) { +// setup_view(EDIT, "AB", CRLF, 0); +// send_keys(ModNone, KEY_LEFT); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(ctrl+left should do nothing at beginning of buffer) { +// setup_view(EDIT, "AB", CRLF, 0); +// send_keys(ModCtrl, KEY_LEFT); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(ctrl+left should move left by one word) { +// setup_view(EDIT, "AB CD", CRLF, 3); +// send_keys(ModCtrl, KEY_LEFT); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(left should move left by one rune) { +// setup_view(EDIT, "AB", CRLF, 1); +// send_keys(ModNone, KEY_LEFT); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(right should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModNone, KEY_RIGHT); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(right should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModCtrl, KEY_RIGHT); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(ctrl+right should do nothing at end of buffer) { +// setup_view(EDIT, "AB", CRLF, 2); +// send_keys(ModNone, KEY_RIGHT); +// CHECK(getsel(EDIT)->beg == 2); +// CHECK(getsel(EDIT)->end == 2); +// } +// +// TEST(ctrl+right should do nothing at end of buffer) { +// setup_view(EDIT, "AB", CRLF, 2); +// send_keys(ModCtrl, KEY_RIGHT); +// CHECK(getsel(EDIT)->beg == 2); +// CHECK(getsel(EDIT)->end == 2); +// } +// +// TEST(ctrl+right should move right by one word) { +// setup_view(EDIT, "AB CD", CRLF, 0); +// send_keys(ModCtrl, KEY_RIGHT); +// CHECK(getsel(EDIT)->beg == 3); +// CHECK(getsel(EDIT)->end == 3); +// } +// +// TEST(right should move right by one rune) { +// setup_view(EDIT, "AB", CRLF, 1); +// send_keys(ModNone, KEY_RIGHT); +// CHECK(getsel(EDIT)->beg == 2); +// CHECK(getsel(EDIT)->end == 2); +// } +// +// TEST(up should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModNone, KEY_UP); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(up should move cursor up one line) { +// setup_view(EDIT, "AB\nCD", CRLF, 4); +// send_keys(ModNone, KEY_UP); +// CHECK(getsel(EDIT)->beg == 1); +// CHECK(getsel(EDIT)->end == 1); +// } +// +// TEST(up should do nothing for first line) { +// setup_view(EDIT, "AB\nCD", CRLF, 1); +// send_keys(ModNone, KEY_UP); +// CHECK(getsel(EDIT)->beg == 1); +// CHECK(getsel(EDIT)->end == 1); +// } +// +// TEST(down should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModNone, KEY_DOWN); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(down should move down one line) { +// setup_view(EDIT, "AB\nCD", CRLF, 1); +// send_keys(ModNone, KEY_DOWN); +// CHECK(getsel(EDIT)->beg == 4); +// CHECK(getsel(EDIT)->end == 4); +// } +// +// TEST(down should do nothing on last line) { +// setup_view(EDIT, "AB\nCD", CRLF, 4); +// send_keys(ModNone, KEY_DOWN); +// CHECK(getsel(EDIT)->beg == 4); +// CHECK(getsel(EDIT)->end == 4); +// } +// +// TEST(home should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModNone, KEY_HOME); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(ctrl+home should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModCtrl, KEY_HOME); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(ctrl+home should move to beginning of buffer) { +// setup_view(EDIT, "ABCD", CRLF, 4); +// send_keys(ModCtrl, KEY_HOME); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(home should move to beginning of indented content) { +// setup_view(EDIT, " ABCD", CRLF, 7); +// send_keys(ModNone, KEY_HOME); +// CHECK(getsel(EDIT)->beg == 4); +// CHECK(getsel(EDIT)->end == 4); +// } +// +// TEST(home should move to beginning of line if at beginning of indented content) { +// setup_view(EDIT, " ABCD", CRLF, 7); +// send_keys(ModNone, KEY_HOME); +// CHECK(getsel(EDIT)->beg == 4); +// CHECK(getsel(EDIT)->end == 4); +// } +// +// TEST(home should move to beginning of indented content when at beginning of line) { +// setup_view(EDIT, " ABCD", CRLF, 0); +// send_keys(ModNone, KEY_HOME); +// CHECK(getsel(EDIT)->beg == 4); +// CHECK(getsel(EDIT)->end == 4); +// } +// +// TEST(end should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModNone, KEY_END); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(ctrl+end should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModCtrl, KEY_END); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(ctrl+end should move to end of buffer) { +// setup_view(EDIT, "ABCD", CRLF, 0); +// send_keys(ModCtrl, KEY_END); +// CHECK(getsel(EDIT)->beg == 4); +// CHECK(getsel(EDIT)->end == 4); +// } +// +// TEST(end should do nothing at end of line) { +// setup_view(EDIT, "AB\nCD", CRLF, 2); +// send_keys(ModNone, KEY_END); +// CHECK(getsel(EDIT)->beg == 2); +// CHECK(getsel(EDIT)->end == 2); +// } +// +// TEST(end should move to end of line) { +// setup_view(EDIT, "AB\nCD", CRLF, 0); +// send_keys(ModNone, KEY_END); +// CHECK(getsel(EDIT)->beg == 2); +// CHECK(getsel(EDIT)->end == 2); +// } +// +// /* Key Handling - Unix Editing Shortcuts +// *************************************************************************/ +// TEST(ctrl+u should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModCtrl, 'u'); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(ctrl+u should delete to beginning of line) { +// setup_view(EDIT, "\nABC\n", CRLF, 2); +// send_keys(ModCtrl, 'u'); +// CHECK(getsel(EDIT)->beg == 1); +// CHECK(getsel(EDIT)->end == 1); +// CHECK(buf_end(getbuf(EDIT)) == 4); +// } +// +// TEST(ctrl+u should delete entire lines contents) { +// setup_view(EDIT, "\nABC\n", CRLF, 3); +// send_keys(ModCtrl, 'u'); +// CHECK(getsel(EDIT)->beg == 1); +// CHECK(getsel(EDIT)->end == 1); +// CHECK(buf_end(getbuf(EDIT)) == 3); +// } +// +// TEST(ctrl+k should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModCtrl, 'k'); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// CHECK(buf_end(getbuf(EDIT)) == 0); +// } +// +// TEST(ctrl+k should delete to end of line) { +// setup_view(EDIT, "\nABC\n", CRLF, 2); +// send_keys(ModCtrl, 'k'); +// CHECK(getsel(EDIT)->beg == 2); +// CHECK(getsel(EDIT)->end == 2); +// CHECK(buf_end(getbuf(EDIT)) == 3); +// } +// +// TEST(ctrl+k should delete entire lines contents) { +// setup_view(EDIT, "\nABC\n", CRLF, 1); +// send_keys(ModCtrl, 'k'); +// CHECK(getsel(EDIT)->beg == 1); +// CHECK(getsel(EDIT)->end == 1); +// CHECK(buf_end(getbuf(EDIT)) == 2); +// } +// +// TEST(ctrl+w should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModCtrl, 'w'); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// CHECK(buf_end(getbuf(EDIT)) == 0); +// } +// +// TEST(ctrl+w should delete previous word) { +// setup_view(EDIT, "abc def", CRLF, 4); +// send_keys(ModCtrl, 'w'); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// CHECK(buf_end(getbuf(EDIT)) == 3); +// } +// +// TEST(ctrl+h should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModCtrl, 'h'); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(ctrl+h should delete previous character) { +// setup_view(EDIT, "AB", CRLF, 1); +// send_keys(ModCtrl, 'h'); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// CHECK(buf_end(getbuf(EDIT)) == 1); +// } +// +// TEST(ctrl+a should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModCtrl, 'a'); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(ctrl+a should move to beginning of indented content) { +// setup_view(EDIT, " ABCD", CRLF, 7); +// send_keys(ModCtrl, 'a'); +// CHECK(getsel(EDIT)->beg == 4); +// CHECK(getsel(EDIT)->end == 4); +// } +// +// TEST(ctrl+a should move to beginning of line if at beginning of indented content) { +// setup_view(EDIT, " ABCD", CRLF, 7); +// send_keys(ModCtrl, 'a'); +// CHECK(getsel(EDIT)->beg == 4); +// CHECK(getsel(EDIT)->end == 4); +// } +// +// TEST(ctrl+a should move to beginning of indented content when at beginning of line) { +// setup_view(EDIT, " ABCD", CRLF, 0); +// send_keys(ModCtrl, 'a'); +// CHECK(getsel(EDIT)->beg == 4); +// CHECK(getsel(EDIT)->end == 4); +// } +// +// TEST(ctrl+e should do nothing for empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModCtrl, 'e'); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(ctrl+e should do nothing at end of line) { +// setup_view(EDIT, "AB\nCD", CRLF, 2); +// send_keys(ModCtrl, 'e'); +// CHECK(getsel(EDIT)->beg == 2); +// CHECK(getsel(EDIT)->end == 2); +// } +// +// TEST(ctrl+e should move to end of line) { +// setup_view(EDIT, "AB\nCD", CRLF, 0); +// send_keys(ModCtrl, 'e'); +// CHECK(getsel(EDIT)->beg == 2); +// CHECK(getsel(EDIT)->end == 2); +// } +// +// TEST(esc should select previously inserted text) { +// setup_view(EDIT, "foo", CRLF, 0); +// send_keys(ModNone, KEY_ESCAPE); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 3); +// } +// +// TEST(esc should select previously edited text) { +// setup_view(EDIT, "foob", CRLF, 4); +// send_keys(ModNone, KEY_BACKSPACE); +// send_keys(ModNone, KEY_ESCAPE); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 3); +// } +// +// /* 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); +// getview(EDIT)->selection = (Sel){ 0, 8, 0 }; +// send_keys(ModCtrl, 'x'); +// getview(EDIT)->selection = (Sel){ 4, 4, 0 }; +// send_keys(ModCtrl, 'v'); +// CHECK(getsel(EDIT)->beg == 4); +// CHECK(getsel(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) { +// getbuf(EDIT)->crlf = 1; +// setup_view(EDIT, "foo\nbar\nbaz\n", CRLF, 0); +// getview(EDIT)->selection = (Sel){ 0, 8, 0 }; +// send_keys(ModCtrl, 'c'); +// getview(EDIT)->selection = (Sel){ 12, 12, 0 }; +// send_keys(ModCtrl, 'v'); +// CHECK(getsel(EDIT)->beg == 12); +// CHECK(getsel(EDIT)->end == 20); +// CHECK(verify_text(EDIT, "foo\r\nbar\r\nbaz\r\nfoo\r\nbar\r\n")); +// } +// +// /* Key Handling - Block Indent +// *************************************************************************/ +// TEST(ctrl+[ should do nothing on empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModCtrl, '['); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(ctrl+[ should do nothing at beginning of buffer) { +// setup_view(EDIT, "a", CRLF, 0); +// send_keys(ModCtrl, '['); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 1); +// } +// +// TEST(ctrl+] should do nothing on empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModCtrl, ']'); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// } +// +// TEST(ctrl+] should indent the first line) { +// setup_view(EDIT, "a", CRLF, 0); +// send_keys(ModCtrl, ']'); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 5); +// CHECK(verify_text(EDIT, " a")); +// } +// +// /* Key Handling - Special +// *************************************************************************/ +// TEST(backspace should do nothing on empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModNone, KEY_BACKSPACE); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// CHECK(verify_text(EDIT, "")); +// } +// +// TEST(backspace should do nothing at beginning of buffer) { +// setup_view(EDIT, "abc", CRLF, 0); +// send_keys(ModNone, KEY_BACKSPACE); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// CHECK(verify_text(EDIT, "abc")); +// } +// +// TEST(backspace should delete previous character) { +// setup_view(EDIT, "abc", CRLF, 1); +// send_keys(ModNone, KEY_BACKSPACE); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// CHECK(verify_text(EDIT, "bc")); +// } +// +// TEST(backspace should delete selection) { +// setup_view(EDIT, "abcde", CRLF, 0); +// getview(EDIT)->selection = (Sel){ .beg = 1, .end = 4 }; +// send_keys(ModNone, KEY_BACKSPACE); +// CHECK(getsel(EDIT)->beg == 1); +// CHECK(getsel(EDIT)->end == 1); +// CHECK(verify_text(EDIT, "ae")); +// } +// +// TEST(delete should do nothing on empty buffer) { +// setup_view(EDIT, "", CRLF, 0); +// send_keys(ModNone, KEY_DELETE); +// CHECK(getsel(EDIT)->beg == 0); +// CHECK(getsel(EDIT)->end == 0); +// CHECK(verify_text(EDIT, "")); +// } +// +// TEST(delete should do nothing at end of buffer) { +// setup_view(EDIT, "abc", CRLF, 3); +// send_keys(ModNone, KEY_DELETE); +// CHECK(getsel(EDIT)->beg == 3); +// CHECK(getsel(EDIT)->end == 3); +// CHECK(verify_text(EDIT, "abc")); +// } +// +// TEST(delete should delete next character) { +// setup_view(EDIT, "abc", CRLF, 2); +// send_keys(ModNone, KEY_DELETE); +// CHECK(getsel(EDIT)->beg == 2); +// CHECK(getsel(EDIT)->end == 2); +// CHECK(verify_text(EDIT, "ab")); +// } +// +// TEST(delete should delete selection) { +// setup_view(EDIT, "abcde", CRLF, 0); +// getview(EDIT)->selection = (Sel){ .beg = 1, .end = 4 }; +// send_keys(ModNone, KEY_DELETE); +// CHECK(getsel(EDIT)->beg == 1); +// CHECK(getsel(EDIT)->end == 1); +// CHECK(verify_text(EDIT, "ae")); +// } +// +// /* Key Handling - Implementation Specific +// *************************************************************************/ +// TEST(ctrl+t should switch focus to EDIT view) { +// Focused = TAGS; +// send_keys(ModCtrl, 't'); +// CHECK(Focused == EDIT); +// } +// +// TEST(ctrl+t should switch focus to TAGs view) { +// Focused = EDIT; +// send_keys(ModCtrl, 't'); +// CHECK(Focused == TAGS); +// } +// +// TEST(ctrl+q should quit) { +// setup_view(TAGS, "", CRLF, 0); +// setup_view(EDIT, "", CRLF, 0); +// getbuf(EDIT)->modified = false; +// ExitCode = 42; +// send_keys(ModCtrl, 'q'); +// CHECK(ExitCode == 0); +// CHECK(verify_text(TAGS, "")); +// } +// +// TEST(ctrl+f should find next occurrence of selected text) { +// setup_view(EDIT, "foobarfoo", CRLF, 0); +// getview(EDIT)->selection = (Sel){ 0, 3, 0 }; +// send_keys(ModCtrl, 'f'); +// CHECK(getview(EDIT)->selection.beg == 6); +// CHECK(getview(EDIT)->selection.end == 9); +// } +// +// TEST(ctrl+f should wrap around to beginning of buffer) { +// setup_view(EDIT, "foobarbazfoo", CRLF, 0); +// getview(EDIT)->selection = (Sel){ 9, 12, 0 }; +// send_keys(ModCtrl, 'f'); +// CHECK(getview(EDIT)->selection.beg == 0); +// CHECK(getview(EDIT)->selection.end == 3); +// } +// +// /* Mouse Input Handling +// *************************************************************************/ +// +// /* Command Execution +// *************************************************************************/ +// TEST(Commands starting with : should be executed as sed scripts) { +// setup_view(EDIT, "foo", CRLF, 0); +// getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 }; +// setup_view(TAGS, ":s/foo/bar/", CRLF, 0); +// getview(TAGS)->selection = (Sel){ .beg = 0, .end = 11 }; +// send_keys(ModCtrl, 'd'); +// #ifdef __MACH__ +// CHECK(verify_text(EDIT, "bar\r\n")); +// #else +// CHECK(verify_text(EDIT, "bar")); +// #endif +// } +// +// TEST(Commands starting with | should be take selection as input and replace it with output) { +// setup_view(EDIT, "foo", CRLF, 0); +// getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 }; +// setup_view(TAGS, "|sed -e 's/foo/bar/'", CRLF, 0); +// getview(TAGS)->selection = (Sel){ .beg = 0, .end = 20 }; +// send_keys(ModCtrl, 'd'); +// #ifdef __MACH__ +// CHECK(verify_text(EDIT, "bar\r\n")); +// #else +// CHECK(verify_text(EDIT, "bar")); +// #endif +// } +// +// TEST(Commands starting with ! should execute in the background with no input or output) { +// setup_view(EDIT, "foo", CRLF, 0); +// getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 }; +// setup_view(TAGS, "!ls", CRLF, 0); +// getview(TAGS)->selection = (Sel){ .beg = 0, .end = 3 }; +// send_keys(ModCtrl, 'd'); +// CHECK(verify_text(EDIT, "foo")); +// } +// +//#if 0 +// TEST(Commands starting with > should execute in the background with selection as input) { +// setup_view(EDIT, "foo", CRLF, 0); +// getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 }; +// setup_view(TAGS, ">cat", CRLF, 0); +// getview(TAGS)->selection = (Sel){ .beg = 0, .end = 4 }; +// send_keys(ModCtrl, 'd'); +// CHECK(verify_text(EDIT, "foo")); +// } +//#endif +// +// TEST(Commands starting with < should replace selection with output) { +// setup_view(EDIT, "foo", CRLF, 0); +// getview(EDIT)->selection = (Sel){ .beg = 0, .end = 3 }; +// setup_view(TAGS, "selection = (Sel){ .beg = 0, .end = 9 }; +// send_keys(ModCtrl, '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); +// getview(EDIT)->selection = (Sel){ .beg = 0, .end = 8 }; +// send_keys(ModCtrl, 'd'); +// CHECK(verify_text(EDIT, "foo\r\n")); +// } +// +// /* Tag Handling +// *************************************************************************/ +// TEST(Quit should quit immediately if buffer is unmodified) { +// setup_view(TAGS, "", CRLF, 0); +// setup_view(EDIT, "", CRLF, 0); +// getbuf(EDIT)->modified = false; +// ExitCode = 42; +// exec("Quit"); +// 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); +// getbuf(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.")); +// } +// +// TEST(Quit should discard changes if quit executed twice in less than 250 ms) { +// setup_view(TAGS, "", CRLF, 0); +// setup_view(EDIT, "", CRLF, 0); +// getbuf(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"); +// CHECK(ExitCode == 0); +// CHECK(verify_text(TAGS, "File is modified. Repeat action twice in < 250ms to quit.")); +// } +// +// TEST(Save should save changes to disk with crlf line endings) { +// setup_view(TAGS, "", CRLF, 0); +// view_init(getview(EDIT), "docs/crlf.txt"); +// CHECK(verify_text(EDIT, "this file\r\nuses\r\ndos\r\nline\r\nendings\r\n")); +// exec("Save"); +// view_init(getview(EDIT), "docs/crlf.txt"); +// CHECK(verify_text(EDIT, "this file\r\nuses\r\ndos\r\nline\r\nendings\r\n")); +// } +// +// TEST(Save should save changes to disk with lf line endings) { +// setup_view(TAGS, "", CRLF, 0); +// view_init(getview(EDIT), "docs/lf.txt"); +// CHECK(verify_text(EDIT, "this file\nuses\nunix\nline\nendings\n")); +// exec("Save"); +// view_init(getview(EDIT), "docs/lf.txt"); +// 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); +// getview(EDIT)->selection = (Sel){ 0, 8, 0 }; +// exec("Cut"); +// getview(EDIT)->selection = (Sel){ 4, 4, 0 }; +// exec("Paste"); +// CHECK(getsel(EDIT)->beg == 4); +// CHECK(getsel(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); +// getview(EDIT)->selection = (Sel){ 0, 8, 0 }; +// exec("Copy"); +// getview(EDIT)->selection = (Sel){ 12, 12, 0 }; +// exec("Paste"); +// CHECK(getsel(EDIT)->beg == 12); +// CHECK(getsel(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); +// exec("Undo"); +// CHECK(verify_text(EDIT, "")); +// exec("Redo"); +// CHECK(verify_text(EDIT, "foo")); +// } +// +// TEST(Undo+Redo should undo+redo the previous delete) { +// setup_view(EDIT, "foo", CRLF, 0); +// getview(EDIT)->selection = (Sel){ 0, 3, 0 }; +// send_keys(ModNone, KEY_DELETE); +// exec("Undo"); +// CHECK(verify_text(EDIT, "foo")); +// exec("Redo"); +// CHECK(verify_text(EDIT, "")); +// } +// +// TEST(Undo+Redo should undo+redo the previous delete with two non-contiguous deletes logged) { +// setup_view(EDIT, "foobarbaz", CRLF, 0); +// getview(EDIT)->selection = (Sel){ 0, 3, 0 }; +// send_keys(ModNone, KEY_DELETE); +// getview(EDIT)->selection = (Sel){ 3, 6, 0 }; +// send_keys(ModNone, KEY_DELETE); +// CHECK(verify_text(EDIT, "bar")); +// exec("Undo"); +// CHECK(verify_text(EDIT, "barbaz")); +// exec("Redo"); +// CHECK(verify_text(EDIT, "bar")); +// } +// +// TEST(Undo+Redo should undo+redo the previous delete performed with backspace) { +// setup_view(EDIT, "foo", CRLF, 0); +// getview(EDIT)->selection = (Sel){ 3, 3, 0 }; +// for(int i = 0; i < 3; i++) +// send_keys(ModNone, KEY_BACKSPACE); +// CHECK(verify_text(EDIT, "")); +// exec("Undo"); +// CHECK(verify_text(EDIT, "foo")); +// exec("Redo"); +// CHECK(verify_text(EDIT, "")); +// } +// +// TEST(Find should find next occurrence of text selected in EDIT view) { +// setup_view(EDIT, "foobarfoo", CRLF, 0); +// getview(EDIT)->selection = (Sel){ 0, 3, 0 }; +// exec("Find"); +// CHECK(getview(EDIT)->selection.beg == 6); +// CHECK(getview(EDIT)->selection.end == 9); +// } +// +// TEST(Find should find wrap around to beginning of EDIT buffer) { +// setup_view(EDIT, "foobarbazfoo", CRLF, 0); +// getview(EDIT)->selection = (Sel){ 9, 12, 0 }; +// exec("Find"); +// CHECK(getview(EDIT)->selection.beg == 0); +// CHECK(getview(EDIT)->selection.end == 3); +// } +// +// TEST(Find should find next occurrence of text selected in TAGS view) { +// setup_view(TAGS, "foo", CRLF, 0); +// getview(TAGS)->selection = (Sel){ 0, 3, 0 }; +// setup_view(EDIT, "barfoo", CRLF, 0); +// exec("Find"); +// CHECK(getview(EDIT)->selection.beg == 3); +// CHECK(getview(EDIT)->selection.end == 6); +// } +// +// TEST(Find should find next occurrence of text selected after tag) { +// setup_view(EDIT, "barfoo", CRLF, 0); +// exec("Find foo"); +// CHECK(getview(EDIT)->selection.beg == 3); +// CHECK(getview(EDIT)->selection.end == 6); +// } +// +//#if 0 +// TEST(Find should do nothing if nothing selected) { +// setup_view(TAGS, "Find", CRLF, 0); +// getview(TAGS)->selection = (Sel){ 0, 4, 0 }; +// send_keys(ModCtrl, 'f'); +// } +//#endif +// +// TEST(Tabs should set indent style to tabs) { +// setup_view(TAGS, "Tabs", CRLF, 0); +// getview(TAGS)->selection = (Sel){ 0, 4, 0 }; +// getbuf(EDIT)->expand_tabs = true; +// getbuf(TAGS)->expand_tabs = true; +// send_keys(ModCtrl, 'd'); +// CHECK(getbuf(EDIT)->expand_tabs == false); +// CHECK(getbuf(TAGS)->expand_tabs == false); +// } +// +// TEST(Tabs should set indent style to spaces) { +// setup_view(TAGS, "Tabs", CRLF, 0); +// getview(TAGS)->selection = (Sel){ 0, 4, 0 }; +// getbuf(EDIT)->expand_tabs = false; +// getbuf(TAGS)->expand_tabs = false; +// send_keys(ModCtrl, 'd'); +// CHECK(getbuf(EDIT)->expand_tabs == true); +// CHECK(getbuf(TAGS)->expand_tabs == true); +// } +// +// TEST(Indent should disable copyindent) { +// setup_view(TAGS, "Indent", CRLF, 0); +// getview(TAGS)->selection = (Sel){ 0, 6, 0 }; +// getbuf(EDIT)->copy_indent = true; +// getbuf(TAGS)->copy_indent = true; +// send_keys(ModCtrl, 'd'); +// CHECK(getbuf(EDIT)->copy_indent == false); +// CHECK(getbuf(TAGS)->copy_indent == false); +// } +// +// TEST(Indent should enable copyindent) { +// setup_view(TAGS, "Indent", CRLF, 0); +// getview(TAGS)->selection = (Sel){ 0, 6, 0 }; +// getbuf(EDIT)->copy_indent = false; +// getbuf(TAGS)->copy_indent = false; +// send_keys(ModCtrl, 'd'); +// CHECK(getbuf(EDIT)->copy_indent == true); +// CHECK(getbuf(TAGS)->copy_indent == true); +// } +} - TEST(Tabs should set indent style to tabs) { - setup_view(TAGS, "Tabs", CRLF, 0); - getview(TAGS)->selection = (Sel){ 0, 4, 0 }; - getbuf(EDIT)->expand_tabs = true; - getbuf(TAGS)->expand_tabs = true; - send_keys(ModCtrl, 'd'); - CHECK(getbuf(EDIT)->expand_tabs == false); - CHECK(getbuf(TAGS)->expand_tabs == false); - } - - TEST(Tabs should set indent style to spaces) { - setup_view(TAGS, "Tabs", CRLF, 0); - getview(TAGS)->selection = (Sel){ 0, 4, 0 }; - getbuf(EDIT)->expand_tabs = false; - getbuf(TAGS)->expand_tabs = false; - send_keys(ModCtrl, 'd'); - CHECK(getbuf(EDIT)->expand_tabs == true); - CHECK(getbuf(TAGS)->expand_tabs == true); - } - - TEST(Indent should disable copyindent) { - setup_view(TAGS, "Indent", CRLF, 0); - getview(TAGS)->selection = (Sel){ 0, 6, 0 }; - getbuf(EDIT)->copy_indent = true; - getbuf(TAGS)->copy_indent = true; - send_keys(ModCtrl, 'd'); - CHECK(getbuf(EDIT)->copy_indent == false); - CHECK(getbuf(TAGS)->copy_indent == false); - } - - TEST(Indent should enable copyindent) { - setup_view(TAGS, "Indent", CRLF, 0); - getview(TAGS)->selection = (Sel){ 0, 6, 0 }; - getbuf(EDIT)->copy_indent = false; - getbuf(TAGS)->copy_indent = false; - send_keys(ModCtrl, 'd'); - CHECK(getbuf(EDIT)->copy_indent == true); - CHECK(getbuf(TAGS)->copy_indent == true); - } +int main(int argc, char** argv) { + atf_init(argc,argv); + RUN_TEST_SUITE(UnitTests); + return atf_print_results(); } diff --git a/tests/xpick.c b/tests/xpick.c new file mode 100644 index 0000000..82adc25 --- /dev/null +++ b/tests/xpick.c @@ -0,0 +1,15 @@ +#define INCLUDE_DEFS +#include +#include + +// Inculd the source file so we can access everything +#include "../xpick.c" + +TEST_SUITE(UnitTests) { +} + +int main(int argc, char** argv) { + atf_init(argc,argv); + RUN_TEST_SUITE(UnitTests); + return atf_print_results(); +} diff --git a/tools/term.c b/tools/term.c new file mode 100644 index 0000000..41ab59a --- /dev/null +++ b/tools/term.c @@ -0,0 +1,72 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include + +#define PIPE_READ 0 +#define PIPE_WRITE 1 + +typedef struct { + int pid; /* process id of the child process */ + int in; /* file descriptor for the child process's standard input */ + int out; /* file descriptor for the child process's standard output */ +} Process; + +static int execute(char** cmd, Process* proc) { + int inpipe[2], outpipe[2]; + /* create the pipes */ + if ((pipe(inpipe) < 0) || (pipe(outpipe) < 0)) + return -1; + /* create the process */ + proc->pid = fork(); + if (proc->pid < 0) { + /* signal that we failed to fork */ + proc->in = -1; + proc->out = -1; + } else if (0 == proc->pid) { + /* redirect child process's io to the pipes */ + if ((dup2(inpipe[PIPE_READ], STDIN_FILENO) < 0) || + (dup2(outpipe[PIPE_WRITE], STDOUT_FILENO) < 0)) { + perror("failed to pipe"); + exit(1); + } + /* execute the process */ + close(inpipe[PIPE_WRITE]); + close(outpipe[PIPE_READ]); + dup2(STDOUT_FILENO, STDERR_FILENO); + close(STDERR_FILENO); + exit(execvp(cmd[0], cmd)); + } else { + close(inpipe[PIPE_READ]); + close(outpipe[PIPE_WRITE]); + proc->in = inpipe[PIPE_WRITE]; + proc->out = outpipe[PIPE_READ]; + } + return proc->pid; +} + +int main(int argc, char** argv){ + setenv("PS1", "$ ", 1); + Process proc; + execute((char*[]){"/bin/sh", "-i", NULL}, &proc); + + int nbytes = 0; + char buffer[8192]; + while (true) { + puts("foo"); + nbytes = read(STDIN_FILENO, buffer, sizeof(buffer)); + if (nbytes < 0) break; + puts("bar"); + write(proc.in, buffer, nbytes); + puts("baa"); + while ((nbytes = read(proc.out, buffer, sizeof(buffer))) > 0) { + puts("boo"); + write(1, buffer, nbytes); + } + puts("baz"); + if (nbytes < 0) break; + } + close(proc.in); + close(proc.out); + + return 0; +} diff --git a/xedit.c b/xedit.c index b8d5769..7e23119 100644 --- a/xedit.c +++ b/xedit.c @@ -9,6 +9,14 @@ #define exit mockexit #endif +typedef struct { + char* tag; + union { + void (*noarg)(void); + void (*arg)(char* arg); + } action; +} Tag; + /* The shell: Filled in with $SHELL. Used to execute commands */ static char* ShellCmd[] = { NULL, "-c", NULL, NULL }; static char* SedCmd[] = { "sed", "-e", NULL, NULL }; diff --git a/xpick.c b/xpick.c index 63367ed..181130d 100644 --- a/xpick.c +++ b/xpick.c @@ -194,6 +194,7 @@ static void keyboard_input(int mods, uint32_t key) { score(); } +#ifndef TEST int main(int argc, char** argv) { load_choices(); if (vec_size(&Choices) > 1) { @@ -213,3 +214,4 @@ int main(int argc, char** argv) { } return 0; } +#endif