"Fossies" - the Fresh Open Source Software Archive

Member "tnftp-20200705/libedit/TEST/test_filecompletion.c" (4 Jul 2020, 11696 Bytes) of package /linux/privat/tnftp-20200705.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*  $NetBSD: test_filecompletion.c,v 1.1.1.1 2020/07/04 12:41:19 lukem Exp $    */
    2 /*  from    NetBSD: test_filecompletion.c,v 1.5 2019/09/08 05:50:58 abhinav Exp */
    3 
    4 /*-
    5  * Copyright (c) 2017 Abhinav Upadhyay <abhinav@NetBSD.org>
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  *
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in
   16  *    the documentation and/or other materials provided with the
   17  *    distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
   23  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
   25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   29  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 #include "config.h"
   34 
   35 #include <assert.h>
   36 #include <err.h>
   37 #include <stdio.h>
   38 #include <histedit.h>
   39 #include <stdlib.h>
   40 #include <string.h>
   41 #include <wchar.h>
   42 
   43 #include "filecomplete.h"
   44 #include "el.h"
   45 
   46 typedef struct {
   47     const wchar_t *user_typed_text; /* The actual text typed by the user on the terminal */
   48     const char *completion_function_input ; /*the text received by fn_filename_completion_function */
   49     const char *expanded_text[2]; /* the value to which completion_function_input should be expanded */
   50     const wchar_t *escaped_output; /* expected escaped value of expanded_text */
   51 } test_input;
   52 
   53 static test_input inputs[] = {
   54     {
   55         /* simple test for escaping angular brackets */
   56         L"ls ang",
   57         "ang",
   58         {"ang<ular>test", NULL},
   59         L"ls ang\\<ular\\>test "
   60     },
   61     {
   62         /* test angular bracket inside double quotes: ls "dq_ang */
   63         L"ls \"dq_ang",
   64         "dq_ang",
   65         {"dq_ang<ular>test", NULL},
   66         L"ls \"dq_ang<ular>test\""
   67     },
   68     {
   69         /* test angular bracket inside singlq quotes: ls "sq_ang */
   70         L"ls 'sq_ang",
   71         "sq_ang",
   72         {"sq_ang<ular>test", NULL},
   73         L"ls 'sq_ang<ular>test'"
   74     },
   75     {
   76         /* simple test for backslash */
   77         L"ls back",
   78         "back",
   79         {"backslash\\test", NULL},
   80         L"ls backslash\\\\test "
   81     },
   82     {
   83         /* backslash inside single quotes */
   84         L"ls 'sback",
   85         "sback",
   86         {"sbackslash\\test", NULL},
   87         L"ls 'sbackslash\\test'"
   88     },
   89     {
   90         /* backslash inside double quotes */
   91         L"ls \"dback",
   92         "dback",
   93         {"dbackslash\\test", NULL},
   94         L"ls \"dbackslash\\\\test\""
   95     },
   96     {
   97         /* test braces */
   98         L"ls br",
   99         "br",
  100         {"braces{test}", NULL},
  101         L"ls braces\\{test\\} "
  102     },
  103     {
  104         /* test braces inside single quotes */
  105         L"ls 'sbr",
  106         "sbr",
  107         {"sbraces{test}", NULL},
  108         L"ls 'sbraces{test}'"
  109     },
  110     {
  111         /* test braces inside double quotes */
  112         L"ls \"dbr",
  113         "dbr",
  114         {"dbraces{test}", NULL},
  115         L"ls \"dbraces{test}\""
  116     },
  117     {
  118         /* test dollar */
  119         L"ls doll",
  120         "doll",
  121         {"doll$artest", NULL},
  122         L"ls doll\\$artest "
  123     },
  124     {
  125         /* test dollar inside single quotes */
  126         L"ls 'sdoll",
  127         "sdoll",
  128         {"sdoll$artest", NULL},
  129         L"ls 'sdoll$artest'"
  130     },
  131     {
  132         /* test dollar inside double quotes */
  133         L"ls \"ddoll",
  134         "ddoll",
  135         {"ddoll$artest", NULL},
  136         L"ls \"ddoll\\$artest\""
  137     },
  138     {
  139         /* test equals */
  140         L"ls eq",
  141         "eq",
  142         {"equals==test", NULL},
  143         L"ls equals\\=\\=test "
  144     },
  145     {
  146         /* test equals inside sinqle quotes */
  147         L"ls 'seq",
  148         "seq",
  149         {"sequals==test", NULL},
  150         L"ls 'sequals==test'"
  151     },
  152     {
  153         /* test equals inside double quotes */
  154         L"ls \"deq",
  155         "deq",
  156         {"dequals==test", NULL},
  157         L"ls \"dequals==test\""
  158     },
  159     {
  160         /* test \n */
  161         L"ls new",
  162         "new",
  163         {"new\\nline", NULL},
  164         L"ls new\\\\nline "
  165     },
  166     {
  167         /* test \n inside single quotes */
  168         L"ls 'snew",
  169         "snew",
  170         {"snew\nline", NULL},
  171         L"ls 'snew\nline'"
  172     },
  173     {
  174         /* test \n inside double quotes */
  175         L"ls \"dnew",
  176         "dnew",
  177         {"dnew\nline", NULL},
  178         L"ls \"dnew\nline\""
  179     },
  180     {
  181         /* test single space */
  182         L"ls spac",
  183         "spac",
  184         {"space test", NULL},
  185         L"ls space\\ test "
  186     },
  187     {
  188         /* test single space inside singlq quotes */
  189         L"ls 's_spac",
  190         "s_spac",
  191         {"s_space test", NULL},
  192         L"ls 's_space test'"
  193     },
  194     {
  195         /* test single space inside double quotes */
  196         L"ls \"d_spac",
  197         "d_spac",
  198         {"d_space test", NULL},
  199         L"ls \"d_space test\""
  200     },
  201     {
  202         /* test multiple spaces */
  203         L"ls multi",
  204         "multi",
  205         {"multi space  test", NULL},
  206         L"ls multi\\ space\\ \\ test "
  207     },
  208     {
  209         /* test multiple spaces inside single quotes */
  210         L"ls 's_multi",
  211         "s_multi",
  212         {"s_multi space  test", NULL},
  213         L"ls 's_multi space  test'"
  214     },
  215     {
  216         /* test multiple spaces inside double quotes */
  217         L"ls \"d_multi",
  218         "d_multi",
  219         {"d_multi space  test", NULL},
  220         L"ls \"d_multi space  test\""
  221     },
  222     {
  223         /* test double quotes */
  224         L"ls doub",
  225         "doub",
  226         {"doub\"quotes", NULL},
  227         L"ls doub\\\"quotes "
  228     },
  229     {
  230         /* test double quotes inside single quotes */
  231         L"ls 's_doub",
  232         "s_doub",
  233         {"s_doub\"quotes", NULL},
  234         L"ls 's_doub\"quotes'"
  235     },
  236     {
  237         /* test double quotes inside double quotes */
  238         L"ls \"d_doub",
  239         "d_doub",
  240         {"d_doub\"quotes", NULL},
  241         L"ls \"d_doub\\\"quotes\""
  242     },
  243     {
  244         /* test multiple double quotes */
  245         L"ls mud",
  246         "mud",
  247         {"mud\"qu\"otes\"", NULL},
  248         L"ls mud\\\"qu\\\"otes\\\" "
  249     },
  250     {
  251         /* test multiple double quotes inside single quotes */
  252         L"ls 'smud",
  253         "smud",
  254         {"smud\"qu\"otes\"", NULL},
  255         L"ls 'smud\"qu\"otes\"'"
  256     },
  257     {
  258         /* test multiple double quotes inside double quotes */
  259         L"ls \"dmud",
  260         "dmud",
  261         {"dmud\"qu\"otes\"", NULL},
  262         L"ls \"dmud\\\"qu\\\"otes\\\"\""
  263     },
  264     {
  265         /* test one single quote */
  266         L"ls sing",
  267         "sing",
  268         {"single'quote", NULL},
  269         L"ls single\\'quote "
  270     },
  271     {
  272         /* test one single quote inside single quote */
  273         L"ls 'ssing",
  274         "ssing",
  275         {"ssingle'quote", NULL},
  276         L"ls 'ssingle'\\''quote'"
  277     },
  278     {
  279         /* test one single quote inside double quote */
  280         L"ls \"dsing",
  281         "dsing",
  282         {"dsingle'quote", NULL},
  283         L"ls \"dsingle'quote\""
  284     },
  285     {
  286         /* test multiple single quotes */
  287         L"ls mu_sing",
  288         "mu_sing",
  289         {"mu_single''quotes''", NULL},
  290         L"ls mu_single\\'\\'quotes\\'\\' "
  291     },
  292     {
  293         /* test multiple single quotes inside single quote */
  294         L"ls 'smu_sing",
  295         "smu_sing",
  296         {"smu_single''quotes''", NULL},
  297         L"ls 'smu_single'\\'''\\''quotes'\\\'''\\'''"
  298     },
  299     {
  300         /* test multiple single quotes inside double quote */
  301         L"ls \"dmu_sing",
  302         "dmu_sing",
  303         {"dmu_single''quotes''", NULL},
  304         L"ls \"dmu_single''quotes''\""
  305     },
  306     {
  307         /* test parenthesis */
  308         L"ls paren",
  309         "paren",
  310         {"paren(test)", NULL},
  311         L"ls paren\\(test\\) "
  312     },
  313     {
  314         /* test parenthesis inside single quote */
  315         L"ls 'sparen",
  316         "sparen",
  317         {"sparen(test)", NULL},
  318         L"ls 'sparen(test)'"
  319     },
  320     {
  321         /* test parenthesis inside double quote */
  322         L"ls \"dparen",
  323         "dparen",
  324         {"dparen(test)", NULL},
  325         L"ls \"dparen(test)\""
  326     },
  327     {
  328         /* test pipe */
  329         L"ls pip",
  330         "pip",
  331         {"pipe|test", NULL},
  332         L"ls pipe\\|test "
  333     },
  334     {
  335         /* test pipe inside single quote */
  336         L"ls 'spip",
  337         "spip",
  338         {"spipe|test", NULL},
  339         L"ls 'spipe|test'",
  340     },
  341     {
  342         /* test pipe inside double quote */
  343         L"ls \"dpip",
  344         "dpip",
  345         {"dpipe|test", NULL},
  346         L"ls \"dpipe|test\""
  347     },
  348     {
  349         /* test tab */
  350         L"ls ta",
  351         "ta",
  352         {"tab\ttest", NULL},
  353         L"ls tab\\\ttest "
  354     },
  355     {
  356         /* test tab inside single quote */
  357         L"ls 'sta",
  358         "sta",
  359         {"stab\ttest", NULL},
  360         L"ls 'stab\ttest'"
  361     },
  362     {
  363         /* test tab inside double quote */
  364         L"ls \"dta",
  365         "dta",
  366         {"dtab\ttest", NULL},
  367         L"ls \"dtab\ttest\""
  368     },
  369     {
  370         /* test back tick */
  371         L"ls tic",
  372         "tic",
  373         {"tick`test`", NULL},
  374         L"ls tick\\`test\\` "
  375     },
  376     {
  377         /* test back tick inside single quote */
  378         L"ls 'stic",
  379         "stic",
  380         {"stick`test`", NULL},
  381         L"ls 'stick`test`'"
  382     },
  383     {
  384         /* test back tick inside double quote */
  385         L"ls \"dtic",
  386         "dtic",
  387         {"dtick`test`", NULL},
  388         L"ls \"dtick\\`test\\`\""
  389     },
  390     {
  391         /* test for @ */
  392         L"ls at",
  393         "at",
  394         {"atthe@rate", NULL},
  395         L"ls atthe\\@rate "
  396     },
  397     {
  398         /* test for @ inside single quote */
  399         L"ls 'sat",
  400         "sat",
  401         {"satthe@rate", NULL},
  402         L"ls 'satthe@rate'"
  403     },
  404     {
  405         /* test for @ inside double quote */
  406         L"ls \"dat",
  407         "dat",
  408         {"datthe@rate", NULL},
  409         L"ls \"datthe@rate\""
  410     },
  411     {
  412         /* test ; */
  413         L"ls semi",
  414         "semi",
  415         {"semi;colon;test", NULL},
  416         L"ls semi\\;colon\\;test "
  417     },
  418     {
  419         /* test ; inside single quote */
  420         L"ls 'ssemi",
  421         "ssemi",
  422         {"ssemi;colon;test", NULL},
  423         L"ls 'ssemi;colon;test'"
  424     },
  425     {
  426         /* test ; inside double quote */
  427         L"ls \"dsemi",
  428         "dsemi",
  429         {"dsemi;colon;test", NULL},
  430         L"ls \"dsemi;colon;test\""
  431     },
  432     {
  433         /* test & */
  434         L"ls amp",
  435         "amp",
  436         {"ampers&and", NULL},
  437         L"ls ampers\\&and "
  438     },
  439     {
  440         /* test & inside single quote */
  441         L"ls 'samp",
  442         "samp",
  443         {"sampers&and", NULL},
  444         L"ls 'sampers&and'"
  445     },
  446     {
  447         /* test & inside double quote */
  448         L"ls \"damp",
  449         "damp",
  450         {"dampers&and", NULL},
  451         L"ls \"dampers&and\""
  452     },
  453     {
  454         /* test completion when cursor at \ */
  455         L"ls foo\\",
  456         "foo",
  457         {"foo bar", NULL},
  458         L"ls foo\\ bar "
  459     },
  460     {
  461         /* test completion when cursor at single quote */
  462         L"ls foo'",
  463         "foo'",
  464         {"foo bar", NULL},
  465         L"ls foo\\ bar "
  466     },
  467     {
  468         /* test completion when cursor at double quote */
  469         L"ls foo\"",
  470         "foo\"",
  471         {"foo bar", NULL},
  472         L"ls foo\\ bar "
  473     },
  474     {
  475         /* test multiple completion matches */
  476         L"ls fo",
  477         "fo",
  478         {"foo bar", "foo baz"},
  479         L"ls foo\\ ba"
  480     },
  481     {
  482         L"ls ba",
  483         "ba",
  484         {"bar <bar>", "bar <baz>"},
  485         L"ls bar\\ \\<ba"
  486     }
  487 };
  488 
  489 static const wchar_t break_chars[] = L" \t\n\"\\'`@$><=;|&{(";
  490 
  491 /*
  492  * Custom completion function passed to fn_complet, NULLe.
  493  * The function returns hardcoded completion matches
  494  * based on the test cases present in inputs[] (above)
  495  */
  496 static char *
  497 mycomplet_func(const char *text, int index)
  498 {
  499     static int last_index = 0;
  500     size_t i = 0;
  501     if (last_index == 2) {
  502         last_index = 0;
  503         return NULL;
  504     }
  505 
  506     for (i = 0; i < sizeof(inputs)/sizeof(inputs[0]); i++) {
  507         if (strcmp(text, inputs[i].completion_function_input) == 0) {
  508             if (inputs[i].expanded_text[last_index] != NULL)
  509                 return strdup(inputs[i].expanded_text[last_index++]);
  510             else {
  511                 last_index = 0;
  512                 return NULL;
  513             }
  514         }
  515     }
  516 
  517     return NULL;
  518 }
  519 
  520 int
  521 main(int argc, char **argv)
  522 {
  523     EditLine *el = el_init(argv[0], stdin, stdout, stderr);
  524     size_t i; 
  525     size_t input_len;
  526     el_line_t line;
  527     wchar_t *buffer = malloc(64 * sizeof(*buffer));
  528     if (buffer == NULL)
  529         err(EXIT_FAILURE, "malloc failed");
  530 
  531     for (i = 0; i < sizeof(inputs)/sizeof(inputs[0]); i++) {
  532         memset(buffer, 0, 64 * sizeof(*buffer));
  533         input_len = wcslen(inputs[i].user_typed_text);
  534         wmemcpy(buffer, inputs[i].user_typed_text, input_len);
  535         buffer[input_len] = 0;
  536         line.buffer = buffer;
  537         line.cursor = line.buffer + input_len ;
  538         line.lastchar = line.cursor - 1;
  539         line.limit = line.buffer + 64 * sizeof(*buffer);
  540         el->el_line = line;
  541         fn_complete(el, mycomplet_func, NULL, break_chars, NULL, NULL, 10, NULL, NULL, NULL, NULL);
  542 
  543         /*
  544          * fn_complete would have expanded and escaped the input in el->el_line.buffer.
  545          * We need to assert that it matches with the expected value in our test data
  546          */
  547         printf("User input: %ls\t Expected output: %ls\t Generated output: %ls\n",
  548                 inputs[i].user_typed_text, inputs[i].escaped_output, el->el_line.buffer);
  549         assert(wcscmp(el->el_line.buffer, inputs[i].escaped_output) == 0);
  550     }
  551     el_end(el);
  552     return 0;
  553 
  554 }