cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

test.c (17622B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Base unit test (KUnit) API.
      4 *
      5 * Copyright (C) 2019, Google LLC.
      6 * Author: Brendan Higgins <brendanhiggins@google.com>
      7 */
      8
      9#include <kunit/resource.h>
     10#include <kunit/test.h>
     11#include <kunit/test-bug.h>
     12#include <linux/kernel.h>
     13#include <linux/moduleparam.h>
     14#include <linux/sched/debug.h>
     15#include <linux/sched.h>
     16
     17#include "debugfs.h"
     18#include "string-stream.h"
     19#include "try-catch-impl.h"
     20
     21#if IS_BUILTIN(CONFIG_KUNIT)
     22/*
     23 * Fail the current test and print an error message to the log.
     24 */
     25void __kunit_fail_current_test(const char *file, int line, const char *fmt, ...)
     26{
     27	va_list args;
     28	int len;
     29	char *buffer;
     30
     31	if (!current->kunit_test)
     32		return;
     33
     34	kunit_set_failure(current->kunit_test);
     35
     36	/* kunit_err() only accepts literals, so evaluate the args first. */
     37	va_start(args, fmt);
     38	len = vsnprintf(NULL, 0, fmt, args) + 1;
     39	va_end(args);
     40
     41	buffer = kunit_kmalloc(current->kunit_test, len, GFP_KERNEL);
     42	if (!buffer)
     43		return;
     44
     45	va_start(args, fmt);
     46	vsnprintf(buffer, len, fmt, args);
     47	va_end(args);
     48
     49	kunit_err(current->kunit_test, "%s:%d: %s", file, line, buffer);
     50	kunit_kfree(current->kunit_test, buffer);
     51}
     52EXPORT_SYMBOL_GPL(__kunit_fail_current_test);
     53#endif
     54
     55/*
     56 * KUnit statistic mode:
     57 * 0 - disabled
     58 * 1 - only when there is more than one subtest
     59 * 2 - enabled
     60 */
     61static int kunit_stats_enabled = 1;
     62module_param_named(stats_enabled, kunit_stats_enabled, int, 0644);
     63MODULE_PARM_DESC(stats_enabled,
     64		  "Print test stats: never (0), only for multiple subtests (1), or always (2)");
     65
     66struct kunit_result_stats {
     67	unsigned long passed;
     68	unsigned long skipped;
     69	unsigned long failed;
     70	unsigned long total;
     71};
     72
     73static bool kunit_should_print_stats(struct kunit_result_stats stats)
     74{
     75	if (kunit_stats_enabled == 0)
     76		return false;
     77
     78	if (kunit_stats_enabled == 2)
     79		return true;
     80
     81	return (stats.total > 1);
     82}
     83
     84static void kunit_print_test_stats(struct kunit *test,
     85				   struct kunit_result_stats stats)
     86{
     87	if (!kunit_should_print_stats(stats))
     88		return;
     89
     90	kunit_log(KERN_INFO, test,
     91		  KUNIT_SUBTEST_INDENT
     92		  "# %s: pass:%lu fail:%lu skip:%lu total:%lu",
     93		  test->name,
     94		  stats.passed,
     95		  stats.failed,
     96		  stats.skipped,
     97		  stats.total);
     98}
     99
    100/*
    101 * Append formatted message to log, size of which is limited to
    102 * KUNIT_LOG_SIZE bytes (including null terminating byte).
    103 */
    104void kunit_log_append(char *log, const char *fmt, ...)
    105{
    106	char line[KUNIT_LOG_SIZE];
    107	va_list args;
    108	int len_left;
    109
    110	if (!log)
    111		return;
    112
    113	len_left = KUNIT_LOG_SIZE - strlen(log) - 1;
    114	if (len_left <= 0)
    115		return;
    116
    117	va_start(args, fmt);
    118	vsnprintf(line, sizeof(line), fmt, args);
    119	va_end(args);
    120
    121	strncat(log, line, len_left);
    122}
    123EXPORT_SYMBOL_GPL(kunit_log_append);
    124
    125size_t kunit_suite_num_test_cases(struct kunit_suite *suite)
    126{
    127	struct kunit_case *test_case;
    128	size_t len = 0;
    129
    130	kunit_suite_for_each_test_case(suite, test_case)
    131		len++;
    132
    133	return len;
    134}
    135EXPORT_SYMBOL_GPL(kunit_suite_num_test_cases);
    136
    137static void kunit_print_suite_start(struct kunit_suite *suite)
    138{
    139	kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "# Subtest: %s",
    140		  suite->name);
    141	kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "1..%zd",
    142		  kunit_suite_num_test_cases(suite));
    143}
    144
    145static void kunit_print_ok_not_ok(void *test_or_suite,
    146				  bool is_test,
    147				  enum kunit_status status,
    148				  size_t test_number,
    149				  const char *description,
    150				  const char *directive)
    151{
    152	struct kunit_suite *suite = is_test ? NULL : test_or_suite;
    153	struct kunit *test = is_test ? test_or_suite : NULL;
    154	const char *directive_header = (status == KUNIT_SKIPPED) ? " # SKIP " : "";
    155
    156	/*
    157	 * We do not log the test suite results as doing so would
    158	 * mean debugfs display would consist of the test suite
    159	 * description and status prior to individual test results.
    160	 * Hence directly printk the suite status, and we will
    161	 * separately seq_printf() the suite status for the debugfs
    162	 * representation.
    163	 */
    164	if (suite)
    165		pr_info("%s %zd - %s%s%s\n",
    166			kunit_status_to_ok_not_ok(status),
    167			test_number, description, directive_header,
    168			(status == KUNIT_SKIPPED) ? directive : "");
    169	else
    170		kunit_log(KERN_INFO, test,
    171			  KUNIT_SUBTEST_INDENT "%s %zd - %s%s%s",
    172			  kunit_status_to_ok_not_ok(status),
    173			  test_number, description, directive_header,
    174			  (status == KUNIT_SKIPPED) ? directive : "");
    175}
    176
    177enum kunit_status kunit_suite_has_succeeded(struct kunit_suite *suite)
    178{
    179	const struct kunit_case *test_case;
    180	enum kunit_status status = KUNIT_SKIPPED;
    181
    182	if (suite->suite_init_err)
    183		return KUNIT_FAILURE;
    184
    185	kunit_suite_for_each_test_case(suite, test_case) {
    186		if (test_case->status == KUNIT_FAILURE)
    187			return KUNIT_FAILURE;
    188		else if (test_case->status == KUNIT_SUCCESS)
    189			status = KUNIT_SUCCESS;
    190	}
    191
    192	return status;
    193}
    194EXPORT_SYMBOL_GPL(kunit_suite_has_succeeded);
    195
    196static size_t kunit_suite_counter = 1;
    197
    198static void kunit_print_suite_end(struct kunit_suite *suite)
    199{
    200	kunit_print_ok_not_ok((void *)suite, false,
    201			      kunit_suite_has_succeeded(suite),
    202			      kunit_suite_counter++,
    203			      suite->name,
    204			      suite->status_comment);
    205}
    206
    207unsigned int kunit_test_case_num(struct kunit_suite *suite,
    208				 struct kunit_case *test_case)
    209{
    210	struct kunit_case *tc;
    211	unsigned int i = 1;
    212
    213	kunit_suite_for_each_test_case(suite, tc) {
    214		if (tc == test_case)
    215			return i;
    216		i++;
    217	}
    218
    219	return 0;
    220}
    221EXPORT_SYMBOL_GPL(kunit_test_case_num);
    222
    223static void kunit_print_string_stream(struct kunit *test,
    224				      struct string_stream *stream)
    225{
    226	struct string_stream_fragment *fragment;
    227	char *buf;
    228
    229	if (string_stream_is_empty(stream))
    230		return;
    231
    232	buf = string_stream_get_string(stream);
    233	if (!buf) {
    234		kunit_err(test,
    235			  "Could not allocate buffer, dumping stream:\n");
    236		list_for_each_entry(fragment, &stream->fragments, node) {
    237			kunit_err(test, "%s", fragment->fragment);
    238		}
    239		kunit_err(test, "\n");
    240	} else {
    241		kunit_err(test, "%s", buf);
    242		kunit_kfree(test, buf);
    243	}
    244}
    245
    246static void kunit_fail(struct kunit *test, const struct kunit_loc *loc,
    247		       enum kunit_assert_type type, const struct kunit_assert *assert,
    248		       const struct va_format *message)
    249{
    250	struct string_stream *stream;
    251
    252	kunit_set_failure(test);
    253
    254	stream = alloc_string_stream(test, GFP_KERNEL);
    255	if (!stream) {
    256		WARN(true,
    257		     "Could not allocate stream to print failed assertion in %s:%d\n",
    258		     loc->file,
    259		     loc->line);
    260		return;
    261	}
    262
    263	kunit_assert_prologue(loc, type, stream);
    264	assert->format(assert, message, stream);
    265
    266	kunit_print_string_stream(test, stream);
    267
    268	WARN_ON(string_stream_destroy(stream));
    269}
    270
    271static void __noreturn kunit_abort(struct kunit *test)
    272{
    273	kunit_try_catch_throw(&test->try_catch); /* Does not return. */
    274
    275	/*
    276	 * Throw could not abort from test.
    277	 *
    278	 * XXX: we should never reach this line! As kunit_try_catch_throw is
    279	 * marked __noreturn.
    280	 */
    281	WARN_ONCE(true, "Throw could not abort from test!\n");
    282}
    283
    284void kunit_do_failed_assertion(struct kunit *test,
    285			       const struct kunit_loc *loc,
    286			       enum kunit_assert_type type,
    287			       const struct kunit_assert *assert,
    288			       const char *fmt, ...)
    289{
    290	va_list args;
    291	struct va_format message;
    292	va_start(args, fmt);
    293
    294	message.fmt = fmt;
    295	message.va = &args;
    296
    297	kunit_fail(test, loc, type, assert, &message);
    298
    299	va_end(args);
    300
    301	if (type == KUNIT_ASSERTION)
    302		kunit_abort(test);
    303}
    304EXPORT_SYMBOL_GPL(kunit_do_failed_assertion);
    305
    306void kunit_init_test(struct kunit *test, const char *name, char *log)
    307{
    308	spin_lock_init(&test->lock);
    309	INIT_LIST_HEAD(&test->resources);
    310	test->name = name;
    311	test->log = log;
    312	if (test->log)
    313		test->log[0] = '\0';
    314	test->status = KUNIT_SUCCESS;
    315	test->status_comment[0] = '\0';
    316}
    317EXPORT_SYMBOL_GPL(kunit_init_test);
    318
    319/*
    320 * Initializes and runs test case. Does not clean up or do post validations.
    321 */
    322static void kunit_run_case_internal(struct kunit *test,
    323				    struct kunit_suite *suite,
    324				    struct kunit_case *test_case)
    325{
    326	if (suite->init) {
    327		int ret;
    328
    329		ret = suite->init(test);
    330		if (ret) {
    331			kunit_err(test, "failed to initialize: %d\n", ret);
    332			kunit_set_failure(test);
    333			return;
    334		}
    335	}
    336
    337	test_case->run_case(test);
    338}
    339
    340static void kunit_case_internal_cleanup(struct kunit *test)
    341{
    342	kunit_cleanup(test);
    343}
    344
    345/*
    346 * Performs post validations and cleanup after a test case was run.
    347 * XXX: Should ONLY BE CALLED AFTER kunit_run_case_internal!
    348 */
    349static void kunit_run_case_cleanup(struct kunit *test,
    350				   struct kunit_suite *suite)
    351{
    352	if (suite->exit)
    353		suite->exit(test);
    354
    355	kunit_case_internal_cleanup(test);
    356}
    357
    358struct kunit_try_catch_context {
    359	struct kunit *test;
    360	struct kunit_suite *suite;
    361	struct kunit_case *test_case;
    362};
    363
    364static void kunit_try_run_case(void *data)
    365{
    366	struct kunit_try_catch_context *ctx = data;
    367	struct kunit *test = ctx->test;
    368	struct kunit_suite *suite = ctx->suite;
    369	struct kunit_case *test_case = ctx->test_case;
    370
    371	current->kunit_test = test;
    372
    373	/*
    374	 * kunit_run_case_internal may encounter a fatal error; if it does,
    375	 * abort will be called, this thread will exit, and finally the parent
    376	 * thread will resume control and handle any necessary clean up.
    377	 */
    378	kunit_run_case_internal(test, suite, test_case);
    379	/* This line may never be reached. */
    380	kunit_run_case_cleanup(test, suite);
    381}
    382
    383static void kunit_catch_run_case(void *data)
    384{
    385	struct kunit_try_catch_context *ctx = data;
    386	struct kunit *test = ctx->test;
    387	struct kunit_suite *suite = ctx->suite;
    388	int try_exit_code = kunit_try_catch_get_result(&test->try_catch);
    389
    390	if (try_exit_code) {
    391		kunit_set_failure(test);
    392		/*
    393		 * Test case could not finish, we have no idea what state it is
    394		 * in, so don't do clean up.
    395		 */
    396		if (try_exit_code == -ETIMEDOUT) {
    397			kunit_err(test, "test case timed out\n");
    398		/*
    399		 * Unknown internal error occurred preventing test case from
    400		 * running, so there is nothing to clean up.
    401		 */
    402		} else {
    403			kunit_err(test, "internal error occurred preventing test case from running: %d\n",
    404				  try_exit_code);
    405		}
    406		return;
    407	}
    408
    409	/*
    410	 * Test case was run, but aborted. It is the test case's business as to
    411	 * whether it failed or not, we just need to clean up.
    412	 */
    413	kunit_run_case_cleanup(test, suite);
    414}
    415
    416/*
    417 * Performs all logic to run a test case. It also catches most errors that
    418 * occur in a test case and reports them as failures.
    419 */
    420static void kunit_run_case_catch_errors(struct kunit_suite *suite,
    421					struct kunit_case *test_case,
    422					struct kunit *test)
    423{
    424	struct kunit_try_catch_context context;
    425	struct kunit_try_catch *try_catch;
    426
    427	kunit_init_test(test, test_case->name, test_case->log);
    428	try_catch = &test->try_catch;
    429
    430	kunit_try_catch_init(try_catch,
    431			     test,
    432			     kunit_try_run_case,
    433			     kunit_catch_run_case);
    434	context.test = test;
    435	context.suite = suite;
    436	context.test_case = test_case;
    437	kunit_try_catch_run(try_catch, &context);
    438
    439	/* Propagate the parameter result to the test case. */
    440	if (test->status == KUNIT_FAILURE)
    441		test_case->status = KUNIT_FAILURE;
    442	else if (test_case->status != KUNIT_FAILURE && test->status == KUNIT_SUCCESS)
    443		test_case->status = KUNIT_SUCCESS;
    444}
    445
    446static void kunit_print_suite_stats(struct kunit_suite *suite,
    447				    struct kunit_result_stats suite_stats,
    448				    struct kunit_result_stats param_stats)
    449{
    450	if (kunit_should_print_stats(suite_stats)) {
    451		kunit_log(KERN_INFO, suite,
    452			  "# %s: pass:%lu fail:%lu skip:%lu total:%lu",
    453			  suite->name,
    454			  suite_stats.passed,
    455			  suite_stats.failed,
    456			  suite_stats.skipped,
    457			  suite_stats.total);
    458	}
    459
    460	if (kunit_should_print_stats(param_stats)) {
    461		kunit_log(KERN_INFO, suite,
    462			  "# Totals: pass:%lu fail:%lu skip:%lu total:%lu",
    463			  param_stats.passed,
    464			  param_stats.failed,
    465			  param_stats.skipped,
    466			  param_stats.total);
    467	}
    468}
    469
    470static void kunit_update_stats(struct kunit_result_stats *stats,
    471			       enum kunit_status status)
    472{
    473	switch (status) {
    474	case KUNIT_SUCCESS:
    475		stats->passed++;
    476		break;
    477	case KUNIT_SKIPPED:
    478		stats->skipped++;
    479		break;
    480	case KUNIT_FAILURE:
    481		stats->failed++;
    482		break;
    483	}
    484
    485	stats->total++;
    486}
    487
    488static void kunit_accumulate_stats(struct kunit_result_stats *total,
    489				   struct kunit_result_stats add)
    490{
    491	total->passed += add.passed;
    492	total->skipped += add.skipped;
    493	total->failed += add.failed;
    494	total->total += add.total;
    495}
    496
    497int kunit_run_tests(struct kunit_suite *suite)
    498{
    499	char param_desc[KUNIT_PARAM_DESC_SIZE];
    500	struct kunit_case *test_case;
    501	struct kunit_result_stats suite_stats = { 0 };
    502	struct kunit_result_stats total_stats = { 0 };
    503
    504	if (suite->suite_init) {
    505		suite->suite_init_err = suite->suite_init(suite);
    506		if (suite->suite_init_err) {
    507			kunit_err(suite, KUNIT_SUBTEST_INDENT
    508				  "# failed to initialize (%d)", suite->suite_init_err);
    509			goto suite_end;
    510		}
    511	}
    512
    513	kunit_print_suite_start(suite);
    514
    515	kunit_suite_for_each_test_case(suite, test_case) {
    516		struct kunit test = { .param_value = NULL, .param_index = 0 };
    517		struct kunit_result_stats param_stats = { 0 };
    518		test_case->status = KUNIT_SKIPPED;
    519
    520		if (!test_case->generate_params) {
    521			/* Non-parameterised test. */
    522			kunit_run_case_catch_errors(suite, test_case, &test);
    523			kunit_update_stats(&param_stats, test.status);
    524		} else {
    525			/* Get initial param. */
    526			param_desc[0] = '\0';
    527			test.param_value = test_case->generate_params(NULL, param_desc);
    528			kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT
    529				  "# Subtest: %s", test_case->name);
    530
    531			while (test.param_value) {
    532				kunit_run_case_catch_errors(suite, test_case, &test);
    533
    534				if (param_desc[0] == '\0') {
    535					snprintf(param_desc, sizeof(param_desc),
    536						 "param-%d", test.param_index);
    537				}
    538
    539				kunit_log(KERN_INFO, &test,
    540					  KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT
    541					  "%s %d - %s",
    542					  kunit_status_to_ok_not_ok(test.status),
    543					  test.param_index + 1, param_desc);
    544
    545				/* Get next param. */
    546				param_desc[0] = '\0';
    547				test.param_value = test_case->generate_params(test.param_value, param_desc);
    548				test.param_index++;
    549
    550				kunit_update_stats(&param_stats, test.status);
    551			}
    552		}
    553
    554
    555		kunit_print_test_stats(&test, param_stats);
    556
    557		kunit_print_ok_not_ok(&test, true, test_case->status,
    558				      kunit_test_case_num(suite, test_case),
    559				      test_case->name,
    560				      test.status_comment);
    561
    562		kunit_update_stats(&suite_stats, test_case->status);
    563		kunit_accumulate_stats(&total_stats, param_stats);
    564	}
    565
    566	if (suite->suite_exit)
    567		suite->suite_exit(suite);
    568
    569	kunit_print_suite_stats(suite, suite_stats, total_stats);
    570suite_end:
    571	kunit_print_suite_end(suite);
    572
    573	return 0;
    574}
    575EXPORT_SYMBOL_GPL(kunit_run_tests);
    576
    577static void kunit_init_suite(struct kunit_suite *suite)
    578{
    579	kunit_debugfs_create_suite(suite);
    580	suite->status_comment[0] = '\0';
    581	suite->suite_init_err = 0;
    582}
    583
    584int __kunit_test_suites_init(struct kunit_suite * const * const suites)
    585{
    586	unsigned int i;
    587
    588	for (i = 0; suites[i] != NULL; i++) {
    589		kunit_init_suite(suites[i]);
    590		kunit_run_tests(suites[i]);
    591	}
    592	return 0;
    593}
    594EXPORT_SYMBOL_GPL(__kunit_test_suites_init);
    595
    596static void kunit_exit_suite(struct kunit_suite *suite)
    597{
    598	kunit_debugfs_destroy_suite(suite);
    599}
    600
    601void __kunit_test_suites_exit(struct kunit_suite **suites)
    602{
    603	unsigned int i;
    604
    605	for (i = 0; suites[i] != NULL; i++)
    606		kunit_exit_suite(suites[i]);
    607
    608	kunit_suite_counter = 1;
    609}
    610EXPORT_SYMBOL_GPL(__kunit_test_suites_exit);
    611
    612struct kunit_kmalloc_array_params {
    613	size_t n;
    614	size_t size;
    615	gfp_t gfp;
    616};
    617
    618static int kunit_kmalloc_array_init(struct kunit_resource *res, void *context)
    619{
    620	struct kunit_kmalloc_array_params *params = context;
    621
    622	res->data = kmalloc_array(params->n, params->size, params->gfp);
    623	if (!res->data)
    624		return -ENOMEM;
    625
    626	return 0;
    627}
    628
    629static void kunit_kmalloc_array_free(struct kunit_resource *res)
    630{
    631	kfree(res->data);
    632}
    633
    634void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp)
    635{
    636	struct kunit_kmalloc_array_params params = {
    637		.size = size,
    638		.n = n,
    639		.gfp = gfp
    640	};
    641
    642	return kunit_alloc_resource(test,
    643				    kunit_kmalloc_array_init,
    644				    kunit_kmalloc_array_free,
    645				    gfp,
    646				    &params);
    647}
    648EXPORT_SYMBOL_GPL(kunit_kmalloc_array);
    649
    650void kunit_kfree(struct kunit *test, const void *ptr)
    651{
    652	struct kunit_resource *res;
    653
    654	res = kunit_find_resource(test, kunit_resource_instance_match,
    655				  (void *)ptr);
    656
    657	/*
    658	 * Removing the resource from the list of resources drops the
    659	 * reference count to 1; the final put will trigger the free.
    660	 */
    661	kunit_remove_resource(test, res);
    662
    663	kunit_put_resource(res);
    664
    665}
    666EXPORT_SYMBOL_GPL(kunit_kfree);
    667
    668void kunit_cleanup(struct kunit *test)
    669{
    670	struct kunit_resource *res;
    671	unsigned long flags;
    672
    673	/*
    674	 * test->resources is a stack - each allocation must be freed in the
    675	 * reverse order from which it was added since one resource may depend
    676	 * on another for its entire lifetime.
    677	 * Also, we cannot use the normal list_for_each constructs, even the
    678	 * safe ones because *arbitrary* nodes may be deleted when
    679	 * kunit_resource_free is called; the list_for_each_safe variants only
    680	 * protect against the current node being deleted, not the next.
    681	 */
    682	while (true) {
    683		spin_lock_irqsave(&test->lock, flags);
    684		if (list_empty(&test->resources)) {
    685			spin_unlock_irqrestore(&test->lock, flags);
    686			break;
    687		}
    688		res = list_last_entry(&test->resources,
    689				      struct kunit_resource,
    690				      node);
    691		/*
    692		 * Need to unlock here as a resource may remove another
    693		 * resource, and this can't happen if the test->lock
    694		 * is held.
    695		 */
    696		spin_unlock_irqrestore(&test->lock, flags);
    697		kunit_remove_resource(test, res);
    698	}
    699	current->kunit_test = NULL;
    700}
    701EXPORT_SYMBOL_GPL(kunit_cleanup);
    702
    703static int __init kunit_init(void)
    704{
    705	kunit_debugfs_init();
    706
    707	return 0;
    708}
    709late_initcall(kunit_init);
    710
    711static void __exit kunit_exit(void)
    712{
    713	kunit_debugfs_cleanup();
    714}
    715module_exit(kunit_exit);
    716
    717MODULE_LICENSE("GPL v2");