1f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#!/usr/bin/env python 2f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# Copyright (c) 2014 The Chromium Authors. All rights reserved. 3f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# Use of this source code is governed by a BSD-style license that can be 4f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# found in the LICENSE file. 5f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 6f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch"""Test for TranslationUnitGenerator tool.""" 7f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 8f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochimport difflib 9f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochimport glob 10f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochimport json 11f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochimport ntpath 12f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochimport os 13f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochimport os.path 14f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochimport subprocess 15f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochimport sys 16f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 17f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 18f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochdef _GenerateCompileCommands(template_path, test_files_dir): 19f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch """Returns a JSON string containing a compilation database for the input.""" 20f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch with open(template_path) as fh: 21f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return fh.read().replace('$test_files_dir', test_files_dir) 22f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 23f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 24f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochdef _NumberOfTestsToString(tests): 25f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch """Returns an English sentence describing the number of tests.""" 26f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return "%d test%s" % (tests, 's' if tests != 1 else '') 27f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 28f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 29f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# Before running this test script, please build the translation_unit clang tool 30f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# first. This is explained here: 31f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch# https://chromium.googlesource.com/chromium/src/+/master/docs/clang_tool_refactoring.md 32f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochdef main(): 33f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch tools_clang_directory = os.path.dirname(os.path.dirname( 34f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch os.path.realpath(__file__))) 35f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch tools_clang_scripts_directory = os.path.join(tools_clang_directory, 'scripts') 36f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch test_directory_for_tool = os.path.join( 37f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch tools_clang_directory, 'translation_unit', 'test_files') 38f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch compile_database = os.path.join(test_directory_for_tool, 39f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 'compile_commands.json') 40f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch compile_database_template = compile_database + '.template' 41f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch source_files = glob.glob(os.path.join(test_directory_for_tool, '*.cc')) 42f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 43f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch # Generate a temporary compilation database to run the tool over. 44f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch with open(compile_database, 'w') as f: 45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch f.write(_GenerateCompileCommands(compile_database_template, 46f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch test_directory_for_tool)) 47f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 48f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch args = ['python', 49f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch os.path.join(tools_clang_scripts_directory, 'run_tool.py'), 50f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 'translation_unit', 51f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch test_directory_for_tool] 52f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch args.extend(source_files) 53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch run_tool = subprocess.Popen(args, stdout=subprocess.PIPE) 54f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch stdout, _ = run_tool.communicate() 55f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if run_tool.returncode != 0: 56f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch print 'run_tool failed:\n%s' % stdout 57f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch sys.exit(1) 58f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 59f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch passed = 0 60f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch failed = 0 61f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for actual in source_files: 62f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch actual += '.filepaths' 63f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch expected = actual + '.expected' 64f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch print '[ RUN ] %s' % os.path.relpath(actual) 65f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch expected_output = actual_output = None 66f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch with open(expected, 'r') as f: 67f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch expected_output = f.readlines() 68f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch with open(actual, 'r') as f: 69f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch actual_output = f.readlines() 70f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch has_same_filepaths = True 71f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for expected_line, actual_line in zip(expected_output, actual_output): 72f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if '//' in actual_line: 73f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch actual_line = '//' + actual_line.split('//')[1] 74f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 75f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if ntpath.basename(expected_line) != ntpath.basename(actual_line): 76f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch sys.stdout.write('expected: %s' % ntpath.basename(expected_line)) 77f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch sys.stdout.write('actual: %s' % ntpath.basename(actual_line)) 78f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch has_same_filepaths = False 79f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break 80f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if not has_same_filepaths: 81f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch failed += 1 82f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for line in difflib.unified_diff(expected_output, actual_output, 83f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch fromfile=os.path.relpath(expected), 84f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch tofile=os.path.relpath(actual)): 85f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch sys.stdout.write(line) 86f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch print '[ FAILED ] %s' % os.path.relpath(actual) 87f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch # Don't clean up the file on failure, so the results can be referenced 88f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch # more easily. 89f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch continue 90f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch print '[ OK ] %s' % os.path.relpath(actual) 91f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch passed += 1 92f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch os.remove(actual) 93f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 94f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if failed == 0: 95f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch os.remove(compile_database) 96f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 97f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch print '[==========] %s ran.' % _NumberOfTestsToString(len(source_files)) 98f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if passed > 0: 99f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch print '[ PASSED ] %s.' % _NumberOfTestsToString(passed) 100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if failed > 0: 101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch print '[ FAILED ] %s.' % _NumberOfTestsToString(failed) 102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochif __name__ == '__main__': 105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch sys.exit(main()) 106