162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * An API to allow a function, that may fail, to be executed, and recover in a
462306a36Sopenharmony_ci * controlled manner.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 2019, Google LLC.
762306a36Sopenharmony_ci * Author: Brendan Higgins <brendanhiggins@google.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifndef _KUNIT_TRY_CATCH_H
1162306a36Sopenharmony_ci#define _KUNIT_TRY_CATCH_H
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/types.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_citypedef void (*kunit_try_catch_func_t)(void *);
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistruct completion;
1862306a36Sopenharmony_cistruct kunit;
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/**
2162306a36Sopenharmony_ci * struct kunit_try_catch - provides a generic way to run code which might fail.
2262306a36Sopenharmony_ci * @test: The test case that is currently being executed.
2362306a36Sopenharmony_ci * @try_completion: Completion that the control thread waits on while test runs.
2462306a36Sopenharmony_ci * @try_result: Contains any errno obtained while running test case.
2562306a36Sopenharmony_ci * @try: The function, the test case, to attempt to run.
2662306a36Sopenharmony_ci * @catch: The function called if @try bails out.
2762306a36Sopenharmony_ci * @context: used to pass user data to the try and catch functions.
2862306a36Sopenharmony_ci *
2962306a36Sopenharmony_ci * kunit_try_catch provides a generic, architecture independent way to execute
3062306a36Sopenharmony_ci * an arbitrary function of type kunit_try_catch_func_t which may bail out by
3162306a36Sopenharmony_ci * calling kunit_try_catch_throw(). If kunit_try_catch_throw() is called, @try
3262306a36Sopenharmony_ci * is stopped at the site of invocation and @catch is called.
3362306a36Sopenharmony_ci *
3462306a36Sopenharmony_ci * struct kunit_try_catch provides a generic interface for the functionality
3562306a36Sopenharmony_ci * needed to implement kunit->abort() which in turn is needed for implementing
3662306a36Sopenharmony_ci * assertions. Assertions allow stating a precondition for a test simplifying
3762306a36Sopenharmony_ci * how test cases are written and presented.
3862306a36Sopenharmony_ci *
3962306a36Sopenharmony_ci * Assertions are like expectations, except they abort (call
4062306a36Sopenharmony_ci * kunit_try_catch_throw()) when the specified condition is not met. This is
4162306a36Sopenharmony_ci * useful when you look at a test case as a logical statement about some piece
4262306a36Sopenharmony_ci * of code, where assertions are the premises for the test case, and the
4362306a36Sopenharmony_ci * conclusion is a set of predicates, rather expectations, that must all be
4462306a36Sopenharmony_ci * true. If your premises are violated, it does not makes sense to continue.
4562306a36Sopenharmony_ci */
4662306a36Sopenharmony_cistruct kunit_try_catch {
4762306a36Sopenharmony_ci	/* private: internal use only. */
4862306a36Sopenharmony_ci	struct kunit *test;
4962306a36Sopenharmony_ci	struct completion *try_completion;
5062306a36Sopenharmony_ci	int try_result;
5162306a36Sopenharmony_ci	kunit_try_catch_func_t try;
5262306a36Sopenharmony_ci	kunit_try_catch_func_t catch;
5362306a36Sopenharmony_ci	void *context;
5462306a36Sopenharmony_ci};
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_civoid kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context);
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_civoid __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistatic inline int kunit_try_catch_get_result(struct kunit_try_catch *try_catch)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	return try_catch->try_result;
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#endif /* _KUNIT_TRY_CATCH_H */
66