blob: be938ac26bedb992865e2cae40052ecccb005b73 [file] [log] [blame]
The Android Open Source Project23580ca2008-10-21 07:00:00 -07001/*
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;
30 PermissionRequestList *permissions;
31 int returnValue;
32 char *functionResult;
33} gTestCommandState;
34
35static int
36testCommand(const char *name, void *cookie, int argc, const char *argv[],
37 PermissionRequestList *permissions)
38{
39 gTestCommandState.called = true;
40 gTestCommandState.name = name;
41 gTestCommandState.cookie = cookie;
42 gTestCommandState.argc = argc;
43 gTestCommandState.argv = argv;
44 gTestCommandState.permissions = permissions;
45 return gTestCommandState.returnValue;
46}
47
48static int
49testFunction(const char *name, void *cookie, int argc, const char *argv[],
50 char **result, size_t *resultLen, PermissionRequestList *permissions)
51{
52 gTestCommandState.called = true;
53 gTestCommandState.name = name;
54 gTestCommandState.cookie = cookie;
55 gTestCommandState.argc = argc;
56 gTestCommandState.argv = argv;
57 gTestCommandState.permissions = permissions;
58 if (result != NULL) {
59 *result = gTestCommandState.functionResult;
60 if (resultLen != NULL) {
61 *resultLen = strlen(*result);
62 }
63 }
64 return gTestCommandState.returnValue;
65}
66
67static int
68test_commands()
69{
70 Command *cmd;
71 int ret;
72 CommandArgumentType argType;
73
74 ret = commandInit();
75 assert(ret == 0);
76
77 /* Make sure we can't initialize twice.
78 */
79 ret = commandInit();
80 assert(ret < 0);
81
82 /* Try calling with some bad values.
83 */
84 ret = registerCommand(NULL, CMD_ARGS_UNKNOWN, NULL, NULL);
85 assert(ret < 0);
86
87 ret = registerCommand("hello", CMD_ARGS_UNKNOWN, NULL, NULL);
88 assert(ret < 0);
89
90 ret = registerCommand("hello", CMD_ARGS_WORDS, NULL, NULL);
91 assert(ret < 0);
92
93 cmd = findCommand(NULL);
94 assert(cmd == NULL);
95
96 argType = getCommandArgumentType(NULL);
97 assert((int)argType < 0);
98
99 ret = callCommand(NULL, -1, NULL);
100 assert(ret < 0);
101
102 ret = callBooleanCommand(NULL, false);
103 assert(ret < 0);
104
105 /* Register some commands.
106 */
107 ret = registerCommand("one", CMD_ARGS_WORDS, testCommand,
108 &gTestCommandState);
109 assert(ret == 0);
110
111 ret = registerCommand("two", CMD_ARGS_WORDS, testCommand,
112 &gTestCommandState);
113 assert(ret == 0);
114
115 ret = registerCommand("bool", CMD_ARGS_BOOLEAN, testCommand,
116 &gTestCommandState);
117 assert(ret == 0);
118
119 /* Make sure that all of those commands exist and that their
120 * argument types are correct.
121 */
122 cmd = findCommand("one");
123 assert(cmd != NULL);
124 argType = getCommandArgumentType(cmd);
125 assert(argType == CMD_ARGS_WORDS);
126
127 cmd = findCommand("two");
128 assert(cmd != NULL);
129 argType = getCommandArgumentType(cmd);
130 assert(argType == CMD_ARGS_WORDS);
131
132 cmd = findCommand("bool");
133 assert(cmd != NULL);
134 argType = getCommandArgumentType(cmd);
135 assert(argType == CMD_ARGS_BOOLEAN);
136
137 /* Make sure that no similar commands exist.
138 */
139 cmd = findCommand("on");
140 assert(cmd == NULL);
141
142 cmd = findCommand("onee");
143 assert(cmd == NULL);
144
145 /* Make sure that a double insertion fails.
146 */
147 ret = registerCommand("one", CMD_ARGS_WORDS, testCommand,
148 &gTestCommandState);
149 assert(ret < 0);
150
151 /* Make sure that bad args fail.
152 */
153 cmd = findCommand("one");
154 assert(cmd != NULL);
155
156 ret = callCommand(cmd, -1, NULL); // argc must be non-negative
157 assert(ret < 0);
158
159 ret = callCommand(cmd, 1, NULL); // argv can't be NULL if argc > 0
160 assert(ret < 0);
161
162 /* Make sure that you can't make a boolean call on a regular command.
163 */
164 cmd = findCommand("one");
165 assert(cmd != NULL);
166
167 ret = callBooleanCommand(cmd, false);
168 assert(ret < 0);
169
170 /* Make sure that you can't make a regular call on a boolean command.
171 */
172 cmd = findCommand("bool");
173 assert(cmd != NULL);
174
175 ret = callCommand(cmd, 0, NULL);
176 assert(ret < 0);
177
178 /* Set up some arguments.
179 */
180 int argc = 4;
181 const char *argv[4] = { "ONE", "TWO", "THREE", "FOUR" };
182
183 /* Make a call and make sure that it occurred.
184 */
185 cmd = findCommand("one");
186 assert(cmd != NULL);
187 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
188 gTestCommandState.called = false;
189 gTestCommandState.returnValue = 25;
190 gTestCommandState.permissions = (PermissionRequestList *)1;
191 ret = callCommand(cmd, argc, argv);
192//xxx also try calling with a null argv element (should fail)
193 assert(ret == 25);
194 assert(gTestCommandState.called);
195 assert(strcmp(gTestCommandState.name, "one") == 0);
196 assert(gTestCommandState.cookie == &gTestCommandState);
197 assert(gTestCommandState.argc == argc);
198 assert(gTestCommandState.argv == argv);
199 assert(gTestCommandState.permissions == NULL);
200
201 /* Make a boolean call and make sure that it occurred.
202 */
203 cmd = findCommand("bool");
204 assert(cmd != NULL);
205
206 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
207 gTestCommandState.called = false;
208 gTestCommandState.returnValue = 12;
209 gTestCommandState.permissions = (PermissionRequestList *)1;
210 ret = callBooleanCommand(cmd, false);
211 assert(ret == 12);
212 assert(gTestCommandState.called);
213 assert(strcmp(gTestCommandState.name, "bool") == 0);
214 assert(gTestCommandState.cookie == &gTestCommandState);
215 assert(gTestCommandState.argc == 0);
216 assert(gTestCommandState.argv == NULL);
217 assert(gTestCommandState.permissions == NULL);
218
219 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
220 gTestCommandState.called = false;
221 gTestCommandState.returnValue = 13;
222 gTestCommandState.permissions = (PermissionRequestList *)1;
223 ret = callBooleanCommand(cmd, true);
224 assert(ret == 13);
225 assert(gTestCommandState.called);
226 assert(strcmp(gTestCommandState.name, "bool") == 0);
227 assert(gTestCommandState.cookie == &gTestCommandState);
228 assert(gTestCommandState.argc == 1);
229 assert(gTestCommandState.argv == NULL);
230 assert(gTestCommandState.permissions == NULL);
231
232 /* Try looking up permissions.
233 */
234 PermissionRequestList permissions;
235 cmd = findCommand("one");
236 assert(cmd != NULL);
237 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
238 gTestCommandState.called = false;
239 gTestCommandState.returnValue = 27;
240 gTestCommandState.permissions = (PermissionRequestList *)1;
241 argv[1] = NULL; // null out an arg, which should be ok
242 ret = getCommandPermissions(cmd, argc, argv, &permissions);
243 assert(ret == 27);
244 assert(gTestCommandState.called);
245 assert(strcmp(gTestCommandState.name, "one") == 0);
246 assert(gTestCommandState.cookie == &gTestCommandState);
247 assert(gTestCommandState.argc == argc);
248 assert(gTestCommandState.argv == argv);
249 assert(gTestCommandState.permissions == &permissions);
250
251 /* Boolean command permissions
252 */
253 cmd = findCommand("bool");
254 assert(cmd != NULL);
255 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
256 gTestCommandState.called = false;
257 gTestCommandState.returnValue = 55;
258 gTestCommandState.permissions = (PermissionRequestList *)1;
259 // argv[1] is still NULL
260 ret = getBooleanCommandPermissions(cmd, true, &permissions);
261 assert(ret == 55);
262 assert(gTestCommandState.called);
263 assert(strcmp(gTestCommandState.name, "bool") == 0);
264 assert(gTestCommandState.cookie == &gTestCommandState);
265 assert(gTestCommandState.argc == 1);
266 assert(gTestCommandState.argv == NULL);
267 assert(gTestCommandState.permissions == &permissions);
268
269
270 /* Smoke test commandCleanup().
271 */
272 commandCleanup();
273
274 return 0;
275}
276
277static int
278test_functions()
279{
280 Function *fn;
281 int ret;
282
283 ret = commandInit();
284 assert(ret == 0);
285
286 /* Try calling with some bad values.
287 */
288 ret = registerFunction(NULL, NULL, NULL);
289 assert(ret < 0);
290
291 ret = registerFunction("hello", NULL, NULL);
292 assert(ret < 0);
293
294 fn = findFunction(NULL);
295 assert(fn == NULL);
296
297 ret = callFunction(NULL, -1, NULL, NULL, NULL);
298 assert(ret < 0);
299
300 /* Register some functions.
301 */
302 ret = registerFunction("one", testFunction, &gTestCommandState);
303 assert(ret == 0);
304
305 ret = registerFunction("two", testFunction, &gTestCommandState);
306 assert(ret == 0);
307
308 ret = registerFunction("three", testFunction, &gTestCommandState);
309 assert(ret == 0);
310
311 /* Make sure that all of those functions exist.
312 * argument types are correct.
313 */
314 fn = findFunction("one");
315 assert(fn != NULL);
316
317 fn = findFunction("two");
318 assert(fn != NULL);
319
320 fn = findFunction("three");
321 assert(fn != NULL);
322
323 /* Make sure that no similar functions exist.
324 */
325 fn = findFunction("on");
326 assert(fn == NULL);
327
328 fn = findFunction("onee");
329 assert(fn == NULL);
330
331 /* Make sure that a double insertion fails.
332 */
333 ret = registerFunction("one", testFunction, &gTestCommandState);
334 assert(ret < 0);
335
336 /* Make sure that bad args fail.
337 */
338 fn = findFunction("one");
339 assert(fn != NULL);
340
341 // argc must be non-negative
342 ret = callFunction(fn, -1, NULL, (char **)1, NULL);
343 assert(ret < 0);
344
345 // argv can't be NULL if argc > 0
346 ret = callFunction(fn, 1, NULL, (char **)1, NULL);
347 assert(ret < 0);
348
349 // result can't be NULL
350 ret = callFunction(fn, 0, NULL, NULL, NULL);
351 assert(ret < 0);
352
353 /* Set up some arguments.
354 */
355 int argc = 4;
356 const char *argv[4] = { "ONE", "TWO", "THREE", "FOUR" };
357
358 /* Make a call and make sure that it occurred.
359 */
360 char *functionResult;
361 size_t functionResultLen;
362 fn = findFunction("one");
363 assert(fn != NULL);
364 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
365 gTestCommandState.called = false;
366 gTestCommandState.returnValue = 25;
367 gTestCommandState.functionResult = "1234";
368 gTestCommandState.permissions = (PermissionRequestList *)1;
369 functionResult = NULL;
370 functionResultLen = 55;
371 ret = callFunction(fn, argc, argv,
372 &functionResult, &functionResultLen);
373//xxx also try calling with a null resultLen arg (should succeed)
374//xxx also try calling with a null argv element (should fail)
375 assert(ret == 25);
376 assert(gTestCommandState.called);
377 assert(strcmp(gTestCommandState.name, "one") == 0);
378 assert(gTestCommandState.cookie == &gTestCommandState);
379 assert(gTestCommandState.argc == argc);
380 assert(gTestCommandState.argv == argv);
381 assert(gTestCommandState.permissions == NULL);
382 assert(strcmp(functionResult, "1234") == 0);
383 assert(functionResultLen == strlen(functionResult));
384
385 /* Try looking up permissions.
386 */
387 PermissionRequestList permissions;
388 fn = findFunction("one");
389 assert(fn != NULL);
390 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
391 gTestCommandState.called = false;
392 gTestCommandState.returnValue = 27;
393 gTestCommandState.permissions = (PermissionRequestList *)1;
394 argv[1] = NULL; // null out an arg, which should be ok
395 ret = getFunctionPermissions(fn, argc, argv, &permissions);
396 assert(ret == 27);
397 assert(gTestCommandState.called);
398 assert(strcmp(gTestCommandState.name, "one") == 0);
399 assert(gTestCommandState.cookie == &gTestCommandState);
400 assert(gTestCommandState.argc == argc);
401 assert(gTestCommandState.argv == argv);
402 assert(gTestCommandState.permissions == &permissions);
403
404 /* Smoke test commandCleanup().
405 */
406 commandCleanup();
407
408 return 0;
409}
410
411static int
412test_interaction()
413{
414 Command *cmd;
415 Function *fn;
416 int ret;
417
418 ret = commandInit();
419 assert(ret == 0);
420
421 /* Register some commands.
422 */
423 ret = registerCommand("one", CMD_ARGS_WORDS, testCommand, (void *)0xc1);
424 assert(ret == 0);
425
426 ret = registerCommand("two", CMD_ARGS_WORDS, testCommand, (void *)0xc2);
427 assert(ret == 0);
428
429 /* Register some functions, one of which shares a name with a command.
430 */
431 ret = registerFunction("one", testFunction, (void *)0xf1);
432 assert(ret == 0);
433
434 ret = registerFunction("three", testFunction, (void *)0xf3);
435 assert(ret == 0);
436
437 /* Look up each of the commands, and make sure no command exists
438 * with the name used only by our function.
439 */
440 cmd = findCommand("one");
441 assert(cmd != NULL);
442
443 cmd = findCommand("two");
444 assert(cmd != NULL);
445
446 cmd = findCommand("three");
447 assert(cmd == NULL);
448
449 /* Look up each of the functions, and make sure no function exists
450 * with the name used only by our command.
451 */
452 fn = findFunction("one");
453 assert(fn != NULL);
454
455 fn = findFunction("two");
456 assert(fn == NULL);
457
458 fn = findFunction("three");
459 assert(fn != NULL);
460
461 /* Set up some arguments.
462 */
463 int argc = 4;
464 const char *argv[4] = { "ONE", "TWO", "THREE", "FOUR" };
465
466 /* Call the overlapping command and make sure that the cookie is correct.
467 */
468 cmd = findCommand("one");
469 assert(cmd != NULL);
470 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
471 gTestCommandState.called = false;
472 gTestCommandState.returnValue = 123;
473 gTestCommandState.permissions = (PermissionRequestList *)1;
474 ret = callCommand(cmd, argc, argv);
475 assert(ret == 123);
476 assert(gTestCommandState.called);
477 assert(strcmp(gTestCommandState.name, "one") == 0);
478 assert((int)gTestCommandState.cookie == 0xc1);
479 assert(gTestCommandState.argc == argc);
480 assert(gTestCommandState.argv == argv);
481 assert(gTestCommandState.permissions == NULL);
482
483 /* Call the overlapping function and make sure that the cookie is correct.
484 */
485 char *functionResult;
486 size_t functionResultLen;
487 fn = findFunction("one");
488 assert(fn != NULL);
489 memset(&gTestCommandState, 0, sizeof(gTestCommandState));
490 gTestCommandState.called = false;
491 gTestCommandState.returnValue = 125;
492 gTestCommandState.functionResult = "5678";
493 gTestCommandState.permissions = (PermissionRequestList *)2;
494 functionResult = NULL;
495 functionResultLen = 66;
496 ret = callFunction(fn, argc, argv, &functionResult, &functionResultLen);
497 assert(ret == 125);
498 assert(gTestCommandState.called);
499 assert(strcmp(gTestCommandState.name, "one") == 0);
500 assert((int)gTestCommandState.cookie == 0xf1);
501 assert(gTestCommandState.argc == argc);
502 assert(gTestCommandState.argv == argv);
503 assert(gTestCommandState.permissions == NULL);
504 assert(strcmp(functionResult, "5678") == 0);
505 assert(functionResultLen == strlen(functionResult));
506
507 /* Clean up.
508 */
509 commandCleanup();
510
511 return 0;
512}
513
514int
515test_cmd_fn()
516{
517 int ret;
518
519 ret = test_commands();
520 if (ret != 0) {
521 fprintf(stderr, "test_commands() failed: %d\n", ret);
522 return ret;
523 }
524
525 ret = test_functions();
526 if (ret != 0) {
527 fprintf(stderr, "test_functions() failed: %d\n", ret);
528 return ret;
529 }
530
531 ret = test_interaction();
532 if (ret != 0) {
533 fprintf(stderr, "test_interaction() failed: %d\n", ret);
534 return ret;
535 }
536
537 return 0;
538}