Initial tests of the arch interface.

These tests use hftest running as the hypervisor by making hftest
retargetable to this new context.

Change-Id: Ie0472932b8156d57913286cc30de7a2d2db32149
diff --git a/test/hftest/inc/hftest.h b/test/hftest/inc/hftest.h
new file mode 100644
index 0000000..290b467
--- /dev/null
+++ b/test/hftest/inc/hftest.h
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2018 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "hf/dlog.h"
+
+/*
+ * Define a set up function to be run before every test in a test suite.
+ */
+#define SET_UP(suite) HFTEST_SET_UP(suite)
+
+/*
+ * Define a tear down function to be run after every test in a test suite.
+ */
+#define TEAR_DOWN(suite) HFTEST_TEAR_DOWN(suite)
+
+/*
+ * Define a test as part of a test suite.
+ */
+#define TEST(suite, test) HFTEST_TEST(suite, test)
+
+/* Assertions. */
+#define ASSERT_EQ(x, y) ASSERT_OP(x, y, ==, true)
+#define ASSERT_NE(x, y) ASSERT_OP(x, y, !=, true)
+#define ASSERT_LE(x, y) ASSERT_OP(x, y, <=, true)
+#define ASSERT_LT(x, y) ASSERT_OP(x, y, <, true)
+#define ASSERT_GE(x, y) ASSERT_OP(x, y, >=, true)
+#define ASSERT_GT(x, y) ASSERT_OP(x, y, >, true)
+
+#define ASSERT_TRUE(x) ASSERT_EQ(x, true);
+#define ASSERT_FALSE(x) ASSERT_EQ(x, false);
+
+#define EXPECT_EQ(x, y) ASSERT_OP(x, y, ==, false)
+#define EXPECT_NE(x, y) ASSERT_OP(x, y, !=, false)
+#define EXPECT_LE(x, y) ASSERT_OP(x, y, <=, false)
+#define EXPECT_LT(x, y) ASSERT_OP(x, y, <, false)
+#define EXPECT_GE(x, y) ASSERT_OP(x, y, >=, false)
+#define EXPECT_GT(x, y) ASSERT_OP(x, y, >, false)
+
+#define EXPECT_TRUE(x) EXPECT_EQ(x, true);
+#define EXPECT_FALSE(x) EXPECT_EQ(x, false);
+
+/*
+ * This must be used exactly once in a test image to signal to the linker that
+ * the .hftest section is allowed to be included in the generated image.
+ */
+#define HFTEST_ENABLE() int hftest_enable
+
+/*
+ * Prefixed to log lines from tests for easy filtering in the console.
+ */
+#define HFTEST_LOG_PREFIX "[hftest] "
+
+/* Above this point is the public API. Below are the implementation details. */
+
+/* Log with the HFTEST_LOG_PREFIX and a new line. The zero is added so there is
+ * always at least one variadic argument. */
+#define HFTEST_LOG(...) HFTEST_LOG_IMPL(__VA_ARGS__, 0)
+#define HFTEST_LOG_IMPL(format, ...) \
+	dlog("%s" format "\n", HFTEST_LOG_PREFIX, __VA_ARGS__)
+
+/* Helper to wrap the argument in quotes. */
+#define HFTEST_STR(str) #str
+
+/* Sections are names such that when the linker sorts them, all entries for the
+ * same test suite are contiguous and the set up and tear down entries come
+ * before the tests. This order simplifies test discovery in the running image.
+ */
+#define HFTEST_SET_UP_SECTION(suite_name) \
+	HFTEST_STR(.hftest.suite_name .1set_up)
+#define HFTEST_TEAR_DOWN_SECTION(suite_name) \
+	HFTEST_STR(.hftest.suite_name .1tear_down)
+#define HFTEST_TEST_SECTION(suite_name, test_name) \
+	HFTEST_STR(.hftest.suite_name .2test.test_name)
+
+/* Helpers to construct unique identifiers. */
+#define HFTEST_SET_UP_STRUCT(suite_name) hftest_set_up_##suite_name
+#define HFTEST_TEAR_DOWN_STRUCT(suite_name) hftest_tear_down_##suite_name
+#define HFTEST_TEST_STRUCT(suite_name, test_name) \
+	hftest_test_##suite_name##_##test_name
+
+#define HFTEST_SET_UP_FN(suite_name) hftest_set_up_fn_##suite_name
+#define HFTEST_TEAR_DOWN_FN(suite_name) hftest_tear_down_fn_##suite_name
+#define HFTEST_TEST_FN(suite_name, test_name) \
+	hftest_test_fn_##suite_name##_##test_name
+
+/* Register test functions. */
+#define HFTEST_SET_UP(suite_name)                                           \
+	static void HFTEST_SET_UP_FN(suite_name)(struct hftest_context *    \
+						 hftest_ctx);               \
+	const struct hftest_test __attribute__((used))                      \
+		__attribute__((section(HFTEST_SET_UP_SECTION(suite_name)))) \
+			HFTEST_SET_UP_STRUCT(suite_name) = {                \
+				.suite = #suite_name,                       \
+				.kind = HFTEST_KIND_SET_UP,                 \
+				.fn = HFTEST_SET_UP_FN(suite_name),         \
+	};                                                                  \
+	static void HFTEST_SET_UP_FN(suite_name)(                           \
+		__attribute__((unused)) struct hftest_context * hftest_ctx)
+
+#define HFTEST_TEAR_DOWN(suite_name)                                           \
+	static void HFTEST_TEAR_DOWN_FN(suite_name)(struct hftest_context *    \
+						    hftest_ctx);               \
+	const struct hftest_test __attribute__((used))                         \
+		__attribute__((section(HFTEST_TEAR_DOWN_SECTION(suite_name)))) \
+			HFTEST_TEAR_DOWN_STRUCT(suite_name) = {                \
+				.suite = #suite_name,                          \
+				.kind = HFTEST_KIND_TEAR_DOWN,                 \
+				.fn = HFTEST_TEAR_DOWN_FN(suite_name),         \
+	};                                                                     \
+	static void HFTEST_TEAR_DOWN_FN(suite_name)(                           \
+		__attribute__((unused)) struct hftest_context * hftest_ctx)
+
+#define HFTEST_TEST(suite_name, test_name)                                  \
+	static void HFTEST_TEST_FN(                                         \
+		suite_name, test_name)(struct hftest_context * hftest_ctx); \
+	const struct hftest_test __attribute__((used)) __attribute__(       \
+		(section(HFTEST_TEST_SECTION(suite_name, test_name))))      \
+		HFTEST_TEST_STRUCT(suite_name, test_name) = {               \
+			.suite = #suite_name,                               \
+			.kind = HFTEST_KIND_TEST,                           \
+			.name = #test_name,                                 \
+			.fn = HFTEST_TEST_FN(suite_name, test_name),        \
+	};                                                                  \
+	static void HFTEST_TEST_FN(suite_name, test_name)(                  \
+		__attribute__((unused)) struct hftest_context * hftest_ctx)
+
+/* Context for tests. */
+struct hftest_context {
+	uint32_t failures;
+};
+
+/* A test case. */
+typedef void (*hftest_test_fn)(struct hftest_context *);
+
+enum hftest_kind {
+	HFTEST_KIND_SET_UP = 0,
+	HFTEST_KIND_TEST = 1,
+	HFTEST_KIND_TEAR_DOWN = 2,
+};
+
+struct hftest_test {
+	const char *suite;
+	enum hftest_kind kind;
+	const char *name;
+	hftest_test_fn fn;
+};
+
+/*
+ * This union can store any of the primitive types supported by the assertion
+ * macros.
+ *
+ * It does not include pointers as comparison of pointers is not often needed
+ * and could be a mistake for string comparison. If pointer comparison is needed
+ * and explicit assertion such as ASSERT_PTR_EQ() would be more appropriate.
+ */
+union hftest_any {
+	bool b;
+	char c;
+	signed char sc;
+	unsigned char uc;
+	signed short ss;
+	unsigned short us;
+	signed int si;
+	unsigned int ui;
+	signed long int sli;
+	unsigned long int uli;
+	signed long long int slli;
+	unsigned long long int ulli;
+};
+
+/* _Generic formatting doesn't seem to be supported so doing this manually. */
+/* clang-format off */
+
+/* Select the union member to match the type of the expression. */
+#define hftest_any_get(any, x)                      \
+	_Generic((x),                               \
+		bool:                   (any).b,    \
+		char:                   (any).c,    \
+		signed char:            (any).sc,   \
+		unsigned char:          (any).uc,   \
+		signed short:           (any).ss,   \
+		unsigned short:         (any).us,   \
+		signed int:             (any).si,   \
+		unsigned int:           (any).ui,   \
+		signed long int:        (any).sli,  \
+		unsigned long int:      (any).uli,  \
+		signed long long int:   (any).slli, \
+		unsigned long long int: (any).ulli)
+
+/*
+ * dlog format specifier for types. Note, these aren't the standard specifiers
+ * for the types.
+ */
+#define hftest_dlog_format(x)                 \
+	_Generic((x),                         \
+		bool:                   "%u", \
+		char:                   "%c", \
+		signed char:            "%d", \
+		unsigned char:          "%u", \
+		signed short:           "%d", \
+		unsigned short:         "%u", \
+		signed int:             "%d", \
+		unsigned int:           "%u", \
+		signed long int:        "%d", \
+		unsigned long int:      "%u", \
+		signed long long int:   "%d", \
+		unsigned long long int: "%u")
+
+/* clang-format on */
+
+#define ASSERT_OP(lhs, rhs, op, fatal)                                         \
+	do {                                                                   \
+		union hftest_any lhs_value;                                    \
+		union hftest_any rhs_value;                                    \
+		hftest_any_get(lhs_value, lhs) = (lhs);                        \
+		hftest_any_get(rhs_value, rhs) = (rhs);                        \
+		if (!(hftest_any_get(lhs_value, lhs)                           \
+			      op hftest_any_get(rhs_value, rhs))) {            \
+			++hftest_ctx->failures;                                \
+			dlog(HFTEST_LOG_PREFIX "  %s:%u: Failure\n", __FILE__, \
+			     __LINE__);                                        \
+			dlog(HFTEST_LOG_PREFIX "    %s %s %s (%s=", #lhs, #op, \
+			     #rhs, #lhs);                                      \
+			dlog(hftest_dlog_format(lhs),                          \
+			     hftest_any_get(lhs_value, lhs));                  \
+			dlog(", %s=", #rhs);                                   \
+			dlog(hftest_dlog_format(rhs),                          \
+			     hftest_any_get(rhs_value, rhs));                  \
+			dlog(")\n");                                           \
+			if (fatal) {                                           \
+				return;                                        \
+			}                                                      \
+		}                                                              \
+	} while (0)