From: Dave Hansen <[email protected]>

Here are some simple tests for the early command-line code.  It
had way more bugs than it should have, so let's make sure they
never pop up again.

Note, there are a few failures in here now.  We will fix those
up in the next few patches.

This is complete overkill for this code, but I had to do it to
convince myself that I wasn't making it any worse.

Signed-off-by: Dave Hansen <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---

 b/arch/x86/Kconfig.debug  |    7 ++
 b/arch/x86/kernel/check.c |    4 +
 b/arch/x86/lib/cmdline.c  |  122 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 133 insertions(+)

diff -puN arch/x86/Kconfig.debug~x86-early-command-line-test 
arch/x86/Kconfig.debug
--- a/arch/x86/Kconfig.debug~x86-early-command-line-test        2015-12-17 
13:55:30.619652300 -0800
+++ b/arch/x86/Kconfig.debug    2015-12-17 13:55:30.625652571 -0800
@@ -400,4 +400,11 @@ config PUNIT_ATOM_DEBUG
          The current power state can be read from
          /sys/kernel/debug/punit_atom/dev_power_state
 
+config X86_TEST_EARLY_CMDLINE
+       bool "Early command line runtime tests"
+       ---help---
+         This creates some test command-lines and tries to parse
+         a bunch of options from them.  The overhead is small both
+         at boot and increased text/data sizes.
+
 endmenu
diff -puN arch/x86/kernel/check.c~x86-early-command-line-test 
arch/x86/kernel/check.c
--- a/arch/x86/kernel/check.c~x86-early-command-line-test       2015-12-17 
13:55:30.621652391 -0800
+++ b/arch/x86/kernel/check.c   2015-12-17 13:55:30.626652617 -0800
@@ -165,3 +165,7 @@ static int start_periodic_check_for_corr
 }
 device_initcall(start_periodic_check_for_corruption);
 
+#ifdef CONFIG_X86_TEST_EARLY_CMDLINE
+int test_early_cmdline(void)
+late_initcall(test_early_cmdline);
+#endif /* CONFIG_X86_TEST_EARLY_CMDLINE */
diff -puN arch/x86/lib/cmdline.c~x86-early-command-line-test 
arch/x86/lib/cmdline.c
--- a/arch/x86/lib/cmdline.c~x86-early-command-line-test        2015-12-17 
13:55:30.622652436 -0800
+++ b/arch/x86/lib/cmdline.c    2015-12-17 13:55:30.626652617 -0800
@@ -4,6 +4,7 @@
  *
  * Misc librarized functions for cmdline poking.
  */
+#include <linux/bug.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
@@ -89,3 +90,124 @@ int cmdline_find_option_bool(const char
        return __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE,
                        option);
 }
+
+#ifdef CONFIG_X86_TEST_EARLY_CMDLINE
+
+static int __cmdtest(char *cmdline, int str_size, char *option,
+               int expected_result, int do_shrink)
+{
+       int ret;
+       int null_terminate;
+       /* Results are 1-based, so bias back down by 1 */
+       int option_end = expected_result + strlen(option) - 1;
+       int shrink_max = 0;
+
+       if (cmdline && do_shrink)
+               shrink_max = strlen(cmdline);
+       /*
+        * The option was not found.  If it was not found in the
+        * *full* command-line, it should never be found in any
+        * *part* of the command-line.
+        */
+       for (null_terminate = 0; null_terminate <= 1; null_terminate++) {
+               int shrink_by;
+               for (shrink_by = 0; shrink_by < shrink_max; shrink_by++) {
+                       int str_size_tst = str_size - shrink_by;
+                       char tmp = cmdline[str_size_tst];
+
+                       /*
+                        * Do not run tests that would truncate
+                        * over the expected option
+                        */
+                       if (str_size_tst <= option_end)
+                               continue;
+
+                       if (null_terminate)
+                               cmdline[str_size_tst] = '\0';
+                       ret = __cmdline_find_option_bool(cmdline, str_size_tst,
+                                       option);
+                       if (null_terminate)
+                               cmdline[str_size_tst] = tmp;
+
+                       if (ret == expected_result)
+                               continue;
+                       pr_err("failed cmdline test ('%s', %d, '%s') == %d "
+                                       "nulld: %d got: %d\n",
+                                       cmdline, str_size_tst, option,
+                                       expected_result, null_terminate,
+                                       ret);
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+#define cmdtest(cmdline, option, result)       \
+       WARN_ON(__cmdtest(cmdline, sizeof(cmdline), option, result, 1))
+
+#define cmdtest_noshrink(cmdline, option, result)      \
+       WARN_ON(__cmdtest(cmdline, sizeof(cmdline), option, result, 0))
+
+char cmdline1[] = "CALL me Ishmael  ";
+char cmdline2[] = "Whenever I find myself growing grim about the mouth  ";
+char cmdline3[] = "grow growing  ";
+int test_early_cmdline(void)
+{
+       /* NULL command-line: */
+       WARN_ON(__cmdline_find_option_bool(NULL, 22, "Ishmael") != -1);
+       /* zero-length command-line: */
+       cmdtest("", "Ishmael", 0);
+
+       /* Find words at each of 3 positions: start, middle, end */
+       cmdtest(cmdline1, "CALL", 1);
+       cmdtest(cmdline1, "me", 6);
+       cmdtest(cmdline1, "Ishmael", 9);
+
+       /*
+        * Fail to find strings that all occur in the cmdline,
+        * but not as full words
+        */
+       /*
+        * If "option" is _present_ in "cmdline" as the start of a
+        * word, like cmdline="foo bar" and we pass in option="b",
+        * when we shrink cmdline to "foo b", it will match.  So,
+        * skip shrink tests for those.
+        */
+       cmdtest_noshrink(cmdline1, "m", 0);
+       cmdtest(cmdline1, "e", 0);
+       cmdtest(cmdline1, "C", 0);
+       cmdtest(cmdline1, "l", 0);
+       cmdtest_noshrink(cmdline1, "Ishmae", 0);
+       cmdtest(cmdline1, "mael", 0);
+       /*
+        * Look for strings that do not occur, but match until
+        * close to the end of cmdline
+        */
+       cmdtest_noshrink(cmdline1, "Ishmae", 0);
+       cmdtest(cmdline1, "Ishmaels", 0);
+       cmdtest(cmdline1, "maels", 0);
+
+       /*
+        * Look for full words that do not occur in a different
+        * cmdline
+        */
+       cmdtest(cmdline2, "CALL", 0);
+       cmdtest(cmdline2, "me", 0);
+       cmdtest(cmdline2, "Ishmael", 0);
+       /*
+        * Look for full words which do occur in cmdline2
+        */
+       cmdtest(cmdline2, "Whenever", 1);
+       cmdtest(cmdline2, "growing", 24);
+       cmdtest(cmdline2, "grim", 32);
+       cmdtest(cmdline2, "mouth", 47);
+
+       /*
+        * Catch the bug where if we match a partial word and
+        * then have a space, we do not match the _next_ word.
+        */
+       cmdtest(cmdline3, "grow", 1);
+       cmdtest(cmdline3, "growing", 6);
+       return 0;
+}
+#endif /* CONFIG_X86_TEST_EARLY_CMDLINE */
_
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to