htest: service boilerplate for secondary VMs.
In order to keep it easy to add tests, we need to avoid requiring new
VMs for each case as this will lead to an explosion of duplication and
build artifacts.
Allowing secondary VMs to contain selectable services for different
tests means they don't each require a separate VM and run into resource
limits. The resulting services are also avoid boilerplate so the source
gets to the point of the test more easily.
The primary VMs are also refactored to encourage splitting tests across
file but bundling them into the same VM so as to cut down on build
artifacts and make it easier to find and run tests.
Assertions can now be used in any context of a test, including in a test
service.
Change-Id: Id3b8a7579d0facdfceb9d77f62ef57241b31a88a
diff --git a/test/hftest/hftest.c b/test/hftest/hftest.c
index 6a66fed..04a07a6 100644
--- a/test/hftest/hftest.c
+++ b/test/hftest/hftest.c
@@ -19,8 +19,11 @@
#include <stdalign.h>
#include <stdint.h>
+#include "hf/arch/vm/power_mgmt.h"
+
#include "hf/fdt.h"
#include "hf/memiter.h"
+#include "hf/std.h"
alignas(4096) uint8_t kstack[4096];
@@ -29,6 +32,13 @@
extern struct hftest_test hftest_begin[];
extern struct hftest_test hftest_end[];
+static struct hftest_context global_context;
+
+struct hftest_context *hftest_get_context(void)
+{
+ return &global_context;
+}
+
static void json(void)
{
struct hftest_test *test;
@@ -62,9 +72,11 @@
if (!tests_in_suite) {
HFTEST_LOG(" \"tests\": [");
}
- /* It's easier to put the comma at the start of the line
+ /*
+ * It's easier to put the comma at the start of the line
* than the end even
- * though the JSON looks a bit funky. */
+ * though the JSON looks a bit funky.
+ */
HFTEST_LOG(" %c\"%s\"",
tests_in_suite ? ',' : ' ', test->name);
++tests_in_suite;
@@ -78,37 +90,43 @@
HFTEST_LOG("}");
}
+static noreturn void abort(void)
+{
+ HFTEST_LOG("FAIL");
+ shutdown();
+}
+
static void run_test(hftest_test_fn set_up, hftest_test_fn test,
hftest_test_fn tear_down)
{
- struct hftest_context ctx = {
- .failures = 0,
- };
+ /* Prepare the context. */
+ struct hftest_context *ctx = hftest_get_context();
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->abort = abort;
+ /* Run any set up functions. */
if (set_up) {
- set_up(&ctx);
- if (ctx.failures) {
- goto fail;
+ set_up();
+ if (ctx->failures) {
+ abort();
}
}
- test(&ctx);
- if (ctx.failures) {
- goto fail;
+ /* Run the test. */
+ test();
+ if (ctx->failures) {
+ abort();
}
+ /* Run any tear down functions. */
if (tear_down) {
- tear_down(&ctx);
- if (ctx.failures) {
- goto fail;
+ tear_down();
+ if (ctx->failures) {
+ abort();
}
}
- HFTEST_LOG("PASS");
- return;
-
-fail:
- HFTEST_LOG("FAIL");
+ HFTEST_LOG("FINISHED");
}
static void run(struct memiter *args)
@@ -151,8 +169,10 @@
}
switch (test->kind) {
- /* The first entries in the suite are the set up and tear down
- * functions. */
+ /*
+ * The first entries in the suite are the set up and tear down
+ * functions.
+ */
case HFTEST_KIND_SET_UP:
suite_set_up = test->fn;
break;
@@ -167,13 +187,16 @@
return;
}
break;
+ default:
+ /* Ignore other kinds. */
+ break;
}
}
HFTEST_LOG("Unable to find requested tests.");
}
-void help(void)
+static void help(void)
{
HFTEST_LOG("usage:");
HFTEST_LOG("");
@@ -193,7 +216,7 @@
HFTEST_LOG(" Run the named test from the named test suite.");
}
-void main(const struct fdt_header *fdt)
+void kmain(const struct fdt_header *fdt)
{
struct fdt_node n;
const char *bootargs;
@@ -241,8 +264,3 @@
help();
}
-
-void kmain(const struct fdt_header *fdt)
-{
- main(fdt);
-}