All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arpitha Raghunandan <98.arpi@gmail.com>
To: brendanhiggins@google.com, skhan@linuxfoundation.org,
	elver@google.com, yzaikin@google.com, tytso@mit.edu,
	adilger.kernel@dilger.ca
Cc: Arpitha Raghunandan <98.arpi@gmail.com>,
	linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com,
	linux-kernel@vger.kernel.org,
	linux-kernel-mentees@lists.linuxfoundation.org,
	linux-ext4@vger.kernel.org
Subject: [PATCH v4 1/2] kunit: Support for Parameterized Testing
Date: Tue, 27 Oct 2020 23:16:30 +0530	[thread overview]
Message-ID: <20201027174630.85213-1-98.arpi@gmail.com> (raw)

Implementation of support for parameterized testing in KUnit.
This approach requires the creation of a test case using the
KUNIT_CASE_PARAM macro that accepts a generator function as input.
This generator function should return the next parameter given the
previous parameter in parameterized tests. It also provides
a macro to generate common-case generators.

Signed-off-by: Arpitha Raghunandan <98.arpi@gmail.com>
Co-developed-by: Marco Elver <elver@google.com>
Signed-off-by: Marco Elver <elver@google.com>
---
Changes v3->v4:
- Rename kunit variables
- Rename generator function helper macro
- Add documentation for generator approach
- Display test case name in case of failure along with param index
Changes v2->v3:
- Modifictaion of generator macro and method
Changes v1->v2:
- Use of a generator method to access test case parameters

 include/kunit/test.h | 34 ++++++++++++++++++++++++++++++++++
 lib/kunit/test.c     | 21 ++++++++++++++++++++-
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/include/kunit/test.h b/include/kunit/test.h
index 9197da792336..ec2307ee9bb0 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -107,6 +107,13 @@ struct kunit;
  *
  * @run_case: the function representing the actual test case.
  * @name:     the name of the test case.
+ * @generate_params: the generator function for parameterized tests.
+ *
+ * The generator function is used to lazily generate a series of
+ * arbitrarily typed values that fit into a void*. The argument @prev
+ * is the previously returned value, which should be used to derive the
+ * next value; @prev is set to NULL on the initial generator call.
+ * When no more values are available, the generator must return NULL.
  *
  * A test case is a function with the signature,
  * ``void (*)(struct kunit *)``
