summaryrefslogtreecommitdiffstats
path: root/testing/gtest/mozilla/GTestRunner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'testing/gtest/mozilla/GTestRunner.cpp')
-rw-r--r--testing/gtest/mozilla/GTestRunner.cpp179
1 files changed, 179 insertions, 0 deletions
diff --git a/testing/gtest/mozilla/GTestRunner.cpp b/testing/gtest/mozilla/GTestRunner.cpp
new file mode 100644
index 0000000000..7c1581f058
--- /dev/null
+++ b/testing/gtest/mozilla/GTestRunner.cpp
@@ -0,0 +1,179 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * * This Source Code Form is subject to the terms of the Mozilla Public
+ * * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GTestRunner.h"
+#include "gtest/gtest.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/glean/fog_ffi_generated.h"
+#include "nsICrashReporter.h"
+#include "nsString.h"
+#include "testing/TestHarness.h"
+#include "prenv.h"
+#ifdef ANDROID
+# include <android/log.h>
+#endif
+#ifdef XP_WIN
+# include "mozilla/ipc/WindowsMessageLoop.h"
+#endif
+
+using ::testing::EmptyTestEventListener;
+using ::testing::InitGoogleTest;
+using ::testing::TestEventListeners;
+using ::testing::TestInfo;
+using ::testing::TestPartResult;
+using ::testing::UnitTest;
+
+namespace mozilla {
+
+#ifdef ANDROID
+# define MOZ_STDOUT_PRINT(...) \
+ __android_log_print(ANDROID_LOG_INFO, "gtest", __VA_ARGS__);
+#else
+# define MOZ_STDOUT_PRINT(...) printf(__VA_ARGS__);
+#endif
+
+#define MOZ_PRINT(...) \
+ MOZ_STDOUT_PRINT(__VA_ARGS__); \
+ if (mLogFile) { \
+ fprintf(mLogFile, __VA_ARGS__); \
+ }
+
+// See gtest.h for method documentation
+class MozillaPrinter : public EmptyTestEventListener {
+ public:
+ MozillaPrinter() : mLogFile(nullptr) {
+ char* path = PR_GetEnv("MOZ_GTEST_LOG_PATH");
+ if (path) {
+ mLogFile = fopen(path, "w");
+ }
+ }
+ virtual void OnTestProgramStart(const UnitTest& /* aUnitTest */) override {
+ MOZ_PRINT("TEST-INFO | GTest unit test starting\n");
+ }
+ virtual void OnTestProgramEnd(const UnitTest& aUnitTest) override {
+ MOZ_PRINT("TEST-%s | GTest unit test: %s\n",
+ aUnitTest.Passed() ? "PASS" : "UNEXPECTED-FAIL",
+ aUnitTest.Passed() ? "passed" : "failed");
+ MOZ_PRINT("Passed: %d\n", aUnitTest.successful_test_count());
+ MOZ_PRINT("Failed: %d\n", aUnitTest.failed_test_count());
+ if (mLogFile) {
+ fclose(mLogFile);
+ mLogFile = nullptr;
+ }
+ }
+ virtual void OnTestStart(const TestInfo& aTestInfo) override {
+ mTestInfo = &aTestInfo;
+ MOZ_PRINT("TEST-START | %s.%s\n", mTestInfo->test_case_name(),
+ mTestInfo->name());
+ }
+ virtual void OnTestPartResult(
+ const TestPartResult& aTestPartResult) override {
+ MOZ_PRINT("TEST-%s | %s.%s | %s @ %s:%i\n",
+ !aTestPartResult.failed() ? "PASS" : "UNEXPECTED-FAIL",
+ mTestInfo ? mTestInfo->test_case_name() : "?",
+ mTestInfo ? mTestInfo->name() : "?", aTestPartResult.summary(),
+ aTestPartResult.file_name(), aTestPartResult.line_number());
+ }
+ virtual void OnTestEnd(const TestInfo& aTestInfo) override {
+ MOZ_PRINT("TEST-%s | %s.%s | test completed (time: %" PRIi64 "ms)\n",
+ aTestInfo.result()->Passed() ? "PASS" : "UNEXPECTED-FAIL",
+ aTestInfo.test_case_name(), aTestInfo.name(),
+ aTestInfo.result()->elapsed_time());
+ MOZ_ASSERT(&aTestInfo == mTestInfo);
+ mTestInfo = nullptr;
+ }
+
+ const TestInfo* mTestInfo;
+ FILE* mLogFile;
+};
+
+static void ReplaceGTestLogger() {
+ // Replace the GTest logger so that it can be passed
+ // by the mozilla test parsers.
+ // Code is based on:
+ // http://googletest.googlecode.com/svn/trunk/samples/sample9_unittest.cc
+ UnitTest& unitTest = *UnitTest::GetInstance();
+ TestEventListeners& listeners = unitTest.listeners();
+ delete listeners.Release(listeners.default_result_printer());
+
+ listeners.Append(new MozillaPrinter);
+}
+
+int RunGTestFunc(int* argc, char** argv) {
+ InitGoogleTest(argc, argv);
+
+ if (getenv("MOZ_TBPL_PARSER")) {
+ ReplaceGTestLogger();
+ }
+
+ PR_SetEnv("XPCOM_DEBUG_BREAK=stack-and-abort");
+
+ ScopedXPCOM xpcom("GTest");
+
+#ifdef XP_WIN
+ mozilla::ipc::windows::InitUIThread();
+#endif
+#ifdef ANDROID
+ // On Android, gtest is running in an application, which uses a
+ // current working directory of '/' by default. Desktop tests
+ // sometimes assume that support files are in the current
+ // working directory. For compatibility with desktop, the Android
+ // harness pushes test support files to the device at the location
+ // specified by MOZ_GTEST_CWD and gtest changes the cwd to that
+ // location.
+ char* path = PR_GetEnv("MOZ_GTEST_CWD");
+ chdir(path);
+#endif
+ nsCOMPtr<nsICrashReporter> crashreporter;
+ char* crashreporterStr = PR_GetEnv("MOZ_CRASHREPORTER");
+ if (crashreporterStr && !strcmp(crashreporterStr, "1")) {
+ // TODO: move this to an even-more-common location to use in all
+ // C++ unittests
+ crashreporter = do_GetService("@mozilla.org/toolkit/crash-reporter;1");
+ if (crashreporter) {
+ printf_stderr("Setting up crash reporting\n");
+ char* path = PR_GetEnv("MOZ_GTEST_MINIDUMPS_PATH");
+ nsCOMPtr<nsIFile> file;
+ if (path) {
+ nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(path), true,
+ getter_AddRefs(file));
+ if (NS_FAILED(rv)) {
+ printf_stderr("Ignoring invalid MOZ_GTEST_MINIDUMPS_PATH\n");
+ }
+ }
+ if (!file) {
+ nsCOMPtr<nsIProperties> dirsvc =
+ do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
+ nsresult rv = dirsvc->Get(NS_OS_CURRENT_WORKING_DIR,
+ NS_GET_IID(nsIFile), getter_AddRefs(file));
+ MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
+ }
+ crashreporter->SetEnabled(true);
+ crashreporter->SetMinidumpPath(file);
+ }
+ }
+
+ // FOG should init exactly once, as early into running as possible, to enable
+ // instrumentation tests to work properly.
+ // However, at init, Glean may decide to send a ping. So let's first tell FOG
+ // that these pings shouldn't actually be uploaded.
+ Preferences::SetInt("telemetry.fog.test.localhost_port", -1);
+ const nsCString empty;
+ glean::impl::fog_init(&empty, &empty);
+
+ return RUN_ALL_TESTS();
+}
+
+// We use a static var 'RunGTest' defined in nsAppRunner.cpp.
+// RunGTest is initialized to nullptr but if GTest (this file)
+// is linked in then RunGTest will be set here indicating
+// GTest is supported.
+class _InitRunGTest {
+ public:
+ _InitRunGTest() { RunGTest = RunGTestFunc; }
+} InitRunGTest;
+
+} // namespace mozilla