~ubuntu-branches/ubuntu/precise/protobuf/precise

« back to all changes in this revision

Viewing changes to gtest/test/gtest_output_test.py

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2009-11-16 10:41:33 UTC
  • mfrom: (2.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20091116104133-ykhy3deg5l4975tw
Tags: 2.1.0-1ubuntu1
* Merge from Debian testing.
* Remaining Ubuntu changes:
  - Disable the death tests on IA64, now as a quilt patch.
  - Don't use python2.4, also as a quilt patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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++ Testing Framework.
 
33
 
 
34
SYNOPSIS
 
35
       gtest_output_test.py --gtest_build_dir=BUILD/DIR --gengolden
 
36
         # where BUILD/DIR contains the built gtest_output_test_ file.
 
37
       gtest_output_test.py --gengolden
 
38
       gtest_output_test.py
 
39
"""
 
40
 
 
41
__author__ = 'wan@google.com (Zhanyong Wan)'
 
42
 
 
43
import os
 
44
import re
 
45
import string
 
46
import sys
 
47
import unittest
 
48
import gtest_test_utils
 
49
 
 
50
 
 
51
# The flag for generating the golden file
 
52
GENGOLDEN_FLAG = '--gengolden'
 
53
 
 
54
IS_WINDOWS = os.name == 'nt'
 
55
 
 
56
if IS_WINDOWS:
 
57
  GOLDEN_NAME = 'gtest_output_test_golden_win.txt'
 
58
else:
 
59
  GOLDEN_NAME = 'gtest_output_test_golden_lin.txt'
 
60
 
 
61
PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath('gtest_output_test_')
 
62
 
 
63
# At least one command we exercise must not have the
 
64
# --gtest_internal_skip_environment_and_ad_hoc_tests flag.
 
65
COMMAND_LIST_TESTS = ({}, PROGRAM_PATH + ' --gtest_list_tests')
 
66
COMMAND_WITH_COLOR = ({}, PROGRAM_PATH + ' --gtest_color=yes')
 
67
COMMAND_WITH_TIME = ({}, PROGRAM_PATH + ' --gtest_print_time '
 
68
                     '--gtest_internal_skip_environment_and_ad_hoc_tests '
 
69
                     '--gtest_filter="FatalFailureTest.*:LoggingTest.*"')
 
70
COMMAND_WITH_DISABLED = ({}, PROGRAM_PATH + ' --gtest_also_run_disabled_tests '
 
71
                         '--gtest_internal_skip_environment_and_ad_hoc_tests '
 
72
                         '--gtest_filter="*DISABLED_*"')
 
73
COMMAND_WITH_SHARDING = ({'GTEST_SHARD_INDEX': '1', 'GTEST_TOTAL_SHARDS': '2'},
 
74
                         PROGRAM_PATH +
 
75
                         ' --gtest_internal_skip_environment_and_ad_hoc_tests '
 
76
                         ' --gtest_filter="PassingTest.*"')
 
77
 
 
78
GOLDEN_PATH = os.path.join(gtest_test_utils.GetSourceDir(), GOLDEN_NAME)
 
79
 
 
80
 
 
81
def ToUnixLineEnding(s):
 
82
  """Changes all Windows/Mac line endings in s to UNIX line endings."""
 
83
 
 
84
  return s.replace('\r\n', '\n').replace('\r', '\n')
 
85
 
 
86
 
 
87
def RemoveLocations(output):
 
88
  """Removes all file location info from a Google Test program's output.
 
89
 
 
90
  Args:
 
91
       output:  the output of a Google Test program.
 
92
 
 
93
  Returns:
 
94
       output with all file location info (in the form of
 
95
       'DIRECTORY/FILE_NAME:LINE_NUMBER: 'or
 
96
       'DIRECTORY\\FILE_NAME(LINE_NUMBER): ') replaced by
 
97
       'FILE_NAME:#: '.
 
98
  """
 
99
 
 
100
  return re.sub(r'.*[/\\](.+)(\:\d+|\(\d+\))\: ', r'\1:#: ', output)
 
101
 
 
102
 
 
103
def RemoveStackTraces(output):
 
104
  """Removes all stack traces from a Google Test program's output."""
 
105
 
 
106
  # *? means "find the shortest string that matches".
 
107
  return re.sub(r'Stack trace:(.|\n)*?\n\n',
 
108
                'Stack trace: (omitted)\n\n', output)
 
109
 
 
110
 
 
111
def RemoveTime(output):
 
112
  """Removes all time information from a Google Test program's output."""
 
113
 
 
114
  return re.sub(r'\(\d+ ms', '(? ms', output)
 
115
 
 
116
 
 
117
def RemoveTestCounts(output):
 
118
  """Removes test counts from a Google Test program's output."""
 
119
 
 
120
  output = re.sub(r'\d+ tests, listed below',
 
121
                  '? tests, listed below', output)
 
122
  output = re.sub(r'\d+ FAILED TESTS',
 
123
                  '? FAILED TESTS', output)
 
124
  output = re.sub(r'\d+ tests from \d+ test cases',
 
125
                  '? tests from ? test cases', output)
 
126
  return re.sub(r'\d+ tests\.', '? tests.', output)
 
127
 
 
128
 
 
129
def RemoveMatchingTests(test_output, pattern):
 
130
  """Removes typed test information from a Google Test program's output.
 
131
 
 
132
  This function strips not only the beginning and the end of a test but also all
 
133
  output in between.
 
134
 
 
135
  Args:
 
136
    test_output:       A string containing the test output.
 
137
    pattern:           A string that matches names of test cases to remove.
 
138
 
 
139
  Returns:
 
140
    Contents of test_output with removed test case whose names match pattern.
 
141
  """
 
142
 
 
143
  test_output = re.sub(
 
144
      r'\[ RUN      \] .*%s(.|\n)*?\[(  FAILED  |       OK )\] .*%s.*\n' % (
 
145
          pattern, pattern),
 
146
      '',
 
147
      test_output)
 
148
  return re.sub(r'.*%s.*\n' % pattern, '', test_output)
 
149
 
 
150
 
 
151
def NormalizeOutput(output):
 
152
  """Normalizes output (the output of gtest_output_test_.exe)."""
 
153
 
 
154
  output = ToUnixLineEnding(output)
 
155
  output = RemoveLocations(output)
 
156
  output = RemoveStackTraces(output)
 
157
  output = RemoveTime(output)
 
158
  return output
 
159
 
 
160
 
 
161
def IterShellCommandOutput(env_cmd, stdin_string=None):
 
162
  """Runs a command in a sub-process, and iterates the lines in its STDOUT.
 
163
 
 
164
  Args:
 
165
 
 
166
    env_cmd:           The shell command. A 2-tuple where element 0 is a dict
 
167
                       of extra environment variables to set, and element 1
 
168
                       is a string with the command and any flags.
 
169
    stdin_string:      The string to be fed to the STDIN of the sub-process;
 
170
                       If None, the sub-process will inherit the STDIN
 
171
                       from the parent process.
 
172
  """
 
173
 
 
174
  # Spawns cmd in a sub-process, and gets its standard I/O file objects.
 
175
  # Set and save the environment properly.
 
176
  old_env_vars = dict(os.environ)
 
177
  os.environ.update(env_cmd[0])
 
178
  stdin_file, stdout_file = os.popen2(env_cmd[1], 'b')
 
179
  os.environ.clear()
 
180
  os.environ.update(old_env_vars)
 
181
 
 
182
  # If the caller didn't specify a string for STDIN, gets it from the
 
183
  # parent process.
 
184
  if stdin_string is None:
 
185
    stdin_string = sys.stdin.read()
 
186
 
 
187
  # Feeds the STDIN string to the sub-process.
 
188
  stdin_file.write(stdin_string)
 
189
  stdin_file.close()
 
190
 
 
191
  while True:
 
192
    line = stdout_file.readline()
 
193
    if not line:  # EOF
 
194
      stdout_file.close()
 
195
      break
 
196
 
 
197
    yield line
 
198
 
 
199
 
 
200
def GetShellCommandOutput(env_cmd, stdin_string=None):
 
201
  """Runs a command in a sub-process, and returns its STDOUT in a string.
 
202
 
 
203
  Args:
 
204
 
 
205
    env_cmd:           The shell command. A 2-tuple where element 0 is a dict
 
206
                       of extra environment variables to set, and element 1
 
207
                       is a string with the command and any flags.
 
208
    stdin_string:      The string to be fed to the STDIN of the sub-process;
 
209
                       If None, the sub-process will inherit the STDIN
 
210
                       from the parent process.
 
211
  """
 
212
 
 
213
  lines = list(IterShellCommandOutput(env_cmd, stdin_string))
 
214
  return string.join(lines, '')
 
215
 
 
216
 
 
217
def GetCommandOutput(env_cmd):
 
218
  """Runs a command and returns its output with all file location
 
219
  info stripped off.
 
220
 
 
221
  Args:
 
222
    env_cmd:  The shell command. A 2-tuple where element 0 is a dict of extra
 
223
              environment variables to set, and element 1 is a string with
 
224
              the command and any flags.
 
225
  """
 
226
 
 
227
  # Disables exception pop-ups on Windows.
 
228
  os.environ['GTEST_CATCH_EXCEPTIONS'] = '1'
 
229
  return NormalizeOutput(GetShellCommandOutput(env_cmd, ''))
 
230
 
 
231
 
 
232
def GetOutputOfAllCommands():
 
233
  """Returns concatenated output from several representative commands."""
 
234
 
 
235
  return (GetCommandOutput(COMMAND_WITH_COLOR) +
 
236
          GetCommandOutput(COMMAND_WITH_TIME) +
 
237
          GetCommandOutput(COMMAND_WITH_DISABLED) +
 
238
          GetCommandOutput(COMMAND_WITH_SHARDING))
 
239
 
 
240
 
 
241
test_list = GetShellCommandOutput(COMMAND_LIST_TESTS, '')
 
242
SUPPORTS_DEATH_TESTS = 'DeathTest' in test_list
 
243
SUPPORTS_TYPED_TESTS = 'TypedTest' in test_list
 
244
 
 
245
 
 
246
class GTestOutputTest(unittest.TestCase):
 
247
  def RemoveUnsupportedTests(self, test_output):
 
248
    if not SUPPORTS_DEATH_TESTS:
 
249
      test_output = RemoveMatchingTests(test_output, 'DeathTest')
 
250
    if not SUPPORTS_TYPED_TESTS:
 
251
      test_output = RemoveMatchingTests(test_output, 'TypedTest')
 
252
    return test_output
 
253
 
 
254
  def testOutput(self):
 
255
    output = GetOutputOfAllCommands()
 
256
    golden_file = open(GOLDEN_PATH, 'rb')
 
257
    golden = golden_file.read()
 
258
    golden_file.close()
 
259
 
 
260
    # We want the test to pass regardless of death tests being
 
261
    # supported or not.
 
262
    if SUPPORTS_DEATH_TESTS and SUPPORTS_TYPED_TESTS:
 
263
      self.assert_(golden == output)
 
264
    else:
 
265
      self.assert_(RemoveTestCounts(self.RemoveUnsupportedTests(golden)) ==
 
266
                   RemoveTestCounts(output))
 
267
 
 
268
 
 
269
if __name__ == '__main__':
 
270
  if sys.argv[1:] == [GENGOLDEN_FLAG]:
 
271
    if SUPPORTS_DEATH_TESTS and SUPPORTS_TYPED_TESTS:
 
272
      output = GetOutputOfAllCommands()
 
273
      golden_file = open(GOLDEN_PATH, 'wb')
 
274
      golden_file.write(output)
 
275
      golden_file.close()
 
276
    else:
 
277
      print >> sys.stderr, ('Unable to write a golden file when compiled in an '
 
278
                            'environment that does not support death tests and '
 
279
                            'typed tests. Are you using VC 7.1?')
 
280
      sys.exit(1)
 
281
  else:
 
282
    gtest_test_utils.Main()