diff options
author | zhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925> | 2009-12-18 05:23:04 +0000 |
---|---|---|
committer | zhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925> | 2009-12-18 05:23:04 +0000 |
commit | a3dd9d97c57eb1be851a27ffcd6edaed69ee816e (patch) | |
tree | 1b0ba9ecfc2d495d6c293110c6331a77304e35e1 | |
parent | 88e97c822c988eaa9f8bcbaa1ea5d702ffd7d384 (diff) | |
download | googletest-a3dd9d97c57eb1be851a27ffcd6edaed69ee816e.tar.gz googletest-a3dd9d97c57eb1be851a27ffcd6edaed69ee816e.tar.bz2 googletest-a3dd9d97c57eb1be851a27ffcd6edaed69ee816e.zip |
Supports building gtest as a DLL (by Vlad Losev).
-rw-r--r-- | Makefile.am | 7 | ||||
-rw-r--r-- | scons/SConscript | 19 | ||||
-rw-r--r-- | scons/SConscript.common | 18 | ||||
-rw-r--r-- | scons/SConstruct | 2 | ||||
-rwxr-xr-x | scripts/generate_gtest_def.py | 169 | ||||
-rw-r--r-- | src/gtest.def | 123 | ||||
-rw-r--r-- | test/gtest_dll_test_.cc | 498 |
7 files changed, 834 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am index d147d13f..7ca39162 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,6 +17,7 @@ EXTRA_DIST = \ scons/SConstruct.common \ scripts/fuse_gtest_files.py \ scripts/gen_gtest_pred_impl.py \ + scripts/generate_gtest_def.py \ scripts/test/Makefile # gtest source files that we don't compile directly. @@ -27,7 +28,8 @@ EXTRA_DIST += \ src/gtest-internal-inl.h \ src/gtest-port.cc \ src/gtest-test-part.cc \ - src/gtest-typed-test.cc + src/gtest-typed-test.cc \ + src/gtest.def # Sample files that we don't compile. EXTRA_DIST += \ @@ -86,7 +88,8 @@ EXTRA_DIST += \ test/gtest_uninitialized_test_.cc \ test/gtest_xml_outfile1_test_.cc \ test/gtest_xml_outfile2_test_.cc \ - test/gtest_xml_output_unittest_.cc + test/gtest_xml_output_unittest_.cc \ + test/gtest_dll_test_.cc # Python tests that we don't run. EXTRA_DIST += \ diff --git a/scons/SConscript b/scons/SConscript index 25220eea..a2c31dc1 100644 --- a/scons/SConscript +++ b/scons/SConscript @@ -292,6 +292,25 @@ if BUILD_TESTS: GtestBinary(env_without_rtti, 'gtest_no_rtti_test', gtest_main_no_rtti, ['../test/gtest_unittest.cc']) + # Tests that gtest works when built as a DLL on Windows. + # We don't need to actually run this test. + # Note: this is not supported under VC 7.1. + if env['PLATFORM'] == 'win32' and env.get('GTEST_BUILD_DLL_TEST', None): + test_env = EnvCreator.Create(env, EnvCreator.DllBuild) + dll_env = test_env.Clone() + dll_env.Append(LINKFLAGS=['-DEF:../src/gtest.def']) + + gtest_dll = dll_env.SharedLibrary( + target='gtest_dll', + source=[dll_env.SharedObject('gtest_all_dll', + '../src/gtest-all.cc'), + dll_env.SharedObject('gtest_main_dll', + '../src/gtest_main.cc')]) + # TODO(vladl@google.com): Get rid of the .data[1] hack. Find a proper + # way to depend on a shared library without knowing its path in advance. + test_env.Program('gtest_dll_test_', + ['../test/gtest_dll_test_.cc', gtest_dll.data[1]]) + ############################################################ # Sample targets. diff --git a/scons/SConscript.common b/scons/SConscript.common index 7fda32e1..7943e77c 100644 --- a/scons/SConscript.common +++ b/scons/SConscript.common @@ -132,6 +132,24 @@ class EnvCreator: env.Append(CPPDEFINES='GTEST_HAS_RTTI=0') NoRtti = classmethod(NoRtti) + def DllBuild(cls, env): + """Enables building gtets as a DLL.""" + + env['OBJ_SUFFIX'] = '_dll' + # -MT(d) instructs MSVC to link to the static version of the C++ + # runtime library; -MD(d) tells it to link to the DLL version. + flags = env['CCFLAGS'] + if '-MTd' in flags: + flags.remove('-MTd') + flags.append('-MDd') + elif '-MT' in flags: + flags.remove('-MT') + flags.append('-MD') + + # Disables the "non dll-interface class 'stdext::exception' used as + # base for dll-interface class" warning triggered by the STL code. + env.Append(CCFLAGS=['/wd4275']) + DllBuild = classmethod(DllBuild) sconscript_exports = {'EnvCreator': EnvCreator} Return('sconscript_exports') diff --git a/scons/SConstruct b/scons/SConstruct index c749d6a8..f4f82374 100644 --- a/scons/SConstruct +++ b/scons/SConstruct @@ -56,6 +56,8 @@ win_base = sconstruct_helper.MakeWinBaseEnvironment() # setting for our users. if win_base.get('MSVS_VERSION', None) == '7.1': sconstruct_helper.EnableExceptions(win_base) +else: + win_base['GTEST_BUILD_DLL_TEST'] = True sconstruct_helper.MakeWinDebugEnvironment(win_base, 'win-dbg') sconstruct_helper.MakeWinOptimizedEnvironment(win_base, 'win-opt') diff --git a/scripts/generate_gtest_def.py b/scripts/generate_gtest_def.py new file mode 100755 index 00000000..9de7038b --- /dev/null +++ b/scripts/generate_gtest_def.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python +# +# Copyright 2009 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. + +"""Generates the gtest.def file to build Google Test as a DLL on Windows. + +SYNOPSIS + Put diagnostic messages from building gtest_dll_test_.exe into + BUILD_RESULTS_FILE and invoke + + generate_gtest_def.py <BUILD_RESULTS_FILE + + Reads output of VC++ linker and re-generates the src/gtest.def file + required for building gtest as a DLL. + + Use this script if you modify Google Test's source code and Visual + Studio linker starts complaining about unresolved external symbols. + You may have to repeate the build/re-generate cycle several times + because VC++ limits the number of unresolved external symbols it can + report at a time. + +EXAMPLES + scons\scons.py | scripts\generate_gtest_def.py + +This tool is experimental. Please report any problems to +googletestframework@googlegroups.com. You can read +http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide for more +information. +""" + +__author__ = 'vladl@google.com (Vlad Losev)' + +import os +import re +import sets +import sys + +# We assume that this file is in the scripts/ directory in the Google +# Test root directory. +GTEST_DEF_PATH = os.path.join(os.path.dirname(__file__), '../src/gtest.def') + +# Locates the header of the EXPORTS section. +EXPORTS_SECTION_REGEX = re.compile(r'^EXPORTS\s*$', re.IGNORECASE) + +# Determines if a line looks like an export definition in the EXPORTS +# section of a module definition file. +EXPORT_REGEX = re.compile(r'^\s+(\S+)') + +# Determines if a given line contains an error message about unresolved +# linker symbol. +IS_UNRESOLVED_SYMBOL_REGEX = re.compile(r'\bunresolved external symbol\b') + +# Fetches the symbol name from a line that contains an unresolved linker +# symbol message. +UNRESOLVED_SYMBOL_REGEX = re.compile(r'^.*?"[^"]+" \((\S+)\)') + + +def ReadDefExports(stream): + """Reads contents of a def file and returns a list of exported symbols.""" + + is_export = False + exports = sets.Set() + for line in stream: + if EXPORTS_SECTION_REGEX.match(line): + is_export = True + elif EXPORT_REGEX.match(line): + if is_export: + exports.add(EXPORT_REGEX.match(line).group(1)) + else: + is_export = False + + return exports + + +def ReadUnresolvedExternals(stream): + """Reads linker output and returns list of unresolved linker symbols.""" + + unresolved = sets.Set() + + for line in stream: + if IS_UNRESOLVED_SYMBOL_REGEX.search(line): + unresolved.add(UNRESOLVED_SYMBOL_REGEX.match(line).group(1)) + + return unresolved + + +def AdjustExports(exports, unresolved): + """Adjusts exports list based on the list of unresolved symbols.""" + + if unresolved & exports: + # There are symbols that are listed as exported but are also reported + # unresolved. This is most likely because they have been removed from + # Google Test but their mentions in gtest.def constitute references. We + # need to remove such symbols from the EXPORTS section. Also, their + # presence means that the Google Test DLL has failed to link and + # consequently linking of the test .exe was not attempted, meaning that + # at this time, there will be no unresolved externals that need to be + # added to the exports list. + exports -= unresolved + else: + # Finding unresolved exports means that the Google Test DLL had link + # errors and the build script did not build gtest_dll_test_.exe. The user + # has to build the test once again and run this script on the diagnostic + # output of the build. + exports |= unresolved + + return exports + + +def WriteGtestDefFile(stream, exports): + """Writes contents of gtest.def given a list of exported symbols.""" + + stream.write('; This file is auto-generated. DO NOT EDIT DIRECTLY.\n' + '; For more information, see scripts/generate_gtest_def.py.\n' + '\nLIBRARY\n' + '\nEXPORTS\n') + for symbol in sorted(exports): + stream.write(' %s\n' % symbol) + + +def main(): + unresolved = ReadUnresolvedExternals(sys.stdin) + if unresolved: + try: + gtest_def = open(GTEST_DEF_PATH, 'r') + exports = ReadDefExports(gtest_def) + gtest_def.close() + except IOError: + exports = sets.Set() + + exports = AdjustExports(exports, unresolved) + WriteGtestDefFile(open(GTEST_DEF_PATH, 'w'), exports) + sys.stderr.write('Updated test/gtest.def. Please clean the .dll file\n' + 'produced by your Google Test DLL build, run the build\n' + 'again and pass its diagnostic output to this script\n' + 'unless the build succeeds.\n') + else: + sys.stderr.write('The build diagnostic output indicates no unresolved\n' + 'externals. test/gtest.def is likely up to date and\n' + 'has not been updated.\n') + +if __name__ == '__main__': + main() diff --git a/src/gtest.def b/src/gtest.def new file mode 100644 index 00000000..a5583dfd --- /dev/null +++ b/src/gtest.def @@ -0,0 +1,123 @@ +; This file is auto-generated. DO NOT EDIT DIRECTLY.
+; For more information, see scripts/generate_gtest_def.py.
+
+LIBRARY
+
+EXPORTS
+ ??0AssertHelper@internal@testing@@QAE@W4Type@TestPartResult@2@PBDH1@Z
+ ??0AssertionResult@testing@@QAE@ABV01@@Z
+ ??0ExitedWithCode@testing@@QAE@H@Z
+ ??0GTestLog@internal@testing@@QAE@W4GTestLogSeverity@12@PBDH@Z
+ ??0HasNewFatalFailureHelper@internal@testing@@QAE@XZ
+ ??0ScopedFakeTestPartResultReporter@testing@@QAE@W4InterceptMode@01@PAVTestPartResultArray@1@@Z
+ ??0ScopedTrace@internal@testing@@QAE@PBDHABVMessage@2@@Z
+ ??0SingleFailureChecker@internal@testing@@QAE@PBVTestPartResultArray@2@W4Type@TestPartResult@2@PBD@Z
+ ??0Test@testing@@IAE@XZ
+ ??0TestPartResultArray@testing@@QAE@XZ
+ ??1AssertHelper@internal@testing@@QAE@XZ
+ ??1GTestLog@internal@testing@@QAE@XZ
+ ??1HasNewFatalFailureHelper@internal@testing@@UAE@XZ
+ ??1RE@internal@testing@@QAE@XZ
+ ??1ScopedFakeTestPartResultReporter@testing@@UAE@XZ
+ ??1ScopedTrace@internal@testing@@QAE@XZ
+ ??1SingleFailureChecker@internal@testing@@QAE@XZ
+ ??1Test@testing@@UAE@XZ
+ ??1TestPartResultArray@testing@@QAE@XZ
+ ??4AssertHelper@internal@testing@@QBEXABVMessage@2@@Z
+ ??6Message@testing@@QAEAAV01@ABV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@Z
+ ??7AssertionResult@testing@@QBE?AV01@XZ
+ ??RExitedWithCode@testing@@QBE_NH@Z
+ ?AddEnvironment@UnitTest@testing@@AAEPAVEnvironment@2@PAV32@@Z
+ ?AlwaysTrue@internal@testing@@YA_NXZ
+ ?Append@TestEventListeners@testing@@QAEXPAVTestEventListener@2@@Z
+ ?AssertionFailure@testing@@YA?AVAssertionResult@1@ABVMessage@1@@Z
+ ?AssertionFailure@testing@@YA?AVAssertionResult@1@XZ
+ ?AssertionSuccess@testing@@YA?AVAssertionResult@1@XZ
+ ?CmpHelperSTRCASEEQ@internal@testing@@YA?AVAssertionResult@2@PBD000@Z
+ ?CmpHelperSTRCASENE@internal@testing@@YA?AVAssertionResult@2@PBD000@Z
+ ?CmpHelperSTREQ@internal@testing@@YA?AVAssertionResult@2@PBD000@Z
+ ?CmpHelperSTREQ@internal@testing@@YA?AVAssertionResult@2@PBD0PB_W1@Z
+ ?CmpHelperSTRNE@internal@testing@@YA?AVAssertionResult@2@PBD000@Z
+ ?CmpHelperSTRNE@internal@testing@@YA?AVAssertionResult@2@PBD0PB_W1@Z
+ ?Compare@String@internal@testing@@QBEHABV123@@Z
+ ?Create@DeathTest@internal@testing@@SA_NPBDPBVRE@23@0HPAPAV123@@Z
+ ?DoubleLE@testing@@YA?AVAssertionResult@1@PBD0NN@Z
+ ?DoubleNearPredFormat@internal@testing@@YA?AVAssertionResult@2@PBD00NNN@Z
+ ?EqFailure@internal@testing@@YA?AVAssertionResult@2@PBD0ABVString@12@1_N@Z
+ ?ExitedUnsuccessfully@internal@testing@@YA_NH@Z
+ ?FLAGS_gtest_also_run_disabled_tests@testing@@3_NA
+ ?FLAGS_gtest_break_on_failure@testing@@3_NA
+ ?FLAGS_gtest_catch_exceptions@testing@@3_NA
+ ?FLAGS_gtest_color@testing@@3VString@internal@1@A
+ ?FLAGS_gtest_filter@testing@@3VString@internal@1@A
+ ?FLAGS_gtest_output@testing@@3VString@internal@1@A
+ ?FLAGS_gtest_print_time@testing@@3_NA
+ ?FLAGS_gtest_random_seed@testing@@3HA
+ ?FLAGS_gtest_repeat@testing@@3HA
+ ?FLAGS_gtest_shuffle@testing@@3_NA
+ ?FLAGS_gtest_stack_trace_depth@testing@@3HA
+ ?FLAGS_gtest_throw_on_failure@testing@@3_NA
+ ?Failed@TestResult@testing@@QBE_NXZ
+ ?Failed@UnitTest@testing@@QBE_NXZ
+ ?FloatLE@testing@@YA?AVAssertionResult@1@PBD0MM@Z
+ ?Format@String@internal@testing@@SA?AV123@PBDZZ
+ ?FormatForFailureMessage@internal@testing@@YA?AVString@12@D@Z
+ ?GetBoolAssertionFailureMessage@internal@testing@@YA?AVString@12@ABVAssertionResult@2@PBD11@Z
+ ?GetInstance@UnitTest@testing@@SAPAV12@XZ
+ ?GetTestCase@UnitTest@testing@@QBEPBVTestCase@2@H@Z
+ ?GetTestInfo@TestCase@testing@@QBEPBVTestInfo@2@H@Z
+ ?GetTestPartResult@TestResult@testing@@QBEABVTestPartResult@2@H@Z
+ ?GetTestProperty@TestResult@testing@@QBEABVTestProperty@2@H@Z
+ ?GetTestTypeId@internal@testing@@YAPBXXZ
+ ?HasFatalFailure@Test@testing@@SA_NXZ
+ ?HasFatalFailure@TestResult@testing@@QBE_NXZ
+ ?HasNonfatalFailure@Test@testing@@SA_NXZ
+ ?HasNonfatalFailure@TestResult@testing@@QBE_NXZ
+ ?Init@RE@internal@testing@@AAEXPBD@Z
+ ?InitGoogleTest@testing@@YAXPAHPAPAD@Z
+ ?IsHRESULTFailure@internal@testing@@YA?AVAssertionResult@2@PBDJ@Z
+ ?IsHRESULTSuccess@internal@testing@@YA?AVAssertionResult@2@PBDJ@Z
+ ?IsTrue@internal@testing@@YA_N_N@Z
+ ?LastMessage@DeathTest@internal@testing@@SAPBDXZ
+ ?MakeAndRegisterTestInfo@internal@testing@@YAPAVTestInfo@2@PBD000PBXP6AXXZ2PAVTestFactoryBase@12@@Z
+ ?Passed@UnitTest@testing@@QBE_NXZ
+ ?RecordProperty@Test@testing@@SAXPBD0@Z
+ ?Release@TestEventListeners@testing@@QAEPAVTestEventListener@2@PAV32@@Z
+ ?ReportInvalidTestCaseType@internal@testing@@YAXPBD0H@Z
+ ?Run@UnitTest@testing@@QAEHXZ
+ ?SetUp@Test@testing@@MAEXXZ
+ ?ShowCStringQuoted@String@internal@testing@@SA?AV123@PBD@Z
+ ?ShowWideCStringQuoted@String@internal@testing@@SA?AV123@PB_W@Z
+ ?StrStreamToString@internal@testing@@YA?AVString@12@PAV?$basic_stringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z
+ ?TearDown@Test@testing@@MAEXXZ
+ ?VerifyRegisteredTestNames@TypedTestCasePState@internal@testing@@QAEPBDPBDH0@Z
+ ?comment@TestInfo@testing@@QBEPBDXZ
+ ?current_test_case@UnitTest@testing@@QBEPBVTestCase@2@XZ
+ ?current_test_info@UnitTest@testing@@QBEPBVTestInfo@2@XZ
+ ?disabled_test_count@TestCase@testing@@QBEHXZ
+ ?disabled_test_count@UnitTest@testing@@QBEHXZ
+ ?elapsed_time@UnitTest@testing@@QBE_JXZ
+ ?failed_test_case_count@UnitTest@testing@@QBEHXZ
+ ?failed_test_count@TestCase@testing@@QBEHXZ
+ ?failed_test_count@UnitTest@testing@@QBEHXZ
+ ?g_linked_ptr_mutex@internal@testing@@3VMutex@12@A
+ ?listeners@UnitTest@testing@@QAEAAVTestEventListeners@2@XZ
+ ?name@TestInfo@testing@@QBEPBDXZ
+ ?original_working_dir@UnitTest@testing@@QBEPBDXZ
+ ?parameterized_test_registry@UnitTest@testing@@QAEAAVParameterizedTestCaseRegistry@internal@2@XZ
+ ?random_seed@UnitTest@testing@@QBEHXZ
+ ?result@TestInfo@testing@@QBEPBVTestResult@2@XZ
+ ?should_run@TestInfo@testing@@QBE_NXZ
+ ?successful_test_case_count@UnitTest@testing@@QBEHXZ
+ ?successful_test_count@TestCase@testing@@QBEHXZ
+ ?successful_test_count@UnitTest@testing@@QBEHXZ
+ ?test_case_comment@TestInfo@testing@@QBEPBDXZ
+ ?test_case_name@TestInfo@testing@@QBEPBDXZ
+ ?test_case_to_run_count@UnitTest@testing@@QBEHXZ
+ ?test_property_count@TestResult@testing@@QBEHXZ
+ ?test_to_run_count@TestCase@testing@@QBEHXZ
+ ?test_to_run_count@UnitTest@testing@@QBEHXZ
+ ?total_part_count@TestResult@testing@@QBEHXZ
+ ?total_test_case_count@UnitTest@testing@@QBEHXZ
+ ?total_test_count@TestCase@testing@@QBEHXZ
+ ?total_test_count@UnitTest@testing@@QBEHXZ
diff --git a/test/gtest_dll_test_.cc b/test/gtest_dll_test_.cc new file mode 100644 index 00000000..c99358aa --- /dev/null +++ b/test/gtest_dll_test_.cc @@ -0,0 +1,498 @@ +// Copyright 2009 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. +// +// Author: vladl@google.com (Vlad Losev) +// +// Tests for Google Test itself. This verifies that Google Test can be +// linked into an executable successfully when built as a DLL on Windows. +// The test is not meant to check the success of test assertions employed in +// it. It only checks that constructs in them can be successfully linked. +// +// If you add new features to Google Test's documented interface, you need to +// add tests exercising them to this file. +// +// If you start having 'unresolved external symbol' linker errors in this file +// after the changes you have made, re-generate src/gtest.def by running +// scripts/generate_gtest_def.py. + +#include <gtest/gtest.h> +#include <gtest/gtest-spi.h> + +#include <windows.h> +#include <vector> + +using ::std::vector; +using ::std::tr1::tuple; + + +using ::testing::AddGlobalTestEnvironment; +using ::testing::AssertionFailure; +using ::testing::AssertionResult; +using ::testing::AssertionSuccess; +using ::testing::DoubleLE; +using ::testing::EmptyTestEventListener; +using ::testing::Environment; +using ::testing::ExitedWithCode; +using ::testing::FloatLE; +using ::testing::GTEST_FLAG(also_run_disabled_tests); +using ::testing::GTEST_FLAG(break_on_failure); +using ::testing::GTEST_FLAG(catch_exceptions); +using ::testing::GTEST_FLAG(color); +using ::testing::GTEST_FLAG(filter); +using ::testing::GTEST_FLAG(output); +using ::testing::GTEST_FLAG(print_time); +using ::testing::GTEST_FLAG(random_seed); +using ::testing::GTEST_FLAG(repeat); +using ::testing::GTEST_FLAG(shuffle); +using ::testing::GTEST_FLAG(stack_trace_depth); +using ::testing::GTEST_FLAG(throw_on_failure); +using ::testing::InitGoogleTest; +using ::testing::Message; +using ::testing::Test; +using ::testing::TestCase; +using ::testing::TestEventListener; +using ::testing::TestEventListeners; +using ::testing::TestInfo; +using ::testing::TestPartResult; +using ::testing::TestProperty; +using ::testing::TestResult; +using ::testing::UnitTest; +using ::testing::internal::AlwaysTrue; +using ::testing::internal::AlwaysFalse; + +#if GTEST_HAS_PARAM_TEST +using ::testing::Bool; +using ::testing::Combine; +using ::testing::TestWithParam; +using ::testing::Values; +using ::testing::ValuesIn; +#endif // GTEST_HAS_PARAM_TEST + +#if GTEST_HAS_TYPED_TEST +using ::testing::Types; +#endif // GTEST_HAS_TYPED_TEST + +// Tests linking of TEST constructs. +TEST(TestMacroTest, LinksSuccessfully) { +} + +// Tests linking of TEST_F constructs. +class FixtureTest : public Test { +}; + +TEST_F(FixtureTest, LinksSuccessfully) { +} + +// Tests linking of value parameterized tests. +#if GTEST_HAS_PARAM_TEST +class IntParamTest : public TestWithParam<int> {}; + +TEST_P(IntParamTest, LinksSuccessfully) {} + +const int c_array[] = {1, 2}; +INSTANTIATE_TEST_CASE_P(ValuesInCArrayTest, IntParamTest, ValuesIn(c_array)); + +INSTANTIATE_TEST_CASE_P(ValuesInIteratorPairTest, IntParamTest, + ValuesIn(c_array, c_array + 2)); + +vector<int> stl_vector(c_array, c_array + 2); +INSTANTIATE_TEST_CASE_P(ValuesInStlVectorTest, IntParamTest, + ValuesIn(stl_vector)); + +class BoolParamTest : public TestWithParam<bool> {}; + +INSTANTIATE_TEST_CASE_P(BoolTest, BoolParamTest, Bool()); + +INSTANTIATE_TEST_CASE_P(ValuesTest, IntParamTest, Values(1, 2)); + +#if GTEST_HAS_COMBINE +class CombineTest : public TestWithParam<tuple<int, bool> > {}; + +INSTANTIATE_TEST_CASE_P(CombineTest, CombineTest, Combine(Values(1), Bool())); +#endif // GTEST_HAS_COMBINE +#endif // GTEST_HAS_PARAM_TEST + +// Tests linking of typed tests. +#if GTEST_HAS_TYPED_TEST +template <typename T> class TypedTest : public Test {}; + +TYPED_TEST_CASE(TypedTest, Types<int>); + +TYPED_TEST(TypedTest, LinksSuccessfully) {} +#endif // GTEST_HAS_TYPED_TEST + +// Tests linking of type-parameterized tests. +#if GTEST_HAS_TYPED_TEST_P +template <typename T> class TypeParameterizedTest : public Test {}; + +TYPED_TEST_CASE_P(TypeParameterizedTest); + +TYPED_TEST_P(TypeParameterizedTest, LinksSuccessfully) {} + +REGISTER_TYPED_TEST_CASE_P(TypeParameterizedTest, LinksSuccessfully); + +INSTANTIATE_TYPED_TEST_CASE_P(Char, TypeParameterizedTest, Types<char>); +#endif // GTEST_HAS_TYPED_TEST_P + +// Tests linking of explicit success or failure. +TEST(ExplicitSuccessFailureTest, ExplicitSuccessAndFailure) { + if (AlwaysTrue()) + SUCCEED() << "This is a success statement"; + if (AlwaysFalse()) { + ADD_FAILURE() << "This is a non-fatal failure assertion"; + FAIL() << "This is a fatal failure assertion"; + } +} + +// Tests linking of Boolean assertions. +AssertionResult IsEven(int n) { + if (n % 2 == 0) + return AssertionSuccess() << n << " is even"; + else + return AssertionFailure() << n << " is odd"; +} + +TEST(BooleanAssertionTest, LinksSuccessfully) { + EXPECT_TRUE(true) << "true is true"; + EXPECT_FALSE(false) << "false is not true"; + ASSERT_TRUE(true); + ASSERT_FALSE(false); + EXPECT_TRUE(IsEven(2)); + EXPECT_FALSE(IsEven(3)); +} + +// Tests linking of predicate assertions. +bool IsOdd(int n) { return n % 2 != 0; } + +bool Ge(int val1, int val2) { return val1 >= val2; } + +TEST(PredicateAssertionTest, LinksSuccessfully) { + EXPECT_PRED1(IsOdd, 1); + EXPECT_PRED2(Ge, 2, 1); +} + +AssertionResult AddToFive(const char* val1_expr, + const char* val2_expr, + int val1, + int val2) { + if (val1 + val2 == 5) + return AssertionSuccess(); + + return AssertionFailure() << val1_expr << " and " << val2_expr + << " (" << val1 << " and " << val2 << ") " + << "do not add up to five, as their sum is " + << val1 + val2; +} + +TEST(PredicateFormatterAssertionTest, LinksSuccessfully) { + EXPECT_PRED_FORMAT2(AddToFive, 1 + 2, 2); +} + + +// Tests linking of comparison assertions. +TEST(ComparisonAssertionTest, LinksSuccessfully) { + EXPECT_EQ(1, 1); + EXPECT_NE(1, 2); + EXPECT_LT(1, 2); + EXPECT_LE(1, 1); + EXPECT_GT(2, 1); + EXPECT_GE(2, 1); + + EXPECT_EQ('\n', '\n'); + EXPECT_NE('\n', '\r'); + EXPECT_LT('\n', 'a'); + EXPECT_LE('\n', 'b'); + EXPECT_GT('a', '\t'); + EXPECT_GE('b', '\t'); +} + +TEST(StringComparisonAssertionTest, LinksSuccessfully) { + EXPECT_STREQ("test", "test"); + EXPECT_STRNE("test", "prod"); + + char test_str[5] = "test"; + char prod_str[5] = "prod"; + + EXPECT_STREQ(test_str, test_str); + EXPECT_STRNE(test_str, prod_str); + + EXPECT_STRCASEEQ("test", "TEST"); + EXPECT_STRCASENE("test", "prod"); + + wchar_t test_wstr[5] = L"test"; + wchar_t prod_wstr[5] = L"prod"; + + EXPECT_STREQ(L"test", L"test"); + EXPECT_STRNE(L"test", L"prod"); + + EXPECT_STREQ(test_wstr, test_wstr); + EXPECT_STRNE(test_wstr, prod_wstr); + +#if GTEST_HAS_STD_STRING + EXPECT_EQ("test", ::std::string("test")); + EXPECT_NE("test", ::std::string("prod")); + + EXPECT_EQ(::std::string("test"), "test"); + EXPECT_NE(::std::string("prod"), "test"); + + EXPECT_EQ(test_str, ::std::string("test")); + EXPECT_NE(test_str, ::std::string("prod")); + + EXPECT_EQ(::std::string("test"), test_str); + EXPECT_NE(::std::string("prod"), test_str); + + EXPECT_EQ(::std::string("test"), ::std::string("test")); + EXPECT_NE(::std::string("test"), ::std::string("prod")); +#endif // GTEST_HAS_STD_STRING + +#if GTEST_HAS_STD_WSTRING + EXPECT_EQ(L"test", ::std::wstring(L"test")); + EXPECT_NE(L"test", ::std::wstring(L"prod")); + + EXPECT_EQ(::std::wstring(L"test"), L"test"); + EXPECT_NE(::std::wstring(L"prod"), L"test"); + + EXPECT_EQ(test_wstr, ::std::wstring(L"test")); + EXPECT_NE(test_wstr, ::std::wstring(L"prod")); + + EXPECT_EQ(::std::wstring(L"test"), test_wstr); + EXPECT_NE(::std::wstring(L"prod"), test_wstr); + + EXPECT_EQ(::std::wstring(L"test"), ::std::wstring(L"test")); + EXPECT_NE(::std::wstring(L"test"), ::std::wstring(L"prod")); +#endif // GTEST_HAS_STD_WSTRING +} + +// Tests linking of floating point assertions. +TEST(FloatingPointComparisonAssertionTest, LinksSuccessfully) { + EXPECT_FLOAT_EQ(0.0f, 0.0f); + EXPECT_DOUBLE_EQ(0.0, 0.0); + EXPECT_NEAR(0.0, 0.1, 0.2); + EXPECT_PRED_FORMAT2(::testing::FloatLE, 0.0f, 0.01f); + EXPECT_PRED_FORMAT2(::testing::DoubleLE, 0.0, 0.001); +} + +// Tests linking of HRESULT assertions. +TEST(HresultAssertionTest, LinksSuccessfully) { + EXPECT_HRESULT_SUCCEEDED(S_OK); + EXPECT_HRESULT_FAILED(E_FAIL); +} + +#if GTEST_HAS_EXCEPTIONS +// Tests linking of exception assertions. +TEST(ExceptionAssertionTest, LinksSuccessfully) { + EXPECT_THROW(throw 1, int); + EXPECT_ANY_THROW(throw 1); + EXPECT_NO_THROW(int x = 1); +} +#endif // GTEST_HAS_EXCEPTIONS + +// Tests linking of death test assertions. +TEST(DeathTestAssertionDeathTest, LinksSuccessfully) { + EXPECT_DEATH_IF_SUPPORTED(exit(1), ""); + +#if GTEST_HAS_DEATH_TEST + EXPECT_EXIT(exit(1), ExitedWithCode(1), ""); +#endif // GTEST_HAS_DEATH_TEST +} + +// Tests linking of SCOPED_TRACE. +void Sub() { EXPECT_EQ(1, 1); } + +TEST(ScopedTraceTest, LinksSuccessfully) { + SCOPED_TRACE("X"); + Sub(); +} + +// Tests linking of failure absence assertions. +TEST(NoFailureAssertionTest, LinksSuccessfully) { + EXPECT_NO_FATAL_FAILURE(IsEven(2)); +} + +// Tests linking of HasFatalFailure. +TEST(HasFatalFailureTest, LinksSuccessfully) { + EXPECT_FALSE(HasFatalFailure()); + EXPECT_FALSE(HasNonfatalFailure()); + EXPECT_FALSE(HasFailure()); +} + +// Tests linking of RecordProperty. +TEST(RecordPropertyTest, LinksSuccessfully) { + RecordProperty("DummyPropery", "DummyValue"); +} + +// Tests linking of environments. +class MyEnvironment : public Environment {}; + +Environment* const environment = AddGlobalTestEnvironment(new MyEnvironment); + +// Tests linking of flags. +TEST(FlagTest, LinksSuccessfully) { + Message message; + + message << GTEST_FLAG(filter); + message << GTEST_FLAG(also_run_disabled_tests); + message << GTEST_FLAG(repeat); + message << GTEST_FLAG(shuffle); + message << GTEST_FLAG(random_seed); + message << GTEST_FLAG(color); + message << GTEST_FLAG(print_time); + message << GTEST_FLAG(output); + message << GTEST_FLAG(break_on_failure); + message << GTEST_FLAG(throw_on_failure); + message << GTEST_FLAG(catch_exceptions); + message << GTEST_FLAG(stack_trace_depth); +} + +// Tests linking of failure catching assertions. +void FunctionWithFailure() { FAIL(); } + +TEST(FailureCatchingAssertionTest, LinksCorrectly) { + EXPECT_FATAL_FAILURE(FunctionWithFailure(), ""); + EXPECT_NONFATAL_FAILURE(ADD_FAILURE(), ""); + EXPECT_FATAL_FAILURE_ON_ALL_THREADS(FunctionWithFailure(), ""); + EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(ADD_FAILURE(), ""); +} + +// Tests linking of the reflection API. +TEST(ReflectionApiTest, LinksCorrectly) { + // UnitTest API. + UnitTest* unit_test = UnitTest::GetInstance(); + + unit_test->original_working_dir(); + EXPECT_TRUE(unit_test->current_test_case() != NULL); + EXPECT_TRUE(unit_test->current_test_info() != NULL); + EXPECT_NE(0, unit_test->random_seed()); + EXPECT_GE(unit_test->successful_test_case_count(), 0); + EXPECT_EQ(0, unit_test->failed_test_case_count()); + EXPECT_GE(unit_test->total_test_case_count(), 0); + EXPECT_GT(unit_test->test_case_to_run_count(), 0); + EXPECT_GE(unit_test->successful_test_count(), 0); + EXPECT_EQ(0, unit_test->failed_test_count()); + EXPECT_EQ(0, unit_test->disabled_test_count()); + EXPECT_GT(unit_test->total_test_count(), 0); + EXPECT_GT(unit_test->test_to_run_count(), 0); + EXPECT_GE(unit_test->elapsed_time(), 0); + EXPECT_TRUE(unit_test->Passed()); + EXPECT_FALSE(unit_test->Failed()); + EXPECT_TRUE(unit_test->GetTestCase(0) != NULL); + + // TestCase API. + const TestCase*const test_case = unit_test->current_test_case(); + + EXPECT_STRNE("", test_case->name()); + const char* const test_case_comment = test_case->comment(); + EXPECT_TRUE(test_case->should_run()); + EXPECT_GE(test_case->successful_test_count(), 0); + EXPECT_EQ(0, test_case->failed_test_count()); + EXPECT_EQ(0, test_case->disabled_test_count()); + EXPECT_GT(test_case->test_to_run_count(), 0); + EXPECT_GT(test_case->total_test_count(), 0); + EXPECT_TRUE(test_case->Passed()); + EXPECT_FALSE(test_case->Failed()); + EXPECT_GE(test_case->elapsed_time(), 0); + EXPECT_TRUE(test_case->GetTestInfo(0) != NULL); + + // TestInfo API. + const TestInfo* const test_info = unit_test->current_test_info(); + + EXPECT_STRNE("", test_info->test_case_name()); + EXPECT_STRNE("", test_info->name()); + EXPECT_STREQ(test_case_comment, test_info->test_case_comment()); + const char* const comment = test_info->comment(); + EXPECT_TRUE(comment == NULL || strlen(comment) >= 0); + EXPECT_TRUE(test_info->should_run()); + EXPECT_TRUE(test_info->result() != NULL); + + // TestResult API. + const TestResult* const test_result = test_info->result(); + + SUCCEED() << "This generates a successful test part instance for API testing"; + RecordProperty("Test Name", "Test Value"); + EXPECT_EQ(1, test_result->total_part_count()); + EXPECT_EQ(1, test_result->test_property_count()); + EXPECT_TRUE(test_result->Passed()); + EXPECT_FALSE(test_result->Failed()); + EXPECT_FALSE(test_result->HasFatalFailure()); + EXPECT_FALSE(test_result->HasNonfatalFailure()); + EXPECT_GE(test_result->elapsed_time(), 0); + const TestPartResult& test_part_result = test_result->GetTestPartResult(0); + const TestProperty& test_property = test_result->GetTestProperty(0); + + // TestPartResult API. + EXPECT_EQ(TestPartResult::kSuccess, test_part_result.type()); + EXPECT_STRNE("", test_part_result.file_name()); + EXPECT_GT(test_part_result.line_number(), 0); + EXPECT_STRNE("", test_part_result.summary()); + EXPECT_STRNE("", test_part_result.message()); + EXPECT_TRUE(test_part_result.passed()); + EXPECT_FALSE(test_part_result.failed()); + EXPECT_FALSE(test_part_result.nonfatally_failed()); + EXPECT_FALSE(test_part_result.fatally_failed()); + + // TestProperty API. + EXPECT_STREQ("Test Name", test_property.key()); + EXPECT_STREQ("Test Value", test_property.value()); +} + +// Tests linking of the event listener API. +class MyListener : public TestEventListener { + virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationStart(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} + virtual void OnTestStart(const TestInfo& /*test_info*/) {} + virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {} + virtual void OnTestEnd(const TestInfo& /*test_info*/) {} + virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} + virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {} + virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} + virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/, + int /*iteration*/) {} + virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} +}; + +class MyOtherListener : public EmptyTestEventListener {}; + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + + TestEventListeners& listeners = UnitTest::GetInstance()->listeners(); + TestEventListener* listener = new MyListener; + + listeners.Append(listener); + listeners.Release(listener); + listeners.Append(new MyOtherListener); + listener = listeners.default_result_printer(); + listener = listeners.default_xml_generator(); + + RUN_ALL_TESTS(); + return 0; +} |