From d7e58c5a812988c341ec4ad19f79faf067388d58 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 17 Apr 2024 15:49:37 +0100 Subject: [test] Add test cases for editable strings Signed-off-by: Michael Brown --- src/tests/editstring_test.c | 198 ++++++++++++++++++++++++++++++++++++++++++++ src/tests/tests.c | 1 + 2 files changed, 199 insertions(+) create mode 100644 src/tests/editstring_test.c diff --git a/src/tests/editstring_test.c b/src/tests/editstring_test.c new file mode 100644 index 0000000..72da33a --- /dev/null +++ b/src/tests/editstring_test.c @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2024 Michael Brown . + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +/** @file + * + * Editable string tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include +#include +#include +#include +#include +#include + +/** An editable string test */ +struct editstring_test { + /** Initial string, or NULL */ + const char *start; + /** Key sequence */ + const int *keys; + /** Length of key sequence */ + unsigned int count; + /** Expected result */ + const char *expected; +}; + +/** Define an inline key sequence */ +#define KEYS(...) { __VA_ARGS__ } + +/** Define an editable string test */ +#define EDITSTRING_TEST( name, START, EXPECTED, KEYS ) \ + static const int name ## _keys[] = KEYS; \ + static struct editstring_test name = { \ + .start = START, \ + .keys = name ## _keys, \ + .count = ( sizeof ( name ## _keys ) / \ + sizeof ( name ## _keys[0] ) ), \ + .expected = EXPECTED, \ + }; + +/* Simple typing */ +EDITSTRING_TEST ( simple, "", "hello world!", + KEYS ( 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', + 'd', '!' ) ); + +/* Simple typing from a NULL starting value */ +EDITSTRING_TEST ( simple_null, NULL, "hi there", + KEYS ( 'h', 'i', ' ', 't', 'h', 'e', 'r', 'e' ) ); + +/* Insertion */ +EDITSTRING_TEST ( insert, "in middle", "in the middle", + KEYS ( KEY_LEFT, KEY_LEFT, KEY_LEFT, KEY_LEFT, KEY_LEFT, + KEY_LEFT, 't', 'h', 'e', ' ' ) ); + +/* Backspace at end */ +EDITSTRING_TEST ( backspace_end, "byebye", "bye", + KEYS ( KEY_BACKSPACE, KEY_BACKSPACE, KEY_BACKSPACE ) ); + +/* Backspace of whole string */ +EDITSTRING_TEST ( backspace_all, "abc", "", + KEYS ( KEY_BACKSPACE, KEY_BACKSPACE, KEY_BACKSPACE ) ); + +/* Backspace of empty string */ +EDITSTRING_TEST ( backspace_empty, NULL, "", KEYS ( KEY_BACKSPACE ) ); + +/* Backspace beyond start of string */ +EDITSTRING_TEST ( backspace_beyond, "too far", "", + KEYS ( KEY_BACKSPACE, KEY_BACKSPACE, KEY_BACKSPACE, + KEY_BACKSPACE, KEY_BACKSPACE, KEY_BACKSPACE, + KEY_BACKSPACE, KEY_BACKSPACE, KEY_BACKSPACE ) ); + +/* Deletion of character at cursor via DEL */ +EDITSTRING_TEST ( delete_dc, "go away", "goaway", + KEYS ( KEY_HOME, KEY_RIGHT, KEY_RIGHT, KEY_DC ) ); + +/* Deletion of character at cursor via Ctrl-D */ +EDITSTRING_TEST ( delete_ctrl_d, "not here", "nohere", + KEYS ( KEY_LEFT, KEY_LEFT, KEY_LEFT, KEY_LEFT, KEY_LEFT, + KEY_LEFT, CTRL_D, CTRL_D ) ); + +/* Deletion of word at end of string */ +EDITSTRING_TEST ( word_end, "remove these two words", "remove these ", + KEYS ( CTRL_W, CTRL_W ) ); + +/* Deletion of word at start of string */ +EDITSTRING_TEST ( word_start, "no word", "word", + KEYS ( CTRL_A, KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, CTRL_W ) ); + +/* Deletion of word mid-string */ +EDITSTRING_TEST ( word_mid, "delete this word", "delete word", + KEYS ( KEY_LEFT, KEY_LEFT, KEY_LEFT, KEY_LEFT, CTRL_W ) ); + +/* Deletion to start of line */ +EDITSTRING_TEST ( sol, "everything must go", "go", + KEYS ( KEY_LEFT, KEY_LEFT, CTRL_U ) ); + +/* Delete to end of line */ +EDITSTRING_TEST ( eol, "all is lost", "all", + KEYS ( KEY_HOME, KEY_RIGHT, KEY_RIGHT, KEY_RIGHT, CTRL_K ) ); + +/** + * Report an editable string test result + * + * @v test Editable string test + * @v file Test code file + * @v line Test code line + */ +static void editstring_okx ( struct editstring_test *test, const char *file, + unsigned int line ) { + struct edit_string string; + unsigned int i; + char *actual; + int key; + + /* Initialise editable string */ + memset ( &string, 0, sizeof ( string ) ); + actual = NULL; + init_editstring ( &string, &actual ); + + /* Set initial string content */ + okx ( replace_string ( &string, test->start ) == 0, file, line ); + okx ( actual != NULL, file, line ); + okx ( string.cursor == ( test->start ? strlen ( test->start ) : 0 ), + file, line ); + DBGC ( test, "Initial string: \"%s\"\n", actual ); + + /* Inject keypresses */ + for ( i = 0 ; i < test->count ; i++ ) { + key = test->keys[i]; + okx ( edit_string ( &string, key ) == 0, file, line ); + okx ( actual != NULL, file, line ); + okx ( string.cursor <= strlen ( actual ), file, line ); + DBGC ( test, "After key %#02x (%c): \"%s\"\n", + key, ( isprint ( key ) ? key : '.' ), actual ); + } + + /* Verify result string */ + okx ( strcmp ( actual, test->expected ) == 0, file, line ); + + /* Free result string */ + free ( actual ); +} +#define editstring_ok( test ) editstring_okx ( test, __FILE__, __LINE__ ) + +/** + * Perform editable string self-tests + * + */ +static void editstring_test_exec ( void ) { + + editstring_ok ( &simple ); + editstring_ok ( &simple_null ); + editstring_ok ( &insert ); + editstring_ok ( &backspace_end ); + editstring_ok ( &backspace_all ); + editstring_ok ( &backspace_empty ); + editstring_ok ( &backspace_beyond ); + editstring_ok ( &delete_dc ); + editstring_ok ( &delete_ctrl_d ); + editstring_ok ( &word_end ); + editstring_ok ( &word_start ); + editstring_ok ( &word_mid ); + editstring_ok ( &sol ); + editstring_ok ( &eol ); +} + +/** Editable string self-test */ +struct self_test editstring_test __self_test = { + .name = "editstring", + .exec = editstring_test_exec, +}; diff --git a/src/tests/tests.c b/src/tests/tests.c index cb29604..0e9b3e8 100644 --- a/src/tests/tests.c +++ b/src/tests/tests.c @@ -85,3 +85,4 @@ REQUIRE_OBJECT ( x25519_test ); REQUIRE_OBJECT ( des_test ); REQUIRE_OBJECT ( mschapv2_test ); REQUIRE_OBJECT ( uuid_test ); +REQUIRE_OBJECT ( editstring_test ); -- cgit v1.1