Message ID | 20190812182421.141150-5-brendanhiggins@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | kunit: introduce KUnit, the Linux kernel unit testing framework | expand |
Quoting Brendan Higgins (2019-08-12 11:24:07) > Add `struct kunit_assert` and friends which provide a structured way to > capture data from an expectation or an assertion (introduced later in > the series) so that it may be printed out in the event of a failure. > > Signed-off-by: Brendan Higgins <brendanhiggins@google.com> > --- Reviewed-by: Stephen Boyd <sboyd@kernel.org> Just some minor nits below > diff --git a/include/kunit/assert.h b/include/kunit/assert.h > new file mode 100644 > index 0000000000000..55f1b88b0cb4d > --- /dev/null > +++ b/include/kunit/assert.h > @@ -0,0 +1,183 @@ [...] > + struct string_stream *stream); > + > +struct kunit_fail_assert { > + struct kunit_assert assert; > +}; > + > +void kunit_fail_assert_format(const struct kunit_assert *assert, > + struct string_stream *stream); > + > +#define KUNIT_INIT_FAIL_ASSERT_STRUCT(test, type) { \ > + .assert = KUNIT_INIT_ASSERT_STRUCT(test, \ > + type, \ > + kunit_fail_assert_format) \ This one got indented one too many times? > +} > + > +struct kunit_unary_assert { > + struct kunit_assert assert; > + const char *condition; > + bool expected_true; > +}; > + > +void kunit_unary_assert_format(const struct kunit_assert *assert, > + struct string_stream *stream); > + [...] > +#define KUNIT_INIT_BINARY_STR_ASSERT_STRUCT(test, \ > + type, \ > + op_str, \ > + left_str, \ > + left_val, \ > + right_str, \ > + right_val) { \ > + .assert = KUNIT_INIT_ASSERT_STRUCT(test, \ > + type, \ > + kunit_binary_str_assert_format), \ > + .operation = op_str, \ > + .left_text = left_str, \ > + .left_value = left_val, \ > + .right_text = right_str, \ > + .right_value = right_val \ > +} It would be nice to have kernel doc on these macros so we know how to use them.
On Mon, Aug 12, 2019 at 4:46 PM Stephen Boyd <sboyd@kernel.org> wrote: > > Quoting Brendan Higgins (2019-08-12 11:24:07) > > Add `struct kunit_assert` and friends which provide a structured way to > > capture data from an expectation or an assertion (introduced later in > > the series) so that it may be printed out in the event of a failure. > > > > Signed-off-by: Brendan Higgins <brendanhiggins@google.com> > > --- > > Reviewed-by: Stephen Boyd <sboyd@kernel.org> > > Just some minor nits below > > > diff --git a/include/kunit/assert.h b/include/kunit/assert.h > > new file mode 100644 > > index 0000000000000..55f1b88b0cb4d > > --- /dev/null > > +++ b/include/kunit/assert.h > > @@ -0,0 +1,183 @@ > [...] > > + struct string_stream *stream); > > + > > +struct kunit_fail_assert { > > + struct kunit_assert assert; > > +}; > > + > > +void kunit_fail_assert_format(const struct kunit_assert *assert, > > + struct string_stream *stream); > > + > > +#define KUNIT_INIT_FAIL_ASSERT_STRUCT(test, type) { \ > > + .assert = KUNIT_INIT_ASSERT_STRUCT(test, \ > > + type, \ > > + kunit_fail_assert_format) \ > > This one got indented one too many times? Not unless I have been using the wrong formatting for multiline macros. You can see this commit applied here: https://kunit.googlesource.com/linux/+/870964da2990920030990dd1ffb647ef408e52df/include/kunit/assert.h#59 I have test, type, and kunit_fail_assert_format all column aligned (it just doesn't render nicely in the patch format). > > +} > > + > > +struct kunit_unary_assert { > > + struct kunit_assert assert; > > + const char *condition; > > + bool expected_true; > > +}; > > + > > +void kunit_unary_assert_format(const struct kunit_assert *assert, > > + struct string_stream *stream); > > + > [...] > > +#define KUNIT_INIT_BINARY_STR_ASSERT_STRUCT(test, \ > > + type, \ > > + op_str, \ > > + left_str, \ > > + left_val, \ > > + right_str, \ > > + right_val) { \ > > + .assert = KUNIT_INIT_ASSERT_STRUCT(test, \ > > + type, \ > > + kunit_binary_str_assert_format), \ > > + .operation = op_str, \ > > + .left_text = left_str, \ > > + .left_value = left_val, \ > > + .right_text = right_str, \ > > + .right_value = right_val \ > > +} > > It would be nice to have kernel doc on these macros so we know how to > use them. Sounds good. Will fix.
On Mon, Aug 12, 2019 at 4:56 PM Brendan Higgins <brendanhiggins@google.com> wrote: > > On Mon, Aug 12, 2019 at 4:46 PM Stephen Boyd <sboyd@kernel.org> wrote: > > > > Quoting Brendan Higgins (2019-08-12 11:24:07) > > > Add `struct kunit_assert` and friends which provide a structured way to > > > capture data from an expectation or an assertion (introduced later in > > > the series) so that it may be printed out in the event of a failure. > > > > > > Signed-off-by: Brendan Higgins <brendanhiggins@google.com> > > > --- > > > > Reviewed-by: Stephen Boyd <sboyd@kernel.org> > > > > Just some minor nits below > > > > > diff --git a/include/kunit/assert.h b/include/kunit/assert.h > > > new file mode 100644 > > > index 0000000000000..55f1b88b0cb4d > > > --- /dev/null > > > +++ b/include/kunit/assert.h > > > @@ -0,0 +1,183 @@ > > [...] > > > + struct string_stream *stream); > > > + > > > +struct kunit_fail_assert { > > > + struct kunit_assert assert; > > > +}; > > > + > > > +void kunit_fail_assert_format(const struct kunit_assert *assert, > > > + struct string_stream *stream); > > > + > > > +#define KUNIT_INIT_FAIL_ASSERT_STRUCT(test, type) { \ > > > + .assert = KUNIT_INIT_ASSERT_STRUCT(test, \ > > > + type, \ > > > + kunit_fail_assert_format) \ > > > > This one got indented one too many times? > > Not unless I have been using the wrong formatting for multiline > macros. You can see this commit applied here: > https://kunit.googlesource.com/linux/+/870964da2990920030990dd1ffb647ef408e52df/include/kunit/assert.h#59 > > I have test, type, and kunit_fail_assert_format all column aligned (it > just doesn't render nicely in the patch format). Disregard that last comment. I just looked at the line immediately above your comment and thought it looked correct. Sorry about that (you were pointing out that the .assert line looked wrong, correct?). > > > +} > > > + > > > +struct kunit_unary_assert { > > > + struct kunit_assert assert; > > > + const char *condition; > > > + bool expected_true; > > > +}; > > > + > > > +void kunit_unary_assert_format(const struct kunit_assert *assert, > > > + struct string_stream *stream); > > > + > > [...] > > > +#define KUNIT_INIT_BINARY_STR_ASSERT_STRUCT(test, \ > > > + type, \ > > > + op_str, \ > > > + left_str, \ > > > + left_val, \ > > > + right_str, \ > > > + right_val) { \ > > > + .assert = KUNIT_INIT_ASSERT_STRUCT(test, \ > > > + type, \ > > > + kunit_binary_str_assert_format), \ > > > + .operation = op_str, \ > > > + .left_text = left_str, \ > > > + .left_value = left_val, \ > > > + .right_text = right_str, \ > > > + .right_value = right_val \ > > > +} > > > > It would be nice to have kernel doc on these macros so we know how to > > use them. > > Sounds good. Will fix.
Quoting Brendan Higgins (2019-08-12 21:27:05) > On Mon, Aug 12, 2019 at 4:56 PM Brendan Higgins > <brendanhiggins@google.com> wrote: > > > > On Mon, Aug 12, 2019 at 4:46 PM Stephen Boyd <sboyd@kernel.org> wrote: > > > > > > Quoting Brendan Higgins (2019-08-12 11:24:07) > > > > +#define KUNIT_INIT_FAIL_ASSERT_STRUCT(test, type) { \ > > > > + .assert = KUNIT_INIT_ASSERT_STRUCT(test, \ > > > > + type, \ > > > > + kunit_fail_assert_format) \ > > > > > > This one got indented one too many times? > > > > Not unless I have been using the wrong formatting for multiline > > macros. You can see this commit applied here: > > https://kunit.googlesource.com/linux/+/870964da2990920030990dd1ffb647ef408e52df/include/kunit/assert.h#59 > > > > I have test, type, and kunit_fail_assert_format all column aligned (it > > just doesn't render nicely in the patch format). > > Disregard that last comment. I just looked at the line immediately > above your comment and thought it looked correct. Sorry about that > (you were pointing out that the .assert line looked wrong, correct?). Yes. .assert is double tabbed?
On Mon, Aug 12, 2019 at 9:57 PM Stephen Boyd <sboyd@kernel.org> wrote: > > Quoting Brendan Higgins (2019-08-12 21:27:05) > > On Mon, Aug 12, 2019 at 4:56 PM Brendan Higgins > > <brendanhiggins@google.com> wrote: > > > > > > On Mon, Aug 12, 2019 at 4:46 PM Stephen Boyd <sboyd@kernel.org> wrote: > > > > > > > > Quoting Brendan Higgins (2019-08-12 11:24:07) > > > > > +#define KUNIT_INIT_FAIL_ASSERT_STRUCT(test, type) { \ > > > > > + .assert = KUNIT_INIT_ASSERT_STRUCT(test, \ > > > > > + type, \ > > > > > + kunit_fail_assert_format) \ > > > > > > > > This one got indented one too many times? > > > > > > Not unless I have been using the wrong formatting for multiline > > > macros. You can see this commit applied here: > > > https://kunit.googlesource.com/linux/+/870964da2990920030990dd1ffb647ef408e52df/include/kunit/assert.h#59 > > > > > > I have test, type, and kunit_fail_assert_format all column aligned (it > > > just doesn't render nicely in the patch format). > > > > Disregard that last comment. I just looked at the line immediately > > above your comment and thought it looked correct. Sorry about that > > (you were pointing out that the .assert line looked wrong, correct?). > > Yes. .assert is double tabbed? Yes it is. Sorry about the confusion. Will fix.
diff --git a/include/kunit/assert.h b/include/kunit/assert.h new file mode 100644 index 0000000000000..55f1b88b0cb4d --- /dev/null +++ b/include/kunit/assert.h @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Assertion and expectation serialization API. + * + * Copyright (C) 2019, Google LLC. + * Author: Brendan Higgins <brendanhiggins@google.com> + */ + +#ifndef _KUNIT_ASSERT_H +#define _KUNIT_ASSERT_H + +#include <linux/err.h> +#include <kunit/string-stream.h> + +struct kunit; + +enum kunit_assert_type { + KUNIT_ASSERTION, + KUNIT_EXPECTATION, +}; + +struct kunit_assert { + struct kunit *test; + enum kunit_assert_type type; + int line; + const char *file; + struct va_format message; + void (*format)(const struct kunit_assert *assert, + struct string_stream *stream); +}; + +#define KUNIT_INIT_VA_FMT_NULL { .fmt = NULL, .va = NULL } + +#define KUNIT_INIT_ASSERT_STRUCT(kunit, assert_type, fmt) { \ + .test = kunit, \ + .type = assert_type, \ + .file = __FILE__, \ + .line = __LINE__, \ + .message = KUNIT_INIT_VA_FMT_NULL, \ + .format = fmt \ +} + +void kunit_base_assert_format(const struct kunit_assert *assert, + struct string_stream *stream); + +void kunit_assert_print_msg(const struct kunit_assert *assert, + struct string_stream *stream); + +struct kunit_fail_assert { + struct kunit_assert assert; +}; + +void kunit_fail_assert_format(const struct kunit_assert *assert, + struct string_stream *stream); + +#define KUNIT_INIT_FAIL_ASSERT_STRUCT(test, type) { \ + .assert = KUNIT_INIT_ASSERT_STRUCT(test, \ + type, \ + kunit_fail_assert_format) \ +} + +struct kunit_unary_assert { + struct kunit_assert assert; + const char *condition; + bool expected_true; +}; + +void kunit_unary_assert_format(const struct kunit_assert *assert, + struct string_stream *stream); + +#define KUNIT_INIT_UNARY_ASSERT_STRUCT(test, type, cond, expect_true) { \ + .assert = KUNIT_INIT_ASSERT_STRUCT(test, \ + type, \ + kunit_unary_assert_format), \ + .condition = cond, \ + .expected_true = expect_true \ +} + +struct kunit_ptr_not_err_assert { + struct kunit_assert assert; + const char *text; + const void *value; +}; + +void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert, + struct string_stream *stream); + +#define KUNIT_INIT_PTR_NOT_ERR_STRUCT(test, type, txt, val) { \ + .assert = KUNIT_INIT_ASSERT_STRUCT(test, \ + type, \ + kunit_ptr_not_err_assert_format), \ + .text = txt, \ + .value = val \ +} + +struct kunit_binary_assert { + struct kunit_assert assert; + const char *operation; + const char *left_text; + long long left_value; + const char *right_text; + long long right_value; +}; + +void kunit_binary_assert_format(const struct kunit_assert *assert, + struct string_stream *stream); + +#define KUNIT_INIT_BINARY_ASSERT_STRUCT(test, \ + type, \ + op_str, \ + left_str, \ + left_val, \ + right_str, \ + right_val) { \ + .assert = KUNIT_INIT_ASSERT_STRUCT(test, \ + type, \ + kunit_binary_assert_format), \ + .operation = op_str, \ + .left_text = left_str, \ + .left_value = left_val, \ + .right_text = right_str, \ + .right_value = right_val \ +} + +struct kunit_binary_ptr_assert { + struct kunit_assert assert; + const char *operation; + const char *left_text; + const void *left_value; + const char *right_text; + const void *right_value; +}; + +void kunit_binary_ptr_assert_format(const struct kunit_assert *assert, + struct string_stream *stream); + +#define KUNIT_INIT_BINARY_PTR_ASSERT_STRUCT(test, \ + type, \ + op_str, \ + left_str, \ + left_val, \ + right_str, \ + right_val) { \ + .assert = KUNIT_INIT_ASSERT_STRUCT(test, \ + type, \ + kunit_binary_ptr_assert_format), \ + .operation = op_str, \ + .left_text = left_str, \ + .left_value = left_val, \ + .right_text = right_str, \ + .right_value = right_val \ +} + +struct kunit_binary_str_assert { + struct kunit_assert assert; + const char *operation; + const char *left_text; + const char *left_value; + const char *right_text; + const char *right_value; +}; + +void kunit_binary_str_assert_format(const struct kunit_assert *assert, + struct string_stream *stream); + +#define KUNIT_INIT_BINARY_STR_ASSERT_STRUCT(test, \ + type, \ + op_str, \ + left_str, \ + left_val, \ + right_str, \ + right_val) { \ + .assert = KUNIT_INIT_ASSERT_STRUCT(test, \ + type, \ + kunit_binary_str_assert_format), \ + .operation = op_str, \ + .left_text = left_str, \ + .left_value = left_val, \ + .right_text = right_str, \ + .right_value = right_val \ +} + +#endif /* _KUNIT_ASSERT_H */ diff --git a/kunit/Makefile b/kunit/Makefile index 275b565a0e81f..6dcbe309036b8 100644 --- a/kunit/Makefile +++ b/kunit/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_KUNIT) += test.o \ - string-stream.o + string-stream.o \ + assert.o diff --git a/kunit/assert.c b/kunit/assert.c new file mode 100644 index 0000000000000..86013d4cf891c --- /dev/null +++ b/kunit/assert.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Assertion and expectation serialization API. + * + * Copyright (C) 2019, Google LLC. + * Author: Brendan Higgins <brendanhiggins@google.com> + */ +#include <kunit/assert.h> + +void kunit_base_assert_format(const struct kunit_assert *assert, + struct string_stream *stream) +{ + const char *expect_or_assert = NULL; + + switch (assert->type) { + case KUNIT_EXPECTATION: + expect_or_assert = "EXPECTATION"; + break; + case KUNIT_ASSERTION: + expect_or_assert = "ASSERTION"; + break; + } + + string_stream_add(stream, "%s FAILED at %s:%d\n", + expect_or_assert, assert->file, assert->line); +} + +void kunit_assert_print_msg(const struct kunit_assert *assert, + struct string_stream *stream) +{ + if (assert->message.fmt) + string_stream_add(stream, "\n%pV", &assert->message); +} + +void kunit_fail_assert_format(const struct kunit_assert *assert, + struct string_stream *stream) +{ + kunit_base_assert_format(assert, stream); + string_stream_add(stream, "%pV", &assert->message); +} + +void kunit_unary_assert_format(const struct kunit_assert *assert, + struct string_stream *stream) +{ + struct kunit_unary_assert *unary_assert = container_of( + assert, struct kunit_unary_assert, assert); + + kunit_base_assert_format(assert, stream); + if (unary_assert->expected_true) + string_stream_add(stream, + "\tExpected %s to be true, but is false\n", + unary_assert->condition); + else + string_stream_add(stream, + "\tExpected %s to be false, but is true\n", + unary_assert->condition); + kunit_assert_print_msg(assert, stream); +} + +void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert, + struct string_stream *stream) +{ + struct kunit_ptr_not_err_assert *ptr_assert = container_of( + assert, struct kunit_ptr_not_err_assert, assert); + + kunit_base_assert_format(assert, stream); + if (!ptr_assert->value) { + string_stream_add(stream, + "\tExpected %s is not null, but is\n", + ptr_assert->text); + } else if (IS_ERR(ptr_assert->value)) { + string_stream_add(stream, + "\tExpected %s is not error, but is: %ld\n", + ptr_assert->text, + PTR_ERR(ptr_assert->value)); + } + kunit_assert_print_msg(assert, stream); +} + +void kunit_binary_assert_format(const struct kunit_assert *assert, + struct string_stream *stream) +{ + struct kunit_binary_assert *binary_assert = container_of( + assert, struct kunit_binary_assert, assert); + + kunit_base_assert_format(assert, stream); + string_stream_add(stream, + "\tExpected %s %s %s, but\n", + binary_assert->left_text, + binary_assert->operation, + binary_assert->right_text); + string_stream_add(stream, "\t\t%s == %lld\n", + binary_assert->left_text, + binary_assert->left_value); + string_stream_add(stream, "\t\t%s == %lld", + binary_assert->right_text, + binary_assert->right_value); + kunit_assert_print_msg(assert, stream); +} + +void kunit_binary_ptr_assert_format(const struct kunit_assert *assert, + struct string_stream *stream) +{ + struct kunit_binary_ptr_assert *binary_assert = container_of( + assert, struct kunit_binary_ptr_assert, assert); + + kunit_base_assert_format(assert, stream); + string_stream_add(stream, + "\tExpected %s %s %s, but\n", + binary_assert->left_text, + binary_assert->operation, + binary_assert->right_text); + string_stream_add(stream, "\t\t%s == %pK\n", + binary_assert->left_text, + binary_assert->left_value); + string_stream_add(stream, "\t\t%s == %pK", + binary_assert->right_text, + binary_assert->right_value); + kunit_assert_print_msg(assert, stream); +} + +void kunit_binary_str_assert_format(const struct kunit_assert *assert, + struct string_stream *stream) +{ + struct kunit_binary_str_assert *binary_assert = container_of( + assert, struct kunit_binary_str_assert, assert); + + kunit_base_assert_format(assert, stream); + string_stream_add(stream, + "\tExpected %s %s %s, but\n", + binary_assert->left_text, + binary_assert->operation, + binary_assert->right_text); + string_stream_add(stream, "\t\t%s == %s\n", + binary_assert->left_text, + binary_assert->left_value); + string_stream_add(stream, "\t\t%s == %s", + binary_assert->right_text, + binary_assert->right_value); + kunit_assert_print_msg(assert, stream); +}
Add `struct kunit_assert` and friends which provide a structured way to capture data from an expectation or an assertion (introduced later in the series) so that it may be printed out in the event of a failure. Signed-off-by: Brendan Higgins <brendanhiggins@google.com> --- include/kunit/assert.h | 183 +++++++++++++++++++++++++++++++++++++++++ kunit/Makefile | 3 +- kunit/assert.c | 141 +++++++++++++++++++++++++++++++ 3 files changed, 326 insertions(+), 1 deletion(-) create mode 100644 include/kunit/assert.h create mode 100644 kunit/assert.c