#!/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. """Tests for gmock_doctor.py.""" import os import sys IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux' if not IS_LINUX: sys.stderr.write( 'WARNING: Negative compilation tests are not supported on this platform') sys.exit(0) # Suppresses the 'Import not at the top of the file' lint complaint. # pylint: disable-msg=C6204 import google3.third_party.googletest.googlemock.scripts.gmock_doctor gmock_doctor = google3.third_party.googletest.googlemock.scripts.gmock_doctor from google3.testing.pybase import fake_target_util from google3.testing.pybase import googletest # pylint: enable-msg=C6204 def GetCompilerCommand(): """Returns the command used for compiling gmock_doctor_nc.cc.""" # Parses the fake output generated by the cc_fake_binary rule. target = fake_target_util.ParseFakeTargetFile( 'google3/third_party/googletest/googlemock/test/gmock_doctor_nc') # Looks up the command for making the desired target. command = target.CommandMap()['gmock_doctor_nc.o'] # Looks up where Makefile is. makefile_dir = target.MakefileDir() # Changes the current directory to where Makefile is - the # compilation must be done there. os.chdir(makefile_dir) return command def CompileSection(section_name): """Compiles the given section in gmock_doctor_nc.cc. The error messages from the compiler will be printed on stdout such that they can be easily piped to the Google Mock Doctor. Args: section_name: Name of the section in gmock_doctor_nc.cc that should be compiled. """ command = GetCompilerCommand() (_, compiler_errors) = googletest.GetCommandStderr( command + ' -DTEST_' + section_name, env = {'TEST_TMPDIR': os.environ['TEST_TMPDIR']}) print compiler_errors class GMockDoctorTest(googletest.TestCase): def setUp(self): self.command = GetCompilerCommand() def CheckDiagnoses(self, test_name, diseases): """Checks the diagnoses for the given compiler output. Args: test_name: Name of the section in gmock_doctor_nc.cc that should be compiled. diseases: A list of disease short names that Google Mock Doctor should diagnose. """ _, compiler_errors = googletest.GetCommandStderr( self.command + ' -DTEST_' + test_name, env = {'TEST_TMPDIR': os.environ['TEST_TMPDIR']}) self.CheckDiagnosesForOutput(compiler_errors, diseases) def CheckDiagnosesForOutput(self, compiler_errors, diseases): """Checks the diagnoses for the given test. Args: compiler_errors: The compiler diagnostics to check for diseases. diseases: A list of disease short names that Google Mock Doctor should diagnose. """ diagnoses = gmock_doctor.Diagnose(compiler_errors) num_diseases = len(diseases) num_diagnoses = len(diagnoses) for i in range(min(num_diseases, num_diagnoses)): self.assert_(('[' + diseases[i] + ' ') in diagnoses[i], ('Compiler error message:\n\n' '%sgmock_doctor.py\'s diagnoses:\n%s\n\n' 'Failed to diagnose the %s disease.') % (compiler_errors, diagnoses[i], diseases[i])) self.assertEquals(num_diseases, num_diagnoses, ('%d diseases, but %d diagnoses, where the ' 'compiler errors are:\n%s\n' 'and where the diseases are:\n%s\n' 'and where the diagnoses are:\n%s\n') % (num_diseases, num_diagnoses, compiler_errors, str(diseases), str(diagnoses))) def testMOP(self): self.CheckDiagnoses('MOP', 2 * ['MOP']) def testNRS1(self): self.CheckDiagnoses('NRS1', ['NRS']) def testNRS2(self): self.CheckDiagnoses('NRS2', ['NRS']) def testNRS3(self): self.CheckDiagnoses('NRS3', ['NRS']) def testIBRA(self): self.CheckDiagnoses('IBRA', ['IBRA']) def testOFM(self): self.CheckDiagnoses('OFM', ['OFM']) def testNoNUSForNonGMockSymbol(self): self.CheckDiagnoses('NO_NUS_FOR_NON_GMOCK_SYMBOL', []) def testNUSVariable(self): self.CheckDiagnoses('NUS_VARIABLE', ['NUS']) def testNUSFunction(self): self.CheckDiagnoses('NUS_FUNCTION', ['NUS']) def testNUSFunctionTemplate(self): self.CheckDiagnoses('NUS_FUNCTION_TEMPLATE', ['NUS']) def testNUSFunctionTemplateWithTypeArg(self): self.CheckDiagnoses('NUS_FUNCTION_TEMPLATE_WITH_TYPE_ARG', ['NUS']) def testNUSFunctionTemplateWithNontypeArg(self): self.CheckDiagnoses('NUS_FUNCTION_TEMPLATE_WITH_NONTYPE_ARG', ['NUS']) def testNUSClass(self): self.CheckDiagnoses('NUS_CLASS', 2 * ['NUS']) def testNRR(self): self.CheckDiagnoses('NRR', ['NRR']) def testMultipleOccurrences(self): self.CheckDiagnoses('MULTI_OCCURRENCES_OF_SAME_DISEASE', 2 * ['IBRA']) def testNRNULL(self): self.CheckDiagnoses('NRNULL', ['NRNULL']) def testWPP(self): self.CheckDiagnoses('WPP', 3 * ['WPP']) def testTTB(self): self.CheckDiagnoses('TTB', 3 * ['TTB']) def testUnderstandsCharaterPositionsInGcc(self): # We cannot guarantee that the system compiler will output character # positions so we inject the compiler output. compiler_errors = ( 'In file included from /usr/include/gmock/gmock.h:58:0,\n' ' from foo.cpp:4:\n' '/usr/include/gmock/gmock-actions.h: In member function' " 'testing::internal::ReturnAction::operator testing::Action()" ' const [with F = const std::complex&(unsigned int),' " R = std::complex]':\n" 'foo.cpp:116:28: instantiated from here\n' '/usr/include/gmock/gmock-actions.h:449:5: error:' " creating array with negative size ('-0x00000000000000001')") self.CheckDiagnosesForOutput(compiler_errors, ['NRR']) def testUnderstandsLeftAndRightSingleQuotes(self): # We cannot guarantee that the system compiler will output single quote # characters so we inject the compiler output. compiler_errors = ( 'In file included from /usr/include/gmock/gmock.h:58,\n' ' from foo.cpp:4:\n' '/usr/include/gmock/gmock-actions.h: In member function' ' \xe2\x80\x98testing::internal::ReturnAction::operator' ' testing::Action() const' ' [with F = const std::complex&(unsigned int),' ' R = std::complex]\xe2\x80\x99:\n' 'foo.cpp:116: instantiated from here\n' '/usr/include/gmock/gmock-actions.h:449: error:' ' creating array with negative size' ' (\xe2\x80\x98-0x00000000000000001\xe2\x80\x99)') self.CheckDiagnosesForOutput(compiler_errors, ['NRR']) if __name__ == '__main__': if len(sys.argv) == 1: googletest.main() else: # To make it easy for a user to see Google Mock Doctor in action, # we compile the given section in gmock_doctor_nc.cc and direct # the error messages to stdout, when the test is run with a # section name on the command line. Then the user can pipe the # output to Google Mock Doctor and see what the diagnoses are # like. For example, to demo how Google Mock Doctor diagnoses the # NRN disease: # # $ blaze build third_party/googletest/googlemock/test:gmock_doctor_test # $ blaze-bin/third_party/googletest/googlemock/test/gmock_doctor_test NRN | \ # third_party/googletest/googlemock/scripts/gmock_doctor.py CompileSection(sys.argv[1])