blob: 452f808b0f308c5e2361dae7500ecbe3e1f1c154 [file] [log] [blame]
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdlib.h>
18#include <string.h>
19#include <stdio.h>
20#undef NDEBUG
21#include <assert.h>
22#include "commands.h"
23
24static struct {
25 bool called;
26 const char *name;
27 void *cookie;
28 int argc;
29 const char **argv;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080030 int returnValue;
31 char *functionResult;
32} gTestCommandState;
33
34static int
Doug Zongkerf28c9162009-06-02 15:30:11 -070035testCommand(const char *name, void *cookie, int argc, const char *argv[])
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080036{
37 gTestCommandState.called = true;
38 gTestCommandState.name = name;
39 gTestCommandState.cookie = cookie;
40 gTestCommandState.argc = argc;
41 gTestCommandState.argv = argv;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080042 return gTestCommandState.returnValue;
43}
44
45static int
46testFunction(const char *name, void *cookie, int argc, const char *argv[],
Doug Zongkerf28c9162009-06-02 15:30:11 -070047 char **result, size_t *resultLen)
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080048{
49 gTestCommandState.called = true;
50 gTestCommandState.name = name;
51 gTestCommandState.cookie = cookie;
52 gTestCommandState.argc = argc;
53 gTestCommandState.argv = argv;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -080054 if (result != NULL) {
55 *result = gTestCommandState.functionResult;
56 if (resultLen != NULL) {
57 *resultLen = strlen(*result);
58 }
59 }
60 return gTestCommandState.returnValue;
61}
62
63static int
64test_commands()
65{
66 Command *cmd;
67 int ret;
68 CommandArgumentType argType;
69
70 ret = commandInit();
71 assert(ret == 0);
72
73 /* Make sure we can't initialize twice.
74 */
75 ret = commandInit();
76 assert(ret < 0);
77
78 /* Try calling with some bad values.
79 */
80 ret = registerCommand(NULL, CMD_ARGS_UNKNOWN, NULL, NULL);
81 assert(ret < 0);
82
83 ret = registerCommand("hello", CMD_ARGS_UNKNOWN, NULL, NULL);
84 assert(ret < 0);
85
86 ret = registerCommand("hello", CMD_ARGS_WORDS, NULL, NULL);
87 assert(ret < 0);
88
89 cmd = findCommand(NULL);
90 assert(cmd == NULL);
91
92 argType = getCommandArgumentType(NULL);
93 assert((int)argType < 0);
94
95 ret = callCommand(NULL, -1, NULL);
96 assert(ret < 0);
97
98 ret = callBooleanCommand(NULL, false);
99 assert(ret < 0);
100
101 /* Register some commands.
102 */
103 ret = registerCommand("one", CMD_ARGS_WORDS, testCommand,
104 &gTestCommandState);
105 assert(ret == 0);
106
107 ret = registerCommand("two", CMD_ARGS_WORDS, testCommand,
108 &gTestCommandState);
109 assert(ret == 0);
110
111 ret = registerCommand("bool", CMD_ARGS_BOOLEAN, testCommand,
112 &gTestCommandState);
113 assert(ret == 0);
114
115 /* Make sure that all of those commands exist and that their
116 * argument types are correct.
117 */
118 cmd = findCommand("one");
119 assert(cmd != NULL);
120 argType = getCommandArgumentType(cmd);
121 assert(argType == CMD_ARGS_WORDS);
122
123 cmd = findCommand("two");
124 assert(cmd != NULL);
125 argType = getCommandArgumentType(cmd);
126 assert(argType == CMD_ARGS_WORDS);
127
128 cmd = findCommand("bool");
129 assert(cmd != NULL);
130 argType = getCommandArgumentType(cmd);
131 assert(argType == CMD_ARGS_BOOLEAN);
132
133 /* Make sure that no similar commands exist.
134 */
135 cmd = findCommand("on");
136 assert(cmd == NULL);
137
138 cmd = findCommand("onee");
139 assert(cmd == NULL);
140
141 /* Make sure that a double insertion fails.
142 */
143 ret = registerCommand("one", CMD_ARGS_WORDS, testCommand,
144 &gTestCommandState);
145 assert(ret < 0);
146
147 /* Make sure that bad args fail.
148 */
149 cmd = findCommand("one");
150 assert(cmd != NULL);
151
152 ret = callCommand(cmd, -1, NULL); // argc must be non-negative
153 assert(ret < 0);
154
155 ret = callCommand(cmd, 1, NULL); // argv can't be NULL if argc > 0
156 assert(ret < 0);
157
158 /* Make sure that you can't make a boolean call on a regular command.
159 */
160 cmd = findCommand("one");
161 assert(cmd != NULL);
162
163 ret = callBooleanCommand(cmd, false);
164 assert(ret < 0);
165
166 /* Make sure that you can't make a regular call on a boolean command.
167 */
168 cmd = findCommand("bool");
169 assert(cmd != NULL);
170
171 ret = callCommand(cmd, 0, NULL);
172 assert(ret < 0);
173
174 /* Set up some arguments.
175 */
176 int argc = 4;
177 const char *argv[4] = { "ONE", "TWO", "THREE", "FOUR" };
178
179 /* Make a call and make sure that it occurred.
180 */
181 cmd = findCommand("one");
182 assert(cmd != NULL);
183 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
184 gTestCommandState.called = false;
185 gTestCommandState.returnValue = 25;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800186 ret = callCommand(cmd, argc, argv);
187//xxx also try calling with a null argv element (should fail)
188 assert(ret == 25);
189 assert(gTestCommandState.called);
190 assert(strcmp(gTestCommandState.name, "one") == 0);
191 assert(gTestCommandState.cookie == &gTestCommandState);
192 assert(gTestCommandState.argc == argc);
193 assert(gTestCommandState.argv == argv);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800194
195 /* Make a boolean call and make sure that it occurred.
196 */
197 cmd = findCommand("bool");
198 assert(cmd != NULL);
199
200 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
201 gTestCommandState.called = false;
202 gTestCommandState.returnValue = 12;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800203 ret = callBooleanCommand(cmd, false);
204 assert(ret == 12);
205 assert(gTestCommandState.called);
206 assert(strcmp(gTestCommandState.name, "bool") == 0);
207 assert(gTestCommandState.cookie == &gTestCommandState);
208 assert(gTestCommandState.argc == 0);
209 assert(gTestCommandState.argv == NULL);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800210
211 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
212 gTestCommandState.called = false;
213 gTestCommandState.returnValue = 13;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800214 ret = callBooleanCommand(cmd, true);
215 assert(ret == 13);
216 assert(gTestCommandState.called);
217 assert(strcmp(gTestCommandState.name, "bool") == 0);
218 assert(gTestCommandState.cookie == &gTestCommandState);
219 assert(gTestCommandState.argc == 1);
220 assert(gTestCommandState.argv == NULL);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800221
222 /* Smoke test commandCleanup().
223 */
224 commandCleanup();
225
226 return 0;
227}
228
229static int
230test_functions()
231{
232 Function *fn;
233 int ret;
234
235 ret = commandInit();
236 assert(ret == 0);
237
238 /* Try calling with some bad values.
239 */
240 ret = registerFunction(NULL, NULL, NULL);
241 assert(ret < 0);
242
243 ret = registerFunction("hello", NULL, NULL);
244 assert(ret < 0);
245
246 fn = findFunction(NULL);
247 assert(fn == NULL);
248
249 ret = callFunction(NULL, -1, NULL, NULL, NULL);
250 assert(ret < 0);
251
252 /* Register some functions.
253 */
254 ret = registerFunction("one", testFunction, &gTestCommandState);
255 assert(ret == 0);
256
257 ret = registerFunction("two", testFunction, &gTestCommandState);
258 assert(ret == 0);
259
260 ret = registerFunction("three", testFunction, &gTestCommandState);
261 assert(ret == 0);
262
263 /* Make sure that all of those functions exist.
264 * argument types are correct.
265 */
266 fn = findFunction("one");
267 assert(fn != NULL);
268
269 fn = findFunction("two");
270 assert(fn != NULL);
271
272 fn = findFunction("three");
273 assert(fn != NULL);
274
275 /* Make sure that no similar functions exist.
276 */
277 fn = findFunction("on");
278 assert(fn == NULL);
279
280 fn = findFunction("onee");
281 assert(fn == NULL);
282
283 /* Make sure that a double insertion fails.
284 */
285 ret = registerFunction("one", testFunction, &gTestCommandState);
286 assert(ret < 0);
287
288 /* Make sure that bad args fail.
289 */
290 fn = findFunction("one");
291 assert(fn != NULL);
292
293 // argc must be non-negative
294 ret = callFunction(fn, -1, NULL, (char **)1, NULL);
295 assert(ret < 0);
296
297 // argv can't be NULL if argc > 0
298 ret = callFunction(fn, 1, NULL, (char **)1, NULL);
299 assert(ret < 0);
300
301 // result can't be NULL
302 ret = callFunction(fn, 0, NULL, NULL, NULL);
303 assert(ret < 0);
304
305 /* Set up some arguments.
306 */
307 int argc = 4;
308 const char *argv[4] = { "ONE", "TWO", "THREE", "FOUR" };
309
310 /* Make a call and make sure that it occurred.
311 */
312 char *functionResult;
313 size_t functionResultLen;
314 fn = findFunction("one");
315 assert(fn != NULL);
316 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
317 gTestCommandState.called = false;
318 gTestCommandState.returnValue = 25;
319 gTestCommandState.functionResult = "1234";
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800320 functionResult = NULL;
321 functionResultLen = 55;
322 ret = callFunction(fn, argc, argv,
323 &functionResult, &functionResultLen);
324//xxx also try calling with a null resultLen arg (should succeed)
325//xxx also try calling with a null argv element (should fail)
326 assert(ret == 25);
327 assert(gTestCommandState.called);
328 assert(strcmp(gTestCommandState.name, "one") == 0);
329 assert(gTestCommandState.cookie == &gTestCommandState);
330 assert(gTestCommandState.argc == argc);
331 assert(gTestCommandState.argv == argv);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800332 assert(strcmp(functionResult, "1234") == 0);
333 assert(functionResultLen == strlen(functionResult));
334
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800335 /* Smoke test commandCleanup().
336 */
337 commandCleanup();
338
339 return 0;
340}
341
342static int
343test_interaction()
344{
345 Command *cmd;
346 Function *fn;
347 int ret;
348
349 ret = commandInit();
350 assert(ret == 0);
351
352 /* Register some commands.
353 */
354 ret = registerCommand("one", CMD_ARGS_WORDS, testCommand, (void *)0xc1);
355 assert(ret == 0);
356
357 ret = registerCommand("two", CMD_ARGS_WORDS, testCommand, (void *)0xc2);
358 assert(ret == 0);
359
360 /* Register some functions, one of which shares a name with a command.
361 */
362 ret = registerFunction("one", testFunction, (void *)0xf1);
363 assert(ret == 0);
364
365 ret = registerFunction("three", testFunction, (void *)0xf3);
366 assert(ret == 0);
367
368 /* Look up each of the commands, and make sure no command exists
369 * with the name used only by our function.
370 */
371 cmd = findCommand("one");
372 assert(cmd != NULL);
373
374 cmd = findCommand("two");
375 assert(cmd != NULL);
376
377 cmd = findCommand("three");
378 assert(cmd == NULL);
379
380 /* Look up each of the functions, and make sure no function exists
381 * with the name used only by our command.
382 */
383 fn = findFunction("one");
384 assert(fn != NULL);
385
386 fn = findFunction("two");
387 assert(fn == NULL);
388
389 fn = findFunction("three");
390 assert(fn != NULL);
391
392 /* Set up some arguments.
393 */
394 int argc = 4;
395 const char *argv[4] = { "ONE", "TWO", "THREE", "FOUR" };
396
397 /* Call the overlapping command and make sure that the cookie is correct.
398 */
399 cmd = findCommand("one");
400 assert(cmd != NULL);
401 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
402 gTestCommandState.called = false;
403 gTestCommandState.returnValue = 123;
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800404 ret = callCommand(cmd, argc, argv);
405 assert(ret == 123);
406 assert(gTestCommandState.called);
407 assert(strcmp(gTestCommandState.name, "one") == 0);
408 assert((int)gTestCommandState.cookie == 0xc1);
409 assert(gTestCommandState.argc == argc);
410 assert(gTestCommandState.argv == argv);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800411
412 /* Call the overlapping function and make sure that the cookie is correct.
413 */
414 char *functionResult;
415 size_t functionResultLen;
416 fn = findFunction("one");
417 assert(fn != NULL);
418 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
419 gTestCommandState.called = false;
420 gTestCommandState.returnValue = 125;
421 gTestCommandState.functionResult = "5678";
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800422 functionResult = NULL;
423 functionResultLen = 66;
424 ret = callFunction(fn, argc, argv, &functionResult, &functionResultLen);
425 assert(ret == 125);
426 assert(gTestCommandState.called);
427 assert(strcmp(gTestCommandState.name, "one") == 0);
428 assert((int)gTestCommandState.cookie == 0xf1);
429 assert(gTestCommandState.argc == argc);
430 assert(gTestCommandState.argv == argv);
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -0800431 assert(strcmp(functionResult, "5678") == 0);
432 assert(functionResultLen == strlen(functionResult));
433
434 /* Clean up.
435 */
436 commandCleanup();
437
438 return 0;
439}
440
441int
442test_cmd_fn()
443{
444 int ret;
445
446 ret = test_commands();
447 if (ret != 0) {
448 fprintf(stderr, "test_commands() failed: %d\n", ret);
449 return ret;
450 }
451
452 ret = test_functions();
453 if (ret != 0) {
454 fprintf(stderr, "test_functions() failed: %d\n", ret);
455 return ret;
456 }
457
458 ret = test_interaction();
459 if (ret != 0) {
460 fprintf(stderr, "test_interaction() failed: %d\n", ret);
461 return ret;
462 }
463
464 return 0;
465}