[PATCH v1] DO NOT MERGE: started playing around with the serialization api

From: Brendan Higgins
Date: Thu Jul 18 2019 - 19:08:52 EST


---
include/kunit/assert.h | 130 ++++++++++++++++++++++++++++++
include/kunit/mock.h | 4 +
kunit/Makefile | 3 +-
kunit/assert.c | 179 +++++++++++++++++++++++++++++++++++++++++
kunit/mock.c | 6 +-
5 files changed, 318 insertions(+), 4 deletions(-)
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..e054fdff4642f
--- /dev/null
+++ b/include/kunit/assert.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Assertion and expectation serialization API.
+ *
+ * Copyright (C) 2019, Google LLC.
+ * Author: Brendan Higgins <brendanhiggins@xxxxxxxxxx>
+ */
+
+#ifndef _KUNIT_ASSERT_H
+#define _KUNIT_ASSERT_H
+
+#include <kunit/test.h>
+#include <kunit/mock.h>
+
+enum kunit_assert_type {
+ KUNIT_ASSERTION,
+ KUNIT_EXPECTATION,
+};
+
+struct kunit_assert {
+ enum kunit_assert_type type;
+ const char *line;
+ const char *file;
+ struct va_format message;
+ void (*format)(struct kunit_assert *assert,
+ struct kunit_stream *stream);
+};
+
+void kunit_base_assert_format(struct kunit_assert *assert,
+ struct kunit_stream *stream);
+
+void kunit_assert_print_msg(struct kunit_assert *assert,
+ struct kunit_stream *stream);
+
+struct kunit_unary_assert {
+ struct kunit_assert assert;
+ const char *condition;
+ bool expected_true;
+};
+
+void kunit_unary_assert_format(struct kunit_assert *assert,
+ struct kunit_stream *stream);
+
+struct kunit_ptr_not_err_assert {
+ struct kunit_assert assert;
+ const char *text;
+ void *value;
+};
+
+void kunit_ptr_not_err_assert_format(struct kunit_assert *assert,
+ struct kunit_stream *stream);
+
+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(struct kunit_assert *assert,
+ struct kunit_stream *stream);
+
+struct kunit_binary_ptr_assert {
+ struct kunit_assert assert;
+ const char *operation;
+ const char *left_text;
+ void *left_value;
+ const char *right_text;
+ void *right_value;
+};
+
+void kunit_binary_ptr_assert_format(struct kunit_assert *assert,
+ struct kunit_stream *stream);
+
+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(struct kunit_assert *assert,
+ struct kunit_stream *stream);
+
+struct kunit_mock_assert {
+ struct kunit_assert assert;
+};
+
+struct kunit_mock_no_expectations {
+ struct kunit_mock_assert assert;
+};
+
+struct kunit_mock_declaration {
+ const char *function_name;
+ const char **type_names;
+ const void **params;
+ int len;
+};
+
+void kunit_mock_declaration_format(struct kunit_mock_declaration *declaration,
+ struct kunit_stream *stream);
+
+struct kunit_matcher_result {
+ struct kunit_assert assert;
+};
+
+struct kunit_mock_failed_match {
+ struct list_head node;
+ const char *expectation_text;
+ struct kunit_matcher_result *matcher_list;
+ size_t matcher_list_len;
+};
+
+void kunit_mock_failed_match_format(struct kunit_mock_failed_match *match,
+ struct kunit_stream *stream);
+
+struct kunit_mock_no_match {
+ struct kunit_mock_assert assert;
+ struct kunit_mock_declaration declaration;
+ struct list_head failed_match_list;
+};
+
+void kunit_mock_no_match_format(struct kunit_assert *assert,
+ struct kunit_stream *stream);
+
+#endif /* _KUNIT_ASSERT_H */
diff --git a/include/kunit/mock.h b/include/kunit/mock.h
index 001b96af62f1e..52c9e427c831b 100644
--- a/include/kunit/mock.h
+++ b/include/kunit/mock.h
@@ -144,6 +144,10 @@ void mock_register_formatter(struct mock_param_formatter *formatter);

void mock_unregister_formatter(struct mock_param_formatter *formatter);

+void mock_format_param(struct kunit_stream *stream,
+ const char *type_name,
+ const void *param);
+
struct mock *mock_get_global_mock(void);

#define MOCK(name) name##_mock
diff --git a/kunit/Makefile b/kunit/Makefile
index bbf43fcfb93a9..149d856a30f04 100644
--- a/kunit/Makefile
+++ b/kunit/Makefile
@@ -3,7 +3,8 @@ obj-$(CONFIG_KUNIT) += test.o \
common-mocks.o \
string-stream.o \
kunit-stream.o \
- try-catch.o
+ try-catch.o \
+ assert.o