@@ -141,6 +148,7 @@ struct kunit;
 struct kunit_case {
 	void (*run_case)(struct kunit *test);
 	const char *name;
+	void* (*generate_params)(void *prev);
 
 	/* private: internal use only. */
 	bool success;
@@ -162,6 +170,9 @@ static inline char *kunit_status_to_string(bool status)
  * &struct kunit_case for an example on how to use it.
  */
 #define KUNIT_CASE(test_name) { .run_case = test_name, .name = #test_name }
+#define KUNIT_CASE_PARAM(test_name, gen_params)			\
+		{ .run_case = test_name, .name = #test_name,	\
+		  .generate_params = gen_params }
 
 /**
  * struct kunit_suite - describes a related collection of &struct kunit_case
@@ -208,6 +219,15 @@ struct kunit {
 	const char *name; /* Read only after initialization! */
 	char *log; /* Points at case log after initialization */
 	struct kunit_try_catch try_catch;
+	/* param_value points to test case parameters in parameterized tests */
+	void *param_value;
+	/*
+	 * param_index stores the index of the parameter in
+	 * parameterized tests. param_index + 1 is printed
+	 * to indicate the parameter that causes the test
+	 * to fail in case of test failure.
+	 */
+	int param_index;
 	/*
 	 * success starts as true, and may only be set to false during a
 	 * test case; thus, it is safe to update this across multiple
@@ -1742,4 +1762,18 @@ do {									       \
 						fmt,			       \
 						##__VA_ARGS__)
 
+/**
+ * KUNIT_ARRAY_PARAM() - Helper method for test parameter generators
+ * 			 required in parameterized tests.
+ * @name:  prefix of the name for the test parameter generator function.
+ *	   It will be suffixed by "_gen_params".
+ * @array: a user-supplied pointer to an array of test parameters.
+ */
+#define KUNIT_ARRAY_PARAM(name, array)								\
+	static void *name##_gen_params(void *prev)						\
+	{											\
+		typeof((array)[0]) * __next = prev ? ((typeof(__next)) prev) + 1 : (array);	\
+		return __next - (array) < ARRAY_SIZE((array)) ? __next : NULL;			\
+	}
+
 #endif /* _KUNIT_TEST_H */
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index 750704abe89a..8ad908b61494 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -127,6 +127,12 @@ unsigned int kunit_test_case_num(struct kunit_suite *suite,
 }
 EXPORT_SYMBOL_GPL(kunit_test_case_num);
 
+static void kunit_print_failed_param(struct kunit *test)
+{
+	kunit_err(test, "\n\tTest failed at:\n\ttest case: %s\n\tparameter: %d\n",
+						test->name, test->param_index + 1);
+}
+
 static void kunit_print_string_stream(struct kunit *test,
 				      struct string_stream *stream)
 {
@@ -168,6 +174,8 @@ static void kunit_fail(struct kunit *test, struct kunit_assert *assert)
 	assert->format(assert, stream);
 
 	kunit_print_string_stream(test, stream);
+	if (test->param_value)
+		kunit_print_failed_param(test);
 
 	WARN_ON(string_stream_destroy(stream));
 }
@@ -239,7 +247,18 @@ static void kunit_run_case_internal(struct kunit *test,
 		}
 	}
 
-	test_case->run_case(test);
+	if (!test_case->generate_params) {
+		test_case->run_case(test);
+	} else {
+		test->param_value = test_case->generate_params(NULL);
+		test->param_index = 0;
+
+		while (test->param_value) {
+			test_case->run_case(test);
+			test->param_value = test_case->generate_params(test->param_value);
+			test->param_index++;
+		}
+	}
 }
 
 static void kunit_case_internal_cleanup(struct kunit *test)
-- 
2.25.1


WARNING: multiple messages have this Message-ID (diff)
From: Arpitha Raghunandan <98.arpi@gmail.com>
To: brendanhiggins@google.com, skhan@linuxfoundation.org,
	elver@google.com, yzaikin@google.com, tytso@mit.edu,
	adilger.kernel@dilger.ca
Cc: Arpitha Raghunandan <98.arpi@gmail.com>,
	linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
	linux-ext4@vger.kernel.org,
	linux-kernel-mentees@lists.linuxfoundation.org,
	kunit-dev@googlegroups.com
Subject: [Linux-kernel-mentees] [PATCH v4 1/2] kunit: Support for Parameterized Testing
Date: Tue, 27 Oct 2020 23:16:30 +0530	[thread overview]
Message-ID: <20201027174630.85213-1-98.arpi@gmail.com> (raw)

Implementation of support for parameterized testing in KUnit.
This approach requires the creation of a test case using the
KUNIT_CASE_PARAM macro that accepts a generator function as input.
This generator function should return the next parameter given the
previous parameter in parameterized tests. It also provides
a macro to generate common-case generators.

Signed-off-by: Arpitha Raghunandan <98.arpi@gmail.com>
Co-developed-by: Marco Elver <elver@google.com>
Signed-off-by: Marco Elver <elver@google.com>
---
Changes v3->v4:
- Rename kunit variables
- Rename generator function helper macro
- Add documentation for generator approach
- Display test case name in case of failure along with param index
Changes v2->v3:
- Modifictaion of generator macro and method
Changes v1->v2:
- Use of a generator method to access test case parameters

 include/kunit/test.h | 34 ++++++++++++++++++++++++++++++++++
 lib/kunit/test.c     | 21 ++++++++++++++++++++-
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/include/kunit/test.h b/include/kunit/test.h
index 9197da792336..ec2307ee9bb0 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -107,6 +107,13 @@ struct kunit;
  *
  * @run_case: the function representing the actual test case.
  * @name:     the name of the test case.
