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 32 """Tests the text output of Google C++ Mocking Framework. 33 34 SYNOPSIS 35 gmock_output_test.py --build_dir=BUILD/DIR --gengolden 36 # where BUILD/DIR contains the built gmock_output_test_ file. 37 gmock_output_test.py --gengolden 38 gmock_output_test.py 39 """ 40 41 __author__ = 'wan (at] google.com (Zhanyong Wan)' 42 43 import os 44 import re 45 import sys 46 47 import gmock_test_utils 48 49 50 # The flag for generating the golden file 51 GENGOLDEN_FLAG = '--gengolden' 52 53 PROGRAM_PATH = gmock_test_utils.GetTestExecutablePath('gmock_output_test_') 54 COMMAND = [PROGRAM_PATH, '--gtest_stack_trace_depth=0', '--gtest_print_time=0'] 55 GOLDEN_NAME = 'gmock_output_test_golden.txt' 56 GOLDEN_PATH = os.path.join(gmock_test_utils.GetSourceDir(), GOLDEN_NAME) 57 58 59 def ToUnixLineEnding(s): 60 """Changes all Windows/Mac line endings in s to UNIX line endings.""" 61 62 return s.replace('\r\n', '\n').replace('\r', '\n') 63 64 65 def RemoveReportHeaderAndFooter(output): 66 """Removes Google Test result report's header and footer from the output.""" 67 68 output = re.sub(r'.*gtest_main.*\n', '', output) 69 output = re.sub(r'\[.*\d+ tests.*\n', '', output) 70 output = re.sub(r'\[.* test environment .*\n', '', output) 71 output = re.sub(r'\[=+\] \d+ tests .* ran.*', '', output) 72 output = re.sub(r'.* FAILED TESTS\n', '', output) 73 return output 74 75 76 def RemoveLocations(output): 77 """Removes all file location info from a Google Test program's output. 78 79 Args: 80 output: the output of a Google Test program. 81 82 Returns: 83 output with all file location info (in the form of 84 'DIRECTORY/FILE_NAME:LINE_NUMBER: 'or 85 'DIRECTORY\\FILE_NAME(LINE_NUMBER): ') replaced by 86 'FILE:#: '. 87 """ 88 89 return re.sub(r'.*[/\\](.+)(\:\d+|\(\d+\))\:', 'FILE:#:', output) 90 91 92 def NormalizeErrorMarker(output): 93 """Normalizes the error marker, which is different on Windows vs on Linux.""" 94 95 return re.sub(r' error: ', ' Failure\n', output) 96 97 98 def RemoveMemoryAddresses(output): 99 """Removes memory addresses from the test output.""" 100 101 return re.sub(r'@\w+', '@0x#', output) 102 103 104 def RemoveTestNamesOfLeakedMocks(output): 105 """Removes the test names of leaked mock objects from the test output.""" 106 107 return re.sub(r'\(used in test .+\) ', '', output) 108 109 110 def GetLeakyTests(output): 111 """Returns a list of test names that leak mock objects.""" 112 113 # findall() returns a list of all matches of the regex in output. 114 # For example, if '(used in test FooTest.Bar)' is in output, the 115 # list will contain 'FooTest.Bar'. 116 return re.findall(r'\(used in test (.+)\)', output) 117 118 119 def GetNormalizedOutputAndLeakyTests(output): 120 """Normalizes the output of gmock_output_test_. 121 122 Args: 123 output: The test output. 124 125 Returns: 126 A tuple (the normalized test output, the list of test names that have 127 leaked mocks). 128 """ 129 130 output = ToUnixLineEnding(output) 131 output = RemoveReportHeaderAndFooter(output) 132 output = NormalizeErrorMarker(output) 133 output = RemoveLocations(output) 134 output = RemoveMemoryAddresses(output) 135 return (RemoveTestNamesOfLeakedMocks(output), GetLeakyTests(output)) 136 137 138 def GetShellCommandOutput(cmd): 139 """Runs a command in a sub-process, and returns its STDOUT in a string.""" 140 141 return gmock_test_utils.Subprocess(cmd, capture_stderr=False).output 142 143 144 def GetNormalizedCommandOutputAndLeakyTests(cmd): 145 """Runs a command and returns its normalized output and a list of leaky tests. 146 147 Args: 148 cmd: the shell command. 149 """ 150 151 # Disables exception pop-ups on Windows. 152 os.environ['GTEST_CATCH_EXCEPTIONS'] = '1' 153 return GetNormalizedOutputAndLeakyTests(GetShellCommandOutput(cmd)) 154 155 156 class GMockOutputTest(gmock_test_utils.TestCase): 157 def testOutput(self): 158 (output, leaky_tests) = GetNormalizedCommandOutputAndLeakyTests(COMMAND) 159 golden_file = open(GOLDEN_PATH, 'rb') 160 golden = golden_file.read() 161 golden_file.close() 162 163 # The normalized output should match the golden file. 164 self.assertEquals(golden, output) 165 166 # The raw output should contain 2 leaked mock object errors for 167 # test GMockOutputTest.CatchesLeakedMocks. 168 self.assertEquals(['GMockOutputTest.CatchesLeakedMocks', 169 'GMockOutputTest.CatchesLeakedMocks'], 170 leaky_tests) 171 172 173 if __name__ == '__main__': 174 if sys.argv[1:] == [GENGOLDEN_FLAG]: 175 (output, _) = GetNormalizedCommandOutputAndLeakyTests(COMMAND) 176 golden_file = open(GOLDEN_PATH, 'wb') 177 golden_file.write(output) 178 golden_file.close() 179 else: 180 gmock_test_utils.Main() 181