LCOV - code coverage report
Current view: top level - lib/kunit - try-catch.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 17 31 54.8 %
Date: 2023-08-24 13:40:31 Functions: 2 3 66.7 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * An API to allow a function, that may fail, to be executed, and recover in a
       4             :  * controlled manner.
       5             :  *
       6             :  * Copyright (C) 2019, Google LLC.
       7             :  * Author: Brendan Higgins <brendanhiggins@google.com>
       8             :  */
       9             : 
      10             : #include <kunit/test.h>
      11             : #include <linux/completion.h>
      12             : #include <linux/kernel.h>
      13             : #include <linux/kthread.h>
      14             : 
      15             : #include "try-catch-impl.h"
      16             : 
      17           0 : void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)
      18             : {
      19           0 :         try_catch->try_result = -EFAULT;
      20           0 :         kthread_complete_and_exit(try_catch->try_completion, -EFAULT);
      21             : }
      22             : EXPORT_SYMBOL_GPL(kunit_try_catch_throw);
      23             : 
      24         160 : static int kunit_generic_run_threadfn_adapter(void *data)
      25             : {
      26         160 :         struct kunit_try_catch *try_catch = data;
      27             : 
      28         160 :         try_catch->try(try_catch->context);
      29             : 
      30         160 :         kthread_complete_and_exit(try_catch->try_completion, 0);
      31             : }
      32             : 
      33             : static unsigned long kunit_test_timeout(void)
      34             : {
      35             :         /*
      36             :          * TODO(brendanhiggins@google.com): We should probably have some type of
      37             :          * variable timeout here. The only question is what that timeout value
      38             :          * should be.
      39             :          *
      40             :          * The intention has always been, at some point, to be able to label
      41             :          * tests with some type of size bucket (unit/small, integration/medium,
      42             :          * large/system/end-to-end, etc), where each size bucket would get a
      43             :          * default timeout value kind of like what Bazel does:
      44             :          * https://docs.bazel.build/versions/master/be/common-definitions.html#test.size
      45             :          * There is still some debate to be had on exactly how we do this. (For
      46             :          * one, we probably want to have some sort of test runner level
      47             :          * timeout.)
      48             :          *
      49             :          * For more background on this topic, see:
      50             :          * https://mike-bland.com/2011/11/01/small-medium-large.html
      51             :          *
      52             :          * If tests timeout due to exceeding sysctl_hung_task_timeout_secs,
      53             :          * the task will be killed and an oops generated.
      54             :          */
      55         160 :         return 300 * msecs_to_jiffies(MSEC_PER_SEC); /* 5 min */
      56             : }
      57             : 
      58         160 : void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
      59             : {
      60         160 :         DECLARE_COMPLETION_ONSTACK(try_completion);
      61         160 :         struct kunit *test = try_catch->test;
      62             :         struct task_struct *task_struct;
      63             :         int exit_code, time_remaining;
      64             : 
      65         160 :         try_catch->context = context;
      66         160 :         try_catch->try_completion = &try_completion;
      67         160 :         try_catch->try_result = 0;
      68         320 :         task_struct = kthread_run(kunit_generic_run_threadfn_adapter,
      69             :                                   try_catch,
      70             :                                   "kunit_try_catch_thread");
      71         160 :         if (IS_ERR(task_struct)) {
      72           0 :                 try_catch->catch(try_catch->context);
      73           0 :                 return;
      74             :         }
      75             : 
      76         160 :         time_remaining = wait_for_completion_timeout(&try_completion,
      77             :                                                      kunit_test_timeout());
      78         160 :         if (time_remaining == 0) {
      79           0 :                 kunit_err(test, "try timed out\n");
      80           0 :                 try_catch->try_result = -ETIMEDOUT;
      81           0 :                 kthread_stop(task_struct);
      82             :         }
      83             : 
      84         160 :         exit_code = try_catch->try_result;
      85             : 
      86         160 :         if (!exit_code)
      87             :                 return;
      88             : 
      89           0 :         if (exit_code == -EFAULT)
      90           0 :                 try_catch->try_result = 0;
      91           0 :         else if (exit_code == -EINTR)
      92           0 :                 kunit_err(test, "wake_up_process() was never called\n");
      93             :         else if (exit_code)
      94           0 :                 kunit_err(test, "Unknown error: %d\n", exit_code);
      95             : 
      96           0 :         try_catch->catch(try_catch->context);
      97             : }
      98             : EXPORT_SYMBOL_GPL(kunit_try_catch_run);

Generated by: LCOV version 1.14