Some of these tests currently fail including hard failures where the shell quits entirely (this would lead to a kernel panic). A followup commit will rewrite the parse_cmdline function to improve it and fix these deficiencies. --- Makefile | 3 + test/test_parse_cmdline | 233 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 236 insertions(+) create mode 100755 test/test_parse_cmdline diff --git a/Makefile b/Makefile index 5af0eb2..6c70718 100644 --- a/Makefile +++ b/Makefile @@ -74,6 +74,9 @@ man/%: man/%.txt Makefile -a manversion=$(VERSION) \ -a manmanual="mkinitcpio manual" $< +check: + @r=0; for t in test/test_*; do $$t || { echo $$t fail; r=1; }; done; exit $$r + clean: $(RM) mkinitcpio-${VERSION}.tar.gz $(MANPAGES) diff --git a/test/test_parse_cmdline b/test/test_parse_cmdline new file mode 100755 index 0000000..9afd9cb --- /dev/null +++ b/test/test_parse_cmdline @@ -0,0 +1,233 @@ +#!/lib/initcpio/busybox ash + +. ./init_functions + +failed=0 +tests=0 + +e_ok=0 +e_parser_failure=2 +e_assertion_failure=130 + +assert() { + local expect_fail= key= expected_value= actual_value + + if [ "$1" = '--expect-fail' ]; then + expect_fail=y + shift + fi + + key=$1 expected_value=$2 + eval actual_value=\$"$1" + + case $actual_value in + $expected_value) + if [ -n "$expect_fail" ]; then + echo "EXPECTED FAIL: $key: expected='$expected_value', got='$actual_value'" + return 1 + fi + ;; + *) + if [ -z "$expect_fail" ]; then + echo "FAIL: $key: expected='$expected_value', got='$actual_value'" + return 1 + fi + ;; + esac + + return 0 +} + +test_parse() { + local flag= cmdline= expect_fail= expect_parse_fail= + + tests=$(( tests + 1 )) + + for flag; do + case $flag in + --expect-fail) + expect_fail='--expect-fail' + shift + ;; + --expect-parse-fail) + expect_parse_fail=y + shift + ;; + *) + break + ;; + esac + done + + cmdline=$1; shift + [ -n "$V" ] && echo "testing cmdline: $cmdline" + + echo "$cmdline" | { + parse_cmdline + + result=0 + while [ "$#" -gt 0 ]; do + key=$1 expected_value=$2 + shift 2 + + assert $expect_fail "$key" "$expected_value" || result=$e_assertion_failure + done + + exit "$result" + } 2>/dev/null + + case $? in + $e_parser_failure) + # parser failure + if [ -z "$expect_parse_fail" ]; then + echo "FAIL: parse_cmdline failed" + failed=$(( failed + 1 )) + fi + ;; + $e_assertion_failure) + # test assertion failure + failed=$(( failed + 1 )) + ;; + $e_ok) + if [ -n "$expect_parse_fail" ]; then + echo "EXPECTED_FAIL: parse_cmdline succeeded" + failed=$(( failed + 1 )) + fi + ;; + esac +} + +# bare words +test_parse 'foo' \ + 'foo' 'y' +test_parse 'foo bar' \ + 'foo' 'y' \ + 'bar' 'y' + +# overwriting +test_parse 'foo=bar bar=baz foo bar="no pe"' \ + 'bar' 'no pe' \ + 'foo' 'y' + +# simple key=value assignment +test_parse 'foo=bar' \ + 'foo' 'bar' +test_parse 'foo=bar bar=baz' \ + 'foo' 'bar' \ + 'bar' 'baz' +test_parse '_derpy=hooves' \ + '_derpy' 'hooves' +test_parse 'f5=abc f_5_=abc' \ + 'f5' 'abc' \ + 'f_5_' 'abc' +test_parse 'v="foo bar=baz"' \ + 'v' 'foo bar=baz' + +# double quoting +test_parse 'foo="bar"' \ + 'foo' 'bar' +test_parse 'foo="bar baz"' \ + 'foo' 'bar baz' + +# single quoting +test_parse --expect-fail "foo='bar'" \ + 'foo' 'bar' +test_parse --expect-parse-fail "foo='bar baz'" \ + 'foo' 'bar baz' + +# dangling quotes +test_parse --expect-fail 'foo="bar' \ + 'foo' '"bar' +test_parse 'foo=bar"' \ + 'foo' 'bar"' + +# nested quotes +test_parse --expect-parse-fail "foo='\"bar baz\"' herp='\"de\"rp'" \ + 'foo' '"bar baz"' \ + 'herp' '"de"rp' + +# escaped quotes +test_parse 'foo=bar"baz' \ + 'foo' 'bar"baz' + +# neighboring quoted regions +test_parse --expect-fail 'foo="bar""baz"' \ + 'foo' 'barbaz' +test_parse --expect-fail "foo=\"bar\"'baz'" \ + 'foo' "barbaz" +test_parse --expect-fail "foo='bar'\"baz\"" \ + 'foo' "barbaz" + +# comments +test_parse 'foo=bar # ignored content' \ + 'foo' 'bar' \ + 'ignored' '' \ + 'content' '' +test_parse 'foo=bar #ignored content' \ + 'foo' 'bar' \ + 'ignored' '' \ + 'content' '' +test_parse 'foo="bar #baz" parse=this' \ + 'foo' 'bar #baz' \ + 'parse' 'this' + +# shell metachars +test_parse 'foo=*' \ + 'foo' '\*' +test_parse --expect-fail 'Make*' \ + 'Makefile' '' +test_parse --expect-fail '[Makefile]*' \ + 'Makefile' '' \ + 'init' '' \ + 'functions' '' + +# invalid names +test_parse 'in-valid=name' +test_parse '6foo=bar' +test_parse --expect-parse-fail '"gar bage"' \ + 'gar' '' \ + 'bage' '' + +# special handling +test_parse 'rw' \ + 'ro' '' \ + 'rw' '' \ + 'rwopt' 'rw' +test_parse 'ro' \ + 'ro' '' \ + 'rw' '' \ + 'rwopt' 'ro' +test_parse --expect-fail 'fstype=btrfs' \ + 'rootfstype' 'btrfs' +test_parse 'fsck.mode=force' \ + 'forcefsck' 'y' \ + 'fastboot' '' +test_parse 'fsck.mode=skip' \ + 'forcefsck' '' \ + 'fastboot' 'y' +test_parse 'rd.debug' \ + 'rd_debug' 'y' +test_parse 'rd.log' \ + 'rd_logmask' '6' +test_parse 'rd.log=all' \ + 'rd_logmask' '7' +test_parse 'rd.log=console' \ + 'rd_logmask' '4' +test_parse 'rd.log=kmsg' \ + 'rd_logmask' '2' +test_parse 'rd.log=file' \ + 'rd_logmask' '1' + +# a mix of stuff +test_parse 'foo=bar bareword bar="ba az"' \ + 'foo' 'bar' \ + 'bareword' 'y' \ + 'bar' 'ba az' + +if [ "$failed" -eq 0 ]; then + echo "PASS: ${0##*/test_} ($tests tests)" + exit 0 +else + echo "FAIL: $failed tests failed" + exit 1 +fi -- 2.8.3