obj-$(CONFIG_KUNIT_TEST) += test-test.o \
test-mock.o \
diff --git a/kunit/assert.c b/kunit/assert.c
new file mode 100644
index 0000000000000..75bb6922a994e
--- /dev/null
+++ b/kunit/assert.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Assertion and expectation serialization API.
+ *
+ * Copyright (C) 2019, Google LLC.
+ * Author: Brendan Higgins <brendanhiggins@xxxxxxxxxx>
+ */
+#include <kunit/assert.h>
+
+void kunit_base_assert_format(struct kunit_assert *assert,
+ struct kunit_stream *stream)
+{
+ const char *expect_or_assert;
+
+ if (assert->type == KUNIT_EXPECTATION)
+ expect_or_assert = "EXPECTATION";
+ else
+ expect_or_assert = "ASSERTION";
+
+ kunit_stream_add(stream, "%s FAILED at %s:%s\n",
+ expect_or_assert, assert->file, assert->line);
+}
+
+void kunit_assert_print_msg(struct kunit_assert *assert,
+ struct kunit_stream *stream)
+{
+ if (assert->message.fmt)
+ kunit_stream_add(stream, "\n%pV", &assert->message);
+}
+
+void kunit_unary_assert_format(struct kunit_assert *assert,
+ struct kunit_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)
+ kunit_stream_add(stream,
+ "\tExpected %s to be true, but is false\n",
+ unary_assert->condition);
+ else
+ kunit_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(struct kunit_assert *assert,
+ struct kunit_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) {
+ kunit_stream_add(stream,
+ "\tExpected %s is not null, but is\n",
+ ptr_assert->text);
+ } else if (IS_ERR(ptr_assert->value)) {
+ kunit_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(struct kunit_assert *assert,
+ struct kunit_stream *stream)
+{
+ struct kunit_binary_assert *binary_assert = container_of(
+ assert, struct kunit_binary_assert, assert);
+
+ kunit_base_assert_format(assert, stream);
+ kunit_stream_add(stream,
+ "\tExpected %s %s %s, but\n",
+ binary_assert->left_text,
+ binary_assert->operation,
+ binary_assert->right_text);
+ kunit_stream_add(stream, "\t\t%s == %lld\n",
+ binary_assert->left_text,
+ binary_assert->left_value);
+ kunit_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(struct kunit_assert *assert,
+ struct kunit_stream *stream)
+{
+ struct kunit_binary_ptr_assert *binary_assert = container_of(
+ assert, struct kunit_binary_ptr_assert, assert);
+
+ kunit_base_assert_format(assert, stream);
+ kunit_stream_add(stream,
+ "\tExpected %s %s %s, but\n",
+ binary_assert->left_text,
+ binary_assert->operation,
+ binary_assert->right_text);
+ kunit_stream_add(stream, "\t\t%s == %pK\n",
+ binary_assert->left_text,
+ binary_assert->left_value);
+ kunit_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(struct kunit_assert *assert,
+ struct kunit_stream *stream)
+{
+ struct kunit_binary_str_assert *binary_assert = container_of(
+ assert, struct kunit_binary_str_assert, assert);
+
+ kunit_base_assert_format(assert, stream);
+ kunit_stream_add(stream,
+ "\tExpected %s %s %s, but\n",
+ binary_assert->left_text,
+ binary_assert->operation,
+ binary_assert->right_text);
+ kunit_stream_add(stream, "\t\t%s == %s\n",
+ binary_assert->left_text,
+ binary_assert->left_value);
+ kunit_stream_add(stream, "\t\t%s == %s",
+ binary_assert->right_text,
+ binary_assert->right_value);
+ kunit_assert_print_msg(assert, stream);
+}
+
+void kunit_mock_declaration_format(struct kunit_mock_declaration *declaration,
+ struct kunit_stream *stream)
+{
+ int i;
+
+ kunit_stream_add(stream, "%s(", declaration->function_name);
+ for (i = 0; i < declaration->len; i++) {
+ mock_format_param(stream,
+ declaration->type_names[i],
+ declaration->params[i]);
+ if (i < declaration->len - 1)
+ kunit_stream_add(stream, ", ");
+ }
+ kunit_stream_add(stream, ")\n");
+}
+
+void kunit_mock_failed_match_format(struct kunit_mock_failed_match *match,
+ struct kunit_stream *stream)
+{
+ struct kunit_matcher_result *result;
+ size_t i;
+
+ kunit_stream_add(stream,
+ "Tried expectation: %s, but\n",
+ match->expectation_text);
+ for (i = 0; i < match->matcher_list_len; i++) {
+ result = &match->matcher_list[i];
+ kunit_stream_add(stream, "\t");
+ result->assert.format(&result->assert, stream);
+ kunit_stream_add(stream, "\n");
+ }
+}
+
+void kunit_mock_no_match_format(struct kunit_assert *assert,
+ struct kunit_stream *stream)
+{
+ struct kunit_mock_assert *mock_assert = container_of(
+ assert, struct kunit_mock_assert, assert);
+ struct kunit_mock_no_match *no_match = container_of(
+ mock_assert, struct kunit_mock_no_match, assert);
+ struct kunit_mock_failed_match *expectation;
+
+ kunit_base_assert_format(assert, stream);
+ kunit_mock_declaration_format(&no_match->declaration, stream);
+
+ list_for_each_entry(expectation, &no_match->failed_match_list, node)
+ kunit_mock_failed_match_format(expectation, stream);
+}
diff --git a/kunit/mock.c b/kunit/mock.c
index ccb0abe111402..ab441a58a918c 100644
--- a/kunit/mock.c
+++ b/kunit/mock.c
@@ -269,9 +269,9 @@ struct mock_param_formatter *mock_find_formatter(const char *type_name)
return NULL;
}

-static void mock_format_param(struct kunit_stream *stream,
- const char *type_name,
- const void *param)
+void mock_format_param(struct kunit_stream *stream,
+ const char *type_name,
+ const void *param)
{
struct mock_param_formatter *formatter;

--
2.22.0.657.g960e92d24f-goog