All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jakub Kicinski <kuba@kernel.org>
To: shuah@kernel.org, keescook@chromium.org
Cc: luto@amacapital.net, wad@chromium.org,
	linux-kselftest@vger.kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, kernel-team@fb.com,
	Jakub Kicinski <kuba@kernel.org>
Subject: [PATCH v2 3/4] kselftest: add fixture parameters
Date: Fri, 13 Mar 2020 17:55:00 -0700	[thread overview]
Message-ID: <20200314005501.2446494-4-kuba@kernel.org> (raw)
In-Reply-To: <20200314005501.2446494-1-kuba@kernel.org>

Allow users to pass parameters to fixtures.

Each test will be run once for each set of
its fixture parameter sets (or once if none).

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
--
v2:
 - don't pass params to functions, use a member
   of _metadata instead
---
 Documentation/dev-tools/kselftest.rst       |   3 +-
 tools/testing/selftests/kselftest_harness.h | 133 ++++++++++++++++++--
 2 files changed, 126 insertions(+), 10 deletions(-)

diff --git a/Documentation/dev-tools/kselftest.rst b/Documentation/dev-tools/kselftest.rst
index 61ae13c44f91..8aff58d11937 100644
--- a/Documentation/dev-tools/kselftest.rst
+++ b/Documentation/dev-tools/kselftest.rst
@@ -301,7 +301,8 @@ Helpers
 
 .. kernel-doc:: tools/testing/selftests/kselftest_harness.h
     :functions: TH_LOG TEST TEST_SIGNAL FIXTURE FIXTURE_DATA FIXTURE_SETUP
-                FIXTURE_TEARDOWN TEST_F TEST_HARNESS_MAIN
+                FIXTURE_TEARDOWN TEST_F TEST_HARNESS_MAIN FIXTURE_PARAMS
+                FIXTURE_PARAMS_ADD CURRENT_PARAMS
 
 Operators
 ---------
diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h
index 66c2397d8c51..b7e1ecda441c 100644
--- a/tools/testing/selftests/kselftest_harness.h
+++ b/tools/testing/selftests/kselftest_harness.h
@@ -214,6 +214,7 @@
  * populated and cleaned up using FIXTURE_SETUP() and FIXTURE_TEARDOWN().
  */
 #define FIXTURE(fixture_name) \
+	FIXTURE_PARAMS(fixture_name); \
 	static struct __fixture_metadata _##fixture_name##_fixture_object = \
 		{ .name =  #fixture_name, }; \
 	static void __attribute__((constructor)) \
@@ -246,6 +247,7 @@
 	void fixture_name##_setup( \
 		struct __test_metadata __attribute__((unused)) *_metadata, \
 		FIXTURE_DATA(fixture_name) __attribute__((unused)) *self)
