Message ID | 20240517173607.800549-1-devarsht@ti.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add V4L2 M2M Driver for E5010 JPEG Encoder | expand |
On Fri, May 17, 2024 at 11:06:07PM +0530, Devarsh Thakkar wrote: > From: Daniel Latypov <dlatypov@google.com> > > Add basic test coverage for files that don't require any config options: > * part of math.h (what seem to be the most commonly used macros) > * gcd.c > * lcm.c > * int_sqrt.c > * reciprocal_div.c > (Ignored int_pow.c since it's a simple textbook algorithm.) > > These tests aren't particularly interesting, but they > * provide short and simple examples of parameterized tests > * provide a place to add tests for any new files in this dir > * are written so adding new test cases to cover edge cases should be > easy > * looking at code coverage, we hit all the branches in the .c files ... > [devarsht: Rebase to 6.9 and change license to GPL] I'm not sure that you may change license. It needs the author's confirmation. > --- > Changes since v6: > * Rebase to linux-next, change license to GPL as suggested by checkpatch. Note, checkpatch.pl is not false positives free. Be careful with what it suggests. > +#include <kunit/test.h> > +#include <linux/gcd.h> > +#include <linux/kernel.h> Do you know why this header is included? > +#include <linux/lcm.h> + math.h // obviously + module.h > +#include <linux/reciprocal_div.h> + types.h ... Other than above, LGTM.
On Fri, May 17, 2024 at 1:14 PM Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote: > > [devarsht: Rebase to 6.9 and change license to GPL] > > I'm not sure that you may change license. It needs the author's confirmation. Checking, this is referring to the MODULE_LICENSE, which used to be MODULE_LICENSE("GPL v2"); and is now MODULE_LICENSE("GPL"); If checkpatch is suggesting that now, then changing it sounds good to me. > > > --- > > Changes since v6: > > * Rebase to linux-next, change license to GPL as suggested by checkpatch. > > Note, checkpatch.pl is not false positives free. Be careful > with what it suggests. > > > +#include <kunit/test.h> > > +#include <linux/gcd.h> > > > +#include <linux/kernel.h> > > Do you know why this header is included? I think I had put it in the original before a lot of the work you did to split things out of kernel.h. I haven't had time to look apply this patch series locally yet, but I'd be pretty sure we can remove it without anything breaking. Thanks, Daniel
On Fri, May 17, 2024 at 01:53:47PM -0700, Daniel Latypov wrote: > On Fri, May 17, 2024 at 1:14 PM Andy Shevchenko > <andriy.shevchenko@linux.intel.com> wrote: ... > > > [devarsht: Rebase to 6.9 and change license to GPL] > > > > I'm not sure that you may change license. It needs the author's confirmation. > > Checking, this is referring to the MODULE_LICENSE, which used to be > MODULE_LICENSE("GPL v2"); > > and is now > MODULE_LICENSE("GPL"); > > If checkpatch is suggesting that now, then changing it sounds good to me. In this case I agree on the change as it's purely syntax and not semantic. > > > --- > > > Changes since v6: > > > * Rebase to linux-next, change license to GPL as suggested by checkpatch. > > > > Note, checkpatch.pl is not false positives free. Be careful > > with what it suggests. > > > > > +#include <kunit/test.h> > > > +#include <linux/gcd.h> > > > > > +#include <linux/kernel.h> > > > > Do you know why this header is included? > > I think I had put it in the original before a lot of the work you did > to split things out of kernel.h. > I haven't had time to look apply this patch series locally yet, but > I'd be pretty sure we can remove it without anything breaking. Briefly looking at the code I even not sure it was needed before, but maybe I missed something, in any case, please remove / replace it.
Hi Andy, Daniel, On 18/05/24 01:44, Andy Shevchenko wrote: > On Fri, May 17, 2024 at 11:06:07PM +0530, Devarsh Thakkar wrote: [..] > >> [devarsht: Rebase to 6.9 and change license to GPL] > > I'm not sure that you may change license. It needs the author's confirmation. > As per latest licensing doc [1], It quotes that GPL is same as GPL v2 and GPL v2 exists only for historical reasons as shared below : “GPL v2 Same as “GPL”. It exists for historic reasons." So I think it should be fine and more apt to use GPL. This is also highlighted in below commit: bf7fbeeae6db644ef5995085de2bc5c6121f8c8d module: Cure the MODULE_LICENSE "GPL" vs. "GPL v2" bogosity >> --- >> Changes since v6: >> * Rebase to linux-next, change license to GPL as suggested by checkpatch. > > Note, checkpatch.pl is not false positives free. Be careful > with what it suggests. > >> +#include <kunit/test.h> >> +#include <linux/gcd.h> > >> +#include <linux/kernel.h> > > Do you know why this header is included? > It includes all the other required headers (including those you mentioned below), and header list is probably copied from other files in same directory. But it does suffice the requirements as I have verified the compilation. >> +#include <linux/lcm.h> > > + math.h // obviously > + module.h > >> +#include <linux/reciprocal_div.h> > > + types.h > All the above headers are already included as part of kernel.h Kindly let me know if any queries. [1]: https://docs.kernel.org/process/license-rules.html Regards Devarsh
On Mon, May 20, 2024 at 05:11:18PM +0530, Devarsh Thakkar wrote: > On 18/05/24 01:44, Andy Shevchenko wrote: > > On Fri, May 17, 2024 at 11:06:07PM +0530, Devarsh Thakkar wrote: [..] > >> +#include <kunit/test.h> > >> +#include <linux/gcd.h> > > > >> +#include <linux/kernel.h> > > > > Do you know why this header is included? > > It includes all the other required headers (including those you mentioned > below), and header list is probably copied from other files in same directory. > But it does suffice the requirements as I have verified the compilation. Yes, and one should follow IWYU principle and not cargo cult or whatever arbitrary lists. > >> +#include <linux/lcm.h> > > > > + math.h // obviously > > + module.h > > > >> +#include <linux/reciprocal_div.h> > > > > + types.h > > All the above headers are already included as part of kernel.h Yes, that's why you should not use "proxy" headers. Have you read the top comment in the kernel.h?
On 20/05/24 17:52, Andy Shevchenko wrote: > On Mon, May 20, 2024 at 05:11:18PM +0530, Devarsh Thakkar wrote: >> On 18/05/24 01:44, Andy Shevchenko wrote: >>> On Fri, May 17, 2024 at 11:06:07PM +0530, Devarsh Thakkar wrote: > > [..] > [..] > Yes, and one should follow IWYU principle and not cargo cult or whatever > arbitrary lists. > Agreed. >>>> +#include <linux/lcm.h> >>> >>> + math.h // obviously >>> + module.h >>> >>>> +#include <linux/reciprocal_div.h> >>> >>> + types.h >> >> All the above headers are already included as part of kernel.h > > Yes, that's why you should not use "proxy" headers. > Have you read the top comment in the kernel.h? > Yes, it says it is not recommended to include this inside another header file. Although here we are adding it inside c file, but I can still try avoid it and include only the required headers instead of kernel.h as you recommended. Regards Devarsh
On Mon, May 20, 2024 at 07:51:24PM +0530, Devarsh Thakkar wrote: > On 20/05/24 17:52, Andy Shevchenko wrote: > > On Mon, May 20, 2024 at 05:11:18PM +0530, Devarsh Thakkar wrote: > >> On 18/05/24 01:44, Andy Shevchenko wrote: > >>> On Fri, May 17, 2024 at 11:06:07PM +0530, Devarsh Thakkar wrote: [..] > > Yes, and one should follow IWYU principle and not cargo cult or whatever > > arbitrary lists. > > Agreed. > >>>> +#include <linux/lcm.h> > >>> > >>> + math.h // obviously > >>> + module.h > >>> > >>>> +#include <linux/reciprocal_div.h> > >>> > >>> + types.h > >> > >> All the above headers are already included as part of kernel.h > > > > Yes, that's why you should not use "proxy" headers. > > Have you read the top comment in the kernel.h? > > Yes, it says it is not recommended to include this inside another header file. > Although here we are adding it inside c file, but I can still try avoid it and > include only the required headers instead of kernel.h as you recommended. Right, but the first sentence there is "This header has combined a lot of unrelated to each other stuff." Can you explain how you use in your code all that unrelated stuff? For example, how do you use *trace_*() calls? Or maybe might_*() calls? or anything else that is directly provided by kernel.h? Besides IWYU principle above, it's good to have a justification for each inclusion the C file has. I believe there is no a such in _this_ case.
diff --git a/lib/math/Kconfig b/lib/math/Kconfig index 0634b428d0cb..832c6989ca13 100644 --- a/lib/math/Kconfig +++ b/lib/math/Kconfig @@ -15,3 +15,14 @@ config PRIME_NUMBERS config RATIONAL tristate + +config MATH_KUNIT_TEST + tristate "KUnit test for math helper functions" + help + This builds unit test for math helper functions as defined in lib/math + and math.h. + + For more information on KUNIT and unit tests in general, please refer + to the KUnit documentation in Documentation/dev-tools/kunit/. + + If unsure, say N. diff --git a/lib/math/Makefile b/lib/math/Makefile index 91fcdb0c9efe..dcf65d10dab2 100644 --- a/lib/math/Makefile +++ b/lib/math/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_RATIONAL) += rational.o obj-$(CONFIG_TEST_DIV64) += test_div64.o obj-$(CONFIG_RATIONAL_KUNIT_TEST) += rational-test.o +obj-$(CONFIG_MATH_KUNIT_TEST) += math_kunit.o diff --git a/lib/math/math_kunit.c b/lib/math/math_kunit.c new file mode 100644 index 000000000000..1b00e4195a1a --- /dev/null +++ b/lib/math/math_kunit.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Simple KUnit suite for math helper funcs that are always enabled. + * + * Copyright (C) 2020, Google LLC. + * Author: Daniel Latypov <dlatypov@google.com> + */ + +#include <kunit/test.h> +#include <linux/gcd.h> +#include <linux/kernel.h> +#include <linux/lcm.h> +#include <linux/reciprocal_div.h> + +static void abs_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, abs((char)0), (char)0); + KUNIT_EXPECT_EQ(test, abs((char)42), (char)42); + KUNIT_EXPECT_EQ(test, abs((char)-42), (char)42); + + /* The expression in the macro is actually promoted to an int. */ + KUNIT_EXPECT_EQ(test, abs((short)0), 0); + KUNIT_EXPECT_EQ(test, abs((short)42), 42); + KUNIT_EXPECT_EQ(test, abs((short)-42), 42); + + KUNIT_EXPECT_EQ(test, abs(0), 0); + KUNIT_EXPECT_EQ(test, abs(42), 42); + KUNIT_EXPECT_EQ(test, abs(-42), 42); + + KUNIT_EXPECT_EQ(test, abs(0L), 0L); + KUNIT_EXPECT_EQ(test, abs(42L), 42L); + KUNIT_EXPECT_EQ(test, abs(-42L), 42L); + + KUNIT_EXPECT_EQ(test, abs(0LL), 0LL); + KUNIT_EXPECT_EQ(test, abs(42LL), 42LL); + KUNIT_EXPECT_EQ(test, abs(-42LL), 42LL); + + /* Unsigned types get casted to signed. */ + KUNIT_EXPECT_EQ(test, abs(0ULL), 0LL); + KUNIT_EXPECT_EQ(test, abs(42ULL), 42LL); +} + +static void int_sqrt_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, int_sqrt(0UL), 0UL); + KUNIT_EXPECT_EQ(test, int_sqrt(1UL), 1UL); + KUNIT_EXPECT_EQ(test, int_sqrt(4UL), 2UL); + KUNIT_EXPECT_EQ(test, int_sqrt(5UL), 2UL); + KUNIT_EXPECT_EQ(test, int_sqrt(8UL), 2UL); + KUNIT_EXPECT_EQ(test, int_sqrt(1UL << 30), 1UL << 15); +} + +static void round_up_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, round_up(0, 1), 0); + KUNIT_EXPECT_EQ(test, round_up(1, 2), 2); + KUNIT_EXPECT_EQ(test, round_up(3, 2), 4); + KUNIT_EXPECT_EQ(test, round_up((1 << 30) - 1, 2), 1 << 30); + KUNIT_EXPECT_EQ(test, round_up((1 << 30) - 1, 1 << 29), 1 << 30); +} + +static void round_down_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, round_down(0, 1), 0); + KUNIT_EXPECT_EQ(test, round_down(1, 2), 0); + KUNIT_EXPECT_EQ(test, round_down(3, 2), 2); + KUNIT_EXPECT_EQ(test, round_down((1 << 30) - 1, 2), (1 << 30) - 2); + KUNIT_EXPECT_EQ(test, round_down((1 << 30) - 1, 1 << 29), 1 << 29); +} + +/* These versions can round to numbers that aren't a power of two */ +static void roundup_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, roundup(0, 1), 0); + KUNIT_EXPECT_EQ(test, roundup(1, 2), 2); + KUNIT_EXPECT_EQ(test, roundup(3, 2), 4); + KUNIT_EXPECT_EQ(test, roundup((1 << 30) - 1, 2), 1 << 30); + KUNIT_EXPECT_EQ(test, roundup((1 << 30) - 1, 1 << 29), 1 << 30); + + KUNIT_EXPECT_EQ(test, roundup(3, 2), 4); + KUNIT_EXPECT_EQ(test, roundup(4, 3), 6); +} + +static void rounddown_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, rounddown(0, 1), 0); + KUNIT_EXPECT_EQ(test, rounddown(1, 2), 0); + KUNIT_EXPECT_EQ(test, rounddown(3, 2), 2); + KUNIT_EXPECT_EQ(test, rounddown((1 << 30) - 1, 2), (1 << 30) - 2); + KUNIT_EXPECT_EQ(test, rounddown((1 << 30) - 1, 1 << 29), 1 << 29); + + KUNIT_EXPECT_EQ(test, rounddown(3, 2), 2); + KUNIT_EXPECT_EQ(test, rounddown(4, 3), 3); +} + +static void div_round_up_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, DIV_ROUND_UP(0, 1), 0); + KUNIT_EXPECT_EQ(test, DIV_ROUND_UP(20, 10), 2); + KUNIT_EXPECT_EQ(test, DIV_ROUND_UP(21, 10), 3); + KUNIT_EXPECT_EQ(test, DIV_ROUND_UP(21, 20), 2); + KUNIT_EXPECT_EQ(test, DIV_ROUND_UP(21, 99), 1); +} + +static void div_round_closest_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, DIV_ROUND_CLOSEST(0, 1), 0); + KUNIT_EXPECT_EQ(test, DIV_ROUND_CLOSEST(20, 10), 2); + KUNIT_EXPECT_EQ(test, DIV_ROUND_CLOSEST(21, 10), 2); + KUNIT_EXPECT_EQ(test, DIV_ROUND_CLOSEST(25, 10), 3); +} + +/* Generic test case for unsigned long inputs. */ +struct test_case { + unsigned long a, b; + unsigned long result; +}; + +static struct test_case gcd_cases[] = { + { + .a = 0, .b = 0, + .result = 0, + }, + { + .a = 0, .b = 1, + .result = 1, + }, + { + .a = 2, .b = 2, + .result = 2, + }, + { + .a = 2, .b = 4, + .result = 2, + }, + { + .a = 3, .b = 5, + .result = 1, + }, + { + .a = 3 * 9, .b = 3 * 5, + .result = 3, + }, + { + .a = 3 * 5 * 7, .b = 3 * 5 * 11, + .result = 15, + }, + { + .a = 1 << 21, + .b = (1 << 21) - 1, + .result = 1, + }, +}; + +KUNIT_ARRAY_PARAM(gcd, gcd_cases, NULL); + +static void gcd_test(struct kunit *test) +{ + const char *message_fmt = "gcd(%lu, %lu)"; + const struct test_case *test_param = test->param_value; + + KUNIT_EXPECT_EQ_MSG(test, test_param->result, + gcd(test_param->a, test_param->b), + message_fmt, test_param->a, + test_param->b); + + if (test_param->a == test_param->b) + return; + + /* gcd(a,b) == gcd(b,a) */ + KUNIT_EXPECT_EQ_MSG(test, test_param->result, + gcd(test_param->b, test_param->a), + message_fmt, test_param->b, + test_param->a); +} + +static struct test_case lcm_cases[] = { + { + .a = 0, .b = 0, + .result = 0, + }, + { + .a = 0, .b = 1, + .result = 0, + }, + { + .a = 1, .b = 2, + .result = 2, + }, + { + .a = 2, .b = 2, + .result = 2, + }, + { + .a = 3 * 5, .b = 3 * 7, + .result = 3 * 5 * 7, + }, +}; + +KUNIT_ARRAY_PARAM(lcm, lcm_cases, NULL); + +static void lcm_test(struct kunit *test) +{ + const char *message_fmt = "lcm(%lu, %lu)"; + const struct test_case *test_param = test->param_value; + + KUNIT_EXPECT_EQ_MSG(test, test_param->result, + lcm(test_param->a, test_param->b), + message_fmt, test_param->a, + test_param->b); + + if (test_param->a == test_param->b) + return; + + /* lcm(a,b) == lcm(b,a) */ + KUNIT_EXPECT_EQ_MSG(test, test_param->result, + lcm(test_param->b, test_param->a), + message_fmt, test_param->b, + test_param->a); +} + +struct u32_test_case { + u32 a, b; + u32 result; +}; + +static struct u32_test_case reciprocal_div_cases[] = { + { + .a = 0, .b = 1, + .result = 0, + }, + { + .a = 42, .b = 20, + .result = 2, + }, + { + .a = 42, .b = 9999, + .result = 0, + }, + { + .a = (1 << 16), .b = (1 << 14), + .result = 1 << 2, + }, +}; + +KUNIT_ARRAY_PARAM(reciprocal_div, reciprocal_div_cases, NULL); + +static void reciprocal_div_test(struct kunit *test) +{ + const struct u32_test_case *test_param = test->param_value; + struct reciprocal_value rv = reciprocal_value(test_param->b); + + KUNIT_EXPECT_EQ_MSG(test, test_param->result, + reciprocal_divide(test_param->a, rv), + "reciprocal_divide(%u, %u)", + test_param->a, test_param->b); +} + +static void reciprocal_scale_test(struct kunit *test) +{ + KUNIT_EXPECT_EQ(test, reciprocal_scale(0u, 100), 0u); + KUNIT_EXPECT_EQ(test, reciprocal_scale(1u, 100), 0u); + KUNIT_EXPECT_EQ(test, reciprocal_scale(1u << 4, 1 << 28), 1u); + KUNIT_EXPECT_EQ(test, reciprocal_scale(1u << 16, 1 << 28), 1u << 12); + KUNIT_EXPECT_EQ(test, reciprocal_scale(~0u, 1 << 28), (1u << 28) - 1); +} + +static struct kunit_case math_test_cases[] = { + KUNIT_CASE(abs_test), + KUNIT_CASE(int_sqrt_test), + KUNIT_CASE(round_up_test), + KUNIT_CASE(round_down_test), + KUNIT_CASE(roundup_test), + KUNIT_CASE(rounddown_test), + KUNIT_CASE(div_round_up_test), + KUNIT_CASE(div_round_closest_test), + KUNIT_CASE_PARAM(gcd_test, gcd_gen_params), + KUNIT_CASE_PARAM(lcm_test, lcm_gen_params), + KUNIT_CASE_PARAM(reciprocal_div_test, reciprocal_div_gen_params), + KUNIT_CASE(reciprocal_scale_test), + {} +}; + +static struct kunit_suite math_test_suite = { + .name = "lib-math", + .test_cases = math_test_cases, +}; + +kunit_test_suites(&math_test_suite); + +MODULE_LICENSE("GPL");