1 /* $NetBSD: test_filecompletion.c,v 1.5 2019/09/08 05:50:58 abhinav Exp $ */
4 * Copyright (c) 2017 Abhinav Upadhyay <abhinav@NetBSD.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 #include "filecomplete.h"
46 const wchar_t *user_typed_text; /* The actual text typed by the user on the terminal */
47 const char *completion_function_input ; /*the text received by fn_filename_completion_function */
48 const char *expanded_text[2]; /* the value to which completion_function_input should be expanded */
49 const wchar_t *escaped_output; /* expected escaped value of expanded_text */
52 static test_input inputs[] = {
54 /* simple test for escaping angular brackets */
57 {"ang<ular>test", NULL},
58 L"ls ang\\<ular\\>test "
61 /* test angular bracket inside double quotes: ls "dq_ang */
64 {"dq_ang<ular>test", NULL},
65 L"ls \"dq_ang<ular>test\""
68 /* test angular bracket inside singlq quotes: ls "sq_ang */
71 {"sq_ang<ular>test", NULL},
72 L"ls 'sq_ang<ular>test'"
75 /* simple test for backslash */
78 {"backslash\\test", NULL},
79 L"ls backslash\\\\test "
82 /* backslash inside single quotes */
85 {"sbackslash\\test", NULL},
86 L"ls 'sbackslash\\test'"
89 /* backslash inside double quotes */
92 {"dbackslash\\test", NULL},
93 L"ls \"dbackslash\\\\test\""
99 {"braces{test}", NULL},
100 L"ls braces\\{test\\} "
103 /* test braces inside single quotes */
106 {"sbraces{test}", NULL},
107 L"ls 'sbraces{test}'"
110 /* test braces inside double quotes */
113 {"dbraces{test}", NULL},
114 L"ls \"dbraces{test}\""
120 {"doll$artest", NULL},
124 /* test dollar inside single quotes */
127 {"sdoll$artest", NULL},
131 /* test dollar inside double quotes */
134 {"ddoll$artest", NULL},
135 L"ls \"ddoll\\$artest\""
141 {"equals==test", NULL},
142 L"ls equals\\=\\=test "
145 /* test equals inside sinqle quotes */
148 {"sequals==test", NULL},
149 L"ls 'sequals==test'"
152 /* test equals inside double quotes */
155 {"dequals==test", NULL},
156 L"ls \"dequals==test\""
162 {"new\\nline", NULL},
166 /* test \n inside single quotes */
169 {"snew\nline", NULL},
173 /* test \n inside double quotes */
176 {"dnew\nline", NULL},
180 /* test single space */
183 {"space test", NULL},
187 /* test single space inside singlq quotes */
190 {"s_space test", NULL},
194 /* test single space inside double quotes */
197 {"d_space test", NULL},
198 L"ls \"d_space test\""
201 /* test multiple spaces */
204 {"multi space test", NULL},
205 L"ls multi\\ space\\ \\ test "
208 /* test multiple spaces inside single quotes */
211 {"s_multi space test", NULL},
212 L"ls 's_multi space test'"
215 /* test multiple spaces inside double quotes */
218 {"d_multi space test", NULL},
219 L"ls \"d_multi space test\""
222 /* test double quotes */
225 {"doub\"quotes", NULL},
226 L"ls doub\\\"quotes "
229 /* test double quotes inside single quotes */
232 {"s_doub\"quotes", NULL},
233 L"ls 's_doub\"quotes'"
236 /* test double quotes inside double quotes */
239 {"d_doub\"quotes", NULL},
240 L"ls \"d_doub\\\"quotes\""
243 /* test multiple double quotes */
246 {"mud\"qu\"otes\"", NULL},
247 L"ls mud\\\"qu\\\"otes\\\" "
250 /* test multiple double quotes inside single quotes */
253 {"smud\"qu\"otes\"", NULL},
254 L"ls 'smud\"qu\"otes\"'"
257 /* test multiple double quotes inside double quotes */
260 {"dmud\"qu\"otes\"", NULL},
261 L"ls \"dmud\\\"qu\\\"otes\\\"\""
264 /* test one single quote */
267 {"single'quote", NULL},
268 L"ls single\\'quote "
271 /* test one single quote inside single quote */
274 {"ssingle'quote", NULL},
275 L"ls 'ssingle'\\''quote'"
278 /* test one single quote inside double quote */
281 {"dsingle'quote", NULL},
282 L"ls \"dsingle'quote\""
285 /* test multiple single quotes */
288 {"mu_single''quotes''", NULL},
289 L"ls mu_single\\'\\'quotes\\'\\' "
292 /* test multiple single quotes inside single quote */
295 {"smu_single''quotes''", NULL},
296 L"ls 'smu_single'\\'''\\''quotes'\\\'''\\'''"
299 /* test multiple single quotes inside double quote */
302 {"dmu_single''quotes''", NULL},
303 L"ls \"dmu_single''quotes''\""
306 /* test parenthesis */
309 {"paren(test)", NULL},
310 L"ls paren\\(test\\) "
313 /* test parenthesis inside single quote */
316 {"sparen(test)", NULL},
320 /* test parenthesis inside double quote */
323 {"dparen(test)", NULL},
324 L"ls \"dparen(test)\""
334 /* test pipe inside single quote */
337 {"spipe|test", NULL},
341 /* test pipe inside double quote */
344 {"dpipe|test", NULL},
355 /* test tab inside single quote */
358 {"stab\ttest", NULL},
362 /* test tab inside double quote */
365 {"dtab\ttest", NULL},
372 {"tick`test`", NULL},
373 L"ls tick\\`test\\` "
376 /* test back tick inside single quote */
379 {"stick`test`", NULL},
383 /* test back tick inside double quote */
386 {"dtick`test`", NULL},
387 L"ls \"dtick\\`test\\`\""
393 {"atthe@rate", NULL},
397 /* test for @ inside single quote */
400 {"satthe@rate", NULL},
404 /* test for @ inside double quote */
407 {"datthe@rate", NULL},
408 L"ls \"datthe@rate\""
414 {"semi;colon;test", NULL},
415 L"ls semi\\;colon\\;test "
418 /* test ; inside single quote */
421 {"ssemi;colon;test", NULL},
422 L"ls 'ssemi;colon;test'"
425 /* test ; inside double quote */
428 {"dsemi;colon;test", NULL},
429 L"ls \"dsemi;colon;test\""
435 {"ampers&and", NULL},
439 /* test & inside single quote */
442 {"sampers&and", NULL},
446 /* test & inside double quote */
449 {"dampers&and", NULL},
450 L"ls \"dampers&and\""
453 /* test completion when cursor at \ */
460 /* test completion when cursor at single quote */
467 /* test completion when cursor at double quote */
474 /* test multiple completion matches */
477 {"foo bar", "foo baz"},
483 {"bar <bar>", "bar <baz>"},
488 static const wchar_t break_chars[] = L" \t\n\"\\'`@$><=;|&{(";
491 * Custom completion function passed to fn_complet, NULLe.
492 * The function returns hardcoded completion matches
493 * based on the test cases present in inputs[] (above)
496 mycomplet_func(const char *text, int index)
498 static int last_index = 0;
500 if (last_index == 2) {
505 for (i = 0; i < sizeof(inputs)/sizeof(inputs[0]); i++) {
506 if (strcmp(text, inputs[i].completion_function_input) == 0) {
507 if (inputs[i].expanded_text[last_index] != NULL)
508 return strdup(inputs[i].expanded_text[last_index++]);
520 main(int argc, char **argv)
522 EditLine *el = el_init(argv[0], stdin, stdout, stderr);
526 wchar_t *buffer = malloc(64 * sizeof(*buffer));
528 err(EXIT_FAILURE, "malloc failed");
530 for (i = 0; i < sizeof(inputs)/sizeof(inputs[0]); i++) {
531 memset(buffer, 0, 64 * sizeof(*buffer));
532 input_len = wcslen(inputs[i].user_typed_text);
533 wmemcpy(buffer, inputs[i].user_typed_text, input_len);
534 buffer[input_len] = 0;
535 line.buffer = buffer;
536 line.cursor = line.buffer + input_len ;
537 line.lastchar = line.cursor - 1;
538 line.limit = line.buffer + 64 * sizeof(*buffer);
540 fn_complete(el, mycomplet_func, NULL, break_chars, NULL, NULL, 10, NULL, NULL, NULL, NULL);
543 * fn_complete would have expanded and escaped the input in el->el_line.buffer.
544 * We need to assert that it matches with the expected value in our test data
546 printf("User input: %ls\t Expected output: %ls\t Generated output: %ls\n",
547 inputs[i].user_typed_text, inputs[i].escaped_output, el->el_line.buffer);
548 assert(wcscmp(el->el_line.buffer, inputs[i].escaped_output) == 0);