Pulls in gtest r344; improves implicit_cast (by Zhanyong Wan); makes the Python tests work on Windows (by Vlad Losev); adds run_tests.py (by Vlad Losev).

This commit is contained in:
zhanyong.wan 2009-11-24 20:23:18 +00:00
parent e56daa7de1
commit 19eb9e9e3d
8 changed files with 170 additions and 127 deletions

View File

@ -81,39 +81,22 @@ namespace internal {
#error "At least Visual C++ 2003 (7.1) is required to compile Google Mock."
#endif
// Use implicit_cast as a safe version of static_cast or const_cast
// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
// a const pointer to Foo).
// When you use implicit_cast, the compiler checks that the cast is safe.
// Such explicit implicit_casts are necessary in surprisingly many
// situations where C++ demands an exact type match instead of an
// argument type convertable to a target type.
// Use implicit_cast as a safe version of static_cast for upcasting in
// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
// const Foo*). When you use implicit_cast, the compiler checks that
// the cast is safe. Such explicit implicit_casts are necessary in
// surprisingly many situations where C++ demands an exact type match
// instead of an argument type convertable to a target type.
//
// The From type can be inferred, so the preferred syntax for using
// implicit_cast is the same as for static_cast etc.:
// The syntax for using implicit_cast is the same as for static_cast:
//
// implicit_cast<ToType>(expr)
//
// implicit_cast would have been part of the C++ standard library,
// but the proposal was submitted too late. It will probably make
// its way into the language in the future.
template<typename To, typename From>
inline To implicit_cast(const From& f) {
return f;
}
// Nokia's compiler can't tell which version of implicit_cast to use when
// the source is a const, causing the compilation to fail with the error
// "ambiguous access to overloaded function". So we only support the const
// version of implicit_cast on Symbian.
#if !GTEST_OS_SYMBIAN
// This overload is needed in case the From type has a non-const type
// conversion operator to type To.
template<typename To, typename From>
inline To implicit_cast(From& f) {
return f;
}
#endif
template<typename To>
inline To implicit_cast(To x) { return x; }
// When you upcast (that is, cast a pointer from type Foo to type
// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
@ -139,7 +122,8 @@ inline To down_cast(From* f) { // so we only accept pointers
// optimized build at run-time, as it will be optimized away
// completely.
if (false) {
implicit_cast<From*, To>(0);
const To to = NULL;
implicit_cast<From*>(to);
}
#if GTEST_HAS_RTTI

82
run_tests.py Executable file
View File

@ -0,0 +1,82 @@
#!/usr/bin/env python
#
# Copyright 2008, 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.
"""Runs the specified tests for Google Mock.
This script requires Python 2.3 or higher. To learn the usage, run it
with -h.
"""
__author__ = 'vladl@google.com (Vlad Losev)'
import os
import sys
SCRIPT_DIR = os.path.dirname(__file__) or '.'
# Path to the Google Test code this Google Mock will use. We assume the
# gtest/ directory is either a subdirectory (possibly via a symbolic link)
# of gmock/ or a sibling.
#
# isdir resolves symbolic links.
if os.path.isdir(os.path.join(SCRIPT_DIR, 'gtest/test')):
RUN_TESTS_UTIL_DIR = os.path.join(SCRIPT_DIR, 'gtest/test')
else:
RUN_TESTS_UTIL_DIR = os.path.join(SCRIPT_DIR, '../gtest/test')
sys.path.append(RUN_TESTS_UTIL_DIR)
import run_tests_util
def GetGmockBuildDir(injected_os, script_dir, config):
return injected_os.path.normpath(injected_os.path.join(script_dir,
'scons/build',
config,
'gmock/scons'))
def _Main():
"""Runs all tests for Google Mock."""
options, args = run_tests_util.ParseArgs('gtest')
test_runner = run_tests_util.TestRunner(
script_dir=SCRIPT_DIR,
build_dir_var_name='GMOCK_BUILD_DIR',
injected_build_dir_finder=GetGmockBuildDir)
tests = test_runner.GetTestsToRun(args,
options.configurations,
options.built_configurations)
if not tests:
sys.exit(1) # Incorrect parameters given, abort execution.
sys.exit(test_runner.RunTests(tests[0], tests[1]))
if __name__ == '__main__':
_Main()

View File

@ -340,11 +340,11 @@ def _NeedToUseReturnNullDiagnoser(msg):
regex = ('instantiated from \'testing::internal::ReturnAction<R>'
'::operator testing::Action<Func>\(\) const.*\n' +
_FILE_LINE_RE + r'instantiated from here\n'
r'.*gmock-port\.h.*error: invalid conversion from '
r'\'long int\' to \'(?P<type>.+\*)')
r'.*error: no matching function for call to \'implicit_cast\('
r'long int&\)')
diagnosis = """
You are probably calling Return(NULL) and the compiler isn't sure how to turn
NULL into a %(type)s*. Use ReturnNull() instead.
NULL into the right type. Use ReturnNull() instead.
Note: the line number may be off; please fix all instances of Return(NULL)."""
return _GenericDiagnoser('NRNULL', 'Need to use ReturnNull',
regex, diagnosis, msg)

View File

@ -545,9 +545,6 @@ TEST(ReturnTest, ConvertsArgumentWhenConverted) {
<< "when performed." ;
}
// We do not support non-const type conversions on Symbian. See
// definition of implicit_cast in gmock-port.h for more information.
#if !GTEST_OS_SYMBIAN
class DestinationType {};
class SourceType {
@ -560,7 +557,6 @@ TEST(ReturnTest, CanConvertArgumentUsingNonConstTypeCastOperator) {
SourceType s;
Action<DestinationType()> action(Return(s));
}
#endif // !GTEST_OS_SYMBIAN
// Tests that ReturnNull() returns NULL in a pointer-returning function.
TEST(ReturnNullTest, WorksInPointerReturningFunction) {

View File

@ -76,10 +76,6 @@ TEST(ImplicitCastTest, CanUseInheritance) {
EXPECT_EQ(derived.member(), base.member());
}
// The non-const version is not enabled for Symbian since the Nokia compiler
// cannot decide which version of the overloaded implicit_cast method to use
// when the source is a const.
#if !GTEST_OS_SYMBIAN
class Castable {
public:
Castable(bool* converted) : converted_(converted) {}
@ -98,7 +94,6 @@ TEST(ImplicitCastTest, CanUseNonConstCastOperator) {
Base base = ::testing::internal::implicit_cast<Base>(castable);
EXPECT_TRUE(converted);
}
#endif // !GTEST_OS_SYMBIAN
class ConstCastable {
public:
@ -119,10 +114,6 @@ TEST(ImplicitCastTest, CanUseConstCastOperatorOnConstValues) {
EXPECT_TRUE(converted);
}
// The non-const version is not enabled for Symbian since the Nokia compiler
// cannot decide which version of the overloaded implicit_cast method to use
// when the source is a const.
#if !GTEST_OS_SYMBIAN
class ConstAndNonConstCastable {
public:
ConstAndNonConstCastable(bool* converted, bool* const_converted)
@ -156,7 +147,6 @@ TEST(ImplicitCastTest, CanSelectBetweenConstAndNonConstCasrAppropriately) {
EXPECT_FALSE(converted);
EXPECT_TRUE(const_converted);
}
#endif // !GTEST_OS_SYMBIAN
class To {
public:

View File

@ -33,51 +33,59 @@
__author__ = 'wan@google.com (Zhanyong Wan)'
import gmock_test_utils
import os
import unittest
IS_WINDOWS = os.name == 'nt'
import gmock_test_utils
if IS_WINDOWS:
# TODO(wan@google.com): test the opt build too. We should do it
# when Vlad Losev's work on Google Test's Python test driver is
# done, such that we can reuse the work.
PROGRAM = r'..\build.dbg\gmock_leak_test_.exe'
else:
PROGRAM = 'gmock_leak_test_'
PROGRAM_PATH = os.path.join(gmock_test_utils.GetBuildDir(), PROGRAM)
TEST_WITH_EXPECT_CALL = PROGRAM_PATH + ' --gtest_filter=*ExpectCall*'
TEST_WITH_ON_CALL = PROGRAM_PATH + ' --gtest_filter=*OnCall*'
TEST_MULTIPLE_LEAKS = PROGRAM_PATH + ' --gtest_filter=*MultipleLeaked*'
PROGRAM_PATH = gmock_test_utils.GetTestExecutablePath('gmock_leak_test_')
TEST_WITH_EXPECT_CALL = [PROGRAM_PATH, '--gtest_filter=*ExpectCall*']
TEST_WITH_ON_CALL = [PROGRAM_PATH, '--gtest_filter=*OnCall*']
TEST_MULTIPLE_LEAKS = [PROGRAM_PATH, '--gtest_filter=*MultipleLeaked*']
class GMockLeakTest(unittest.TestCase):
def testCatchesLeakedMockByDefault(self):
self.assertNotEqual(os.system(TEST_WITH_EXPECT_CALL), 0)
self.assertNotEqual(os.system(TEST_WITH_ON_CALL), 0)
self.assertNotEqual(
0,
gmock_test_utils.Subprocess(TEST_WITH_EXPECT_CALL).exit_code)
self.assertNotEqual(
0,
gmock_test_utils.Subprocess(TEST_WITH_ON_CALL).exit_code)
def testDoesNotCatchLeakedMockWhenDisabled(self):
self.assertEquals(
0, os.system(TEST_WITH_EXPECT_CALL + ' --gmock_catch_leaked_mocks=0'))
0,
gmock_test_utils.Subprocess(TEST_WITH_EXPECT_CALL +
['--gmock_catch_leaked_mocks=0']).exit_code)
self.assertEquals(
0, os.system(TEST_WITH_ON_CALL + ' --gmock_catch_leaked_mocks=0'))
0,
gmock_test_utils.Subprocess(TEST_WITH_ON_CALL +
['--gmock_catch_leaked_mocks=0']).exit_code)
def testCatchesLeakedMockWhenEnabled(self):
self.assertNotEqual(
os.system(TEST_WITH_EXPECT_CALL + ' --gmock_catch_leaked_mocks'), 0)
0,
gmock_test_utils.Subprocess(TEST_WITH_EXPECT_CALL +
['--gmock_catch_leaked_mocks']).exit_code)
self.assertNotEqual(
os.system(TEST_WITH_ON_CALL + ' --gmock_catch_leaked_mocks'), 0)
0,
gmock_test_utils.Subprocess(TEST_WITH_ON_CALL +
['--gmock_catch_leaked_mocks']).exit_code)
def testCatchesLeakedMockWhenEnabledWithExplictFlagValue(self):
self.assertNotEqual(
os.system(TEST_WITH_EXPECT_CALL + ' --gmock_catch_leaked_mocks=1'), 0)
0,
gmock_test_utils.Subprocess(TEST_WITH_EXPECT_CALL +
['--gmock_catch_leaked_mocks=1']).exit_code)
def testCatchesMultipleLeakedMocks(self):
self.assertNotEqual(
os.system(TEST_MULTIPLE_LEAKS + ' --gmock_catch_leaked_mocks'), 0)
0,
gmock_test_utils.Subprocess(TEST_MULTIPLE_LEAKS +
['--gmock_catch_leaked_mocks']).exit_code)
if __name__ == '__main__':

View File

@ -40,29 +40,21 @@ SYNOPSIS
__author__ = 'wan@google.com (Zhanyong Wan)'
import gmock_test_utils
import os
import re
import string
import sys
import unittest
import gmock_test_utils
# The flag for generating the golden file
GENGOLDEN_FLAG = '--gengolden'
IS_WINDOWS = os.name == 'nt'
if IS_WINDOWS:
PROGRAM = r'..\build.dbg\gmock_output_test_.exe'
else:
PROGRAM = 'gmock_output_test_'
PROGRAM_PATH = os.path.join(gmock_test_utils.GetBuildDir(), PROGRAM)
COMMAND = PROGRAM_PATH + ' --gtest_stack_trace_depth=0 --gtest_print_time=0'
PROGRAM_PATH = gmock_test_utils.GetTestExecutablePath('gmock_output_test_')
COMMAND = [PROGRAM_PATH, '--gtest_stack_trace_depth=0', '--gtest_print_time=0']
GOLDEN_NAME = 'gmock_output_test_golden.txt'
GOLDEN_PATH = os.path.join(gmock_test_utils.GetSourceDir(),
GOLDEN_NAME)
GOLDEN_PATH = os.path.join(gmock_test_utils.GetSourceDir(), GOLDEN_NAME)
def ToUnixLineEnding(s):
@ -144,51 +136,10 @@ def GetNormalizedOutputAndLeakyTests(output):
return (RemoveTestNamesOfLeakedMocks(output), GetLeakyTests(output))
def IterShellCommandOutput(cmd, stdin_string=None):
"""Runs a command in a sub-process, and iterates the lines in its STDOUT.
def GetShellCommandOutput(cmd):
"""Runs a command in a sub-process, and returns its STDOUT in a string."""
Args:
cmd: The shell command.
stdin_string: The string to be fed to the STDIN of the sub-process;
If None, the sub-process will inherit the STDIN
from the parent process.
"""
# Spawns cmd in a sub-process, and gets its standard I/O file objects.
stdin_file, stdout_file = os.popen2(cmd, 'b')
# If the caller didn't specify a string for STDIN, gets it from the
# parent process.
if stdin_string is None:
stdin_string = sys.stdin.read()
# Feeds the STDIN string to the sub-process.
stdin_file.write(stdin_string)
stdin_file.close()
while True:
line = stdout_file.readline()
if not line: # EOF
stdout_file.close()
break
yield line
def GetShellCommandOutput(cmd, stdin_string=None):
"""Runs a command in a sub-process, and returns its STDOUT in a string.
Args:
cmd: The shell command.
stdin_string: The string to be fed to the STDIN of the sub-process;
If None, the sub-process will inherit the STDIN
from the parent process.
"""
lines = list(IterShellCommandOutput(cmd, stdin_string))
return string.join(lines, '')
return gmock_test_utils.Subprocess(cmd, capture_stderr=False).output
def GetNormalizedCommandOutputAndLeakyTests(cmd):
@ -200,7 +151,7 @@ def GetNormalizedCommandOutputAndLeakyTests(cmd):
# Disables exception pop-ups on Windows.
os.environ['GTEST_CATCH_EXCEPTIONS'] = '1'
return GetNormalizedOutputAndLeakyTests(GetShellCommandOutput(cmd, ''))
return GetNormalizedOutputAndLeakyTests(GetShellCommandOutput(cmd))
class GMockOutputTest(unittest.TestCase):

View File

@ -35,7 +35,19 @@ __author__ = 'wan@google.com (Zhanyong Wan)'
import os
import sys
import unittest
# Determines path to gtest_test_utils and imports it.
SCRIPT_DIR = os.path.dirname(__file__) or '.'
# isdir resolves symbolic links.
gtest_tests_util_dir = os.path.join(SCRIPT_DIR, '../gtest/test')
if os.path.isdir(gtest_tests_util_dir):
GTEST_TESTS_UTIL_DIR = gtest_tests_util_dir
else:
GTEST_TESTS_UTIL_DIR = os.path.join(SCRIPT_DIR, '../../gtest/test')
sys.path.append(GTEST_TESTS_UTIL_DIR)
import gtest_test_utils # pylint: disable-msg=C6204
# Initially maps a flag to its default value. After
@ -96,6 +108,22 @@ def GetBuildDir():
return os.path.abspath(GetFlag('gmock_build_dir'))
def GetTestExecutablePath(executable_name):
"""Returns the absolute path of the test binary given its name.
The function will print a message and abort the program if the resulting file
doesn't exist.
Args:
executable_name: name of the test binary that the test script runs.
Returns:
The absolute path of the test binary.
"""
return gtest_test_utils.GetTestExecutablePath(executable_name, GetBuildDir())
def GetExitStatus(exit_code):
"""Returns the argument to exit(), or -1 if exit() wasn't called.
@ -116,11 +144,15 @@ def GetExitStatus(exit_code):
return -1
# Exposes Subprocess from gtest_test_utils.
Subprocess = gtest_test_utils.Subprocess # pylint: disable-msg=C6409
def Main():
"""Runs the unit test."""
# We must call _ParseAndStripGMockFlags() before calling
# unittest.main(). Otherwise the latter will be confused by the
# --gmock_* flags.
# gtest_test_utils.Main(). Otherwise unittest.main it calls will be
# confused by the --gmock_* flags.
_ParseAndStripGMockFlags(sys.argv)
unittest.main()
gtest_test_utils.Main()