]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libedit/TEST/test_filecompletion.c
Import DTS files for riscv from Linux 5.4
[FreeBSD/FreeBSD.git] / contrib / libedit / TEST / test_filecompletion.c
1 /*      $NetBSD: test_filecompletion.c,v 1.5 2019/09/08 05:50:58 abhinav Exp $  */
2
3 /*-
4  * Copyright (c) 2017 Abhinav Upadhyay <abhinav@NetBSD.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
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
16  *    distribution.
17  *
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
29  * SUCH DAMAGE.
30  */
31
32 #include "config.h"
33
34 #include <assert.h>
35 #include <err.h>
36 #include <stdio.h>
37 #include <histedit.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <wchar.h>
41
42 #include "filecomplete.h"
43 #include "el.h"
44
45 typedef struct {
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 */
50 } test_input;
51
52 static test_input inputs[] = {
53         {
54                 /* simple test for escaping angular brackets */
55                 L"ls ang",
56                 "ang",
57                 {"ang<ular>test", NULL},
58                 L"ls ang\\<ular\\>test "
59         },
60         {
61                 /* test angular bracket inside double quotes: ls "dq_ang */
62                 L"ls \"dq_ang",
63                 "dq_ang",
64                 {"dq_ang<ular>test", NULL},
65                 L"ls \"dq_ang<ular>test\""
66         },
67         {
68                 /* test angular bracket inside singlq quotes: ls "sq_ang */
69                 L"ls 'sq_ang",
70                 "sq_ang",
71                 {"sq_ang<ular>test", NULL},
72                 L"ls 'sq_ang<ular>test'"
73         },
74         {
75                 /* simple test for backslash */
76                 L"ls back",
77                 "back",
78                 {"backslash\\test", NULL},
79                 L"ls backslash\\\\test "
80         },
81         {
82                 /* backslash inside single quotes */
83                 L"ls 'sback",
84                 "sback",
85                 {"sbackslash\\test", NULL},
86                 L"ls 'sbackslash\\test'"
87         },
88         {
89                 /* backslash inside double quotes */
90                 L"ls \"dback",
91                 "dback",
92                 {"dbackslash\\test", NULL},
93                 L"ls \"dbackslash\\\\test\""
94         },
95         {
96                 /* test braces */
97                 L"ls br",
98                 "br",
99                 {"braces{test}", NULL},
100                 L"ls braces\\{test\\} "
101         },
102         {
103                 /* test braces inside single quotes */
104                 L"ls 'sbr",
105                 "sbr",
106                 {"sbraces{test}", NULL},
107                 L"ls 'sbraces{test}'"
108         },
109         {
110                 /* test braces inside double quotes */
111                 L"ls \"dbr",
112                 "dbr",
113                 {"dbraces{test}", NULL},
114                 L"ls \"dbraces{test}\""
115         },
116         {
117                 /* test dollar */
118                 L"ls doll",
119                 "doll",
120                 {"doll$artest", NULL},
121                 L"ls doll\\$artest "
122         },
123         {
124                 /* test dollar inside single quotes */
125                 L"ls 'sdoll",
126                 "sdoll",
127                 {"sdoll$artest", NULL},
128                 L"ls 'sdoll$artest'"
129         },
130         {
131                 /* test dollar inside double quotes */
132                 L"ls \"ddoll",
133                 "ddoll",
134                 {"ddoll$artest", NULL},
135                 L"ls \"ddoll\\$artest\""
136         },
137         {
138                 /* test equals */
139                 L"ls eq",
140                 "eq",
141                 {"equals==test", NULL},
142                 L"ls equals\\=\\=test "
143         },
144         {
145                 /* test equals inside sinqle quotes */
146                 L"ls 'seq",
147                 "seq",
148                 {"sequals==test", NULL},
149                 L"ls 'sequals==test'"
150         },
151         {
152                 /* test equals inside double quotes */
153                 L"ls \"deq",
154                 "deq",
155                 {"dequals==test", NULL},
156                 L"ls \"dequals==test\""
157         },
158         {
159                 /* test \n */
160                 L"ls new",
161                 "new",
162                 {"new\\nline", NULL},
163                 L"ls new\\\\nline "
164         },
165         {
166                 /* test \n inside single quotes */
167                 L"ls 'snew",
168                 "snew",
169                 {"snew\nline", NULL},
170                 L"ls 'snew\nline'"
171         },
172         {
173                 /* test \n inside double quotes */
174                 L"ls \"dnew",
175                 "dnew",
176                 {"dnew\nline", NULL},
177                 L"ls \"dnew\nline\""
178         },
179         {
180                 /* test single space */
181                 L"ls spac",
182                 "spac",
183                 {"space test", NULL},
184                 L"ls space\\ test "
185         },
186         {
187                 /* test single space inside singlq quotes */
188                 L"ls 's_spac",
189                 "s_spac",
190                 {"s_space test", NULL},
191                 L"ls 's_space test'"
192         },
193         {
194                 /* test single space inside double quotes */
195                 L"ls \"d_spac",
196                 "d_spac",
197                 {"d_space test", NULL},
198                 L"ls \"d_space test\""
199         },
200         {
201                 /* test multiple spaces */
202                 L"ls multi",
203                 "multi",
204                 {"multi space  test", NULL},
205                 L"ls multi\\ space\\ \\ test "
206         },
207         {
208                 /* test multiple spaces inside single quotes */
209                 L"ls 's_multi",
210                 "s_multi",
211                 {"s_multi space  test", NULL},
212                 L"ls 's_multi space  test'"
213         },
214         {
215                 /* test multiple spaces inside double quotes */
216                 L"ls \"d_multi",
217                 "d_multi",
218                 {"d_multi space  test", NULL},
219                 L"ls \"d_multi space  test\""
220         },
221         {
222                 /* test double quotes */
223                 L"ls doub",
224                 "doub",
225                 {"doub\"quotes", NULL},
226                 L"ls doub\\\"quotes "
227         },
228         {
229                 /* test double quotes inside single quotes */
230                 L"ls 's_doub",
231                 "s_doub",
232                 {"s_doub\"quotes", NULL},
233                 L"ls 's_doub\"quotes'"
234         },
235         {
236                 /* test double quotes inside double quotes */
237                 L"ls \"d_doub",
238                 "d_doub",
239                 {"d_doub\"quotes", NULL},
240                 L"ls \"d_doub\\\"quotes\""
241         },
242         {
243                 /* test multiple double quotes */
244                 L"ls mud",
245                 "mud",
246                 {"mud\"qu\"otes\"", NULL},
247                 L"ls mud\\\"qu\\\"otes\\\" "
248         },
249         {
250                 /* test multiple double quotes inside single quotes */
251                 L"ls 'smud",
252                 "smud",
253                 {"smud\"qu\"otes\"", NULL},
254                 L"ls 'smud\"qu\"otes\"'"
255         },
256         {
257                 /* test multiple double quotes inside double quotes */
258                 L"ls \"dmud",
259                 "dmud",
260                 {"dmud\"qu\"otes\"", NULL},
261                 L"ls \"dmud\\\"qu\\\"otes\\\"\""
262         },
263         {
264                 /* test one single quote */
265                 L"ls sing",
266                 "sing",
267                 {"single'quote", NULL},
268                 L"ls single\\'quote "
269         },
270         {
271                 /* test one single quote inside single quote */
272                 L"ls 'ssing",
273                 "ssing",
274                 {"ssingle'quote", NULL},
275                 L"ls 'ssingle'\\''quote'"
276         },
277         {
278                 /* test one single quote inside double quote */
279                 L"ls \"dsing",
280                 "dsing",
281                 {"dsingle'quote", NULL},
282                 L"ls \"dsingle'quote\""
283         },
284         {
285                 /* test multiple single quotes */
286                 L"ls mu_sing",
287                 "mu_sing",
288                 {"mu_single''quotes''", NULL},
289                 L"ls mu_single\\'\\'quotes\\'\\' "
290         },
291         {
292                 /* test multiple single quotes inside single quote */
293                 L"ls 'smu_sing",
294                 "smu_sing",
295                 {"smu_single''quotes''", NULL},
296                 L"ls 'smu_single'\\'''\\''quotes'\\\'''\\'''"
297         },
298         {
299                 /* test multiple single quotes inside double quote */
300                 L"ls \"dmu_sing",
301                 "dmu_sing",
302                 {"dmu_single''quotes''", NULL},
303                 L"ls \"dmu_single''quotes''\""
304         },
305         {
306                 /* test parenthesis */
307                 L"ls paren",
308                 "paren",
309                 {"paren(test)", NULL},
310                 L"ls paren\\(test\\) "
311         },
312         {
313                 /* test parenthesis inside single quote */
314                 L"ls 'sparen",
315                 "sparen",
316                 {"sparen(test)", NULL},
317                 L"ls 'sparen(test)'"
318         },
319         {
320                 /* test parenthesis inside double quote */
321                 L"ls \"dparen",
322                 "dparen",
323                 {"dparen(test)", NULL},
324                 L"ls \"dparen(test)\""
325         },
326         {
327                 /* test pipe */
328                 L"ls pip",
329                 "pip",
330                 {"pipe|test", NULL},
331                 L"ls pipe\\|test "
332         },
333         {
334                 /* test pipe inside single quote */
335                 L"ls 'spip",
336                 "spip",
337                 {"spipe|test", NULL},
338                 L"ls 'spipe|test'",
339         },
340         {
341                 /* test pipe inside double quote */
342                 L"ls \"dpip",
343                 "dpip",
344                 {"dpipe|test", NULL},
345                 L"ls \"dpipe|test\""
346         },
347         {
348                 /* test tab */
349                 L"ls ta",
350                 "ta",
351                 {"tab\ttest", NULL},
352                 L"ls tab\\\ttest "
353         },
354         {
355                 /* test tab inside single quote */
356                 L"ls 'sta",
357                 "sta",
358                 {"stab\ttest", NULL},
359                 L"ls 'stab\ttest'"
360         },
361         {
362                 /* test tab inside double quote */
363                 L"ls \"dta",
364                 "dta",
365                 {"dtab\ttest", NULL},
366                 L"ls \"dtab\ttest\""
367         },
368         {
369                 /* test back tick */
370                 L"ls tic",
371                 "tic",
372                 {"tick`test`", NULL},
373                 L"ls tick\\`test\\` "
374         },
375         {
376                 /* test back tick inside single quote */
377                 L"ls 'stic",
378                 "stic",
379                 {"stick`test`", NULL},
380                 L"ls 'stick`test`'"
381         },
382         {
383                 /* test back tick inside double quote */
384                 L"ls \"dtic",
385                 "dtic",
386                 {"dtick`test`", NULL},
387                 L"ls \"dtick\\`test\\`\""
388         },
389         {
390                 /* test for @ */
391                 L"ls at",
392                 "at",
393                 {"atthe@rate", NULL},
394                 L"ls atthe\\@rate "
395         },
396         {
397                 /* test for @ inside single quote */
398                 L"ls 'sat",
399                 "sat",
400                 {"satthe@rate", NULL},
401                 L"ls 'satthe@rate'"
402         },
403         {
404                 /* test for @ inside double quote */
405                 L"ls \"dat",
406                 "dat",
407                 {"datthe@rate", NULL},
408                 L"ls \"datthe@rate\""
409         },
410         {
411                 /* test ; */
412                 L"ls semi",
413                 "semi",
414                 {"semi;colon;test", NULL},
415                 L"ls semi\\;colon\\;test "
416         },
417         {
418                 /* test ; inside single quote */
419                 L"ls 'ssemi",
420                 "ssemi",
421                 {"ssemi;colon;test", NULL},
422                 L"ls 'ssemi;colon;test'"
423         },
424         {
425                 /* test ; inside double quote */
426                 L"ls \"dsemi",
427                 "dsemi",
428                 {"dsemi;colon;test", NULL},
429                 L"ls \"dsemi;colon;test\""
430         },
431         {
432                 /* test & */
433                 L"ls amp",
434                 "amp",
435                 {"ampers&and", NULL},
436                 L"ls ampers\\&and "
437         },
438         {
439                 /* test & inside single quote */
440                 L"ls 'samp",
441                 "samp",
442                 {"sampers&and", NULL},
443                 L"ls 'sampers&and'"
444         },
445         {
446                 /* test & inside double quote */
447                 L"ls \"damp",
448                 "damp",
449                 {"dampers&and", NULL},
450                 L"ls \"dampers&and\""
451         },
452         {
453                 /* test completion when cursor at \ */
454                 L"ls foo\\",
455                 "foo",
456                 {"foo bar", NULL},
457                 L"ls foo\\ bar "
458         },
459         {
460                 /* test completion when cursor at single quote */
461                 L"ls foo'",
462                 "foo'",
463                 {"foo bar", NULL},
464                 L"ls foo\\ bar "
465         },
466         {
467                 /* test completion when cursor at double quote */
468                 L"ls foo\"",
469                 "foo\"",
470                 {"foo bar", NULL},
471                 L"ls foo\\ bar "
472         },
473         {
474                 /* test multiple completion matches */
475                 L"ls fo",
476                 "fo",
477                 {"foo bar", "foo baz"},
478                 L"ls foo\\ ba"
479         },
480         {
481                 L"ls ba",
482                 "ba",
483                 {"bar <bar>", "bar <baz>"},
484                 L"ls bar\\ \\<ba"
485         }
486 };
487
488 static const wchar_t break_chars[] = L" \t\n\"\\'`@$><=;|&{(";
489
490 /*
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)
494  */
495 static char *
496 mycomplet_func(const char *text, int index)
497 {
498         static int last_index = 0;
499         size_t i = 0;
500         if (last_index == 2) {
501                 last_index = 0;
502                 return NULL;
503         }
504
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++]);
509                         else {
510                                 last_index = 0;
511                                 return NULL;
512                         }
513                 }
514         }
515
516         return NULL;
517 }
518
519 int
520 main(int argc, char **argv)
521 {
522         EditLine *el = el_init(argv[0], stdin, stdout, stderr);
523         size_t i; 
524         size_t input_len;
525         el_line_t line;
526         wchar_t *buffer = malloc(64 * sizeof(*buffer));
527         if (buffer == NULL)
528                 err(EXIT_FAILURE, "malloc failed");
529
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);
539                 el->el_line = line;
540                 fn_complete(el, mycomplet_func, NULL, break_chars, NULL, NULL, 10, NULL, NULL, NULL, NULL);
541
542                 /*
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
545                  */
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);
549         }
550         el_end(el);
551         return 0;
552
553 }