+
 /**
  * FIXTURE_TEARDOWN(fixture_name)
  * *_metadata* is included so that EXPECT_* and ASSERT_* work correctly.
@@ -267,6 +269,72 @@
 		struct __test_metadata __attribute__((unused)) *_metadata, \
 		FIXTURE_DATA(fixture_name) __attribute__((unused)) *self)
 
+/**
+ * FIXTURE_PARAMS(fixture_name) - Optionally called once per fixture
+ * to declare fixture parameters
+ *
+ * @fixture_name: fixture name
+ *
+ * .. code-block:: c
+ *
+ *     FIXTURE_PARAMS(datatype name) {
+ *       type property1;
+ *       ...
+ *     };
+ *
+ * Defines type of constant parameters provided to FIXTURE_SETUP() and TEST_F()
+ * as *params*.
+ */
+#define FIXTURE_PARAMS(fixture_name) struct _fixture_params_##fixture_name
+
+/**
+ * FIXTURE_PARAMS_ADD(fixture_name, params_name) - Called once per fixture
+ * params to setup the data and register
+ *
+ * @fixture_name: fixture name
+ * @params_name: name of the parameter set
+ *
+ * .. code-block:: c
+ *
+ *     FIXTURE_ADD(datatype name) {
+ *       .property1 = val1;
+ *       ...
+ *     };
+ *
+ * Defines an instance of parameters accessible in FIXTURE_SETUP(),
+ * FIXTURE_TEARDOWN() and TEST_F(). Tests will be run once for each
+ * parameter set.
+ */
+#define FIXTURE_PARAMS_ADD(fixture_name, params_name) \
+	extern FIXTURE_PARAMS(fixture_name) \
+		_##fixture_name##_##params_name##_params; \
+	static struct __fixture_params_metadata \
+		_##fixture_name##_##params_name##_object = \
+		{ .name = #params_name, \
+		  .data = &_##fixture_name##_##params_name##_params}; \
+	static void __attribute__((constructor)) \
+		_register_##fixture_name##_##params_name(void) \
+	{ \
+		__register_fixture_params(&_##fixture_name##_fixture_object, \
+			&_##fixture_name##_##params_name##_object);	\
+	} \
+	FIXTURE_PARAMS(fixture_name) _##fixture_name##_##params_name##_params =
+
+/**
+ * CURRENT_PARAMS(fixture_name) - Access fixture parameters of the current test
+ *
+ * @fixture_name: fixture name
+ *
+ * .. code-block:: c
+ *
+ *     CURRENT_PARAMS(fixture name)->property1
+ *
+ * Helper macro for accessing parameters of current test. Can be used inside
+ * FIXTURE_SETUP(), FIXTURE_TEARDOWN() and TEST_F().
+ */
+#define CURRENT_PARAMS(fixture_name) \
+	((const FIXTURE_PARAMS(fixture_name) *) _metadata->current_params->data)
+
 /**
  * TEST_F(fixture_name, test_name) - Emits test registration and helpers for
  * fixture-based test cases
@@ -638,11 +706,13 @@
 
 /* Contains all the information for test execution and status checking. */
 struct __fixture_metadata;
+struct __fixture_params_metadata;
 
 struct __test_metadata {
 	const char *name;
 	void (*fn)(struct __test_metadata *);
 	struct __fixture_metadata *fixture;
+	struct __fixture_params_metadata *current_params;
 	int termsig;
 	int passed;
 	int trigger; /* extra handler after the evaluation */
@@ -696,10 +766,41 @@ static inline void __register_test(struct __test_metadata *t)
 /* Contains all the information about a fixture */
 struct __fixture_metadata {
 	const char *name;
+	struct __fixture_params_metadata *params;
 } _fixture_global __attribute__((unused)) = {
 	.name = "global",
 };
 
+struct __fixture_params_metadata {
+	const char *name;
+	const void *data;
+	struct __fixture_params_metadata *prev, *next;
+};
+
+static inline void
+__register_fixture_params(struct __fixture_metadata *f,
+			  struct __fixture_params_metadata *p)
+{
+	/* Circular linked list where only prev is circular. */
+	if (f->params == NULL) {
+		f->params = p;
+		p->next = NULL;
+		p->prev = p;
+		return;
+	}
+	if (__constructor_order == _CONSTRUCTOR_ORDER_FORWARD) {
+		p->next = NULL;
+		p->prev = f->params->prev;
+		p->prev->next = p;
+		f->params->prev = p;
+	} else {
+		p->next = f->params;
+		p->next->prev = p;
+		p->prev = p;
+		f->params = p;
+	}
+}
+
 static inline int __bail(int for_realz, bool no_print, __u8 step)
 {
 	if (for_realz) {
@@ -711,14 +812,21 @@ static inline int __bail(int for_realz, bool no_print, __u8 step)
 }
 
 void __run_test(struct __fixture_metadata *f,
+		struct __fixture_params_metadata *p,
 		struct __test_metadata *t)
 {
 	pid_t child_pid;
 	int status;
 
+	/* reset test struct */
 	t->passed = 1;
 	t->trigger = 0;
-	printf("[ RUN      ] %s.%s\n", f->name, t->name);
+	t->step = 0;
+	t->no_print = 0;
+
+	t->current_params = p;
+
+	printf("[ RUN      ] %s%s.%s\n", f->name, p->name, t->name);
 	alarm(t->timeout);
 	child_pid = fork();
 	if (child_pid < 0) {
@@ -767,14 +875,17 @@ void __run_test(struct __fixture_metadata *f,
 				status);
 		}
 	}
-	printf("[     %4s ] %s.%s\n", (t->passed ? "OK" : "FAIL"),
-	       f->name, t->name);
+	printf("[     %4s ] %s%s.%s\n", (t->passed ? "OK" : "FAIL"),
+	       f->name, p->name, t->name);
 	alarm(0);
 }
 
 static int test_harness_run(int __attribute__((unused)) argc,
 			    char __attribute__((unused)) **argv)
 {
+	struct __fixture_params_metadata no_param = { .name = "", };
+	struct __fixture_params_metadata *p;
+	struct __fixture_metadata *f;
 	struct __test_metadata *t;
 	int ret = 0;
 	unsigned int count = 0;
@@ -784,12 +895,16 @@ static int test_harness_run(int __attribute__((unused)) argc,
 	printf("[==========] Running %u tests from %u test cases.\n",
 	       __test_count, __fixture_count + 1);
 	for (t = __test_list; t; t = t->next) {
-		count++;
-		__run_test(t->fixture, t);
-		if (t->passed)
-			pass_count++;
-		else
-			ret = 1;
+		f = t->fixture;
+
+		for (p = f->params ?: &no_param; p; p = p->next) {
+			count++;
+			__run_test(f, p, t);
+			if (t->passed)
+				pass_count++;
+			else
+				ret = 1;
+		}
 	}
 	printf("[==========] %u / %u tests passed.\n", pass_count, count);
 	printf("[  %s  ]\n", (ret ? "FAILED" : "PASSED"));
-- 
2.24.1


  parent reply	other threads:[~2020-03-14  0:55 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-14  0:54 [PATCH v2 0/4] kselftest: add fixture parameters Jakub Kicinski
2020-03-14  0:54 ` [PATCH v2 1/4] selftests/seccomp: use correct FIXTURE macro Jakub Kicinski
2020-03-14  0:54 ` [PATCH v2 2/4] kselftest: create fixture objects Jakub Kicinski
2020-03-14  0:55 ` Jakub Kicinski [this message]
2020-03-14  0:55 ` [PATCH v2 4/4] selftests: tls: run all tests for TLS 1.2 and TLS 1.3 Jakub Kicinski
2020-03-14  4:41 ` [PATCH v2 0/4] kselftest: add fixture parameters Kees Cook
2020-03-16 15:55   ` Bird, Tim
2020-03-16 20:04     ` Jakub Kicinski
2020-03-16 21:01       ` Kees Cook
2020-03-16 21:27         ` Jakub Kicinski
2020-03-15  7:05 ` David Miller
2020-03-15 20:55   ` Kees Cook

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200314005501.2446494-4-kuba@kernel.org \
    --to=kuba@kernel.org \
    --cc=keescook@chromium.org \
    --cc=kernel-team@fb.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=netdev@vger.kernel.org \
    --cc=shuah@kernel.org \
    --cc=wad@chromium.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.