1 // Copyright (C) 2002 Graydon Hoare <graydon@pobox.com>
2 //               2007 Julio M. Merino Vidal <jmmv@NetBSD.org>
3 //
4 // This program is made available under the GNU GPL version 2.0 or
5 // greater. See the accompanying file COPYING for details.
6 //
7 // This program is distributed WITHOUT ANY WARRANTY; without even the
8 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
9 // PURPOSE.
10 
11 #include "../../../src/base.hh"
12 #include "../unit_tests.hh"
13 #include "../../../src/cmd.hh"
14 #include "../../../src/simplestring_xform.hh"
15 
16 using std::set;
17 
18 // by duplicating these definitions from options.cc we avoid dragging
19 // that file and all its dependencies into the unit tester
20 
21 option::option_set<options>
operator |(option::option_set<options> const & opts,option::option_set<options> const & (* fun)())22 operator | (option::option_set<options> const & opts,
23             option::option_set<options> const & (*fun)())
24 {
25   return opts | fun();
26 }
27 
none()28 options::options_type const & options::opts::none()
29 {
30   static options::options_type val;
31   return val;
32 }
33 
34 CMD_GROUP(__root__, "__root__", "", NULL, "", "");
35 
36 CMD_GROUP(top, "top", "", CMD_REF(__root__),
37           "", "");
38 CMD(test, "test", "", CMD_REF(top),
39     "", "", "", options::opts::none) {}
40 CMD(test1, "test1", "alias1", CMD_REF(top),
41     "", "", "", options::opts::none) {}
42 CMD(test2, "test2", "alias2", CMD_REF(top),
43     "", "", "", options::opts::none) {}
44 CMD_HIDDEN(test3, "test3", "", CMD_REF(top),
45            "", "", "", options::opts::none) {}
46 
47 CMD_GROUP(testg, "testg", "aliasg", CMD_REF(top),
48           "", "");
49 CMD(testg1, "testg1", "", CMD_REF(testg),
50     "", "", "", options::opts::none) {}
51 CMD(testg2, "testg2", "", CMD_REF(testg),
52     "", "", "", options::opts::none) {}
53 CMD_HIDDEN(testg3, "testg3", "", CMD_REF(testg),
54            "", "", "", options::opts::none) {}
55 
56 static args_vector
mkargs(const char * words)57 mkargs(const char *words)
58 {
59   return split_into_words(arg_type(words, origin::user));
60 }
61 
UNIT_TEST(make_command_id)62 UNIT_TEST(make_command_id)
63 {
64   using commands::command_id;
65   using commands::make_command_id;
66 
67   {
68     command_id id = make_command_id("foo");
69     UNIT_TEST_CHECK(id.size() == 1);
70     UNIT_TEST_CHECK(id[0]() == "foo");
71   }
72 
73   {
74     command_id id = make_command_id("foo bar");
75     UNIT_TEST_CHECK(id.size() == 2);
76     UNIT_TEST_CHECK(id[0]() == "foo");
77     UNIT_TEST_CHECK(id[1]() == "bar");
78   }
79 }
80 
UNIT_TEST(complete_command)81 UNIT_TEST(complete_command)
82 {
83   using commands::command_id;
84   using commands::complete_command;
85   using commands::make_command_id;
86 
87   // Single-word identifier, top-level category.
88   {
89     command_id id = complete_command(mkargs("top"));
90     UNIT_TEST_CHECK(id == make_command_id("top"));
91   }
92 
93   // Single-word identifier.
94   {
95     command_id id = complete_command(mkargs("testg"));
96     UNIT_TEST_CHECK(id == make_command_id("top testg"));
97   }
98 
99   // Single-word identifier, non-primary name.
100   {
101     command_id id = complete_command(mkargs("alias1"));
102     UNIT_TEST_CHECK(id == make_command_id("top alias1"));
103   }
104 
105   // Multi-word identifier.
106   {
107     command_id id = complete_command(mkargs("testg testg1"));
108     UNIT_TEST_CHECK(id == make_command_id("top testg testg1"));
109   }
110 
111   // Multi-word identifier, non-primary names.
112   {
113     command_id id = complete_command(mkargs("al testg1"));
114     UNIT_TEST_CHECK(id == make_command_id("top aliasg testg1"));
115   }
116 }
117 
UNIT_TEST(command_complete_command)118 UNIT_TEST(command_complete_command)
119 {
120   using commands::command_id;
121   using commands::make_command_id;
122 
123   // Non-existent single-word identifier.
124   {
125     command_id id = make_command_id("foo");
126     set< command_id > matches = CMD_REF(top)->complete_command(id);
127     UNIT_TEST_REQUIRE(matches.empty());
128   }
129 
130   // Non-existent multi-word identifier.
131   {
132     command_id id = make_command_id("foo bar");
133     set< command_id > matches = CMD_REF(top)->complete_command(id);
134     UNIT_TEST_REQUIRE(matches.empty());
135   }
136 
137   // Single-word identifier with one match. Exact matches are found
138   // before any possible completions.
139   {
140     command_id id = make_command_id("test");
141     set< command_id > matches = CMD_REF(top)->complete_command(id);
142     UNIT_TEST_REQUIRE(matches.size() == 1);
143     UNIT_TEST_CHECK(*matches.begin() == make_command_id("test"));
144   }
145 
146   // Single-word identifier with one match, non-primary name.
147   {
148     command_id id = make_command_id("alias1");
149     set< command_id > matches = CMD_REF(top)->complete_command(id);
150     UNIT_TEST_REQUIRE(matches.size() == 1);
151     UNIT_TEST_CHECK(*matches.begin() == make_command_id("alias1"));
152   }
153 
154   // Single-word identifier with multiple matches.
155   {
156     command_id id = make_command_id("tes");
157     set< command_id > matches = CMD_REF(top)->complete_command(id);
158     UNIT_TEST_REQUIRE(matches.size() == 4);
159 
160     set< command_id > expected;
161     expected.insert(make_command_id("test"));
162     expected.insert(make_command_id("test1"));
163     expected.insert(make_command_id("test2"));
164     expected.insert(make_command_id("testg"));
165     UNIT_TEST_CHECK(matches == expected);
166   }
167 
168   // Single-word identifier with multiple matches, non-primary name.
169   {
170     command_id id = make_command_id("alias");
171     set< command_id > matches = CMD_REF(top)->complete_command(id);
172     UNIT_TEST_REQUIRE(matches.size() == 3);
173 
174     set< command_id > expected;
175     expected.insert(make_command_id("alias1"));
176     expected.insert(make_command_id("alias2"));
177     expected.insert(make_command_id("aliasg"));
178     UNIT_TEST_CHECK(matches == expected);
179   }
180 
181   // Multi-word identifier with one match.
182   {
183     command_id id = make_command_id("testg testg1");
184     set< command_id > matches = CMD_REF(top)->complete_command(id);
185     UNIT_TEST_REQUIRE(matches.size() == 1);
186 
187     set< command_id > expected;
188     expected.insert(make_command_id("testg testg1"));
189     UNIT_TEST_CHECK(matches == expected);
190   }
191 
192   // Multi-word identifier with multiple matches.
193   {
194     command_id id = make_command_id("testg testg");
195     set< command_id > matches = CMD_REF(top)->complete_command(id);
196     UNIT_TEST_REQUIRE(matches.size() == 2);
197 
198     set< command_id > expected;
199     expected.insert(make_command_id("testg testg1"));
200     expected.insert(make_command_id("testg testg2"));
201     UNIT_TEST_CHECK(matches == expected);
202   }
203 
204   // Multi-word identifier with multiple matches at different levels.
205   {
206     command_id id = make_command_id("tes testg1");
207     set< command_id > matches = CMD_REF(top)->complete_command(id);
208     UNIT_TEST_REQUIRE(matches.size() == 4);
209 
210     set< command_id > expected;
211     expected.insert(make_command_id("test"));
212     expected.insert(make_command_id("test1"));
213     expected.insert(make_command_id("test2"));
214     expected.insert(make_command_id("testg testg1"));
215     UNIT_TEST_CHECK(matches == expected);
216   }
217 
218   // Multi-word identifier with one match and extra words.
219   {
220     command_id id = make_command_id("testg testg1 foo");
221     set< command_id > matches = CMD_REF(top)->complete_command(id);
222     UNIT_TEST_REQUIRE(matches.size() == 1);
223 
224     set< command_id > expected;
225     expected.insert(make_command_id("testg testg1"));
226     UNIT_TEST_CHECK(matches == expected);
227   }
228 }
229 
UNIT_TEST(command_find_command)230 UNIT_TEST(command_find_command)
231 {
232   using commands::command;
233   using commands::command_id;
234   using commands::make_command_id;
235 
236   // Non-existent single-word identifier.
237   {
238     command_id id = make_command_id("foo");
239     command const * cmd = CMD_REF(top)->find_command(id);
240     UNIT_TEST_CHECK(cmd == NULL);
241   }
242 
243   // Non-existent multi-word identifier.
244   {
245     command_id id = make_command_id("foo bar");
246     command const * cmd = CMD_REF(top)->find_command(id);
247     UNIT_TEST_CHECK(cmd == NULL);
248   }
249 
250   // Single-word identifier that could be completed.
251   {
252     command_id id = make_command_id("tes");
253     command const * cmd = CMD_REF(top)->find_command(id);
254     UNIT_TEST_CHECK(cmd == NULL);
255   }
256 
257   // Single-word identifier.
258   {
259     command_id id = make_command_id("test1");
260     command const * cmd = CMD_REF(top)->find_command(id);
261     UNIT_TEST_CHECK(cmd == CMD_REF(test1));
262   }
263 
264   // Hidden single-word identifier.
265   {
266     command_id id = make_command_id("test3");
267     command const * cmd = CMD_REF(top)->find_command(id);
268     UNIT_TEST_CHECK(cmd == CMD_REF(test3));
269   }
270 
271   // Multi-word identifier that could be completed.
272   {
273     command_id id = make_command_id("testg testg");
274     command const * cmd = CMD_REF(top)->find_command(id);
275     UNIT_TEST_CHECK(cmd == NULL);
276   }
277 
278   // Multi-word identifier.
279   {
280     command_id id = make_command_id("testg testg1");
281     command const * cmd = CMD_REF(top)->find_command(id);
282     UNIT_TEST_CHECK(cmd == CMD_REF(testg1));
283   }
284 
285   // Hidden multi-word identifier.
286   {
287     command_id id = make_command_id("testg testg3");
288     command const * cmd = CMD_REF(top)->find_command(id);
289     UNIT_TEST_CHECK(cmd == CMD_REF(testg3));
290   }
291 
292   // Multi-word identifier with extra words.
293   {
294     command_id id = make_command_id("testg testg1 foo");
295     command const * cmd = CMD_REF(top)->find_command(id);
296     UNIT_TEST_CHECK(cmd == NULL);
297   }
298 }
299 
300 // Local Variables:
301 // mode: C++
302 // fill-column: 76
303 // c-file-style: "gnu"
304 // indent-tabs-mode: nil
305 // End:
306 // vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
307