test_command_line_parser.cpp
Go to the documentation of this file.
1 //
2 // Bareflank Hypervisor
3 //
4 // Copyright (C) 2015 Assured Information Security, Inc.
5 // Author: Rian Quinn <quinnr@ainfosec.com>
6 // Author: Brendan Kerrigan <kerriganb@ainfosec.com>
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 #include <string>
23 
24 #include <test.h>
25 #include <exception.h>
26 #include <command_line_parser.h>
27 
28 static auto operator"" _uce(const char *str, std::size_t len)
29 { (void)str; (void)len; return std::make_shared<bfn::unknown_command_error>(""); }
30 
31 static auto operator"" _mae(const char *str, std::size_t len)
32 { (void)str; (void)len; return std::make_shared<bfn::missing_argument_error>(); }
33 
34 static auto operator"" _uvte(const char *str, std::size_t len)
35 { (void)str; (void)len; return std::make_shared<bfn::unknown_vmcall_type_error>(""); }
36 
37 static auto operator"" _uvste(const char *str, std::size_t len)
38 { (void)str; (void)len; return std::make_shared<bfn::unknown_vmcall_string_type_error>(""); }
39 
40 static auto operator"" _uvdte(const char *str, std::size_t len)
41 { (void)str; (void)len; return std::make_shared<bfn::unknown_vmcall_data_type_error>(""); }
42 
43 void
44 bfm_ut::test_command_line_parser_with_no_args()
45 {
46  auto &&args = {""_s};
47  auto &&clp = command_line_parser{};
48 
49  this->expect_no_exception([&] { clp.parse(args); });
51 }
52 
53 void
54 bfm_ut::test_command_line_parser_with_empty_args()
55 {
56  auto &&args = {" "_s};
57  auto &&clp = command_line_parser{};
58 
59  this->expect_no_exception([&] { clp.parse(args); });
61 }
62 
63 void
64 bfm_ut::test_command_line_parser_with_unknown_command()
65 {
66  auto &&args = {"unknown"_s};
67  auto &&clp = command_line_parser{};
68 
69  this->expect_exception([&] { clp.parse(args); }, ""_uce);
71 }
72 
73 void
74 bfm_ut::test_command_line_parser_with_unknown_command_resets_state()
75 {
76  auto &&args1 = {"unload"_s};
77  auto &&args2 = {"unknown"_s};
78  auto &&clp = command_line_parser{};
79 
80  this->expect_no_exception([&] { clp.parse(args1); });
82 
83  this->expect_exception([&] { clp.parse(args2); }, ""_uce);
85 }
86 
87 void
88 bfm_ut::test_command_line_parser_with_unknown_option_single_bar()
89 {
90  auto &&args = {"-unknown"_s};
91  auto &&clp = command_line_parser{};
92 
93  this->expect_no_exception([&] { clp.parse(args); });
95 }
96 
97 void
98 bfm_ut::test_command_line_parser_with_unknown_option_dual_bar()
99 {
100  auto &&args = {"--unknown"_s};
101  auto &&clp = command_line_parser{};
102 
103  this->expect_no_exception([&] { clp.parse(args); });
105 }
106 
107 void
108 bfm_ut::test_command_line_parser_with_single_bar_help()
109 {
110  auto &&args = {"-h"_s};
111  auto &&clp = command_line_parser{};
112 
113  this->expect_no_exception([&] { clp.parse(args); });
115 }
116 
117 void
118 bfm_ut::test_command_line_parser_with_dual_bar_help()
119 {
120  auto &&args = {"--help"_s};
121  auto &&clp = command_line_parser{};
122 
123  this->expect_no_exception([&] { clp.parse(args); });
125 }
126 
127 void
128 bfm_ut::test_command_line_parser_with_single_bar_help_unknown_option()
129 {
130  auto &&args = {"-h"_s, "unknown"_s};
131  auto &&clp = command_line_parser{};
132 
133  this->expect_no_exception([&] { clp.parse(args); });
135 }
136 
137 void
138 bfm_ut::test_command_line_parser_with_dual_bar_help_unknown_option()
139 {
140  auto &&args = {"--help"_s, "unknown"_s};
141  auto &&clp = command_line_parser{};
142 
143  this->expect_no_exception([&] { clp.parse(args); });
145 }
146 
147 void
148 bfm_ut::test_command_line_parser_with_load_no_modules()
149 {
150  auto &&args = {"load"_s};
151  auto &&clp = command_line_parser{};
152 
153  this->expect_exception([&] { clp.parse(args); }, ""_mae);
155 }
156 
157 void
158 bfm_ut::test_command_line_parser_with_load_no_modules_empty_arg()
159 {
160  auto &&args = {"load"_s, " "_s};
161  auto &&clp = command_line_parser{};
162 
163  this->expect_exception([&] { clp.parse(args); }, ""_mae);
165 }
166 
167 void
168 bfm_ut::test_command_line_parser_with_valid_load()
169 {
170  auto &&args = {"load"_s, "filename"_s};
171  auto &&clp = command_line_parser{};
172 
173  this->expect_no_exception([&] { clp.parse(args); });
175  this->expect_true(clp.modules() == "filename");
176 }
177 
178 void
179 bfm_ut::test_command_line_parser_with_valid_load_unknown_option()
180 {
181  auto &&args = {"load"_s, "--unknow_option"_s, "filename"_s};
182  auto &&clp = command_line_parser{};
183 
184  this->expect_no_exception([&] { clp.parse(args); });
186  this->expect_true(clp.modules() == "filename");
187 }
188 
189 void
190 bfm_ut::test_command_line_parser_with_unknown_command_before_valid_load()
191 {
192  auto &&args = {"unknown_cmd"_s, "load"_s, "filename"_s};
193  auto &&clp = command_line_parser{};
194 
195  this->expect_exception([&] { clp.parse(args); }, ""_uce);
197 }
198 
199 void
200 bfm_ut::test_command_line_parser_with_unknown_command_after_valid_load()
201 {
202  auto &&args = {"load"_s, "filename"_s, "unknown_cmd"_s};
203  auto &&clp = command_line_parser{};
204 
205  this->expect_no_exception([&] { clp.parse(args); });
207  this->expect_true(clp.modules() == "filename");
208 }
209 
210 void
211 bfm_ut::test_command_line_parser_with_help_and_valid_load()
212 {
213  auto &&args = {"-h"_s, "load"_s, "filename"_s};
214  auto &&clp = command_line_parser{};
215 
216  this->expect_no_exception([&] { clp.parse(args); });
218 }
219 
220 void
221 bfm_ut::test_command_line_parser_with_valid_unload()
222 {
223  auto &&args = {"unload"_s};
224  auto &&clp = command_line_parser{};
225 
226  this->expect_no_exception([&] { clp.parse(args); });
228 }
229 
230 void
231 bfm_ut::test_command_line_parser_with_valid_start()
232 {
233  auto &&args = {"start"_s};
234  auto &&clp = command_line_parser{};
235 
236  this->expect_no_exception([&] { clp.parse(args); });
238 }
239 
240 void
241 bfm_ut::test_command_line_parser_with_valid_stop()
242 {
243  auto &&args = {"stop"_s};
244  auto &&clp = command_line_parser{};
245 
246  this->expect_no_exception([&] { clp.parse(args); });
248 }
249 
250 void
251 bfm_ut::test_command_line_parser_with_valid_dump()
252 {
253  auto &&args = {"dump"_s};
254  auto &&clp = command_line_parser{};
255 
256  this->expect_no_exception([&] { clp.parse(args); });
258  this->expect_true(clp.vcpuid() == 0);
259 }
260 
261 void
262 bfm_ut::test_command_line_parser_with_valid_status()
263 {
264  auto &&args = {"status"_s};
265  auto &&clp = command_line_parser{};
266 
267  this->expect_no_exception([&] { clp.parse(args); });
269 }
270 
271 void
272 bfm_ut::test_command_line_parser_no_vcpuid()
273 {
274  auto &&args = {"dump"_s, "--vcpuid"_s};
275  auto &&clp = command_line_parser{};
276 
277  this->expect_no_exception([&] { clp.parse(args); });
279  this->expect_true(clp.vcpuid() == 0);
280 }
281 
282 void
283 bfm_ut::test_command_line_parser_invalid_vcpuid()
284 {
285  auto &&args = {"dump"_s, "--vcpuid"_s, "not_a_number"_s};
286  auto &&clp = command_line_parser{};
287 
288  this->expect_exception([&] { clp.parse(args); }, ""_ut_iae);
290 }
291 
292 void
293 bfm_ut::test_command_line_parser_valid_vcpuid()
294 {
295  auto &&args = {"dump"_s, "--vcpuid"_s, "2"_s};
296  auto &&clp = command_line_parser{};
297 
298  this->expect_no_exception([&] { clp.parse(args); });
300  this->expect_true(clp.vcpuid() == 2);
301 }
302 
303 void
304 bfm_ut::test_command_line_parser_missing_vmcall_opcode()
305 {
306  auto &&args = {"vmcall"_s};
307  auto &&clp = command_line_parser{};
308 
309  this->expect_exception([&] { clp.parse(args); }, ""_mae);
311 }
312 
313 void
314 bfm_ut::test_command_line_parser_unknown_vmcall_opcode()
315 {
316  auto &&args = {"vmcall"_s, "unknown"_s};
317  auto &&clp = command_line_parser{};
318 
319  this->expect_exception([&] { clp.parse(args); }, ""_uvte);
321 }
322 
323 void
324 bfm_ut::test_command_line_parser_vmcall_versions_missing_index()
325 {
326  auto &&args = {"vmcall"_s, "versions"_s};
327  auto &&clp = command_line_parser{};
328 
329  this->expect_exception([&] { clp.parse(args); }, ""_mae);
331 }
332 
333 void
334 bfm_ut::test_command_line_parser_vmcall_versions_invalid_index()
335 {
336  auto &&args = {"vmcall"_s, "versions"_s, "not_a_number"_s};
337  auto &&clp = command_line_parser{};
338 
339  this->expect_exception([&] { clp.parse(args); }, ""_ut_iae);
341 }
342 
343 void
344 bfm_ut::test_command_line_parser_vmcall_versions_success()
345 {
346  auto &&args = {"vmcall"_s, "versions"_s, "1"_s};
347  auto &&clp = command_line_parser{};
348 
349  this->expect_no_exception([&] { clp.parse(args); });
351  this->expect_true(clp.cpuid() == 0);
352 
353  this->expect_true(clp.registers().r00 == VMCALL_VERSIONS);
354  this->expect_true(clp.registers().r01 == VMCALL_MAGIC_NUMBER);
355  this->expect_true(clp.registers().r02 == 1);
356 }
357 
358 void
359 bfm_ut::test_command_line_parser_vmcall_versions_success_with_missing_cpuid()
360 {
361  auto &&args = {"vmcall"_s, "versions"_s, "1"_s, "--cpuid"_s};
362  auto &&clp = command_line_parser{};
363 
364  this->expect_no_exception([&] { clp.parse(args); });
366  this->expect_true(clp.cpuid() == 0);
367 
368  this->expect_true(clp.registers().r00 == VMCALL_VERSIONS);
369  this->expect_true(clp.registers().r01 == VMCALL_MAGIC_NUMBER);
370  this->expect_true(clp.registers().r02 == 1);
371 }
372 
373 void
374 bfm_ut::test_command_line_parser_vmcall_versions_success_with_invalid_cpuid()
375 {
376  auto &&args = {"vmcall"_s, "versions"_s, "1"_s, "--cpuid"_s, "not_a_number"_s};
377  auto &&clp = command_line_parser{};
378 
379  this->expect_exception([&] { clp.parse(args); }, ""_ut_iae);
381 }
382 
383 void
384 bfm_ut::test_command_line_parser_vmcall_versions_success_with_cpuid()
385 {
386  auto &&args = {"vmcall"_s, "versions"_s, "1"_s, "--cpuid"_s, "2"_s};
387  auto &&clp = command_line_parser{};
388 
389  this->expect_no_exception([&] { clp.parse(args); });
391  this->expect_true(clp.cpuid() == 2);
392 
393  this->expect_true(clp.registers().r00 == VMCALL_VERSIONS);
394  this->expect_true(clp.registers().r01 == VMCALL_MAGIC_NUMBER);
395  this->expect_true(clp.registers().r02 == 1);
396 }
397 
398 void
399 bfm_ut::test_command_line_parser_vmcall_registers_missing_registers()
400 {
401  auto &&args = {"vmcall"_s, "registers"_s};
402  auto &&clp = command_line_parser{};
403 
404  this->expect_no_exception([&] { clp.parse(args); });
406 
407  this->expect_true(clp.registers().r00 == VMCALL_REGISTERS);
408  this->expect_true(clp.registers().r01 == VMCALL_MAGIC_NUMBER);
409 }
410 
411 void
412 bfm_ut::test_command_line_parser_vmcall_registers_one_register_invalid_register()
413 {
414  auto &&args = {"vmcall"_s, "registers"_s, "not_a_number"_s};
415  auto &&clp = command_line_parser{};
416 
417  this->expect_exception([&] { clp.parse(args); }, ""_ut_iae);
419 }
420 
421 void
422 bfm_ut::test_command_line_parser_vmcall_registers_one_register()
423 {
424  auto &&args = {"vmcall"_s, "registers"_s, "2"_s};
425  auto &&clp = command_line_parser{};
426 
427  this->expect_no_exception([&] { clp.parse(args); });
429 
430  this->expect_true(clp.registers().r00 == VMCALL_REGISTERS);
431  this->expect_true(clp.registers().r01 == VMCALL_MAGIC_NUMBER);
432  this->expect_true(clp.registers().r02 == 2);
433 }
434 
435 void
436 bfm_ut::test_command_line_parser_vmcall_registers_all_registers()
437 {
438  auto &&args = {"vmcall"_s, "registers"_s, "2"_s, "3"_s, "4"_s, "5"_s, "6"_s, "7"_s, "8"_s, "9"_s, "10"_s, "11"_s, "12"_s, "13"_s, "14"_s, "15"_s};
439  auto &&clp = command_line_parser{};
440 
441  this->expect_no_exception([&] { clp.parse(args); });
443 
444  this->expect_true(clp.registers().r00 == VMCALL_REGISTERS);
445  this->expect_true(clp.registers().r01 == VMCALL_MAGIC_NUMBER);
446  this->expect_true(clp.registers().r02 == 0x2);
447  this->expect_true(clp.registers().r03 == 0x3);
448  this->expect_true(clp.registers().r04 == 0x4);
449  this->expect_true(clp.registers().r05 == 0x5);
450  this->expect_true(clp.registers().r06 == 0x6);
451  this->expect_true(clp.registers().r07 == 0x7);
452  this->expect_true(clp.registers().r08 == 0x8);
453  this->expect_true(clp.registers().r09 == 0x9);
454  this->expect_true(clp.registers().r10 == 0x10);
455  this->expect_true(clp.registers().r11 == 0x11);
456  this->expect_true(clp.registers().r12 == 0x12);
457  this->expect_true(clp.registers().r13 == 0x13);
458  this->expect_true(clp.registers().r14 == 0x14);
459  this->expect_true(clp.registers().r15 == 0x15);
460 }
461 
462 void
463 bfm_ut::test_command_line_parser_vmcall_string_missing_type()
464 {
465  auto &&args = {"vmcall"_s, "string"_s};
466  auto &&clp = command_line_parser{};
467 
468  this->expect_exception([&] { clp.parse(args); }, ""_mae);
470 }
471 
472 void
473 bfm_ut::test_command_line_parser_vmcall_string_unknown_type()
474 {
475  auto &&args = {"vmcall"_s, "string"_s, "unknown"_s};
476  auto &&clp = command_line_parser{};
477 
478  this->expect_exception([&] { clp.parse(args); }, ""_uvste);
480 }
481 
482 void
483 bfm_ut::test_command_line_parser_vmcall_string_missing_string()
484 {
485  auto &&args = {"vmcall"_s, "string"_s, "unformatted"_s};
486  auto &&clp = command_line_parser{};
487 
488  this->expect_exception([&] { clp.parse(args); }, ""_mae);
490 }
491 
492 void
493 bfm_ut::test_command_line_parser_vmcall_string_unformatted()
494 {
495  auto &&args = {"vmcall"_s, "string"_s, "unformatted"_s, "hello world"_s};
496  auto &&clp = command_line_parser{};
497 
498  this->expect_no_exception([&] { clp.parse(args); });
500 
501  this->expect_true(clp.registers().r00 == VMCALL_DATA);
502  this->expect_true(clp.registers().r01 == VMCALL_MAGIC_NUMBER);
503  this->expect_true(clp.registers().r02 == 0);
504  this->expect_true(clp.registers().r03 == 0);
505  this->expect_true(clp.registers().r04 == VMCALL_DATA_STRING_UNFORMATTED);
506  this->expect_true(clp.registers().r05 != 0);
507  this->expect_true(clp.registers().r06 == 11);
508 }
509 
510 void
511 bfm_ut::test_command_line_parser_vmcall_string_json_missing_json()
512 {
513  auto &&args = {"vmcall"_s, "string"_s, "json"_s};
514  auto &&clp = command_line_parser{};
515 
516  this->expect_exception([&] { clp.parse(args); }, ""_mae);
518 }
519 
520 void
521 bfm_ut::test_command_line_parser_vmcall_string_json_invalid_json()
522 {
523  auto &&args = {"vmcall"_s, "string"_s, "json"_s, "hello world"_s};
524  auto &&clp = command_line_parser{};
525 
526  this->expect_exception([&] { clp.parse(args); }, ""_ut_iae);
528 }
529 
530 void
531 bfm_ut::test_command_line_parser_vmcall_string_json()
532 {
533  auto &&args = {"vmcall"_s, "string"_s, "json"_s, "{\"msg\":\"hello world\"}"_s};
534  auto &&clp = command_line_parser{};
535 
536  this->expect_no_exception([&] { clp.parse(args); });
538 
539  this->expect_true(clp.registers().r00 == VMCALL_DATA);
540  this->expect_true(clp.registers().r01 == VMCALL_MAGIC_NUMBER);
541  this->expect_true(clp.registers().r02 == 0);
542  this->expect_true(clp.registers().r03 == 0);
543  this->expect_true(clp.registers().r04 == VMCALL_DATA_STRING_JSON);
544  this->expect_true(clp.registers().r05 != 0);
545  this->expect_true(clp.registers().r06 == 21);
546 }
547 
548 void
549 bfm_ut::test_command_line_parser_vmcall_data_missing_type()
550 {
551  auto &&args = {"vmcall"_s, "data"_s};
552  auto &&clp = command_line_parser{};
553 
554  this->expect_exception([&] { clp.parse(args); }, ""_mae);
556 }
557 
558 void
559 bfm_ut::test_command_line_parser_vmcall_data_unknown_type()
560 {
561  auto &&args = {"vmcall"_s, "data"_s, "unknown"_s};
562  auto &&clp = command_line_parser{};
563 
564  this->expect_exception([&] { clp.parse(args); }, ""_uvdte);
566 }
567 
568 void
569 bfm_ut::test_command_line_parser_vmcall_data_missing_ifile()
570 {
571  auto &&args = {"vmcall"_s, "data"_s, "unformatted"_s};
572  auto &&clp = command_line_parser{};
573 
574  this->expect_exception([&] { clp.parse(args); }, ""_mae);
576 }
577 
578 void
579 bfm_ut::test_command_line_parser_vmcall_data_missing_ofile()
580 {
581  auto &&args = {"vmcall"_s, "data"_s, "unformatted"_s, "ifile.txt"_s};
582  auto &&clp = command_line_parser{};
583 
584  this->expect_exception([&] { clp.parse(args); }, ""_mae);
586 }
587 
588 void
589 bfm_ut::test_command_line_parser_vmcall_data()
590 {
591  auto &&args = {"vmcall"_s, "data"_s, "unformatted"_s, "ifile.txt"_s, "ofile.txt"_s};
592  auto &&clp = command_line_parser{};
593 
594  this->expect_no_exception([&] { clp.parse(args); });
596  this->expect_true(clp.ifile() == "ifile.txt");
597  this->expect_true(clp.ofile() == "ofile.txt");
598 
599  this->expect_true(clp.registers().r00 == VMCALL_DATA);
600  this->expect_true(clp.registers().r01 == VMCALL_MAGIC_NUMBER);
601  this->expect_true(clp.registers().r02 == 0);
602  this->expect_true(clp.registers().r03 == 0);
603  this->expect_true(clp.registers().r04 == VMCALL_DATA_BINARY_UNFORMATTED);
604 }
605 
606 void
607 bfm_ut::test_command_line_parser_vmcall_unittest_missing_index()
608 {
609  auto &&args = {"vmcall"_s, "unittest"_s};
610  auto &&clp = command_line_parser{};
611 
612  this->expect_exception([&] { clp.parse(args); }, ""_mae);
614 }
615 
616 void
617 bfm_ut::test_command_line_parser_vmcall_unittest_invalid_index()
618 {
619  auto &&args = {"vmcall"_s, "unittest"_s, "not_a_number"_s};
620  auto &&clp = command_line_parser{};
621 
622  this->expect_exception([&] { clp.parse(args); }, ""_ut_iae);
624 }
625 
626 void
627 bfm_ut::test_command_line_parser_vmcall_unittest_success()
628 {
629  auto &&args = {"vmcall"_s, "unittest"_s, "1"_s};
630  auto &&clp = command_line_parser{};
631 
632  this->expect_no_exception([&] { clp.parse(args); });
634  this->expect_true(clp.cpuid() == 0);
635 
636  this->expect_true(clp.registers().r00 == VMCALL_UNITTEST);
637  this->expect_true(clp.registers().r01 == VMCALL_MAGIC_NUMBER);
638  this->expect_true(clp.registers().r02 == 1);
639 }
640 
641 void
642 bfm_ut::test_command_line_parser_vmcall_event_missing_index()
643 {
644  auto &&args = {"vmcall"_s, "event"_s};
645  auto &&clp = command_line_parser{};
646 
647  this->expect_exception([&] { clp.parse(args); }, ""_mae);
649 }
650 
651 void
652 bfm_ut::test_command_line_parser_vmcall_event_invalid_index()
653 {
654  auto &&args = {"vmcall"_s, "event"_s, "not_a_number"_s};
655  auto &&clp = command_line_parser{};
656 
657  this->expect_exception([&] { clp.parse(args); }, ""_ut_iae);
659 }
660 
661 void
662 bfm_ut::test_command_line_parser_vmcall_event_success()
663 {
664  auto &&args = {"vmcall"_s, "event"_s, "1"_s};
665  auto &&clp = command_line_parser{};
666 
667  this->expect_no_exception([&] { clp.parse(args); });
669  this->expect_true(clp.cpuid() == 0);
670 
671  this->expect_true(clp.registers().r00 == VMCALL_EVENT);
672  this->expect_true(clp.registers().r01 == VMCALL_MAGIC_NUMBER);
673  this->expect_true(clp.registers().r02 == 1);
674 }
#define expect_exception(f, e)
Definition: unittest.h:162
#define expect_no_exception(f)
Definition: unittest.h:198
void help()
Definition: main.cpp:70
#define expect_true(a)
#define VMCALL_MAGIC_NUMBER