From f83e66a478217643192e02af8201eb0471fd224d Mon Sep 17 00:00:00 2001 From: Boris Faure Date: Tue, 20 Nov 2018 23:03:21 +0100 Subject: [PATCH] add tytest, a tool to add tests on escape sequence parsing --- meson.build | 8 +++ meson_options.txt | 4 ++ src/bin/main.c | 4 +- src/bin/meson.build | 18 +++++++ src/bin/private.h | 2 +- src/bin/termpty.c | 6 +-- src/bin/termpty.h | 74 +++++++++++++++------------- src/bin/termptyesc.c | 7 +-- src/bin/tyfuzz.c | 113 +++++++++++++++++++++++++++++++++++++++++-- src/bin/tytest.c | 2 + 10 files changed, 191 insertions(+), 47 deletions(-) create mode 100644 src/bin/tytest.c diff --git a/meson.build b/meson.build index 8afade3c..ed68588d 100644 --- a/meson.build +++ b/meson.build @@ -115,6 +115,14 @@ else message('Fuzzing is disabled') endif +tests = get_option('tests') +if tests + config_data.set('ENABLE_TESTS', 1) + message('Tests are enabled') +else + message('Tests are disabled') +endif + message('edje_cc set to:' + edje_cc) configure_file(output: 'terminology_config.h', diff --git a/meson_options.txt b/meson_options.txt index ad5e3c23..ac57a666 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -5,6 +5,10 @@ option('fuzzing', type: 'boolean', value: false, description: 'Enable fuzzing on terminology. Binaries are not suited for production. (default=false)') +option('tests', + type: 'boolean', + value: false, + description: 'Enable generating tytest, used to run tests. (default=false)') option('nls', type: 'boolean', value: true, diff --git a/src/bin/main.c b/src/bin/main.c index a29d0b59..fa012c22 100644 --- a/src/bin/main.c +++ b/src/bin/main.c @@ -454,7 +454,7 @@ _translate_options(void) } #endif -#ifdef ENABLE_FUZZING +#if defined(ENABLE_FUZZING) || defined(ENABLE_TESTS) static void _log_void(const Eina_Log_Domain *_d EINA_UNUSED, Eina_Log_Level level EINA_UNUSED, @@ -548,7 +548,7 @@ elm_main(int argc, char **argv) terminology_starting_up = EINA_TRUE; -#ifdef ENABLE_FUZZING +#if defined(ENABLE_FUZZING) || defined(ENABLE_TESTS) eina_log_print_cb_set(_log_void, NULL); #endif diff --git a/src/bin/meson.build b/src/bin/meson.build index b4a5d319..2320e5b4 100644 --- a/src/bin/meson.build +++ b/src/bin/meson.build @@ -57,6 +57,17 @@ tyfuzz_sources = ['termptyesc.c', 'termptyesc.h', 'config.c', 'config.h', 'col.c', 'col.h', 'tyfuzz.c'] +tytest_sources = ['termptyesc.c', 'termptyesc.h', + 'termptysave.c', 'termptysave.h', + 'termptyops.c', 'termptyops.h', + 'termptydbl.c', 'termptydbl.h', + 'termptyext.c', 'termptyext.h', + 'termptygfx.c', 'termptygfx.h', + 'termpty.c', 'termpty.h', + 'config.c', 'config.h', + 'col.c', 'col.h', + 'md5/md5.c', 'md5/md5.h', + 'tytest.c'] executable('terminology', terminology_sources, @@ -107,3 +118,10 @@ if fuzzing include_directories: config_dir, dependencies: terminology_dependencies) endif +if tests + executable('tytest', + tytest_sources, + install: true, + include_directories: config_dir, + dependencies: terminology_dependencies) +endif diff --git a/src/bin/private.h b/src/bin/private.h index 61779a45..c4e93e74 100644 --- a/src/bin/private.h +++ b/src/bin/private.h @@ -18,7 +18,7 @@ extern int terminology_starting_up; -#ifdef ENABLE_FUZZING +#if defined(ENABLE_FUZZING) || defined(ENABLE_TESTS) #define EINA_LOG_LEVEL_MAXIMUM (-1) #endif extern int _log_domain; diff --git a/src/bin/termpty.c b/src/bin/termpty.c index cd3d91bf..35c1b721 100644 --- a/src/bin/termpty.c +++ b/src/bin/termpty.c @@ -334,7 +334,7 @@ _fd_read_do(Termpty *ty, Ecore_Fd_Handler *fd_handler, Eina_Bool false_on_empty) termpty_handle_buf(ty, codepoint, j); } if (ty->cb.change.func) ty->cb.change.func(ty->cb.change.data); -#ifdef ENABLE_FUZZING +#if defined(ENABLE_FUZZING) || defined(ENABLE_TESTS) if (len <= 0) { ty->exit_code = 0; @@ -525,7 +525,7 @@ termpty_new(const char *cmd, Eina_Bool login_shell, const char *cd, ty->circular_offset = 0; -#ifdef ENABLE_FUZZING +#if defined(ENABLE_FUZZING) || defined(ENABLE_TESTS) ty->fd = STDIN_FILENO; ty->hand_fd = ecore_main_fd_handler_add(ty->fd, ECORE_FD_READ | ECORE_FD_ERROR, @@ -1243,7 +1243,7 @@ termpty_write(Termpty *ty, const char *input, int len) { int fd = ty->fd; -#ifdef ENABLE_FUZZING +#if defined(ENABLE_FUZZING) || defined(ENABLE_TESTS) fd = ty->fd_dev_null; #endif if (fd < 0) return; diff --git a/src/bin/termpty.h b/src/bin/termpty.h index 9fb6c99d..d8206436 100644 --- a/src/bin/termpty.h +++ b/src/bin/termpty.h @@ -90,6 +90,42 @@ struct _Termatt uint16_t link_id; }; +typedef struct _Backlog_Beacon{ + int screen_y; + int backlog_y; +} Backlog_Beacon; + +typedef struct _Term_State { + Termatt att; + unsigned char charset; + unsigned char charsetch; + unsigned char chset[4]; + int top_margin, bottom_margin; + int left_margin, right_margin; + int had_cr_x, had_cr_y; + unsigned int lr_margins : 1; + unsigned int restrict_cursor : 1; + unsigned int multibyte : 1; + unsigned int alt_kp : 1; + unsigned int insert : 1; + unsigned int appcursor : 1; + unsigned int wrap : 1; + unsigned int wrapnext : 1; + unsigned int crlf : 1; + unsigned int send_bs : 1; + unsigned int kbd_lock : 1; + unsigned int reverse : 1; + unsigned int no_autorepeat : 1; + unsigned int cjk_ambiguous_wide : 1; + unsigned int hide_cursor : 1; + unsigned int combining_strike : 1; +} Term_State; + +typedef struct _Term_Cursor { + int cx; + int cy; +} Term_Cursor; + struct _Termpty { Evas_Object *obj; @@ -124,13 +160,10 @@ struct _Termpty size_t backsize, backpos; /* this beacon in the backlog tells about the top line in screen * coordinates that maps to a line in the backlog */ - struct { - int screen_y; - int backlog_y; - } backlog_beacon; + Backlog_Beacon backlog_beacon; int w, h; int fd, slavefd; -#ifdef ENABLE_FUZZING +#if defined(ENABLE_FUZZING) || defined(ENABLE_TESTS) int fd_dev_null; #endif struct { @@ -155,34 +188,9 @@ struct _Termpty unsigned char by_line : 1; unsigned char is_top_to_bottom : 1; } selection; - struct { - Termatt att; - unsigned char charset; - unsigned char charsetch; - unsigned char chset[4]; - int top_margin, bottom_margin; - int left_margin, right_margin; - int had_cr_x, had_cr_y; - unsigned int lr_margins : 1; - unsigned int restrict_cursor : 1; - unsigned int multibyte : 1; - unsigned int alt_kp : 1; - unsigned int insert : 1; - unsigned int appcursor : 1; - unsigned int wrap : 1; - unsigned int wrapnext : 1; - unsigned int crlf : 1; - unsigned int send_bs : 1; - unsigned int kbd_lock : 1; - unsigned int reverse : 1; - unsigned int no_autorepeat : 1; - unsigned int cjk_ambiguous_wide : 1; - unsigned int hide_cursor : 1; - unsigned int combining_strike : 1; - } termstate; - struct { - int cx, cy; - } cursor_state, cursor_save[2]; + Term_State termstate; + Term_Cursor cursor_state; + Term_Cursor cursor_save[2]; int exit_code; pid_t pid; unsigned int altbuf : 1; diff --git a/src/bin/termptyesc.c b/src/bin/termptyesc.c index 0a434580..09830b6c 100644 --- a/src/bin/termptyesc.c +++ b/src/bin/termptyesc.c @@ -532,7 +532,8 @@ static int _approximate_truecolor_rgb(Termpty *ty, int r0, int g0, int b0) { int chosen_color = COL_DEF; -#ifdef ENABLE_FUZZING +/* TODO: use the function in tests */ +#if defined(ENABLE_FUZZING) || defined(ENABLE_TESTS) (void) ty; (void) r0; (void) g0; @@ -1688,7 +1689,7 @@ HVP: cc++; return cc - c; unhandled: -#ifndef ENABLE_FUZZING +#if !defined(ENABLE_FUZZING) && !defined(ENABLE_TESTS) if (eina_log_domain_level_check(_termpty_log_dom, EINA_LOG_LEVEL_WARN)) { Eina_Strbuf *bf = eina_strbuf_new(); @@ -2119,7 +2120,7 @@ _handle_esc_osc(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce) len = cc - c - (p - buf); if (_xterm_parse_color(&p, &r, &g, &b, len) < 0) goto err; -#ifndef ENABLE_FUZZING +#if !defined(ENABLE_FUZZING) && !defined(ENABLE_TESTS) evas_object_textgrid_palette_set( termio_textgrid_get(ty->obj), EVAS_TEXTGRID_PALETTE_STANDARD, 0, diff --git a/src/bin/tyfuzz.c b/src/bin/tyfuzz.c index e9e85cd2..40bb0c4a 100644 --- a/src/bin/tyfuzz.c +++ b/src/bin/tyfuzz.c @@ -13,6 +13,14 @@ #include "termptyops.h" #include +#ifdef TYTEST +#include "md5/md5.h" +#endif + +#define TY_H 25 +#define TY_W 80 +#define TY_BACKSIZE 50 + /* {{{ stub */ int _log_domain = -1; @@ -64,6 +72,91 @@ termio_set_cursor_shape(Evas_Object *obj EINA_UNUSED, { } /* }}} */ +/* {{{ TYTEST */ +#ifdef TYTEST +typedef struct _Termpty_Tests +{ + size_t backsize, backpos; + Backlog_Beacon backlog_beacon; + Term_State termstate; + Term_Cursor cursor_state; + Term_Cursor cursor_save[2]; + int w, h; + unsigned int altbuf : 1; + unsigned int mouse_mode : 3; + unsigned int mouse_ext : 2; + unsigned int bracketed_paste : 1; +} Termpty_Tests; + +static void +_termpty_to_termpty_tests(Termpty *ty, Termpty_Tests *tt) +{ + memset(tt, '\0', sizeof(*tt)); + tt->backsize = ty->backsize; + tt->backpos = ty->backpos; + tt->backlog_beacon = ty->backlog_beacon; + tt->termstate = ty->termstate; + tt->cursor_state = ty->cursor_state; + tt->cursor_save[0] = ty->cursor_save[0]; + tt->cursor_save[1] = ty->cursor_save[1]; + tt->w = ty->w; + tt->h = ty->h; + tt->altbuf = ty->altbuf; + tt->mouse_mode = ty->mouse_mode; + tt->mouse_ext = ty->mouse_ext; + tt->bracketed_paste = ty->bracketed_paste; +} + +static void +_tytest_checksum(Termpty *ty) +{ + MD5_CTX ctx; + Termpty_Tests tests; + char md5out[(2 * MD5_HASHBYTES) + 1]; + unsigned char hash[MD5_HASHBYTES]; + static const char hex[] = "0123456789abcdef"; + int n; + + _termpty_to_termpty_tests(ty, &tests); + + MD5Init(&ctx); + /* Termpty */ + MD5Update(&ctx, + (unsigned char const*)&tests, + sizeof(tests)); + /* The screens */ + MD5Update(&ctx, + (unsigned char const*)ty->screen, + sizeof(Termcell) * ty->w * ty->h); + MD5Update(&ctx, + (unsigned char const*)ty->screen2, + sizeof(Termcell) * ty->w * ty->h); + /* Icon/Title */ + if (ty->prop.icon) + { + MD5Update(&ctx, + (unsigned char const*)ty->prop.icon, + strlen(ty->prop.icon)); + } + if (ty->prop.title) + { + MD5Update(&ctx, + (unsigned char const*)ty->prop.title, + strlen(ty->prop.title)); + } + + MD5Final(hash, &ctx); + + for (n = 0; n < MD5_HASHBYTES; n++) + { + md5out[2 * n] = hex[hash[n] >> 4]; + md5out[2 * n + 1] = hex[hash[n] & 0x0f]; + } + md5out[2 * MD5_HASHBYTES] = '\0'; + printf("%s", md5out); +} +#endif +/* }}} */ @@ -71,9 +164,9 @@ static void _termpty_init(Termpty *ty) { memset(ty, '\0', sizeof(*ty)); - ty->w = 80; - ty->h = 25; - ty->backsize = 50; + ty->w = TY_W; + ty->h = TY_H; + ty->backsize = TY_BACKSIZE; termpty_resize_tabs(ty, 0, ty->w); termpty_reset_state(ty); ty->screen = calloc(1, sizeof(Termcell) * ty->w * ty->h); @@ -106,7 +199,13 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED) eina_init(); - _log_domain = eina_log_domain_register("tyfuzz", NULL); + _log_domain = eina_log_domain_register( +#ifdef TYTEST + "tytest", +#else + "tyfuzz", +#endif + NULL); _config = config_new(); @@ -156,7 +255,7 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED) (len - prev_i) <= (int)sizeof(ty.oldbuf)) { for (k = 0; - (k < (int)sizeof(ty.oldbuf)) && + (k < (int)sizeof(ty.oldbuf)) && (k < (len - prev_i)); k++) { @@ -179,6 +278,10 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED) } while (1); +#ifdef TYTEST + _tytest_checksum(&ty); +#endif + _termpty_shutdown(&ty); eina_shutdown(); diff --git a/src/bin/tytest.c b/src/bin/tytest.c new file mode 100644 index 00000000..95004b95 --- /dev/null +++ b/src/bin/tytest.c @@ -0,0 +1,2 @@ +#define TYTEST 1 +#include "tyfuzz.c"