michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "GTestRunner.h" michael@0: #include "gtest/gtest.h" michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/NullPtr.h" michael@0: #ifdef MOZ_CRASHREPORTER michael@0: #include "nsICrashReporter.h" michael@0: #endif michael@0: #include "testing/TestHarness.h" michael@0: #include "prenv.h" michael@0: michael@0: using ::testing::EmptyTestEventListener; michael@0: using ::testing::InitGoogleTest; michael@0: using ::testing::Test; michael@0: using ::testing::TestCase; michael@0: using ::testing::TestEventListeners; michael@0: using ::testing::TestInfo; michael@0: using ::testing::TestPartResult; michael@0: using ::testing::UnitTest; michael@0: michael@0: namespace mozilla { michael@0: michael@0: // See gtest.h for method documentation michael@0: class MozillaPrinter : public EmptyTestEventListener michael@0: { michael@0: public: michael@0: virtual void OnTestProgramStart(const UnitTest& /* aUnitTest */) MOZ_OVERRIDE { michael@0: printf("TEST-INFO | GTest unit test starting\n"); michael@0: } michael@0: virtual void OnTestProgramEnd(const UnitTest& aUnitTest) MOZ_OVERRIDE { michael@0: printf("TEST-%s | GTest unit test: %s\n", michael@0: aUnitTest.Passed() ? "PASS" : "UNEXPECTED-FAIL", michael@0: aUnitTest.Passed() ? "passed" : "failed"); michael@0: } michael@0: virtual void OnTestStart(const TestInfo& aTestInfo) MOZ_OVERRIDE { michael@0: mTestInfo = &aTestInfo; michael@0: printf("TEST-START | %s.%s\n", michael@0: mTestInfo->test_case_name(), mTestInfo->name()); michael@0: } michael@0: virtual void OnTestPartResult(const TestPartResult& aTestPartResult) MOZ_OVERRIDE { michael@0: printf("TEST-%s | %s.%s | %s @ %s:%i\n", michael@0: !aTestPartResult.failed() ? "PASS" : "UNEXPECTED-FAIL", michael@0: mTestInfo ? mTestInfo->test_case_name() : "?", mTestInfo ? mTestInfo->name() : "?", michael@0: aTestPartResult.summary(), michael@0: aTestPartResult.file_name(), aTestPartResult.line_number()); michael@0: } michael@0: virtual void OnTestEnd(const TestInfo& aTestInfo) MOZ_OVERRIDE { michael@0: printf("TEST-%s | %s.%s | test completed (time: %llims)\n", michael@0: aTestInfo.result()->Passed() ? "PASS": "UNEXPECTED-FAIL", michael@0: aTestInfo.test_case_name(), aTestInfo.name(), michael@0: aTestInfo.result()->elapsed_time()); michael@0: MOZ_ASSERT(&aTestInfo == mTestInfo); michael@0: mTestInfo = nullptr; michael@0: } michael@0: michael@0: const TestInfo* mTestInfo; michael@0: }; michael@0: michael@0: static void ReplaceGTestLogger() michael@0: { michael@0: // Replace the GTest logger so that it can be passed michael@0: // by the mozilla test parsers. michael@0: // Code is based on: http://googletest.googlecode.com/svn/trunk/samples/sample9_unittest.cc michael@0: UnitTest& unitTest = *UnitTest::GetInstance(); michael@0: TestEventListeners& listeners = unitTest.listeners(); michael@0: delete listeners.Release(listeners.default_result_printer()); michael@0: michael@0: listeners.Append(new MozillaPrinter); michael@0: } michael@0: michael@0: int RunGTestFunc() michael@0: { michael@0: int c = 0; michael@0: InitGoogleTest(&c, static_cast(nullptr)); michael@0: michael@0: if (getenv("MOZ_TBPL_PARSER")) { michael@0: ReplaceGTestLogger(); michael@0: } michael@0: michael@0: PR_SetEnv("XPCOM_DEBUG_BREAK=stack-and-abort"); michael@0: michael@0: ScopedXPCOM xpcom("AsyncPanZoomController"); michael@0: michael@0: #ifdef MOZ_CRASHREPORTER michael@0: nsCOMPtr crashreporter; michael@0: char *crashreporterStr = PR_GetEnv("MOZ_CRASHREPORTER"); michael@0: if (crashreporterStr && !strcmp(crashreporterStr, "1")) { michael@0: //TODO: move this to an even-more-common location to use in all michael@0: // C++ unittests michael@0: crashreporter = do_GetService("@mozilla.org/toolkit/crash-reporter;1"); michael@0: if (crashreporter) { michael@0: std::cerr << "Setting up crash reporting" << std::endl; michael@0: michael@0: nsCOMPtr dirsvc = michael@0: do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID); michael@0: nsCOMPtr cwd; michael@0: nsresult rv = dirsvc->Get(NS_OS_CURRENT_WORKING_DIR, michael@0: NS_GET_IID(nsIFile), michael@0: getter_AddRefs(cwd)); michael@0: MOZ_ASSERT(NS_SUCCEEDED(rv)); michael@0: crashreporter->SetEnabled(true); michael@0: crashreporter->SetMinidumpPath(cwd); michael@0: } michael@0: } michael@0: #endif michael@0: michael@0: return RUN_ALL_TESTS(); michael@0: } michael@0: michael@0: // We use a static var 'RunGTest' defined in nsAppRunner.cpp. michael@0: // RunGTest is initialized to nullptr but if GTest (this file) michael@0: // is linked in then RunGTest will be set here indicating michael@0: // GTest is supported. michael@0: class _InitRunGTest { michael@0: public: michael@0: _InitRunGTest() { michael@0: RunGTest = RunGTestFunc; michael@0: } michael@0: } InitRunGTest; michael@0: michael@0: }