2 # Copyright (c) 2014 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Test for TranslationUnitGenerator tool."""
18 def _GenerateCompileCommands(files
):
19 """Returns a JSON string containing a compilation database for the input."""
20 return json
.dumps([{'directory': '.',
21 'command': 'clang++ -fsyntax-only -std=c++11 -c %s' % f
,
22 'file': f
} for f
in files
], indent
=2)
25 def _NumberOfTestsToString(tests
):
26 """Returns an English sentence describing the number of tests."""
27 return "%d test%s" % (tests
, 's' if tests
!= 1 else '')
30 # Before running this test script, please build the translation_unit clang tool
31 # first. This is explained here:
32 # https://code.google.com/p/chromium/wiki/ClangToolRefactoring
34 tools_clang_directory
= os
.path
.dirname(os
.path
.dirname(
35 os
.path
.realpath(__file__
)))
36 tools_clang_scripts_directory
= os
.path
.join(tools_clang_directory
, 'scripts')
37 test_directory_for_tool
= os
.path
.join(
38 tools_clang_directory
, 'translation_unit', 'test_files')
39 compile_database
= os
.path
.join(test_directory_for_tool
,
40 'compile_commands.json')
41 source_files
= glob
.glob(os
.path
.join(test_directory_for_tool
, '*.cc'))
43 # Generate a temporary compilation database to run the tool over.
44 with
open(compile_database
, 'w') as f
:
45 f
.write(_GenerateCompileCommands(source_files
))
48 os
.path
.join(tools_clang_scripts_directory
, 'run_tool.py'),
50 test_directory_for_tool
]
51 args
.extend(source_files
)
52 run_tool
= subprocess
.Popen(args
, stdout
=subprocess
.PIPE
)
53 stdout
, _
= run_tool
.communicate()
54 if run_tool
.returncode
!= 0:
55 print 'run_tool failed:\n%s' % stdout
60 for actual
in source_files
:
61 actual
+= '.filepaths'
62 expected
= actual
+ '.expected'
63 print '[ RUN ] %s' % os
.path
.relpath(actual
)
64 expected_output
= actual_output
= None
65 with
open(expected
, 'r') as f
:
66 expected_output
= f
.readlines()
67 with
open(actual
, 'r') as f
:
68 actual_output
= f
.readlines()
69 has_same_filepaths
= True
70 for expected_line
, actual_line
in zip(expected_output
, actual_output
):
71 if '//' in actual_output
:
72 if actual_output
.split('//')[1] != expected_output
:
73 sys
.stdout
.write('expected: %s' % expected_output
)
74 sys
.stdout
.write('actual: %s' % actual_output
.split('//')[1])
78 if ntpath
.basename(expected_line
) != ntpath
.basename(actual_line
):
79 sys
.stdout
.write('expected: %s' % ntpath
.basename(expected_line
))
80 sys
.stdout
.write('actual: %s' % ntpath
.basename(actual_line
))
81 has_same_filepaths
= False
83 if not has_same_filepaths
:
85 for line
in difflib
.unified_diff(expected_output
, actual_output
,
86 fromfile
=os
.path
.relpath(expected
),
87 tofile
=os
.path
.relpath(actual
)):
88 sys
.stdout
.write(line
)
89 print '[ FAILED ] %s' % os
.path
.relpath(actual
)
90 # Don't clean up the file on failure, so the results can be referenced
93 print '[ OK ] %s' % os
.path
.relpath(actual
)
98 os
.remove(compile_database
)
100 print '[==========] %s ran.' % _NumberOfTestsToString(len(source_files
))
102 print '[ PASSED ] %s.' % _NumberOfTestsToString(passed
)
104 print '[ FAILED ] %s.' % _NumberOfTestsToString(failed
)
107 if __name__
== '__main__':