diff options
Diffstat (limited to 'lib/overflow_kunit.c')
| -rw-r--r-- | lib/overflow_kunit.c | 86 | 
1 files changed, 82 insertions, 4 deletions
diff --git a/lib/overflow_kunit.c b/lib/overflow_kunit.c index c527f6b75789..4ef31b0bb74d 100644 --- a/lib/overflow_kunit.c +++ b/lib/overflow_kunit.c @@ -258,25 +258,84 @@ DEFINE_TEST_ARRAY(s64) = {  									\  	_of = check_ ## op ## _overflow(a, b, &_r);			\  	KUNIT_EXPECT_EQ_MSG(test, _of, of,				\ -		"expected "fmt" "sym" "fmt" to%s overflow (type %s)\n",	\ +		"expected check "fmt" "sym" "fmt" to%s overflow (type %s)\n",	\  		a, b, of ? "" : " not", #t);				\  	KUNIT_EXPECT_EQ_MSG(test, _r, r,				\ -		"expected "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \ +		"expected check "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \  		a, b, r, _r, #t);					\  	/* Check for internal macro side-effects. */			\  	_of = check_ ## op ## _overflow(_a_orig++, _b_orig++, &_r);	\ -	KUNIT_EXPECT_EQ_MSG(test, _a_orig, _a_bump, "Unexpected " #op " macro side-effect!\n"); \ -	KUNIT_EXPECT_EQ_MSG(test, _b_orig, _b_bump, "Unexpected " #op " macro side-effect!\n"); \ +	KUNIT_EXPECT_EQ_MSG(test, _a_orig, _a_bump,			\ +		"Unexpected check " #op " macro side-effect!\n");	\ +	KUNIT_EXPECT_EQ_MSG(test, _b_orig, _b_bump,			\ +		"Unexpected check " #op " macro side-effect!\n");	\ +									\ +	_r = wrapping_ ## op(t, a, b);					\ +	KUNIT_EXPECT_TRUE_MSG(test, _r == r,				\ +		"expected wrap "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \ +		a, b, r, _r, #t);					\ +	/* Check for internal macro side-effects. */			\ +	_a_orig = a;							\ +	_b_orig = b;							\ +	_r = wrapping_ ## op(t, _a_orig++, _b_orig++);			\ +	KUNIT_EXPECT_EQ_MSG(test, _a_orig, _a_bump,			\ +		"Unexpected wrap " #op " macro side-effect!\n");	\ +	KUNIT_EXPECT_EQ_MSG(test, _b_orig, _b_bump,			\ +		"Unexpected wrap " #op " macro side-effect!\n");	\ +} while (0) + +static int global_counter; +static void bump_counter(void) +{ +	global_counter++; +} + +static int get_index(void) +{ +	volatile int index = 0; +	bump_counter(); +	return index; +} + +#define check_self_op(fmt, op, sym, a, b) do {				\ +	typeof(a + 0) _a = a;						\ +	typeof(b + 0) _b = b;						\ +	typeof(a + 0) _a_sym = a;					\ +	typeof(a + 0) _a_orig[1] = { a };				\ +	typeof(b + 0) _b_orig = b;					\ +	typeof(b + 0) _b_bump = b + 1;					\ +	typeof(a + 0) _r;						\ +									\ +	_a_sym sym _b;							\ +	_r = wrapping_ ## op(_a, _b);					\ +	KUNIT_EXPECT_TRUE_MSG(test, _r == _a_sym,			\ +		"expected "fmt" "#op" "fmt" == "fmt", got "fmt"\n",	\ +		a, b, _a_sym, _r);					\ +	KUNIT_EXPECT_TRUE_MSG(test, _a == _a_sym,			\ +		"expected "fmt" "#op" "fmt" == "fmt", got "fmt"\n",	\ +		a, b, _a_sym, _a);					\ +	/* Check for internal macro side-effects. */			\ +	global_counter = 0;						\ +	wrapping_ ## op(_a_orig[get_index()], _b_orig++);		\ +	KUNIT_EXPECT_EQ_MSG(test, global_counter, 1,			\ +		"Unexpected wrapping_" #op " macro side-effect on arg1!\n"); \ +	KUNIT_EXPECT_EQ_MSG(test, _b_orig, _b_bump,			\ +		"Unexpected wrapping_" #op " macro side-effect on arg2!\n"); \  } while (0)  #define DEFINE_TEST_FUNC_TYPED(n, t, fmt)				\  static void do_test_ ## n(struct kunit *test, const struct test_ ## n *p) \  {									\ +	/* check_{add,sub,mul}_overflow() and wrapping_{add,sub,mul} */	\  	check_one_op(t, fmt, add, "+", p->a, p->b, p->sum, p->s_of);	\  	check_one_op(t, fmt, add, "+", p->b, p->a, p->sum, p->s_of);	\  	check_one_op(t, fmt, sub, "-", p->a, p->b, p->diff, p->d_of);	\  	check_one_op(t, fmt, mul, "*", p->a, p->b, p->prod, p->p_of);	\  	check_one_op(t, fmt, mul, "*", p->b, p->a, p->prod, p->p_of);	\ +	/* wrapping_assign_{add,sub}() */				\ +	check_self_op(fmt, assign_add, +=, p->a, p->b);			\ +	check_self_op(fmt, assign_add, +=, p->b, p->a);			\ +	check_self_op(fmt, assign_sub, -=, p->a, p->b);			\  }									\  									\  static void n ## _overflow_test(struct kunit *test) {			\ @@ -1113,6 +1172,24 @@ static void castable_to_type_test(struct kunit *test)  #undef TEST_CASTABLE_TO_TYPE  } +struct foo { +	int a; +	u32 counter; +	s16 array[] __counted_by(counter); +}; + +static void DEFINE_FLEX_test(struct kunit *test) +{ +	DEFINE_RAW_FLEX(struct foo, two, array, 2); +	DEFINE_FLEX(struct foo, eight, array, counter, 8); +	DEFINE_FLEX(struct foo, empty, array, counter, 0); + +	KUNIT_EXPECT_EQ(test, __struct_size(two), +			sizeof(struct foo) + sizeof(s16) + sizeof(s16)); +	KUNIT_EXPECT_EQ(test, __struct_size(eight), 24); +	KUNIT_EXPECT_EQ(test, __struct_size(empty), sizeof(struct foo)); +} +  static struct kunit_case overflow_test_cases[] = {  	KUNIT_CASE(u8_u8__u8_overflow_test),  	KUNIT_CASE(s8_s8__s8_overflow_test), @@ -1135,6 +1212,7 @@ static struct kunit_case overflow_test_cases[] = {  	KUNIT_CASE(overflows_type_test),  	KUNIT_CASE(same_type_test),  	KUNIT_CASE(castable_to_type_test), +	KUNIT_CASE(DEFINE_FLEX_test),  	{}  };  | 