+ * @generate_params: the generator function for parameterized tests.
+ *
+ * The generator function is used to lazily generate a series of
+ * arbitrarily typed values that fit into a void*. The argument @prev
+ * is the previously returned value, which should be used to derive the
+ * next value; @prev is set to NULL on the initial generator call.
+ * When no more values are available, the generator must return NULL.
  *
  * A test case is a function with the signature,
  * ``void (*)(struct kunit *)``
@@ -141,6 +148,7 @@ struct kunit;
 struct kunit_case {
 	void (*run_case)(struct kunit *test);
 	const char *name;
+	void* (*generate_params)(void *prev);
 
 	/* private: internal use only. */
 	bool success;
@@ -162,6 +170,9 @@ static inline char *kunit_status_to_string(bool status)
  * &struct kunit_case for an example on how to use it.
  */
 #define KUNIT_CASE(test_name) { .run_case = test_name, .name = #test_name }
+#define KUNIT_CASE_PARAM(test_name, gen_params)			\
+		{ .run_case = test_name, .name = #test_name,	\
+		  .generate_params = gen_params }
 
 /**
  * struct kunit_suite - describes a related collection of &struct kunit_case
@@ -208,6 +219,15 @@ struct kunit {
 	const char *name; /* Read only after initialization! */
 	char *log; /* Points at case log after initialization */
 	struct kunit_try_catch try_catch;
+	/* param_value points to test case parameters in parameterized tests */
+	void *param_value;
+	/*
+	 * param_index stores the index of the parameter in
+	 * parameterized tests. param_index + 1 is printed
+	 * to indicate the parameter that causes the test
+	 * to fail in case of test failure.
+	 */
+	int param_index;
 	/*
 	 * success starts as true, and may only be set to false during a
 	 * test case; thus, it is safe to update this across multiple
@@ -1742,4 +1762,18 @@ do {									       \
 						fmt,			       \
 						##__VA_ARGS__)
 
+/**
+ * KUNIT_ARRAY_PARAM() - Helper method for test parameter generators
+ * 			 required in parameterized tests.
+ * @name:  prefix of the name for the test parameter generator function.
+ *	   It will be suffixed by "_gen_params".
+ * @array: a user-supplied pointer to an array of test parameters.
+ */
+#define KUNIT_ARRAY_PARAM(name, array)								\
+	static void *name##_gen_params(void *prev)						\
+	{											\
+		typeof((array)[0]) * __next = prev ? ((typeof(__next)) prev) + 1 : (array);	\
+		return __next - (array) < ARRAY_SIZE((array)) ? __next : NULL;			\
+	}
+
 #endif /* _KUNIT_TEST_H */
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index 750704abe89a..8ad908b61494 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -127,6 +127,12 @@ unsigned int kunit_test_case_num(struct kunit_suite *suite,
 }
 EXPORT_SYMBOL_GPL(kunit_test_case_num);
 
+static void kunit_print_failed_param(struct kunit *test)
+{
+	kunit_err(test, "\n\tTest failed at:\n\ttest case: %s\n\tparameter: %d\n",
+						test->name, test->param_index + 1);
+}
+
 static void kunit_print_string_stream(struct kunit *test,
 				      struct string_stream *stream)
 {
@@ -168,6 +174,8 @@ static void kunit_fail(struct kunit *test, struct kunit_assert *assert)
 	assert->format(assert, stream);
 
 	kunit_print_string_stream(test, stream);
+	if (test->param_value)
+		kunit_print_failed_param(test);
 
 	WARN_ON(string_stream_destroy(stream));
 }
@@ -239,7 +247,18 @@ static void kunit_run_case_internal(struct kunit *test,
 		}
 	}
 
