cmd: Add option to add a param at a specific pos
[openafs.git] / tests / cmd / command-t.c
1 /*
2  * Copyright (c) 2010 Your File System Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 /*
26  * Test the command line parsing library
27  */
28
29 #include <afsconfig.h>
30 #include <afs/param.h>
31
32 #include <roken.h>
33
34 #include <afs/cmd.h>
35
36 #include <tap/basic.h>
37
38 static int
39 testproc(struct cmd_syndesc *as, void *rock)
40 {
41     is_string("foo", as->parms[0].items->data,
42               "first option matches");
43     is_string("bar", as->parms[1].items->data,
44               "second option matches");
45     ok(as->parms[2].items != NULL,
46        "flag is set");
47
48     return 0;
49 }
50
51 int
52 main(int argc, char **argv)
53 {
54     char *tv[100];
55     struct cmd_syndesc *opts;
56     struct cmd_syndesc *retopts;
57     int code;
58     int tc;
59
60     plan(51);
61
62     initialize_CMD_error_table();
63
64     opts = cmd_CreateSyntax(NULL, testproc, NULL, NULL);
65     cmd_AddParm(opts, "-first", CMD_SINGLE, CMD_REQUIRED, "first option");
66     cmd_AddParm(opts, "-second", CMD_LIST, CMD_OPTIONAL, "second option");
67     cmd_AddParm(opts, "-flag", CMD_FLAG, CMD_OPTIONAL, "a flag");
68
69     /* A simple command line */
70     code = cmd_ParseLine("-first foo -second bar -flag", tv, &tc, 100);
71     is_int(0, code, "cmd_ParseLine succeeds");
72     code = cmd_Dispatch(tc, tv);
73     is_int(0, code, "dispatching simple comamnd line succeeds");
74     code = cmd_Parse(tc, tv, &retopts);
75     is_int(0, code, "parsing simple command line succeeds");
76     is_string("foo", retopts->parms[0].items->data, " ... 1st option matches");
77     is_string("bar", retopts->parms[1].items->data, " ... 2nd option matches");
78     ok(retopts->parms[2].items != NULL, " ... 3rd option matches");
79     cmd_FreeOptions(&retopts);
80     cmd_FreeArgv(tv);
81
82     /* unknown switch */
83     code = cmd_ParseLine("-first foo -second bar -third -flag", tv, &tc, 100);
84     is_int(0, code, "cmd_ParseLine succeeds");
85     code = cmd_Dispatch(tc, tv);
86     is_int(CMD_UNKNOWNSWITCH, code, "invalid options fail as expected");
87     code = cmd_Parse(tc, tv, &retopts);
88     is_int(CMD_UNKNOWNSWITCH, code, "and still fail with cmd_Parse");
89     cmd_FreeArgv(tv);
90
91     /* missing parameter */
92     code = cmd_ParseLine("-first foo -second -flag", tv, &tc, 100);
93     is_int(0, code, "cmd_ParseLine succeeds");
94     code = cmd_Dispatch(tc, tv);
95     is_int(CMD_TOOFEW, code, "missing parameters fail as expected");
96     code = cmd_Parse(tc, tv, &retopts);
97     is_int(CMD_TOOFEW, code, "and still fail with cmd_Parse");
98     cmd_FreeArgv(tv);
99
100     /* missing option */
101     code = cmd_ParseLine("-second bar -third -flag", tv, &tc, 100);
102     is_int(0, code, "cmd_ParseLine succeeds");
103     code = cmd_Dispatch(tc, tv);
104     is_int(CMD_UNKNOWNSWITCH, code, "missing options fail as expected");
105     code = cmd_Parse(tc, tv, &retopts);
106     is_int(CMD_UNKNOWNSWITCH, code, "and still fail with cmd_Parse");
107     cmd_FreeArgv(tv);
108
109     code = cmd_ParseLine("-first foo baz -second bar -third -flag", tv, &tc, 100);
110     is_int(0, code, "cmd_ParseLine succeeds");
111     code = cmd_Dispatch(tc, tv);
112     is_int(CMD_NOTLIST, code, "too many parameters fails as expected");
113     code = cmd_Parse(tc, tv, &retopts);
114     is_int(CMD_NOTLIST, code, "and still fail with cmd_Parse");
115     cmd_FreeArgv(tv);
116
117     /* Positional parameters */
118     code = cmd_ParseLine("foo bar -flag", tv, &tc, 100);
119     is_int(0, code, "cmd_ParseLine succeeds");
120     code = cmd_Dispatch(tc, tv);
121     is_int(0, code, "dispatching positional parameters succeeds");
122     code = cmd_Parse(tc, tv, &retopts);
123     is_int(0, code, "and works with cmd_Parse");
124     cmd_FreeOptions(&retopts);
125     cmd_FreeArgv(tv);
126
127     /* Abbreviations */
128     code = cmd_ParseLine("-fi foo -s bar -flag", tv, &tc, 100);
129     is_int(0, code, "cmd_ParseLine succeeds");
130     code = cmd_Dispatch(tc, tv);
131     is_int(0, code, "dispatching abbreviations succeeds");
132     code = cmd_Parse(tc, tv, &retopts);
133     is_int(0, code, "and works with cmd_Parse");
134     cmd_FreeOptions(&retopts);
135
136     cmd_FreeArgv(tv);
137
138     /* Ambiguous */
139     code = cmd_ParseLine("-f foo -s bar -flag", tv, &tc, 100);
140     is_int(0, code, "cmd_ParseLine succeeds");
141     code = cmd_Dispatch(tc, tv);
142     is_int(CMD_UNKNOWNSWITCH, code, "ambiguous abbreviations correctly fail");
143     code = cmd_Parse(tc, tv, &retopts);
144     is_int(CMD_UNKNOWNSWITCH, code, "and fail with cmd_Parse too");
145     cmd_FreeArgv(tv);
146
147     /* Disable positional commands */
148     cmd_DisablePositionalCommands();
149     code = cmd_ParseLine("foo bar -flag", tv, &tc, 100);
150     is_int(0, code, "cmd_ParseLine succeeds");
151     code = cmd_Dispatch(tc, tv);
152     is_int(CMD_NOTLIST, code, "positional parameters can be disabled");
153     code = cmd_Parse(tc, tv, &retopts);
154     is_int(CMD_NOTLIST, code, "and fail with cmd_Parse too");
155     cmd_FreeArgv(tv);
156
157     /* Disable abbreviations */
158     cmd_DisableAbbreviations();
159     code = cmd_ParseLine("-fi foo -s bar -flag", tv, &tc, 100);
160     is_int(0, code, "cmd_ParseLine succeeds");
161     code = cmd_Dispatch(tc, tv);
162     is_int(CMD_UNKNOWNSWITCH, code, "dispatching abbreviations succeeds");
163     code = cmd_Parse(tc, tv, &retopts);
164     is_int(CMD_UNKNOWNSWITCH, code, "and fail with cmd_Parse too");
165
166     cmd_FreeArgv(tv);
167
168     /* Try the new cmd_Parse function with something different*/
169     code = cmd_ParseLine("-first one -second two -flag", tv, &tc, 100);
170     is_int(0, code, "cmd_ParseLine succeeds");
171     code = cmd_Parse(tc, tv, &retopts);
172     is_int(0, code, "Parsing with cmd_Parse works");
173     is_string("one", retopts->parms[0].items->data, " ... 1st option matches");
174     is_string("two", retopts->parms[1].items->data, " ... 2nd option matches");
175     ok(retopts->parms[2].items != NULL, " ... 3rd option matches");
176
177     cmd_FreeOptions(&retopts);
178     cmd_FreeArgv(tv);
179     /* Try adding a couple of parameters at specific positions */
180     cmd_AddParmAtOffset(opts, "-fifth", CMD_SINGLE, CMD_OPTIONAL,
181                        "fifth option", 5);
182     cmd_AddParmAtOffset(opts, "-fourth", CMD_SINGLE, CMD_OPTIONAL,
183                        "fourth option", 4);
184     code = cmd_ParseLine("-first a -fourth b -fifth c", tv, &tc, 100);
185     is_int(0, code, "cmd_ParseLine succeeds");
186     code = cmd_Parse(tc, tv, &retopts);
187     is_int(0, code, "parsing our new options succeeds");
188     is_string("b", retopts->parms[4].items->data, " Fourth option in right place");
189     is_string("c", retopts->parms[5].items->data, " Fifth option in right place");
190     cmd_FreeOptions(&retopts);
191     cmd_FreeArgv(tv);
192
193     return 0;
194 }
195