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 <brendanhigg...@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

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 <brendanhigg...@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 <brendanhigg...@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);
+}
-- 
2.23.0.rc1.153.gdeed80330f-goog

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

Reply via email to