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