summaryrefslogtreecommitdiffstats
path: root/testing/gtest/mozilla
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/gtest/mozilla
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/gtest/mozilla')
-rw-r--r--testing/gtest/mozilla/GTestRunner.cpp179
-rw-r--r--testing/gtest/mozilla/GTestRunner.h10
-rw-r--r--testing/gtest/mozilla/MozAssertions.cpp38
-rw-r--r--testing/gtest/mozilla/MozAssertions.h32
-rw-r--r--testing/gtest/mozilla/MozGTestBench.cpp58
-rw-r--r--testing/gtest/mozilla/MozGTestBench.h25
-rw-r--r--testing/gtest/mozilla/MozHelpers.cpp73
-rw-r--r--testing/gtest/mozilla/MozHelpers.h119
-rw-r--r--testing/gtest/mozilla/SanityTest.cpp30
-rw-r--r--testing/gtest/mozilla/WaitFor.cpp19
-rw-r--r--testing/gtest/mozilla/WaitFor.h136
-rw-r--r--testing/gtest/mozilla/gmock-custom/README.md16
-rw-r--r--testing/gtest/mozilla/gmock-custom/gmock-generated-actions.h10
-rw-r--r--testing/gtest/mozilla/gmock-custom/gmock-matchers.h36
-rw-r--r--testing/gtest/mozilla/gmock-custom/gmock-port.h39
-rw-r--r--testing/gtest/mozilla/gtest-custom/README.md56
-rw-r--r--testing/gtest/mozilla/gtest-custom/gtest-port.h39
-rw-r--r--testing/gtest/mozilla/gtest-custom/gtest-printers.h42
-rw-r--r--testing/gtest/mozilla/gtest-custom/gtest.h37
-rw-r--r--testing/gtest/mozilla/moz.build40
20 files changed, 1034 insertions, 0 deletions
diff --git a/testing/gtest/mozilla/GTestRunner.cpp b/testing/gtest/mozilla/GTestRunner.cpp
new file mode 100644
index 0000000000..269adc39b3
--- /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/FOG.h"
+#include "mozilla/Preferences.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;
+ RefPtr<FOG>(FOG::GetSingleton())->InitializeFOG(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
diff --git a/testing/gtest/mozilla/GTestRunner.h b/testing/gtest/mozilla/GTestRunner.h
new file mode 100644
index 0000000000..648a7959fa
--- /dev/null
+++ b/testing/gtest/mozilla/GTestRunner.h
@@ -0,0 +1,10 @@
+/* -*- 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/. */
+
+namespace mozilla {
+
+extern int (*RunGTest)(int*, char**);
+
+} // namespace mozilla
diff --git a/testing/gtest/mozilla/MozAssertions.cpp b/testing/gtest/mozilla/MozAssertions.cpp
new file mode 100644
index 0000000000..ed9c68cb83
--- /dev/null
+++ b/testing/gtest/mozilla/MozAssertions.cpp
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 "MozAssertions.h"
+#include "mozilla/ErrorNames.h"
+#include "nsString.h"
+
+namespace mozilla::gtest {
+
+static testing::AssertionResult NsresultFailureHelper(const char* expr,
+ const char* expected,
+ nsresult rv) {
+ nsAutoCString name;
+ GetErrorName(rv, name);
+
+ return testing::AssertionFailure()
+ << "Expected: " << expr << " " << expected << ".\n"
+ << " Actual: " << name << "\n";
+}
+
+testing::AssertionResult IsNsresultSuccess(const char* expr, nsresult rv) {
+ if (NS_SUCCEEDED(rv)) {
+ return testing::AssertionSuccess();
+ }
+ return NsresultFailureHelper(expr, "succeeds", rv);
+}
+
+testing::AssertionResult IsNsresultFailure(const char* expr, nsresult rv) {
+ if (NS_FAILED(rv)) {
+ return testing::AssertionSuccess();
+ }
+ return NsresultFailureHelper(expr, "failed", rv);
+}
+
+} // namespace mozilla::gtest
diff --git a/testing/gtest/mozilla/MozAssertions.h b/testing/gtest/mozilla/MozAssertions.h
new file mode 100644
index 0000000000..e65231692a
--- /dev/null
+++ b/testing/gtest/mozilla/MozAssertions.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_gtest_MozAssertions_h__
+#define mozilla_gtest_MozAssertions_h__
+
+#include "gtest/gtest.h"
+#include "nsError.h"
+
+namespace mozilla::gtest {
+
+testing::AssertionResult IsNsresultSuccess(const char* expr, nsresult rv);
+testing::AssertionResult IsNsresultFailure(const char* expr, nsresult rv);
+
+} // namespace mozilla::gtest
+
+#define EXPECT_NS_SUCCEEDED(expr) \
+ EXPECT_PRED_FORMAT1(::mozilla::gtest::IsNsresultSuccess, (expr))
+
+#define ASSERT_NS_SUCCEEDED(expr) \
+ ASSERT_PRED_FORMAT1(::mozilla::gtest::IsNsresultSuccess, (expr))
+
+#define EXPECT_NS_FAILED(expr) \
+ EXPECT_PRED_FORMAT1(::mozilla::gtest::IsNsresultFailure, (expr))
+
+#define ASSERT_NS_FAILED(expr) \
+ ASSERT_PRED_FORMAT1(::mozilla::gtest::IsNsresultFailure, (expr))
+
+#endif // mozilla_gtest_MozAssertions_h__
diff --git a/testing/gtest/mozilla/MozGTestBench.cpp b/testing/gtest/mozilla/MozGTestBench.cpp
new file mode 100644
index 0000000000..cc6898099e
--- /dev/null
+++ b/testing/gtest/mozilla/MozGTestBench.cpp
@@ -0,0 +1,58 @@
+/* -*- 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 "MozGTestBench.h"
+#include "mozilla/TimeStamp.h"
+#include <stdio.h>
+#include <string>
+#include <vector>
+
+#define MOZ_GTEST_BENCH_FRAMEWORK "platform_microbench"
+#define MOZ_GTEST_NUM_ITERATIONS 5
+
+namespace mozilla {
+void GTestBench(const char* aSuite, const char* aName,
+ const std::function<void()>& aTest) {
+#if defined(DEBUG) || defined(MOZ_ASAN)
+ // Run the test to make sure that it doesn't fail but don't log
+ // any measurements since it's not an optimized build.
+ aTest();
+#else
+ bool shouldAlert = bool(getenv("PERFHERDER_ALERTING_ENABLED"));
+ std::vector<int> durations;
+
+ for (int i = 0; i < MOZ_GTEST_NUM_ITERATIONS; i++) {
+ mozilla::TimeStamp start = TimeStamp::Now();
+
+ aTest();
+
+ durations.push_back((TimeStamp::Now() - start).ToMicroseconds());
+ }
+
+ std::string replicatesStr = "[" + std::to_string(durations[0]);
+ for (int i = 1; i < MOZ_GTEST_NUM_ITERATIONS; i++) {
+ replicatesStr += "," + std::to_string(durations[i]);
+ }
+ replicatesStr += "]";
+
+ // median is at index floor(i/2) if number of replicates is odd,
+ // (i/2-1) if even
+ std::sort(durations.begin(), durations.end());
+ int medianIndex =
+ (MOZ_GTEST_NUM_ITERATIONS / 2) + ((durations.size() % 2 == 0) ? (-1) : 0);
+
+ // Print the result for each test. Let perfherder aggregate for us
+ printf(
+ "PERFHERDER_DATA: {\"framework\": {\"name\": \"%s\"}, "
+ "\"suites\": [{\"name\": \"%s\", \"subtests\": "
+ "[{\"name\": \"%s\", \"value\": %i, \"replicates\": %s, "
+ "\"lowerIsBetter\": true, \"shouldAlert\": %s}]"
+ "}]}\n",
+ MOZ_GTEST_BENCH_FRAMEWORK, aSuite, aName, durations[medianIndex],
+ replicatesStr.c_str(), shouldAlert ? "true" : "false");
+#endif
+}
+
+} // namespace mozilla
diff --git a/testing/gtest/mozilla/MozGTestBench.h b/testing/gtest/mozilla/MozGTestBench.h
new file mode 100644
index 0000000000..438b977e4b
--- /dev/null
+++ b/testing/gtest/mozilla/MozGTestBench.h
@@ -0,0 +1,25 @@
+/* -*- 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/. */
+
+#ifndef GTEST_MOZGTESTBENCH_H
+#define GTEST_MOZGTESTBENCH_H
+
+#include <functional>
+
+namespace mozilla {
+
+void GTestBench(const char* aSuite, const char* aName,
+ const std::function<void()>& aTest);
+
+} // namespace mozilla
+
+#define MOZ_GTEST_BENCH(suite, test, lambdaOrFunc) \
+ TEST(suite, test) \
+ { mozilla::GTestBench(#suite, #test, lambdaOrFunc); }
+
+#define MOZ_GTEST_BENCH_F(suite, test, lambdaOrFunc) \
+ TEST_F(suite, test) { mozilla::GTestBench(#suite, #test, lambdaOrFunc); }
+
+#endif // GTEST_MOZGTESTBENCH_H
diff --git a/testing/gtest/mozilla/MozHelpers.cpp b/testing/gtest/mozilla/MozHelpers.cpp
new file mode 100644
index 0000000000..78fe614964
--- /dev/null
+++ b/testing/gtest/mozilla/MozHelpers.cpp
@@ -0,0 +1,73 @@
+#include "MozHelpers.h"
+
+#include <iostream>
+
+#include "gtest/gtest-spi.h"
+#include "mozilla/Mutex.h"
+#include "nsDebug.h"
+
+namespace mozilla::gtest {
+
+void DisableCrashReporter() {
+ nsCOMPtr<nsICrashReporter> crashreporter =
+ do_GetService("@mozilla.org/toolkit/crash-reporter;1");
+ if (crashreporter) {
+ crashreporter->SetEnabled(false);
+ }
+}
+
+class ScopedTestResultReporterImpl
+ : public ScopedTestResultReporter,
+ public testing::ScopedFakeTestPartResultReporter {
+ public:
+ explicit ScopedTestResultReporterImpl(ExitMode aExitMode)
+ : testing::ScopedFakeTestPartResultReporter(INTERCEPT_ALL_THREADS,
+ nullptr),
+ mExitMode(aExitMode) {}
+
+ ~ScopedTestResultReporterImpl() {
+ switch (mExitMode) {
+ case ExitMode::ExitOnDtor:
+ exit(ExitCode(Status()));
+ case ExitMode::NoExit:
+ break;
+ }
+ }
+
+ void ReportTestPartResult(const testing::TestPartResult& aResult) override {
+ {
+ MutexAutoLock lock(mMutex);
+ if (aResult.nonfatally_failed() &&
+ mStatus < TestResultStatus::NonFatalFailure) {
+ mStatus = TestResultStatus::NonFatalFailure;
+ }
+
+ if (aResult.fatally_failed() &&
+ mStatus < TestResultStatus::FatalFailure) {
+ mStatus = TestResultStatus::FatalFailure;
+ }
+ }
+
+ std::ostringstream stream;
+ stream << aResult;
+ printf_stderr("%s\n", stream.str().c_str());
+ }
+
+ TestResultStatus Status() const override {
+ MutexAutoLock lock(mMutex);
+ return mStatus;
+ }
+
+ private:
+ const ExitMode mExitMode;
+
+ mutable Mutex mMutex{"ScopedTestResultReporterImpl::mMutex"};
+ TestResultStatus mStatus MOZ_GUARDED_BY(mMutex) = TestResultStatus::Pass;
+};
+
+UniquePtr<ScopedTestResultReporter> ScopedTestResultReporter::Create(
+ ExitMode aExitMode) {
+ return MakeUnique<ScopedTestResultReporterImpl>(aExitMode);
+}
+
+} // namespace mozilla::gtest
diff --git a/testing/gtest/mozilla/MozHelpers.h b/testing/gtest/mozilla/MozHelpers.h
new file mode 100644
index 0000000000..0251f43634
--- /dev/null
+++ b/testing/gtest/mozilla/MozHelpers.h
@@ -0,0 +1,119 @@
+#ifndef TESTING_GTEST_MOZILLA_HELPERS_H_
+#define TESTING_GTEST_MOZILLA_HELPERS_H_
+
+#include "gtest/gtest.h"
+
+#include "mozilla/UniquePtr.h"
+#include "nsCOMPtr.h"
+#include "nsServiceManagerUtils.h"
+#include "nsICrashReporter.h"
+
+#if defined(DEBUG) && !defined(XP_WIN) && !defined(ANDROID)
+# define HAS_GDB_SLEEP_DURATION 1
+extern unsigned int _gdb_sleep_duration;
+#endif
+
+namespace mozilla::gtest {
+
+#if defined(HAS_GDB_SLEEP_DURATION)
+# define ZERO_GDB_SLEEP() _gdb_sleep_duration = 0;
+
+# define SAVE_GDB_SLEEP(v) \
+ v = _gdb_sleep_duration; \
+ ZERO_GDB_SLEEP();
+# define RESTORE_GDB_SLEEP(v) _gdb_sleep_duration = v;
+
+// Some use needs to be in the global namespace
+# define SAVE_GDB_SLEEP_GLOBAL(v) \
+ v = ::_gdb_sleep_duration; \
+ ZERO_GDB_SLEEP();
+# define RESTORE_GDB_SLEEP_GLOBAL(v) ::_gdb_sleep_duration = v;
+
+# define SAVE_GDB_SLEEP_LOCAL() \
+ unsigned int _old_gdb_sleep_duration; \
+ SAVE_GDB_SLEEP(_old_gdb_sleep_duration);
+# define RESTORE_GDB_SLEEP_LOCAL() RESTORE_GDB_SLEEP(_old_gdb_sleep_duration);
+
+#else // defined(HAS_GDB_SLEEP_DURATION)
+
+# define ZERO_GDB_SLEEP() ;
+
+# define SAVE_GDB_SLEEP(v)
+# define SAVE_GDB_SLEEP_GLOBAL(v)
+# define SAVE_GDB_SLEEP_LOCAL()
+# define RESTORE_GDB_SLEEP(v)
+# define RESTORE_GDB_SLEEP_GLOBAL(v)
+# define RESTORE_GDB_SLEEP_LOCAL()
+#endif // defined(HAS_GDB_SLEEP_DURATION)
+
+// Death tests are too slow on OSX because of the system crash reporter.
+#if !defined(XP_DARWIN)
+// Wrap ASSERT_DEATH_IF_SUPPORTED to disable the crash reporter
+// when entering the subprocess, so that the expected crashes don't
+// create a minidump that the gtest harness will interpret as an error.
+# define ASSERT_DEATH_WRAP(a, b) \
+ ASSERT_DEATH_IF_SUPPORTED( \
+ { \
+ mozilla::gtest::DisableCrashReporter(); \
+ a; \
+ }, \
+ b)
+#else
+# define ASSERT_DEATH_WRAP(a, b)
+#endif
+
+void DisableCrashReporter();
+
+/**
+ * Exit mode used for ScopedTestResultReporter.
+ */
+enum class ExitMode {
+ // The user of the reporter handles exit.
+ NoExit,
+ // As the reporter goes out of scope, exit with ExitCode().
+ ExitOnDtor,
+};
+
+/**
+ * Status used by ScopedTestResultReporter.
+ */
+enum class TestResultStatus : int {
+ Pass = 0,
+ NonFatalFailure = 1,
+ FatalFailure = 2,
+};
+
+inline int ExitCode(TestResultStatus aStatus) {
+ return static_cast<int>(aStatus);
+}
+
+/**
+ * This is a helper that reports test results to stderr in death test child
+ * processes, since that is normally disabled by default (with no way of
+ * enabling).
+ *
+ * Note that for this to work as intended the death test child has to, on
+ * failure, exit with an exit code that is unexpected to the death test parent,
+ * so the parent can mark the test case as failed.
+ *
+ * If the parent expects a graceful exit (code 0), ExitCode() can be used with
+ * Status() to exit the child process.
+ *
+ * For simplicity the reporter can exit automatically as it goes out of scope,
+ * when created with ExitMode::ExitOnDtor.
+ */
+class ScopedTestResultReporter {
+ public:
+ virtual ~ScopedTestResultReporter() = default;
+
+ /**
+ * The aggregate status of all observed test results.
+ */
+ virtual TestResultStatus Status() const = 0;
+
+ static UniquePtr<ScopedTestResultReporter> Create(ExitMode aExitMode);
+};
+
+} // namespace mozilla::gtest
+
+#endif // TESTING_GTEST_MOZILLA_HELPERS_H_
diff --git a/testing/gtest/mozilla/SanityTest.cpp b/testing/gtest/mozilla/SanityTest.cpp
new file mode 100644
index 0000000000..7274c43932
--- /dev/null
+++ b/testing/gtest/mozilla/SanityTest.cpp
@@ -0,0 +1,30 @@
+/* -*- 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 "gtest/gtest.h"
+#include "gmock/gmock.h"
+
+using ::testing::AtLeast;
+
+// Sanity test to make sure that GTest is hooked into
+// the mozilla build system correctly
+TEST(MozillaGTestSanity, Runs)
+{ EXPECT_EQ(1, 1); }
+namespace {
+class TestMock {
+ public:
+ TestMock() {}
+ MOCK_METHOD0(MockedCall, void());
+};
+} // namespace
+TEST(MozillaGMockSanity, Runs)
+{
+ TestMock mockedClass;
+ EXPECT_CALL(mockedClass, MockedCall()).Times(AtLeast(3));
+
+ mockedClass.MockedCall();
+ mockedClass.MockedCall();
+ mockedClass.MockedCall();
+}
diff --git a/testing/gtest/mozilla/WaitFor.cpp b/testing/gtest/mozilla/WaitFor.cpp
new file mode 100644
index 0000000000..ab96fa9ae5
--- /dev/null
+++ b/testing/gtest/mozilla/WaitFor.cpp
@@ -0,0 +1,19 @@
+/* -*- 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 "WaitFor.h"
+
+namespace mozilla {
+
+void WaitFor(MediaEventSource<void>& aEvent) {
+ bool done = false;
+ MediaEventListener listener =
+ aEvent.Connect(AbstractThread::GetCurrent(), [&] { done = true; });
+ SpinEventLoopUntil<ProcessFailureBehavior::IgnoreAndContinue>(
+ "WaitFor(MediaEventSource<void>& aEvent)"_ns, [&] { return done; });
+ listener.Disconnect();
+}
+
+} // namespace mozilla
diff --git a/testing/gtest/mozilla/WaitFor.h b/testing/gtest/mozilla/WaitFor.h
new file mode 100644
index 0000000000..86df72fb10
--- /dev/null
+++ b/testing/gtest/mozilla/WaitFor.h
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+#ifndef TESTING_GTEST_MOZILLA_WAITFOR_H_
+#define TESTING_GTEST_MOZILLA_WAITFOR_H_
+
+#include "MediaEventSource.h"
+#include "mozilla/media/MediaUtils.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/MozPromise.h"
+#include "mozilla/ResultVariant.h"
+#include "mozilla/SpinEventLoopUntil.h"
+
+namespace mozilla {
+
+/**
+ * Waits for an occurrence of aEvent on the current thread (by blocking it,
+ * except tasks added to the event loop may run) and returns the event's
+ * templated value, if it's non-void.
+ *
+ * The caller must be wary of eventloop issues, in
+ * particular cases where we rely on a stable state runnable, but there is never
+ * a task to trigger stable state. In such cases it is the responsibility of the
+ * caller to create the needed tasks, as JS would. A noteworthy API that relies
+ * on stable state is MediaTrackGraph::GetInstance.
+ */
+template <typename T>
+T WaitFor(MediaEventSource<T>& aEvent) {
+ Maybe<T> value;
+ MediaEventListener listener = aEvent.Connect(
+ AbstractThread::GetCurrent(), [&](T aValue) { value = Some(aValue); });
+ SpinEventLoopUntil<ProcessFailureBehavior::IgnoreAndContinue>(
+ "WaitFor(MediaEventSource<T>& aEvent)"_ns,
+ [&] { return value.isSome(); });
+ listener.Disconnect();
+ return value.value();
+}
+
+/**
+ * Specialization of WaitFor<T> for void.
+ */
+void WaitFor(MediaEventSource<void>& aEvent);
+
+/**
+ * Variant of WaitFor that blocks the caller until a MozPromise has either been
+ * resolved or rejected.
+ */
+template <typename R, typename E, bool Exc>
+Result<R, E> WaitFor(const RefPtr<MozPromise<R, E, Exc>>& aPromise) {
+ Maybe<R> success;
+ Maybe<E> error;
+ aPromise->Then(
+ GetCurrentSerialEventTarget(), __func__,
+ [&](R aResult) { success = Some(aResult); },
+ [&](E aError) { error = Some(aError); });
+ SpinEventLoopUntil<ProcessFailureBehavior::IgnoreAndContinue>(
+ "WaitFor(const RefPtr<MozPromise<R, E, Exc>>& aPromise)"_ns,
+ [&] { return success.isSome() || error.isSome(); });
+ if (success.isSome()) {
+ return success.extract();
+ }
+ return Err(error.extract());
+}
+
+/**
+ * A variation of WaitFor that takes a callback to be called each time aEvent is
+ * raised. Blocks the caller until the callback function returns true.
+ */
+template <typename... Args, typename CallbackFunction>
+void WaitUntil(MediaEventSource<Args...>& aEvent, CallbackFunction&& aF) {
+ bool done = false;
+ MediaEventListener listener =
+ aEvent.Connect(AbstractThread::GetCurrent(), [&](Args... aValue) {
+ if (!done) {
+ done = aF(std::forward<Args>(aValue)...);
+ }
+ });
+ SpinEventLoopUntil<ProcessFailureBehavior::IgnoreAndContinue>(
+ "WaitUntil(MediaEventSource<Args...>& aEvent, CallbackFunction&& aF)"_ns,
+ [&] { return done; });
+ listener.Disconnect();
+}
+
+template <typename... Args>
+using TakeNPromise = MozPromise<std::vector<std::tuple<Args...>>, bool, true>;
+
+template <ListenerPolicy Lp, typename... Args>
+auto TakeN(MediaEventSourceImpl<Lp, Args...>& aEvent, size_t aN)
+ -> RefPtr<TakeNPromise<Args...>> {
+ using Storage = std::vector<std::tuple<Args...>>;
+ using Promise = TakeNPromise<Args...>;
+ using Values = media::Refcountable<Storage>;
+ using Listener = media::Refcountable<MediaEventListener>;
+ RefPtr<Values> values = MakeRefPtr<Values>();
+ values->reserve(aN);
+ RefPtr<Listener> listener = MakeRefPtr<Listener>();
+ auto promise = InvokeAsync(
+ AbstractThread::GetCurrent(), __func__, [values, aN]() mutable {
+ SpinEventLoopUntil<ProcessFailureBehavior::IgnoreAndContinue>(
+ "TakeN(MediaEventSourceImpl<Lp, Args...>& aEvent, size_t aN)"_ns,
+ [&] { return values->size() == aN; });
+ return Promise::CreateAndResolve(std::move(*values), __func__);
+ });
+ *listener = aEvent.Connect(AbstractThread::GetCurrent(),
+ [values, listener, aN](Args... aValue) {
+ values->push_back({aValue...});
+ if (values->size() == aN) {
+ listener->Disconnect();
+ }
+ });
+ return promise;
+}
+
+/**
+ * Helper that, given that canonicals have just been updated on the current
+ * thread, will block its execution until mirrors and their watchers have
+ * executed on aTarget.
+ */
+inline void WaitForMirrors(const RefPtr<nsISerialEventTarget>& aTarget) {
+ Unused << WaitFor(InvokeAsync(aTarget, __func__, [] {
+ return GenericPromise::CreateAndResolve(true, "WaitForMirrors resolver");
+ }));
+}
+
+/**
+ * Short form of WaitForMirrors that assumes mirrors are on the current thread
+ * (like canonicals).
+ */
+inline void WaitForMirrors() { WaitForMirrors(GetCurrentSerialEventTarget()); }
+
+} // namespace mozilla
+
+#endif // TESTING_GTEST_MOZILLA_WAITFOR_H_
diff --git a/testing/gtest/mozilla/gmock-custom/README.md b/testing/gtest/mozilla/gmock-custom/README.md
new file mode 100644
index 0000000000..f6c93f616d
--- /dev/null
+++ b/testing/gtest/mozilla/gmock-custom/README.md
@@ -0,0 +1,16 @@
+# Customization Points
+
+The custom directory is an injection point for custom user configurations.
+
+## Header `gmock-port.h`
+
+The following macros can be defined:
+
+### Flag related macros:
+
+* `GMOCK_DECLARE_bool_(name)`
+* `GMOCK_DECLARE_int32_(name)`
+* `GMOCK_DECLARE_string_(name)`
+* `GMOCK_DEFINE_bool_(name, default_val, doc)`
+* `GMOCK_DEFINE_int32_(name, default_val, doc)`
+* `GMOCK_DEFINE_string_(name, default_val, doc)`
diff --git a/testing/gtest/mozilla/gmock-custom/gmock-generated-actions.h b/testing/gtest/mozilla/gmock-custom/gmock-generated-actions.h
new file mode 100644
index 0000000000..92d910cf06
--- /dev/null
+++ b/testing/gtest/mozilla/gmock-custom/gmock-generated-actions.h
@@ -0,0 +1,10 @@
+// This file was GENERATED by command:
+// pump.py gmock-generated-actions.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// GOOGLETEST_CM0002 DO NOT DELETE
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
+
+#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_
diff --git a/testing/gtest/mozilla/gmock-custom/gmock-matchers.h b/testing/gtest/mozilla/gmock-custom/gmock-matchers.h
new file mode 100644
index 0000000000..14aafaabe6
--- /dev/null
+++ b/testing/gtest/mozilla/gmock-custom/gmock-matchers.h
@@ -0,0 +1,36 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Injection point for custom user configurations. See README for details
+//
+// GOOGLETEST_CM0002 DO NOT DELETE
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_MATCHERS_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_MATCHERS_H_
+#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_MATCHERS_H_
diff --git a/testing/gtest/mozilla/gmock-custom/gmock-port.h b/testing/gtest/mozilla/gmock-custom/gmock-port.h
new file mode 100644
index 0000000000..0030fe9111
--- /dev/null
+++ b/testing/gtest/mozilla/gmock-custom/gmock-port.h
@@ -0,0 +1,39 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Injection point for custom user configurations. See README for details
+//
+// ** Custom implementation starts here **
+
+// GOOGLETEST_CM0002 DO NOT DELETE
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_
+
+#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_
diff --git a/testing/gtest/mozilla/gtest-custom/README.md b/testing/gtest/mozilla/gtest-custom/README.md
new file mode 100644
index 0000000000..ff391fb4e2
--- /dev/null
+++ b/testing/gtest/mozilla/gtest-custom/README.md
@@ -0,0 +1,56 @@
+# Customization Points
+
+The custom directory is an injection point for custom user configurations.
+
+## Header `gtest.h`
+
+### The following macros can be defined:
+
+* `GTEST_OS_STACK_TRACE_GETTER_` - The name of an implementation of
+ `OsStackTraceGetterInterface`.
+* `GTEST_CUSTOM_TEMPDIR_FUNCTION_` - An override for `testing::TempDir()`. See
+ `testing::TempDir` for semantics and signature.
+
+## Header `gtest-port.h`
+
+The following macros can be defined:
+
+### Flag related macros:
+
+* `GTEST_FLAG(flag_name)`
+* `GTEST_USE_OWN_FLAGFILE_FLAG_` - Define to 0 when the system provides its
+ own flagfile flag parsing.
+* `GTEST_DECLARE_bool_(name)`
+* `GTEST_DECLARE_int32_(name)`
+* `GTEST_DECLARE_string_(name)`
+* `GTEST_DEFINE_bool_(name, default_val, doc)`
+* `GTEST_DEFINE_int32_(name, default_val, doc)`
+* `GTEST_DEFINE_string_(name, default_val, doc)`
+
+### Logging:
+
+* `GTEST_LOG_(severity)`
+* `GTEST_CHECK_(condition)`
+* Functions `LogToStderr()` and `FlushInfoLog()` have to be provided too.
+
+### Threading:
+
+* `GTEST_HAS_NOTIFICATION_` - Enabled if Notification is already provided.
+* `GTEST_HAS_MUTEX_AND_THREAD_LOCAL_` - Enabled if `Mutex` and `ThreadLocal`
+ are already provided. Must also provide `GTEST_DECLARE_STATIC_MUTEX_(mutex)`
+ and `GTEST_DEFINE_STATIC_MUTEX_(mutex)`
+* `GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)`
+* `GTEST_LOCK_EXCLUDED_(locks)`
+
+### Underlying library support features
+
+* `GTEST_HAS_CXXABI_H_`
+
+### Exporting API symbols:
+
+* `GTEST_API_` - Specifier for exported symbols.
+
+## Header `gtest-printers.h`
+
+* See documentation at `gtest/gtest-printers.h` for details on how to define a
+ custom printer.
diff --git a/testing/gtest/mozilla/gtest-custom/gtest-port.h b/testing/gtest/mozilla/gtest-custom/gtest-port.h
new file mode 100644
index 0000000000..3159a6671a
--- /dev/null
+++ b/testing/gtest/mozilla/gtest-custom/gtest-port.h
@@ -0,0 +1,39 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Injection point for custom user configurations. See README for details
+//
+// ** Custom implementation starts here **
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
+
+#define GTEST_API_ /* nothing */
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
diff --git a/testing/gtest/mozilla/gtest-custom/gtest-printers.h b/testing/gtest/mozilla/gtest-custom/gtest-printers.h
new file mode 100644
index 0000000000..eb4467abca
--- /dev/null
+++ b/testing/gtest/mozilla/gtest-custom/gtest-printers.h
@@ -0,0 +1,42 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// This file provides an injection point for custom printers in a local
+// installation of gTest.
+// It will be included from gtest-printers.h and the overrides in this file
+// will be visible to everyone.
+//
+// Injection point for custom user configurations. See README for details
+//
+// ** Custom implementation starts here **
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
diff --git a/testing/gtest/mozilla/gtest-custom/gtest.h b/testing/gtest/mozilla/gtest-custom/gtest.h
new file mode 100644
index 0000000000..4c8e07be23
--- /dev/null
+++ b/testing/gtest/mozilla/gtest-custom/gtest.h
@@ -0,0 +1,37 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Injection point for custom user configurations. See README for details
+//
+// ** Custom implementation starts here **
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
+
+#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
diff --git a/testing/gtest/mozilla/moz.build b/testing/gtest/mozilla/moz.build
new file mode 100644
index 0000000000..e5cccadd18
--- /dev/null
+++ b/testing/gtest/mozilla/moz.build
@@ -0,0 +1,40 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+if CONFIG["ENABLE_TESTS"]:
+ # Export the gtest-custom files so we can override configuration options as
+ # recommended by gtest.
+ EXPORTS.gtest.internal.custom += [
+ "gtest-custom/gtest-port.h",
+ "gtest-custom/gtest-printers.h",
+ "gtest-custom/gtest.h",
+ ]
+ EXPORTS.gmock.internal.custom += [
+ "gmock-custom/gmock-generated-actions.h",
+ "gmock-custom/gmock-matchers.h",
+ "gmock-custom/gmock-port.h",
+ ]
+
+ EXPORTS.mozilla.gtest += [
+ "MozAssertions.h",
+ "MozHelpers.h",
+ "WaitFor.h",
+ ]
+
+ SOURCES += [
+ "GTestRunner.cpp",
+ "MozAssertions.cpp",
+ "MozGTestBench.cpp",
+ "MozHelpers.cpp",
+ "SanityTest.cpp",
+ "WaitFor.cpp",
+ ]
+
+ if CONFIG["OS_ARCH"] == "WINNT":
+ LOCAL_INCLUDES += [
+ "/security/sandbox/chromium",
+ ]
+
+ FINAL_LIBRARY = "xul-gtest"