1#!/usr/bin/env python 2# 3# Copyright 2008, Google Inc. 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are 8# met: 9# 10# * Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# * Redistributions in binary form must reproduce the above 13# copyright notice, this list of conditions and the following disclaimer 14# in the documentation and/or other materials provided with the 15# distribution. 16# * Neither the name of Google Inc. nor the names of its 17# contributors may be used to endorse or promote products derived from 18# this software without specific prior written permission. 19# 20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 32r"""Tests the text output of Google C++ Mocking Framework. 33 34To update the golden file: 35gmock_output_test.py --build_dir=BUILD/DIR --gengolden 36where BUILD/DIR contains the built gmock_output_test_ file. 37gmock_output_test.py --gengolden 38gmock_output_test.py 39 40""" 41 42from io import open # pylint: disable=redefined-builtin, g-importing-member 43import os 44import re 45import sys 46from googlemock.test import gmock_test_utils 47 48 49# The flag for generating the golden file 50GENGOLDEN_FLAG = '--gengolden' 51 52PROGRAM_PATH = gmock_test_utils.GetTestExecutablePath('gmock_output_test_') 53COMMAND = [PROGRAM_PATH, '--gtest_stack_trace_depth=0', '--gtest_print_time=0'] 54GOLDEN_NAME = 'gmock_output_test_golden.txt' 55GOLDEN_PATH = os.path.join(gmock_test_utils.GetSourceDir(), GOLDEN_NAME) 56 57 58def ToUnixLineEnding(s): 59 """Changes all Windows/Mac line endings in s to UNIX line endings.""" 60 61 return s.replace('\r\n', '\n').replace('\r', '\n') 62 63 64def RemoveReportHeaderAndFooter(output): 65 """Removes Google Test result report's header and footer from the output.""" 66 67 output = re.sub(r'.*gtest_main.*\n', '', output) 68 output = re.sub(r'\[.*\d+ tests.*\n', '', output) 69 output = re.sub(r'\[.* test environment .*\n', '', output) 70 output = re.sub(r'\[=+\] \d+ tests .* ran.*', '', output) 71 output = re.sub(r'.* FAILED TESTS\n', '', output) 72 return output 73 74 75def RemoveLocations(output): 76 """Removes all file location info from a Google Test program's output. 77 78 Args: 79 output: the output of a Google Test program. 80 81 Returns: 82 output with all file location info (in the form of 83 'DIRECTORY/FILE_NAME:LINE_NUMBER: 'or 84 'DIRECTORY\\FILE_NAME(LINE_NUMBER): ') replaced by 85 'FILE:#: '. 86 """ 87 88 return re.sub(r'.*[/\\](.+)(\:\d+|\(\d+\))\:', 'FILE:#:', output) 89 90 91def NormalizeErrorMarker(output): 92 """Normalizes the error marker, which is different on Windows vs on Linux.""" 93 94 return re.sub(r' error: ', ' Failure\n', output) 95 96 97def RemoveMemoryAddresses(output): 98 """Removes memory addresses from the test output.""" 99 100 return re.sub(r'@\w+', '@0x#', output) 101 102 103def RemoveTestNamesOfLeakedMocks(output): 104 """Removes the test names of leaked mock objects from the test output.""" 105 106 return re.sub(r'\(used in test .+\) ', '', output) 107 108 109def GetLeakyTests(output): 110 """Returns a list of test names that leak mock objects.""" 111 112 # findall() returns a list of all matches of the regex in output. 113 # For example, if '(used in test FooTest.Bar)' is in output, the 114 # list will contain 'FooTest.Bar'. 115 return re.findall(r'\(used in test (.+)\)', output) 116 117 118def GetNormalizedOutputAndLeakyTests(output): 119 """Normalizes the output of gmock_output_test_. 120 121 Args: 122 output: The test output. 123 124 Returns: 125 A tuple (the normalized test output, the list of test names that have 126 leaked mocks). 127 """ 128 129 output = ToUnixLineEnding(output) 130 output = RemoveReportHeaderAndFooter(output) 131 output = NormalizeErrorMarker(output) 132 output = RemoveLocations(output) 133 output = RemoveMemoryAddresses(output) 134 return (RemoveTestNamesOfLeakedMocks(output), GetLeakyTests(output)) 135 136 137def GetShellCommandOutput(cmd): 138 """Runs a command in a sub-process, and returns its STDOUT in a string.""" 139 140 return gmock_test_utils.Subprocess(cmd, capture_stderr=False).output 141 142 143def GetNormalizedCommandOutputAndLeakyTests(cmd): 144 """Runs a command and returns its normalized output and a list of leaky tests. 145 146 Args: 147 cmd: the shell command. 148 """ 149 150 # Disables exception pop-ups on Windows. 151 os.environ['GTEST_CATCH_EXCEPTIONS'] = '1' 152 return GetNormalizedOutputAndLeakyTests(GetShellCommandOutput(cmd)) 153 154 155class GMockOutputTest(gmock_test_utils.TestCase): 156 157 def testOutput(self): 158 (output, leaky_tests) = GetNormalizedCommandOutputAndLeakyTests(COMMAND) 159 golden_file = open(GOLDEN_PATH, 'rb') 160 golden = golden_file.read().decode('utf-8') 161 golden_file.close() 162 # On Windows the repository might have been checked out with \r\n line 163 # endings, so normalize it here. 164 golden = ToUnixLineEnding(golden) 165 166 # The normalized output should match the golden file. 167 self.assertEqual(golden, output) 168 169 # The raw output should contain 2 leaked mock object errors for 170 # test GMockOutputTest.CatchesLeakedMocks. 171 self.assertEqual( 172 [ 173 'GMockOutputTest.CatchesLeakedMocks', 174 'GMockOutputTest.CatchesLeakedMocks', 175 ], 176 leaky_tests, 177 ) 178 179 180if __name__ == '__main__': 181 if sys.argv[1:] == [GENGOLDEN_FLAG]: 182 (output, _) = GetNormalizedCommandOutputAndLeakyTests(COMMAND) 183 golden_file = open(GOLDEN_PATH, 'wb') 184 golden_file.write(output) 185 golden_file.close() 186 # Suppress the error "googletest was imported but a call to its main() 187 # was never detected." 188 os._exit(0) 189 else: 190 gmock_test_utils.Main() 191