1. 14 12月, 2021 7 次提交
  2. 20 10月, 2021 5 次提交
    • R
      kunit: tool: improve compatibility of kunit_parser with KTAP specification · d65d07cb
      Rae Moar 提交于
      Update to kunit_parser to improve compatibility with KTAP
      specification including arbitrarily nested tests. Patch accomplishes
      three major changes:
      
      - Use a general Test object to represent all tests rather than TestCase
      and TestSuite objects. This allows for easier implementation of arbitrary
      levels of nested tests and promotes the idea that both test suites and test
      cases are tests.
      
      - Print errors incrementally rather than all at once after the
      parsing finishes to maximize information given to the user in the
      case of the parser given invalid input and to increase the helpfulness
      of the timestamps given during printing. Note that kunit.py parse does
      not print incrementally yet. However, this fix brings us closer to
      this feature.
      
      - Increase compatibility for different formats of input. Arbitrary levels
      of nested tests supported. Also, test cases and test suites are now
      supported to be present on the same level of testing.
      
      This patch now implements the draft KTAP specification here:
      https://lore.kernel.org/linux-kselftest/CA+GJov6tdjvY9x12JsJT14qn6c7NViJxqaJk+r-K1YJzPggFDQ@mail.gmail.com/
      We'll update the parser as the spec evolves.
      
      This patch adjusts the kunit_tool_test.py file to check for
      the correct outputs from the new parser and adds a new test to check
      the parsing for a KTAP result log with correct format for multiple nested
      subtests (test_is_test_passed-all_passed_nested.log).
      
      This patch also alters the kunit_json.py file to allow for arbitrarily
      nested tests.
      Signed-off-by: NRae Moar <rmoar@google.com>
      Reviewed-by: NBrendan Higgins <brendanhiggins@google.com>
      Signed-off-by: NDaniel Latypov <dlatypov@google.com>
      Reviewed-by: NDavid Gow <davidgow@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      d65d07cb
    • D
      kunit: tool: yield output from run_kernel in real time · 7d7c48df
      Daniel Latypov 提交于
      Currently, `run_kernel()` dumps all the kernel output to a file
      (.kunit/test.log) and then opens the file and yields it to callers.
      This made it easier to respect the requested timeout, if any.
      
      But it means that we can't yield the results in real time, either to the
      parser or to stdout (if --raw_output is set).
      
      This change spins up a background thread to enforce the timeout, which
      allows us to yield the kernel output in real time, while also copying it
      to the .kunit/test.log file.
      It's also careful to ensure that the .kunit/test.log file is complete,
      even in the kunit_parser throws an exception/otherwise doesn't consume
      every line, see the new `finally` block and unit test.
      
      For example:
      
      $ ./tools/testing/kunit/kunit.py run --arch=x86_64 --raw_output
      <configure + build steps>
      ...
      <can now see output from QEMU in real time>
      
      This does not currently have a visible effect when --raw_output is not
      passed, as kunit_parser.py currently only outputs everything at the end.
      But that could change, and this patch is a necessary step towards
      showing parsed test results in real time.
      Signed-off-by: NDaniel Latypov <dlatypov@google.com>
      Reviewed-by: NDavid Gow <davidgow@google.com>
      Reviewed-by: NBrendan Higgins <brendanhiggins@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      7d7c48df
    • D
      kunit: tool: support running each suite/test separately · ff9e09a3
      Daniel Latypov 提交于
      The new --run_isolated flag makes the tool boot the kernel once per
      suite or test, preventing leftover state from one suite to impact the
      other. This can be useful as a starting point to debugging test
      hermeticity issues.
      
      Note: it takes a lot longer, so people should not use it normally.
      
      Consider the following very simplified example:
      
        bool disable_something_for_test = false;
        void function_being_tested() {
          ...
          if (disable_something_for_test) return;
          ...
        }
      
        static void test_before(struct kunit *test)
        {
          disable_something_for_test = true;
          function_being_tested();
          /* oops, we forgot to reset it back to false */
        }
      
        static void test_after(struct kunit *test)
        {
          /* oops, now "fixing" test_before can cause test_after to fail! */
          function_being_tested();
        }
      
      Presented like this, the issues are obvious, but it gets a lot more
      complicated to track down as the amount of test setup and helper
      functions increases.
      
      Another use case is memory corruption. It might not be surfaced as a
      failure/crash in the test case or suite that caused it. I've noticed in
      kunit's own unit tests, the 3rd suite after might be the one to finally
      crash after an out-of-bounds write, for example.
      
      Example usage:
      
      Per suite:
      $ ./tools/testing/kunit/kunit.py run --kunitconfig=lib/kunit --run_isolated=suite
      ...
      Starting KUnit Kernel (1/7)...
      ============================================================
      ======== [PASSED] kunit_executor_test ========
      ....
      Testing complete. 5 tests run. 0 failed. 0 crashed. 0 skipped.
      Starting KUnit Kernel (2/7)...
      ============================================================
      ======== [PASSED] kunit-try-catch-test ========
      ...
      
      Per test:
      $ ./tools/testing/kunit/kunit.py run --kunitconfig=lib/kunit --run_isolated=test
      Starting KUnit Kernel (1/23)...
      ============================================================
      ======== [PASSED] kunit_executor_test ========
      [PASSED] parse_filter_test
      ============================================================
      Testing complete. 1 tests run. 0 failed. 0 crashed. 0 skipped.
      Starting KUnit Kernel (2/23)...
      ============================================================
      ======== [PASSED] kunit_executor_test ========
      [PASSED] filter_subsuite_test
      ...
      
      It works with filters as well:
      $ ./tools/testing/kunit/kunit.py run --kunitconfig=lib/kunit --run_isolated=suite example
      ...
      Starting KUnit Kernel (1/1)...
      ============================================================
      ======== [PASSED] example ========
      ...
      
      It also handles test filters, '*.*skip*' runs these 3 tests:
        kunit_status.kunit_status_mark_skipped_test
        example.example_skip_test
        example.example_mark_skipped_test
      
      Fixed up merge conflict between:
        d8c23ead ("kunit: tool: better handling of quasi-bool args (--json, --raw_output)") and
        6710951ee039 ("kunit: tool: support running each suite/test separately")
      Reported-by: NStephen Rothwell <sfr@canb.auug.org.au>
          Shuah Khan <skhan@linuxfoundation.org>
      Signed-off-by: NDaniel Latypov <dlatypov@google.com>
      Reviewed-by: NDavid Gow <davidgow@google.com>
      Reviewed-by: NBrendan Higgins <brendanhiggins@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      ff9e09a3
    • D
      kunit: tool: show list of valid --arch options when invalid · fe678fed
      Daniel Latypov 提交于
      Consider this attempt to run KUnit in QEMU:
      $ ./tools/testing/kunit/kunit.py run --arch=x86
      
      Before you'd get this error message:
      kunit_kernel.ConfigError: x86 is not a valid arch
      
      After:
      kunit_kernel.ConfigError: x86 is not a valid arch, options are ['alpha', 'arm', 'arm64', 'i386', 'powerpc', 'riscv', 's390', 'sparc', 'x86_64']
      
      This should make it a bit easier for people to notice when they make
      typos, etc. Currently, one would have to dive into the python code to
      figure out what the valid set is.
      Signed-off-by: NDaniel Latypov <dlatypov@google.com>
      Reviewed-by: NDavid Gow <davidgow@google.com>
      Reviewed-by: NBrendan Higgins <brendanhiggins@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      fe678fed
    • D
      kunit: tool: misc fixes (unused vars, imports, leaked files) · a54ea2e0
      Daniel Latypov 提交于
      Drop some variables in unit tests that were unused and/or add assertions
      based on them.
      
      For ExitStack, it was imported, but the `es` variable wasn't used so it
      didn't do anything, and we were leaking the file objects.
      Refactor it to just use nested `with` statements to properly close them.
      
      And drop the direct use of .close() on file objects in the kunit tool
      unit test, as these can be leaked if test assertions fail.
      Signed-off-by: NDaniel Latypov <dlatypov@google.com>
      Reviewed-by: NDavid Gow <davidgow@google.com>
      Reviewed-by: NBrendan Higgins <brendanhiggins@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      a54ea2e0
  3. 02 10月, 2021 1 次提交
    • D
      kunit: tool: better handling of quasi-bool args (--json, --raw_output) · d8c23ead
      Daniel Latypov 提交于
      Problem:
      
      What does this do?
      $ kunit.py run --json
      Well, it runs all the tests and prints test results out as JSON.
      
      And next is
      $ kunit.py run my-test-suite --json
      This runs just `my-test-suite` and prints results out as JSON.
      
      But what about?
      $ kunit.py run --json my-test-suite
      This runs all the tests and stores the json results in a "my-test-suite"
      file.
      
      Why:
      --json, and now --raw_output are actually string flags. They just have a
      default value. --json in particular takes the name of an output file.
      
      It was intended that you'd do
      $ kunit.py run --json=my_output_file my-test-suite
      if you ever wanted to specify the value.
      
      Workaround:
      It doesn't seem like there's a way to make
      https://docs.python.org/3/library/argparse.html only accept arg values
      after a '='.
      
      I believe that `--json` should "just work" regardless of where it is.
      So this patch automatically rewrites a bare `--json` to `--json=stdout`.
      
      That makes the examples above work the same way.
      Add a regression test that can catch this for --raw_output.
      
      Fixes: 6a499c9c ("kunit: tool: make --raw_output support only showing kunit output")
      Signed-off-by: NDaniel Latypov <dlatypov@google.com>
      Tested-by: NDavid Gow <davidgow@google.com>
      Reviewed-by: NBrendan Higgins <brendanhiggins@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      d8c23ead
  4. 14 8月, 2021 2 次提交
    • D
      kunit: tool: make --raw_output support only showing kunit output · 6a499c9c
      Daniel Latypov 提交于
      --raw_output is nice, but it would be nicer if could show only output
      after KUnit tests have started.
      
      So change the flag to allow specifying a string ('kunit').
      Make it so `--raw_output` alone will default to `--raw_output=all` and
      have the same original behavior.
      
      Drop the small kunit_parser.raw_output() function since it feels wrong
      to put it in "kunit_parser.py" when the point of it is to not parse
      anything.
      
      E.g.
      
      $ ./tools/testing/kunit/kunit.py run --raw_output=kunit
      ...
      [15:24:07] Starting KUnit Kernel ...
      TAP version 14
      1..1
          # Subtest: example
          1..3
          # example_simple_test: initializing
          ok 1 - example_simple_test
          # example_skip_test: initializing
          # example_skip_test: You should not see a line below.
          ok 2 - example_skip_test # SKIP this test should be skipped
          # example_mark_skipped_test: initializing
          # example_mark_skipped_test: You should see a line below.
          # example_mark_skipped_test: You should see this line.
          ok 3 - example_mark_skipped_test # SKIP this test should be skipped
      ok 1 - example
      [15:24:10] Elapsed time: 6.487s total, 0.001s configuring, 3.510s building, 0.000s running
      Signed-off-by: NDaniel Latypov <dlatypov@google.com>
      Reviewed-by: NDavid Gow <davidgow@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      6a499c9c
    • D
      kunit: tool: add --kernel_args to allow setting module params · 6cb51a18
      Daniel Latypov 提交于
      kunit.py currently does not make it possible for users to specify module
      parameters (/kernel arguments more generally) unless one directly tweaks
      the kunit.py code itself.
      
      This hasn't mattered much so far, but this would make it easier to port
      existing tests that expose module parameters over to KUnit and/or let
      current KUnit tests take advantage of them.
      
      Tested using an kunit internal parameter:
      $ ./tools/testing/kunit/kunit.py run --kunitconfig=lib/kunit \
          --kernel_args=kunit.filter_glob=kunit_status
      ...
      Testing complete. 2 tests run. 0 failed. 0 crashed. 0 skipped.
      Signed-off-by: NDaniel Latypov <dlatypov@google.com>
      Reviewed-by: NDavid Gow <davidgow@google.com>
      Reviewed-by: NBrendan Higgins <brendanhiggins@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      6cb51a18
  5. 13 7月, 2021 1 次提交
    • R
      kunit: tool: Fix error messages for cases of no tests and wrong TAP header · ed01ad3a
      Rae Moar 提交于
      This patch addresses misleading error messages reported by kunit_tool in
      two cases. First, in the case of TAP output having an incorrect header
      format or missing a header, the parser used to output an error message of
      'no tests run!'. Now the parser outputs an error message of 'could not
      parse test results!'.
      
      As an example:
      
      Before:
      $ ./tools/testing/kunit/kunit.py parse /dev/null
      [ERROR] no tests run!
      ...
      
      After:
      $ ./tools/testing/kunit/kunit.py parse /dev/null
      [ERROR] could not parse test results!
      ...
      
      Second, in the case of TAP output with the correct header but no
      tests, the parser used to output an error message of 'could not parse
      test results!'. Now the parser outputs an error message of 'no tests
      run!'.
      
      As an example:
      
      Before:
      $ echo -e 'TAP version 14\n1..0' | ./tools/testing/kunit/kunit.py parse
      [ERROR] could not parse test results!
      
      After:
      $ echo -e 'TAP version 14\n1..0' | ./tools/testing/kunit/kunit.py parse
      [ERROR] no tests run!
      
      Additionally, this patch also corrects the tests in kunit_tool_test.py
      and adds a test to check the error in the case of TAP output with the
      correct header but no tests.
      Signed-off-by: NRae Moar <rmoar@google.com>
      Reviewed-by: NDavid Gow <davidgow@google.com>
      Reviewed-by: NDaniel Latypov <dlatypov@google.com>
      Reviewed-by: NBrendan Higgins <brendanhiggins@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      ed01ad3a
  6. 26 6月, 2021 2 次提交
    • D
      kunit: tool: Support skipped tests in kunit_tool · 5acaf603
      David Gow 提交于
      Add support for the SKIP directive to kunit_tool's TAP parser.
      
      Skipped tests now show up as such in the printed summary. The number of
      skipped tests is counted, and if all tests in a suite are skipped, the
      suite is also marked as skipped. Otherwise, skipped tests do affect the
      suite result.
      
      Example output:
      [00:22:34] ======== [SKIPPED] example_skip ========
      [00:22:34] [SKIPPED] example_skip_test # SKIP this test should be skipped
      [00:22:34] [SKIPPED] example_mark_skipped_test # SKIP this test should be skipped
      [00:22:34] ============================================================
      [00:22:34] Testing complete. 2 tests run. 0 failed. 0 crashed. 2 skipped.
      Signed-off-by: NDavid Gow <davidgow@google.com>
      Reviewed-by: NDaniel Latypov <dlatypov@google.com>
      Reviewed-by: NBrendan Higgins <brendanhiggins@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      5acaf603
    • D
      kunit: tool: internal refactor of parser input handling · b29b14f1
      Daniel Latypov 提交于
      Note: this does not change the parser behavior at all (except for making
      one error message more useful). This is just an internal refactor.
      
      The TAP output parser currently operates over a List[str].
      This works, but we only ever need to be able to "peek" at the current
      line and the ability to "pop" it off.
      
      Also, using a List means we need to wait for all the output before we
      can start parsing. While this is not an issue for most tests which are
      really lightweight, we do have some longer (~5 minutes) tests.
      
      This patch introduces an LineStream wrapper class that
      * Exposes a peek()/pop() interface instead of manipulating an array
        * this allows us to more easily add debugging code [1]
      * Can consume an input from a generator
        * we can now parse results as tests are running (the parser code
        currently doesn't print until the end, so no impact yet).
      * Tracks the current line number to print better error messages
      * Would allow us to add additional features more easily, e.g. storing
        N previous lines so we can print out invalid lines in context, etc.
      
      [1] The parsing logic is currently quite fragile.
      E.g. it'll often say the kernel "CRASHED" if there's something slightly
      wrong with the output format. When debugging a test that had some memory
      corruption issues, it resulted in very misleading errors from the parser.
      
      Now we could easily add this to trace all the lines consumed and why
      +import inspect
      ...
              def pop(self) -> str:
                      n = self._next
      +               print(f'popping {n[0]}: {n[1].ljust(40, " ")}| caller={inspect.stack()[1].function}')
      
      Example output:
      popping 77: TAP version 14                          | caller=parse_tap_header
      popping 78: 1..1                                    | caller=parse_test_plan
      popping 79:     # Subtest: kunit_executor_test      | caller=parse_subtest_header
      popping 80:     1..2                                | caller=parse_subtest_plan
      popping 81:     ok 1 - parse_filter_test            | caller=parse_ok_not_ok_test_case
      popping 82:     ok 2 - filter_subsuite_test         | caller=parse_ok_not_ok_test_case
      popping 83: ok 1 - kunit_executor_test              | caller=parse_ok_not_ok_test_suite
      
      If we introduce an invalid line, we can see the parser go down the wrong path:
      popping 77: TAP version 14                          | caller=parse_tap_header
      popping 78: 1..1                                    | caller=parse_test_plan
      popping 79:     # Subtest: kunit_executor_test      | caller=parse_subtest_header
      popping 80:     1..2                                | caller=parse_subtest_plan
      popping 81:     1..2 # this is invalid!             | caller=parse_ok_not_ok_test_case
      popping 82:     ok 1 - parse_filter_test            | caller=parse_ok_not_ok_test_case
      popping 83:     ok 2 - filter_subsuite_test         | caller=parse_ok_not_ok_test_case
      popping 84: ok 1 - kunit_executor_test              | caller=parse_ok_not_ok_test_case
      [ERROR] ran out of lines before end token
      Signed-off-by: NDaniel Latypov <dlatypov@google.com>
      Reviewed-by: NDavid Gow <davidgow@google.com>
      Acked-by: NBrendan Higgins <brendanhiggins@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      b29b14f1
  7. 12 6月, 2021 1 次提交
  8. 03 4月, 2021 1 次提交
  9. 09 2月, 2021 6 次提交
  10. 08 12月, 2020 1 次提交
  11. 11 11月, 2020 1 次提交
    • D
      kunit: tool: fix extra trailing \n in raw + parsed test output · 060352e1
      Daniel Latypov 提交于
      For simplcity, strip all trailing whitespace from parsed output.
      I imagine no one is printing out meaningful trailing whitespace via
      KUNIT_FAIL() or similar, and that if they are, they really shouldn't.
      
      `isolate_kunit_output()` yielded liens with trailing \n, which results
      in artifacty output like this:
      
      $ ./tools/testing/kunit/kunit.py run
      [16:16:46] [FAILED] example_simple_test
      [16:16:46]     # example_simple_test: EXPECTATION FAILED at lib/kunit/kunit-example-test.c:29
      
      [16:16:46]     Expected 1 + 1 == 3, but
      
      [16:16:46]         1 + 1 == 2
      
      [16:16:46]         3 == 3
      
      [16:16:46]     not ok 1 - example_simple_test
      
      [16:16:46]
      
      After this change:
      [16:16:46]     # example_simple_test: EXPECTATION FAILED at lib/kunit/kunit-example-test.c:29
      [16:16:46]     Expected 1 + 1 == 3, but
      [16:16:46]         1 + 1 == 2
      [16:16:46]         3 == 3
      [16:16:46]     not ok 1 - example_simple_test
      [16:16:46]
      
      We should *not* be expecting lines to end with \n in kunit_tool_test.py
      for this reason.
      
      Do the same for `raw_output()` as well which suffers from the same
      issue.
      
      This is a followup to [1], but rebased onto kunit-fixes to pick up the
      other raw_output() fix and fixes for kunit_tool_test.py.
      
      [1] https://lore.kernel.org/linux-kselftest/20201020233219.4146059-1-dlatypov@google.com/Signed-off-by: NDaniel Latypov <dlatypov@google.com>
      Reviewed-by: NDavid Gow <davidgow@google.com>
      Tested-by: NDavid Gow <davidgow@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      060352e1
  12. 27 10月, 2020 1 次提交
  13. 01 9月, 2020 1 次提交
  14. 18 7月, 2020 2 次提交
  15. 27 6月, 2020 1 次提交
  16. 12 5月, 2020 1 次提交
  17. 26 3月, 2020 1 次提交
    • D
      kunit: kunit_tool: Allow .kunitconfig to disable config items · 97752c39
      David Gow 提交于
      Rework kunit_tool in order to allow .kunitconfig files to better enforce
      that disabled items in .kunitconfig are disabled in the generated
      .config.
      
      Previously, kunit_tool simply enforced that any line present in
      .kunitconfig was also present in .config, but this could cause problems
      if a config option was disabled in .kunitconfig, but not listed in .config
      due to (for example) having disabled dependencies.
      
      To fix this, re-work the parser to track config names and values, and
      require values to match unless they are explicitly disabled with the
      "CONFIG_x is not set" comment (or by setting its value to 'n'). Those
      "disabled" values will pass validation if omitted from the .config, but
      not if they have a different value.
      Signed-off-by: NDavid Gow <davidgow@google.com>
      Reviewed-by: NBrendan Higgins <brendanhiggins@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      97752c39
  18. 21 3月, 2020 2 次提交
    • H
      kunit: Run all KUnit tests through allyesconfig · 021ed9f5
      Heidi Fahim 提交于
      Implemented the functionality to run all KUnit tests through kunit_tool
      by specifying an --alltests flag, which builds UML with allyesconfig
      enabled, and consequently runs every KUnit test. A new function was
      added to kunit_kernel: make_allyesconfig.
      Firstly, if --alltests is specified, kunit.py triggers build_um_kernel
      which call make_allyesconfig. This function calls the make command,
      disables the broken configs that would otherwise prevent UML from
      building, then starts the kernel with all possible configurations
      enabled. All stdout and stderr is sent to test.log and read from there
      then fed through kunit_parser to parse the tests to the user. Also added
      a signal_handler in case kunit is interrupted while running.
      Tested: Run under different conditions such as testing with
      --raw_output, testing program interrupt then immediately running kunit
      again without --alltests and making sure to clean the console.
      Signed-off-by: NHeidi Fahim <heidifahim@google.com>
      Reviewed-by: NBrendan Higgins <brendanhiggins@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      021ed9f5
    • H
      kunit: kunit_parser: make parser more robust · afc63da6
      Heidi Fahim 提交于
      Previously, kunit_parser did not properly handle kunit TAP output that
      - had any prefixes (generated from different configs e.g.
      CONFIG_PRINTK_TIME)
      - had unrelated kernel output mixed in the middle of
      it, which has shown up when testing with allyesconfig
      To remove prefixes, the parser looks for the first line that includes
      TAP output, "TAP version 14".  It then determines the length of the
      string before this sequence, and strips that number of characters off
      the beginning of the following lines until the last KUnit output line is
      reached.
      These fixes have been tested with additional tests in the
      KUnitParseTest and their associated logs have also been added.
      Signed-off-by: NHeidi Fahim <heidifahim@google.com>
      Reviewed-by: NBrendan Higgins <brendanhiggins@google.com>
      Signed-off-by: NShuah Khan <skhan@linuxfoundation.org>
      afc63da6
  19. 24 12月, 2019 2 次提交
  20. 10 12月, 2019 1 次提交