A test with the mock arch
Change-Id: I9af804df9cf1019f0b9c5535d7d79aca28229f88
diff --git a/.clang-tidy b/.clang-tidy
index 2eacd36..ff9ba18 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,4 +1,5 @@
-Checks: 'readability-*,portability-*,performance-*,misc-*,bugprone-*,modernize-*'
-HeaderFilterRegex: '.*'
+Checks: 'readability-*,portability-*,performance-*,misc-*,bugprone-*,modernize-*
+ ,-modernize-deprecated-headers,-clang-analyzer-valist.Uninitialized'
+HeaderFilterRegex: '^(?!third_party).+'
FormatStyle: file
WarningsAsErrors: '*'
diff --git a/.gitmodules b/.gitmodules
index d274169..aecbc7a 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -5,3 +5,7 @@
[submodule "driver/linux"]
path = driver/linux
url = sso://hafnium/hafnium/driver/linux
+[submodule "third_party/googletest"]
+ path = third_party/googletest
+ url = sso://hafnium/hafnium/third_party/googletest
+ shallow = true
diff --git a/BUILD.gn b/BUILD.gn
index cef1259..622f91e 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1,6 +1,23 @@
import("//build/image/image.gni")
-group("arch_images") {
+group("tests") {
+ testonly = true
+
+ deps = [
+ ":unit_tests",
+ ":vm_tests",
+ ]
+}
+
+group("unit_tests") {
+ testonly = true
+
+ deps = [
+ "//src:unit_tests($mock_toolchain)",
+ ]
+}
+
+group("vm_tests") {
testonly = true
deps = [
diff --git a/Makefile b/Makefile
index 4c2476c..467b068 100644
--- a/Makefile
+++ b/Makefile
@@ -45,9 +45,9 @@
.PHONY: format
format:
@echo "Formatting..."
- @find src/ -name *.c -o -name *.h | xargs clang-format -style file -i
- @find inc/ -name *.c -o -name *.h | xargs clang-format -style file -i
- @find test/ -name *.c -o -name *.h | xargs clang-format -style file -i
+ @find src/ -name *.c -o -name *.cc -o -name *.h | xargs clang-format -style file -i
+ @find inc/ -name *.c -o -name *.cc -o -name *.h | xargs clang-format -style file -i
+ @find test/ -name *.c -o -name *.cc -o -name *.h | xargs clang-format -style file -i
@find . \( -name *.gn -o -name *.gni \) -exec $(GN) format {} \;
# see .clang-tidy.
@@ -55,12 +55,12 @@
tidy: $(OUT_DIR)/build.ninja
@$(NINJA) -C $(OUT_DIR)
@echo "Tidying..."
- @find src/ -name *.c -exec clang-tidy -p $(OUT_DIR) -fix {} \;
- @find test/ -name *.c -exec clang-tidy -p $(OUT_DIR) -fix {} \;
+ @find src/ \( -name *.c -o -name *.cc \) -exec clang-tidy -p $(OUT_DIR) -fix {} \;
+ @find test/ \( -name *.c -o -name *.cc \) -exec clang-tidy -p $(OUT_DIR) -fix {} \;
.PHONY: check
check: $(OUT_DIR)/build.ninja
@$(NINJA) -C $(OUT_DIR)
@echo "Checking..."
- @find src/ -name *.c -exec clang-check -p $(OUT_DIR) -analyze {} \;
- @find test/ -name *.c -exec clang-check -p $(OUT_DIR) -analyze {} \;
+ @find src/ \( -name *.c -o -name *.cc \) -exec clang-check -p $(OUT_DIR) -analyze {} \;
+ @find test/ \( -name *.c -o -name *.cc \) -exec clang-check -p $(OUT_DIR) -analyze {} \;
diff --git a/build/BUILD.gn b/build/BUILD.gn
index cd5feb1..52793dd 100644
--- a/build/BUILD.gn
+++ b/build/BUILD.gn
@@ -16,39 +16,43 @@
cflags_cc = [ "-std=c++14" ]
- if (is_debug) {
- defines = [ "DEBUG=1" ]
- } else {
- defines = [ "DEBUG=0" ]
- }
-
- # Configuration specific for the bare metal images
- if (current_toolchain == arch_toolchain) {
+ if (current_toolchain == mock_toolchain ||
+ current_toolchain == arch_toolchain) {
include_dirs = [
"//inc",
"//src/arch/${arch}/inc",
- "${root_gen_dir}/inc",
]
- cflags += [
- "-mcpu=${arch_cpu}",
- "-fno-stack-protector",
- "-fno-builtin",
- "-ffreestanding",
- "-fpic",
- ]
-
- defines += [
+ defines = [
# TODO: move these build args for the platforms
"MAX_CPUS=8",
"MAX_VMS=16",
"STACK_SIZE=4096",
]
- # TODO: this should be arch specific but it is currenly used by the
- # platform generic code to map the memory
- if (arch_aarch64_use_pl011) {
- defines += [ "PL011_BASE=${arch_aarch64_pl011_base_address}" ]
+ if (is_debug) {
+ defines += [ "DEBUG=1" ]
+ } else {
+ defines += [ "DEBUG=0" ]
+ }
+
+ # Configuration specific for the bare metal images.
+ if (current_toolchain == arch_toolchain) {
+ include_dirs += [ "${root_gen_dir}/inc" ]
+
+ cflags += [
+ "-mcpu=${arch_cpu}",
+ "-fno-stack-protector",
+ "-fno-builtin",
+ "-ffreestanding",
+ "-fpic",
+ ]
+
+ # TODO: this should be arch specific but it is currenly used by the
+ # platform generic code to map the memory
+ if (arch_aarch64_use_pl011) {
+ defines += [ "PL011_BASE=${arch_aarch64_pl011_base_address}" ]
+ }
}
}
}
@@ -67,5 +71,7 @@
}
config("lto") {
- cflags = [ "-flto" ]
+ if (current_toolchain == arch_toolchain) {
+ cflags = [ "-flto" ]
+ }
}
diff --git a/build/BUILDCONFIG.gn b/build/BUILDCONFIG.gn
index b4100be..605539a 100644
--- a/build/BUILDCONFIG.gn
+++ b/build/BUILDCONFIG.gn
@@ -31,7 +31,7 @@
assert(host_os == "linux", "Only linux builds are currently supported")
# Check that the requested architecture is supported
-assert(arch == "aarch64", "Unsupported arch: $arch")
+assert(arch == "aarch64" || arch == "mock", "Unsupported arch: $arch")
# Setup the standard variables
if (target_os == "") {
@@ -77,10 +77,12 @@
if (use_gcc) {
host_toolchain = "//build/toolchain/host:gcc"
target_toolchain = "//build/toolchain/host:gcc"
+ mock_toolchain = "//build/toolchain/host:gcc_mock_arch"
arch_toolchain = "//build/toolchain/arch:gcc_${arch}"
} else {
host_toolchain = "//build/toolchain/host:clang"
target_toolchain = "//build/toolchain/host:clang"
+ mock_toolchain = "//build/toolchain/host:clang_mock_arch"
arch_toolchain = "//build/toolchain/arch:clang_${arch}"
}
diff --git a/build/toolchain/host/BUILD.gn b/build/toolchain/host/BUILD.gn
index 8ab38e5..7382097 100644
--- a/build/toolchain/host/BUILD.gn
+++ b/build/toolchain/host/BUILD.gn
@@ -104,6 +104,12 @@
command = "cp -af {{source}} {{output}}"
description = "COPY {{source}} {{output}}"
}
+
+ if (defined(invoker.toolchain_args)) {
+ toolchain_args = {
+ forward_variables_from(invoker.toolchain_args, "*")
+ }
+ }
}
}
@@ -115,9 +121,35 @@
cflags = "-fcolor-diagnostics"
}
+cc_toolchain("clang_mock_arch") {
+ ar = "llvm-ar"
+ cc = "clang"
+ cxx = "clang++"
+ cflags = "-fcolor-diagnostics"
+
+ toolchain_args = {
+ # When building for the host, use the mock architecture to make things
+ # testable.
+ arch = "mock"
+ }
+}
+
cc_toolchain("gcc") {
ar = "ar"
cc = "gcc"
cxx = "g++"
cflags = "-fdiagnostics-color=always"
}
+
+cc_toolchain("gcc_mock_arch") {
+ ar = "ar"
+ cc = "gcc"
+ cxx = "g++"
+ cflags = "-fdiagnostics-color=always"
+
+ toolchain_args = {
+ # When building for the host, use the mock architecture to make things
+ # testable.
+ arch = "mock"
+ }
+}
diff --git a/kokoro/ubuntu/test.sh b/kokoro/ubuntu/test.sh
index 6d146b6..cb28a0d 100755
--- a/kokoro/ubuntu/test.sh
+++ b/kokoro/ubuntu/test.sh
@@ -9,8 +9,14 @@
set -x
TIMEOUT="timeout --foreground"
-OUT="out/aarch64/qemu/clang_aarch64"
-HFTEST="timeout --foreground 30s ./test/vm/hftest.py --out $OUT --initrd"
+OUT="out/aarch64/qemu"
+HFTEST="$TIMEOUT 30s ./test/vm/hftest.py --out $OUT/clang_aarch64 --initrd"
+
+# Run the host unit tests
+mkdir -p $OUT/clang_mock_arch/test_log/unit_tests
+$TIMEOUT 30s $OUT/clang_mock_arch/unit_tests \
+ --gtest_output="xml:$OUT/clang_mock_arch/test_log/unit_tests/sponge_log.xml" \
+ | tee $OUT/clang_mock_arch/test_log/unit_tests/sponge_log.log
# Run the tests with a timeout so they can't loop forever.
$HFTEST primary_only_test
diff --git a/src/BUILD.gn b/src/BUILD.gn
index acac35f..82b12c8 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -46,6 +46,11 @@
sources = [
"fdt.c",
]
+
+ deps = [
+ ":common",
+ ":common_debug",
+ ]
}
source_set("memiter") {
@@ -53,3 +58,16 @@
"memiter.c",
]
}
+
+executable("unit_tests") {
+ testonly = true
+
+ sources = [
+ "fdt_test.cc",
+ ]
+
+ deps = [
+ ":fdt",
+ "//third_party:gtest_main",
+ ]
+}
diff --git a/src/arch/aarch64/inc/hf/arch/cpu.h b/src/arch/aarch64/inc/hf/arch/cpu.h
index f2fb4c8..b4d9614 100644
--- a/src/arch/aarch64/inc/hf/arch/cpu.h
+++ b/src/arch/aarch64/inc/hf/arch/cpu.h
@@ -1,6 +1,5 @@
#pragma once
-#include <stdalign.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
diff --git a/src/arch/mock/BUILD.gn b/src/arch/mock/BUILD.gn
new file mode 100644
index 0000000..60c3428
--- /dev/null
+++ b/src/arch/mock/BUILD.gn
@@ -0,0 +1,6 @@
+# Mock implementation of putchar logs to the console.
+source_set("putchar") {
+ sources = [
+ "putchar.c",
+ ]
+}
diff --git a/src/arch/mock/inc/hf/arch/addr.h b/src/arch/mock/inc/hf/arch/addr.h
new file mode 100644
index 0000000..d8ba79d
--- /dev/null
+++ b/src/arch/mock/inc/hf/arch/addr.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <stdint.h>
+
+#define PAGE_BITS 12
+
+/* Integer type large enough to hold a physical address. */
+typedef uintptr_t uintpaddr_t;
+
+/* Integer type large enough to hold a virtual address. */
+typedef uintptr_t uintvaddr_t;
diff --git a/src/arch/mock/inc/hf/arch/cpu.h b/src/arch/mock/inc/hf/arch/cpu.h
new file mode 100644
index 0000000..9fbd041
--- /dev/null
+++ b/src/arch/mock/inc/hf/arch/cpu.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <stdint.h>
+
+struct arch_regs {
+ uint32_t r[5];
+};
+
+static inline struct cpu *cpu(void)
+{
+ /* TODO: */
+ return NULL;
+}
+
+static inline void arch_irq_disable(void)
+{
+ /* TODO */
+}
+
+static inline void arch_irq_enable(void)
+{
+ /* TODO */
+}
diff --git a/src/arch/mock/putchar.c b/src/arch/mock/putchar.c
new file mode 100644
index 0000000..3452b37
--- /dev/null
+++ b/src/arch/mock/putchar.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+#include "hf/dlog.h"
+
+void arch_putchar(char c)
+{
+ putchar(c);
+}
diff --git a/src/cpu.c b/src/cpu.c
index 217baea..cec490e 100644
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -1,5 +1,7 @@
#include "hf/cpu.h"
+#include <stdalign.h>
+
#include "hf/arch/cpu.h"
#include "hf/api.h"
diff --git a/src/fdt_test.cc b/src/fdt_test.cc
new file mode 100644
index 0000000..cb0d14c
--- /dev/null
+++ b/src/fdt_test.cc
@@ -0,0 +1,68 @@
+extern "C" {
+
+#include "hf/fdt.h"
+}
+
+#include <gmock/gmock.h>
+
+using ::testing::Eq;
+
+/*
+ * /dts-v1/;
+ *
+ * / {
+ * model = "SomeModel";
+ * compatible = "Nothing";
+ * #address-cells = <2>;
+ * #size-cells = <2>;
+ *
+ * memory@0 {
+ * device_type = "memory";
+ * reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
+ * };
+ *
+ * cpus {
+ * #address-cells = <1>;
+ * #size-cells = <0>;
+ * };
+ *
+ * };
+ *
+ * $ dtc --boot-cpu 0 --in-format dts --out-format dtb --out-version 17 test.dts
+ * | xxd
+ */
+
+static const uint8_t test_dtb[] = {
+ 0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00, 0x00, 0x38,
+ 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+ 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0a,
+ 0x00, 0x00, 0x00, 0x00, 0x53, 0x6f, 0x6d, 0x65, 0x4d, 0x6f, 0x64, 0x65,
+ 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x06, 0x4e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
+ 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x40, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2c,
+ 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x63, 0x70, 0x75, 0x73,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09,
+ 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x00, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74,
+ 0x69, 0x62, 0x6c, 0x65, 0x00, 0x23, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x2d, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x00, 0x23, 0x73, 0x69, 0x7a,
+ 0x65, 0x2d, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x00, 0x64, 0x65, 0x76, 0x69,
+ 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x00, 0x72, 0x65, 0x67, 0x00};
+
+TEST(fdt, total_size)
+{
+ EXPECT_THAT(fdt_total_size((struct fdt_header *)&test_dtb[0]),
+ Eq(sizeof(test_dtb)));
+}
diff --git a/test/vm/hftest.py b/test/vm/hftest.py
index e21cf35..0e85dd2 100755
--- a/test/vm/hftest.py
+++ b/test/vm/hftest.py
@@ -9,6 +9,7 @@
import xml.etree.ElementTree as ET
import argparse
+import datetime
import json
import os
import re
@@ -81,6 +82,9 @@
test_re = re.compile(args.test or ".*")
sponge = ET.Element("testsuites")
sponge.set("name", args.initrd)
+ sponge.set(
+ "timestamp",
+ datetime.datetime.now().replace(microsecond=0).isoformat())
for suite in tests["suites"]:
if not suite_re.match(suite["name"]):
continue
@@ -93,6 +97,7 @@
continue
sponge_test = ET.SubElement(sponge_suite, "testcase")
sponge_test.set("name", test)
+ sponge_test.set("classname", suite['name'])
sponge_test.set("status", "run")
tests_run_from_suite += 1
if tests_run_from_suite == 1:
diff --git a/third_party/BUILD.gn b/third_party/BUILD.gn
new file mode 100644
index 0000000..af59e92
--- /dev/null
+++ b/third_party/BUILD.gn
@@ -0,0 +1,38 @@
+config("gtest_config") {
+ visibility = [ ":gtest" ]
+
+ include_dirs = [
+ "googletest/googletest/include",
+ "googletest/googlemock/include",
+ ]
+
+ ldflags = [ "-pthread" ]
+}
+
+source_set("gtest") {
+ testonly = true
+
+ sources = [
+ "googletest/googlemock/src/gmock-all.cc",
+ "googletest/googletest/src/gtest-all.cc",
+ ]
+
+ include_dirs = [
+ "googletest/googletest",
+ "googletest/googlemock",
+ ]
+
+ all_dependent_configs = [ ":gtest_config" ]
+}
+
+source_set("gtest_main") {
+ testonly = true
+
+ sources = [
+ "googletest/googlemock/src/gmock_main.cc",
+ ]
+
+ deps = [
+ ":gtest",
+ ]
+}
diff --git a/third_party/googletest b/third_party/googletest
new file mode 160000
index 0000000..c7a8998
--- /dev/null
+++ b/third_party/googletest
@@ -0,0 +1 @@
+Subproject commit c7a899855656fb0bba2c98ba70bc26333471eb92