-	test_case->run_case(test);
+	if (!test_case->generate_params) {
+		test_case->run_case(test);
+	} else {
+		test->param_value = test_case->generate_params(NULL);
+		test->param_index = 0;
+
+		while (test->param_value) {
+			test_case->run_case(test);
+			test->param_value = test_case->generate_params(test->param_value);
+			test->param_index++;
+		}
+	}
 }
 
 static void kunit_case_internal_cleanup(struct kunit *test)
-- 
2.25.1

_______________________________________________
Linux-kernel-mentees mailing list
Linux-kernel-mentees@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/linux-kernel-mentees

             reply	other threads:[~2020-10-27 17:49 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-27 17:46 Arpitha Raghunandan [this message]
2020-10-27 17:46 ` [Linux-kernel-mentees] [PATCH v4 1/2] kunit: Support for Parameterized Testing Arpitha Raghunandan
2020-10-27 17:47 ` [PATCH v4 2/2] fs: ext4: Modify inode-test.c to use KUnit parameterized testing feature Arpitha Raghunandan
2020-10-27 17:47   ` [Linux-kernel-mentees] " Arpitha Raghunandan
2020-10-27 23:49   ` kernel test robot
2020-10-27 23:49     ` kernel test robot
2020-10-28  8:30     ` Marco Elver
2020-10-28  8:30       ` Marco Elver
2020-10-28  8:47       ` Arpitha Raghunandan
2020-10-31 18:41   ` kernel test robot
2020-10-31 18:41     ` kernel test robot
2020-10-27 19:21 ` [PATCH v4 1/2] kunit: Support for Parameterized Testing Marco Elver
2020-10-27 19:21   ` [Linux-kernel-mentees] " Marco Elver via Linux-kernel-mentees
2020-10-28  8:45   ` Arpitha Raghunandan
2020-10-28  8:45     ` [Linux-kernel-mentees] " Arpitha Raghunandan
2020-11-05  7:31   ` Arpitha Raghunandan
2020-11-05  7:31     ` [Linux-kernel-mentees] " Arpitha Raghunandan
2020-11-05  8:30     ` Marco Elver
2020-11-05  8:30       ` [Linux-kernel-mentees] " Marco Elver via Linux-kernel-mentees
2020-11-05 14:30       ` Arpitha Raghunandan
2020-11-05 14:30         ` [Linux-kernel-mentees] " Arpitha Raghunandan
2020-11-05 15:02         ` Marco Elver
2020-11-05 15:02           ` [Linux-kernel-mentees] " Marco Elver via Linux-kernel-mentees
2020-11-05 19:55           ` Marco Elver
2020-11-05 19:55             ` [Linux-kernel-mentees] " Marco Elver via Linux-kernel-mentees
2020-11-06  5:54             ` Arpitha Raghunandan
2020-11-06  5:54               ` [Linux-kernel-mentees] " Arpitha Raghunandan
2020-11-06  8:11               ` Marco Elver
2020-11-06  8:11                 ` [Linux-kernel-mentees] " Marco Elver via Linux-kernel-mentees
2020-11-06 12:34                 ` Marco Elver
2020-11-06 12:34                   ` [Linux-kernel-mentees] " Marco Elver via Linux-kernel-mentees
2020-11-06 16:16                   ` Arpitha Raghunandan
2020-11-06 16:16                     ` [Linux-kernel-mentees] " Arpitha Raghunandan

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=20201027174630.85213-1-98.arpi@gmail.com \
    --to=98.arpi@gmail.com \
    --cc=adilger.kernel@dilger.ca \
    --cc=brendanhiggins@google.com \
    --cc=elver@google.com \
    --cc=kunit-dev@googlegroups.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-kernel-mentees@lists.linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=skhan@linuxfoundation.org \
    --cc=tytso@mit.edu \
    --cc=yzaikin@google.com \
    /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.