Add initial support for gtest
Bug: 138738352
Change-Id: Ifa8b7eabe3faf5cea2c2bf6bce41fd41075d2be8
diff --git a/lib/googletest/include/trusty-gtest.h b/lib/googletest/include/trusty-gtest.h
new file mode 100644
index 0000000..f2d0972
--- /dev/null
+++ b/lib/googletest/include/trusty-gtest.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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 <gtest/gtest.h>
+#include <lib/unittest/unittest.h>
+#include <lk/compiler.h>
+
+#define PORT_GTEST(suite_name, port_name_string) \
+ __BEGIN_CDECLS \
+ static bool run_##suite_name(struct unittest* test) { \
+ return RUN_ALL_TESTS(); \
+ } \
+ \
+ int main(int argc, char** argv) { \
+ static struct unittest test = { \
+ .port_name = port_name_string, \
+ .run_test = run_##suite_name, \
+ }; \
+ struct unittest* tests = &test; \
+ /* gtest requires argc > 1 */ \
+ int fake_argc = 1; \
+ char* fake_argv[] = {(char*)"test", NULL}; \
+ testing::InitGoogleTest(&fake_argc, fake_argv); \
+ return unittest_main(&tests, 1); \
+ } \
+ __END_CDECLS
diff --git a/lib/googletest/rules.mk b/lib/googletest/rules.mk
new file mode 100644
index 0000000..d69278c
--- /dev/null
+++ b/lib/googletest/rules.mk
@@ -0,0 +1,54 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_STATIC_LIB := true
+
+GTEST_DIR := external/googletest/googletest
+
+# Export gtest headers.
+GLOBAL_INCLUDES += $(GTEST_DIR)/include
+
+# gtest has internal includes relative to its root directory.
+MODULE_INCLUDES += $(GTEST_DIR)
+
+# Disable optional features.
+MODULE_COMPILEFLAGS += \
+ -DGTEST_HAS_CLONE=0 \
+ -DGTEST_HAS_EXCEPTIONS=0 \
+ -DGTEST_HAS_POSIX_RE=0 \
+ -DGTEST_HAS_PTHREAD=0 \
+ -DGTEST_HAS_RTTI=0 \
+ -DGTEST_HAS_STD_WSTRING=0 \
+ -DGTEST_HAS_SEH=0 \
+ -DGTEST_HAS_STREAM_REDIRECTION=0 \
+ -DGTEST_LINKED_AS_SHARED_LIBRARY=0 \
+ -DGTEST_CREATE_SHARED_LIBRARY=0 \
+ -DGTEST_HAS_DEATH_TEST=0 \
+
+# Horrible hack for preventing OS detection.
+# If we don't prevent OS detection, gtest-port.h will try to enable death tests.
+MODULE_COMPILEFLAGS += -DGTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_=1
+
+# After disabling a bunch of features, there are dead constants.
+MODULE_COMPILEFLAGS += -Wno-unused-const-variable
+
+# Explicitly list the files instead of using gtest-all.cc so the build can be
+# parallelized. Note we need to build all the files because of how command line
+# flags are handled. For example, we don't support death tests, but still need
+# to compile gtest-death-test.cc because gtest.cc references
+# GTEST_FLAG(death_test_style).
+MODULE_SRCS := \
+ $(GTEST_DIR)/src/gtest.cc \
+ $(GTEST_DIR)/src/gtest-death-test.cc \
+ $(GTEST_DIR)/src/gtest-filepath.cc \
+ $(GTEST_DIR)/src/gtest-matchers.cc \
+ $(GTEST_DIR)/src/gtest-port.cc \
+ $(GTEST_DIR)/src/gtest-printers.cc \
+ $(GTEST_DIR)/src/gtest-test-part.cc \
+ $(GTEST_DIR)/src/gtest-typed-test.cc \
+
+MODULE_DEPS := \
+ trusty/user/base/lib/libstdc++-trusty \
+
+include make/module.mk
diff --git a/lib/libc-trusty/file_stubs.c b/lib/libc-trusty/file_stubs.c
new file mode 100644
index 0000000..af1d32a
--- /dev/null
+++ b/lib/libc-trusty/file_stubs.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* These stubs exist mostly to support gtest. */
+
+FILE* fopen(const char* restrict filename, const char* restrict mode) {
+ errno = ENOENT;
+ return NULL;
+}
+
+/*
+ * gtest expects getcwd to return a non-empty string, otherwise it will error
+ * internally.
+ */
+char* getcwd(char* buf, size_t size) {
+ strncpy(buf, "/", size);
+ return buf;
+}
+
+int isatty(int fd) {
+ return 0;
+}
+
+int remove(const char* pathname) {
+ errno = EACCES;
+ return -1;
+}
+
+int mkdir(const char* pathname, mode_t mode) {
+ errno = EACCES;
+ return -1;
+}
+
+int stat(const char* path, struct stat* buf) {
+ errno = EACCES;
+ return -1;
+}
diff --git a/lib/libc-trusty/include/sys/wait.h b/lib/libc-trusty/include/sys/wait.h
new file mode 100644
index 0000000..29bd9c1
--- /dev/null
+++ b/lib/libc-trusty/include/sys/wait.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * 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
+ *
+ * http://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
+
+/*
+ * The standard version of this file defines "wait" which conflicts with
+ * Trusty's "wait". This causes a problem when compiling gtest.
+ * Trusty's wait function should probally be renamed, but since naming is
+ * difficult we're adding this file to punt and mask the standard version.
+ */
diff --git a/lib/libc-trusty/rules.mk b/lib/libc-trusty/rules.mk
index 3cfb45b..aa903a4 100644
--- a/lib/libc-trusty/rules.mk
+++ b/lib/libc-trusty/rules.mk
@@ -72,6 +72,19 @@
MODULE_COMPILEFLAGS += \
-Wno-unknown-pragmas \
+# Musl will do something like this:
+# weak_alias(a, b); weak_alias(b, c);
+# But it appears the second statement will get eagerly evaluated to:
+# weak_alias(a, c);
+# and overriding b will not affect c. This is likely not intended behavior, but
+# it does not matter for us so ignore it.
+MODULE_COMPILEFLAGS += \
+ -Wno-ignored-attributes \
+
+# The are compares that make sense in 64-bit but do not make sense in 32-bit.
+MODULE_COMPILEFLAGS += \
+ -Wno-tautological-constant-compare
+
# NOTE eabi_unwind_stubs.c because libgcc pulls in unwinding stuff.
# NOTE using dlmalloc because it's difficult to guarentee Musl's malloc will
# work without mmap.
@@ -79,6 +92,7 @@
external/lk/lib/libc/eabi_unwind_stubs.c \
$(LOCAL_DIR)/__dso_handle.c \
$(LOCAL_DIR)/__set_thread_area.c \
+ $(LOCAL_DIR)/file_stubs.c \
$(LOCAL_DIR)/locale_stubs.c \
$(LOCAL_DIR)/malloc.c \
$(LOCAL_DIR)/time_stubs.c \
@@ -261,14 +275,20 @@
$(MUSL_DIR)/src/string/wmemmove.c \
$(MUSL_DIR)/src/string/wmemset.c \
$(MUSL_DIR)/src/stdio/asprintf.c \
+ $(MUSL_DIR)/src/stdio/fclose.c \
$(MUSL_DIR)/src/stdio/fflush.c \
+ $(MUSL_DIR)/src/stdio/fileno.c \
$(MUSL_DIR)/src/stdio/fputc.c \
$(MUSL_DIR)/src/stdio/fputs.c \
$(MUSL_DIR)/src/stdio/fprintf.c \
+ $(MUSL_DIR)/src/stdio/fread.c \
+ $(MUSL_DIR)/src/stdio/fseek.c \
+ $(MUSL_DIR)/src/stdio/ftell.c \
$(MUSL_DIR)/src/stdio/fwrite.c \
$(MUSL_DIR)/src/stdio/getc.c \
$(MUSL_DIR)/src/stdio/ofl.c \
$(MUSL_DIR)/src/stdio/printf.c \
+ $(MUSL_DIR)/src/stdio/putc_unlocked.c \
$(MUSL_DIR)/src/stdio/putchar.c \
$(MUSL_DIR)/src/stdio/puts.c \
$(MUSL_DIR)/src/stdio/sscanf.c \
@@ -279,6 +299,7 @@
$(MUSL_DIR)/src/stdio/stdout.c \
$(MUSL_DIR)/src/stdio/ungetc.c \
$(MUSL_DIR)/src/stdio/vasprintf.c \
+ $(MUSL_DIR)/src/stdio/vprintf.c \
$(MUSL_DIR)/src/stdio/vfprintf.c \
$(MUSL_DIR)/src/stdio/vsnprintf.c \
$(MUSL_DIR)/src/stdio/vsprintf.c \
@@ -300,6 +321,10 @@
$(MUSL_DIR)/src/thread/default_attr.c \
$(MUSL_DIR)/src/thread/pthread_once.c \
$(MUSL_DIR)/src/thread/pthread_cleanup_push.c \
+ $(MUSL_DIR)/src/time/gettimeofday.c \
+ $(MUSL_DIR)/src/time/localtime.c \
+ $(MUSL_DIR)/src/time/localtime_r.c \
+ $(MUSL_DIR)/src/time/__secs_to_tm.c \
# Math
MODULE_SRCS += \
diff --git a/lib/libc-trusty/time_stubs.c b/lib/libc-trusty/time_stubs.c
index 1ca4daa..b2c124c 100644
--- a/lib/libc-trusty/time_stubs.c
+++ b/lib/libc-trusty/time_stubs.c
@@ -37,3 +37,18 @@
const struct tm* restrict tm) {
return strftime_l(s, n, f, tm, 0);
}
+
+/* Mock Musl function for timezone information - no databases available. */
+void __secs_to_zone(long long t,
+ int local,
+ int* isdst,
+ long* offset,
+ long* oppoff,
+ const char** zonename) {
+ /* UTC+0 */
+ *isdst = 0;
+ *offset = 0;
+ if (oppoff)
+ *oppoff = 0;
+ *zonename = "UTC";
+}