iPXE
editstring_test.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 /** @file
27  *
28  * Editable string tests
29  *
30  */
31 
32 /* Forcibly enable assertions */
33 #undef NDEBUG
34 
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <ipxe/keys.h>
39 #include <ipxe/editstring.h>
40 #include <ipxe/test.h>
41 
42 /** An editable string test */
44  /** Initial string, or NULL */
45  const char *start;
46  /** Key sequence */
47  const int *keys;
48  /** Length of key sequence */
49  unsigned int count;
50  /** Expected result */
51  const char *expected;
52 };
53 
54 /** Define an inline key sequence */
55 #define KEYS(...) { __VA_ARGS__ }
56 
57 /** Define an editable string test */
58 #define EDITSTRING_TEST( name, START, EXPECTED, KEYS ) \
59  static const int name ## _keys[] = KEYS; \
60  static struct editstring_test name = { \
61  .start = START, \
62  .keys = name ## _keys, \
63  .count = ( sizeof ( name ## _keys ) / \
64  sizeof ( name ## _keys[0] ) ), \
65  .expected = EXPECTED, \
66  };
67 
68 /* Simple typing */
69 EDITSTRING_TEST ( simple, "", "hello world!",
70  KEYS ( 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l',
71  'd', '!' ) );
72 
73 /* Simple typing from a NULL starting value */
74 EDITSTRING_TEST ( simple_null, NULL, "hi there",
75  KEYS ( 'h', 'i', ' ', 't', 'h', 'e', 'r', 'e' ) );
76 
77 /* Insertion */
78 EDITSTRING_TEST ( insert, "in middle", "in the middle",
80  KEY_LEFT, 't', 'h', 'e', ' ' ) );
81 
82 /* Backspace at end */
83 EDITSTRING_TEST ( backspace_end, "byebye", "bye",
85 
86 /* Backspace of whole string */
87 EDITSTRING_TEST ( backspace_all, "abc", "",
89 
90 /* Backspace of empty string */
91 EDITSTRING_TEST ( backspace_empty, NULL, "", KEYS ( KEY_BACKSPACE ) );
92 
93 /* Backspace beyond start of string */
94 EDITSTRING_TEST ( backspace_beyond, "too far", "",
98 
99 /* Deletion of character at cursor via DEL */
100 EDITSTRING_TEST ( delete_dc, "go away", "goaway",
102 
103 /* Deletion of character at cursor via Ctrl-D */
104 EDITSTRING_TEST ( delete_ctrl_d, "not here", "nohere",
106  KEY_LEFT, CTRL_D, CTRL_D ) );
107 
108 /* Deletion of word at end of string */
109 EDITSTRING_TEST ( word_end, "remove these two words", "remove these ",
110  KEYS ( CTRL_W, CTRL_W ) );
111 
112 /* Deletion of word at start of string */
113 EDITSTRING_TEST ( word_start, "no word", "word",
115 
116 /* Deletion of word mid-string */
117 EDITSTRING_TEST ( word_mid, "delete this word", "delete word",
119 
120 /* Deletion to start of line */
121 EDITSTRING_TEST ( sol, "everything must go", "go",
122  KEYS ( KEY_LEFT, KEY_LEFT, CTRL_U ) );
123 
124 /* Delete to end of line */
125 EDITSTRING_TEST ( eol, "all is lost", "all",
127 
128 /**
129  * Report an editable string test result
130  *
131  * @v test Editable string test
132  * @v file Test code file
133  * @v line Test code line
134  */
135 static void editstring_okx ( struct editstring_test *test, const char *file,
136  unsigned int line ) {
137  struct edit_string string;
138  unsigned int i;
139  char *actual;
140  int key;
141 
142  /* Initialise editable string */
143  memset ( &string, 0, sizeof ( string ) );
144  actual = NULL;
145  init_editstring ( &string, &actual );
146 
147  /* Set initial string content */
148  okx ( replace_string ( &string, test->start ) == 0, file, line );
149  okx ( actual != NULL, file, line );
150  okx ( string.cursor == ( test->start ? strlen ( test->start ) : 0 ),
151  file, line );
152  DBGC ( test, "Initial string: \"%s\"\n", actual );
153 
154  /* Inject keypresses */
155  for ( i = 0 ; i < test->count ; i++ ) {
156  key = test->keys[i];
157  okx ( edit_string ( &string, key ) == 0, file, line );
158  okx ( actual != NULL, file, line );
159  okx ( string.cursor <= strlen ( actual ), file, line );
160  DBGC ( test, "After key %#02x (%c): \"%s\"\n",
161  key, ( isprint ( key ) ? key : '.' ), actual );
162  }
163 
164  /* Verify result string */
165  okx ( strcmp ( actual, test->expected ) == 0, file, line );
166 
167  /* Free result string */
168  free ( actual );
169 }
170 #define editstring_ok( test ) editstring_okx ( test, __FILE__, __LINE__ )
171 
172 /**
173  * Perform editable string self-tests
174  *
175  */
176 static void editstring_test_exec ( void ) {
177 
178  editstring_ok ( &simple );
179  editstring_ok ( &simple_null );
180  editstring_ok ( &insert );
181  editstring_ok ( &backspace_end );
182  editstring_ok ( &backspace_all );
183  editstring_ok ( &backspace_empty );
184  editstring_ok ( &backspace_beyond );
185  editstring_ok ( &delete_dc );
186  editstring_ok ( &delete_ctrl_d );
187  editstring_ok ( &word_end );
188  editstring_ok ( &word_start );
189  editstring_ok ( &word_mid );
190  editstring_ok ( &sol );
191  editstring_ok ( &eol );
192 }
193 
194 /** Editable string self-test */
196  .name = "editstring",
197  .exec = editstring_test_exec,
198 };
Editable strings.
static void editstring_test_exec(void)
Perform editable string self-tests.
static void editstring_okx(struct editstring_test *test, const char *file, unsigned int line)
Report an editable string test result.
int replace_string(struct edit_string *string, const char *replacement)
Replace editable string.
Definition: editstring.c:228
An editable string test.
unsigned int cursor
Cursor position.
Definition: editstring.h:17
#define DBGC(...)
Definition: compiler.h:505
uint32_t string
Definition: multiboot.h:14
Self-test infrastructure.
const char * name
Test set name.
Definition: test.h:17
Character types.
A self-test set.
Definition: test.h:15
struct self_test editstring_test __self_test
Editable string self-test.
#define KEY_HOME
Home.
Definition: keys.h:109
const char * expected
Expected result.
static int isprint(int character)
Check if character is printable.
Definition: ctype.h:97
#define CTRL_K
Definition: keys.h:28
#define okx(success, file, line)
Report test result.
Definition: test.h:44
static __nonnull void init_editstring(struct edit_string *string, char **buf)
Initialise editable string.
Definition: editstring.h:46
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
unsigned int count
Length of key sequence.
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
#define CTRL_W
Definition: keys.h:40
size_t strlen(const char *src)
Get length of string.
Definition: string.c:243
const int * keys
Key sequence.
#define CTRL_A
Definition: keys.h:18
#define CTRL_U
Definition: keys.h:38
#define KEY_DC
Delete.
Definition: keys.h:111
int strcmp(const char *first, const char *second)
Compare strings.
Definition: string.c:173
Key definitions.
An editable string.
Definition: editstring.h:13
#define KEY_RIGHT
Right arrow.
Definition: keys.h:106
#define EDITSTRING_TEST(name, START, EXPECTED, KEYS)
Define an editable string test.
#define CTRL_D
Definition: keys.h:21
#define KEY_BACKSPACE
Definition: keys.h:126
const char * start
Initial string, or NULL.
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
String functions.
#define KEY_LEFT
Left arrow.
Definition: keys.h:107
union @382 key
Sense key.
Definition: crypto.h:284
static int test
Definition: epic100.c:73
#define editstring_ok(test)
#define KEYS(...)
Define an inline key sequence.
void * memset(void *dest, int character, size_t len) __nonnull