>From a2a1b5b25afcc9d2f5ca0433d42d9b2994820a35 Mon Sep 17 00:00:00 2001 From: Bruno Haible Subject: [PATCH 2/2] term-style-control: Add tests. * tests/test-term-style-control-hello.c: New file. * tests/test-term-style-control-yes.c: New file. * modules/term-style-control-tests: New file. --- ChangeLog | 5 ++ modules/term-style-control-tests | 15 ++++ tests/test-term-style-control-hello.c | 160 ++++++++++++++++++++++++++++++++++ tests/test-term-style-control-yes.c | 138 +++++++++++++++++++++++++++++ 4 files changed, 318 insertions(+) create mode 100644 modules/term-style-control-tests create mode 100644 tests/test-term-style-control-hello.c create mode 100644 tests/test-term-style-control-yes.c diff --git a/ChangeLog b/ChangeLog index 481db9d..cd2b500 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2019-03-24 Bruno Haible + term-style-control: Add tests. + * tests/test-term-style-control-hello.c: New file. + * tests/test-term-style-control-yes.c: New file. + * modules/term-style-control-tests: New file. + term-style-control: New module. * lib/term-style-control.h: New file, based on libtextstyle's term-ostream.oo.h and term-ostream.oo.c. diff --git a/modules/term-style-control-tests b/modules/term-style-control-tests new file mode 100644 index 0000000..e07f394 --- /dev/null +++ b/modules/term-style-control-tests @@ -0,0 +1,15 @@ +Files: +tests/test-term-style-control-hello.c +tests/test-term-style-control-yes.c + +Depends-on: +stdbool +unistd +full-write + +configure.ac: + +Makefile.am: +TESTS += test-term-style-control-hello +check_PROGRAMS += test-term-style-control-hello +noinst_PROGRAMS += test-term-style-control-yes diff --git a/tests/test-term-style-control-hello.c b/tests/test-term-style-control-hello.c new file mode 100644 index 0000000..32deb58 --- /dev/null +++ b/tests/test-term-style-control-hello.c @@ -0,0 +1,160 @@ +/* Simple test program for the term-style-control module. + Copyright (C) 2019 Free Software Foundation, Inc. + Written by Bruno Haible , 2019. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "term-style-control.h" + +#include +#include +#include +#include + +#include "full-write.h" + +/* This program outputs the line: Hello Dr. Linus Pauling! + with underlining here: _________________ + and a cyan background color here: _____ + */ + +/* ECMA-48 / ISO 6429 escape sequences. See + https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters + */ +static const char set_underline_on[] = "\033[4m"; +static const char set_underline_off[] = "\033[24m"; +static const char set_background_color_cyan[] = "\033[46m"; +static const char set_background_color_default[] = "\033[49m"; + +struct term_style_user_data +{ + /* These fields are marked volatile, because they are accessed from the + async-safe function async_set_attributes_from_default. */ + bool volatile underline; + bool volatile background_color_cyan; + + struct term_style_control_data ctrl_data; +}; + +static struct term_style_control_data * +get_control_data (struct term_style_user_data *user_data) +{ + return &user_data->ctrl_data; +} + +static void +restore (struct term_style_user_data *user_data) +{ + fputs (set_underline_off, stdout); + fputs (set_background_color_default, stdout); + fflush (stdout); +} + +static _GL_ASYNC_SAFE void +async_restore (struct term_style_user_data *user_data) +{ + /* No calls here! */ + full_write (STDOUT_FILENO, set_underline_off, + strlen (set_underline_off)); + full_write (STDOUT_FILENO, set_background_color_default, + strlen (set_background_color_default)); +} + +static _GL_ASYNC_SAFE void +async_set_attributes_from_default (struct term_style_user_data *user_data) +{ + /* No calls here! */ + if (user_data->underline) + full_write (STDOUT_FILENO, set_underline_on, + strlen (set_underline_on)); + if (user_data->background_color_cyan) + full_write (STDOUT_FILENO, set_background_color_cyan, + strlen (set_background_color_cyan)); +} + +static const struct term_style_controller controller = +{ + get_control_data, + restore, + async_restore, + async_set_attributes_from_default +}; + +int +main (int argc, char *argv[]) +{ + struct term_style_user_data user_data; + + /* Initialization. */ + user_data.underline = false; + user_data.background_color_cyan = false; + + activate_term_style_controller (&controller, &user_data, STDOUT_FILENO, + TTYCTL_AUTO); + + /* As long as no styling is needed, we can stay in the default mode. */ + fputs ("Hello ", stdout); + fflush (stdout); + + /* Before any styling, enable the non-default mode. */ + activate_term_non_default_mode (&controller, &user_data); + + /* Set user_data.underline *before* emitting the appropriate + escape sequences, otherwise async_set_attributes_from_default will not + do its job correctly. */ + user_data.underline = true; + fputs (set_underline_on, stdout); + fflush (stdout); + + fputs ("Dr. ", stdout); + fflush (stdout); + + /* Set user_data.background_color_cyan *before* emitting the appropriate + escape sequences, otherwise async_set_attributes_from_default will not + do its job correctly. */ + user_data.background_color_cyan = true; + fputs (set_background_color_cyan, stdout); + fflush (stdout); + + fputs ("Linus", stdout); + fflush (stdout); + + user_data.background_color_cyan = false; + fputs (set_background_color_default, stdout); + fflush (stdout); + + fputs (" Pauling", stdout); + fflush (stdout); + + user_data.underline = false; + fputs (set_underline_off, stdout); + fflush (stdout); + + /* Needed as a prerequisite of the deactivate_term_style_controller call + below. */ + deactivate_term_non_default_mode (&controller, &user_data); + + fputs ("!\n", stdout); + + /* If the user_data was allocated in heap memory, with indefinite extent, + this call would be optional. But since we have allocated it on the + stack, we must deactivate it before it goes out of scope. Otherwise + we get undefined behaviour in an atexit() handler. */ + deactivate_term_style_controller (&controller, &user_data); + + return 0; +} diff --git a/tests/test-term-style-control-yes.c b/tests/test-term-style-control-yes.c new file mode 100644 index 0000000..83432fd --- /dev/null +++ b/tests/test-term-style-control-yes.c @@ -0,0 +1,138 @@ +/* Interactive test program for the term-style-control module. + Copyright (C) 2019 Free Software Foundation, Inc. + Written by Bruno Haible , 2019. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +/* Specification. */ +#include "term-style-control.h" + +#include +#include +#include +#include + +#include "full-write.h" + +/* This program outputs an endless amount of lines, each consisting of a + single 'y', in red color and underlined. + It can be used to exercise race conditions caused by + - simultaneous keyboard input on the terminal, + - pressing Ctrl-C, + - pressing Ctrl-Z and then "fg". */ + +/* ECMA-48 / ISO 6429 escape sequences. See + https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters + */ +static const char set_underline_on[] = "\033[4m"; +static const char set_underline_off[] = "\033[24m"; +static const char set_foreground_color_red[] = "\033[31m"; +static const char set_foreground_color_default[] = "\033[39m"; + +struct term_style_user_data +{ + /* This field is marked volatile, because it is accessed from the + async-safe function async_set_attributes_from_default. */ + bool volatile red_and_underline; + + struct term_style_control_data ctrl_data; +}; + +static struct term_style_control_data * +get_control_data (struct term_style_user_data *user_data) +{ + return &user_data->ctrl_data; +} + +static void +restore (struct term_style_user_data *user_data) +{ + fputs (set_underline_off, stdout); + fputs (set_foreground_color_default, stdout); + fflush (stdout); +} + +static _GL_ASYNC_SAFE void +async_restore (struct term_style_user_data *user_data) +{ + /* No calls here! */ + full_write (STDOUT_FILENO, set_underline_off, + strlen (set_underline_off)); + full_write (STDOUT_FILENO, set_foreground_color_default, + strlen (set_foreground_color_default)); +} + +static _GL_ASYNC_SAFE void +async_set_attributes_from_default (struct term_style_user_data *user_data) +{ + /* No calls here! */ + if (user_data->red_and_underline) + { + full_write (STDOUT_FILENO, set_underline_on, + strlen (set_underline_on)); + full_write (STDOUT_FILENO, set_foreground_color_red, + strlen (set_foreground_color_red)); + } +} + +static const struct term_style_controller controller = +{ + get_control_data, + restore, + async_restore, + async_set_attributes_from_default +}; + +int +main (int argc, char *argv[]) +{ + struct term_style_user_data user_data; + + /* Initialization. */ + user_data.red_and_underline = false; + + activate_term_style_controller (&controller, &user_data, STDOUT_FILENO, + TTYCTL_AUTO); + + for (;;) + { + /* Before any styling, enable the non-default mode. */ + activate_term_non_default_mode (&controller, &user_data); + + /* Set user_data.red_and_underline *before* emitting the appropriate + escape sequences, otherwise async_set_attributes_from_default will not + do its job correctly. */ + user_data.red_and_underline = true; + fputs (set_underline_on, stdout); + fputs (set_foreground_color_red, stdout); + fflush (stdout); + + fputs ("y", stdout); + fflush (stdout); + + /* Revert to the default style before emitting a newline. */ + user_data.red_and_underline = false; + fputs (set_underline_off, stdout); + fputs (set_foreground_color_default, stdout); + fflush (stdout); + + /* Optional. */ + deactivate_term_non_default_mode (&controller, &user_data); + + fputs ("\n", stdout); + fflush (stdout); + } +} -- 2.7.4