427 lines
14 KiB
Python
427 lines
14 KiB
Python
#!/usr/bin/env python
|
|
# Copyright (c) 2014 Google Inc. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""Tests for analyzer
|
|
"""
|
|
|
|
from __future__ import print_function
|
|
|
|
import json
|
|
import TestGyp
|
|
|
|
found = 'Found dependency'
|
|
found_all = 'Found dependency (all)'
|
|
not_found = 'No dependencies'
|
|
|
|
|
|
def _CreateConfigFile(files, additional_compile_targets, test_targets=[]):
|
|
"""Creates the analyzer config file, which is used as the input to analyzer.
|
|
See description of analyzer.py for description of the arguments."""
|
|
f = open('test_file', 'w')
|
|
to_write = {'files': files,
|
|
'test_targets': test_targets,
|
|
'additional_compile_targets': additional_compile_targets }
|
|
json.dump(to_write, f)
|
|
f.close()
|
|
|
|
|
|
def _CreateBogusConfigFile():
|
|
f = open('test_file','w')
|
|
f.write('bogus')
|
|
f.close()
|
|
|
|
|
|
def _ReadOutputFileContents():
|
|
f = open('analyzer_output', 'r')
|
|
result = json.load(f)
|
|
f.close()
|
|
return result
|
|
|
|
|
|
# NOTE: this would be clearer if it subclassed TestGypCustom, but that trips
|
|
# over a bug in pylint (E1002).
|
|
test = TestGyp.TestGypCustom(format='analyzer')
|
|
|
|
def CommonArgs():
|
|
return ('-Gconfig_path=test_file',
|
|
'-Ganalyzer_output_path=analyzer_output')
|
|
|
|
|
|
def run_analyzer(*args, **kw):
|
|
"""Runs the test specifying a particular config and output path."""
|
|
args += CommonArgs()
|
|
test.run_gyp('test.gyp', *args, **kw)
|
|
|
|
|
|
def run_analyzer2(*args, **kw):
|
|
"""Same as run_analyzer(), but passes in test2.gyp instead of test.gyp."""
|
|
args += CommonArgs()
|
|
test.run_gyp('test2.gyp', *args, **kw)
|
|
|
|
|
|
def run_analyzer3(*args, **kw):
|
|
"""Same as run_analyzer(), but passes in test3.gyp instead of test.gyp."""
|
|
args += CommonArgs()
|
|
test.run_gyp('test3.gyp', *args, **kw)
|
|
|
|
|
|
def run_analyzer4(*args, **kw):
|
|
"""Same as run_analyzer(), but passes in test3.gyp instead of test.gyp."""
|
|
args += CommonArgs()
|
|
test.run_gyp('test4.gyp', *args, **kw)
|
|
|
|
|
|
def EnsureContains(matched=False, compile_targets=set(), test_targets=set()):
|
|
"""Verifies output contains |compile_targets|."""
|
|
result = _ReadOutputFileContents()
|
|
if 'error' in result:
|
|
print('unexpected error', result.get('error'))
|
|
test.fail_test()
|
|
|
|
if 'invalid_targets' in result:
|
|
print('unexpected invalid_targets', result.get('invalid_targets'))
|
|
test.fail_test()
|
|
|
|
actual_compile_targets = set(result['compile_targets'])
|
|
if actual_compile_targets != compile_targets:
|
|
print('actual compile_targets:', actual_compile_targets,
|
|
'\nexpected compile_targets:', compile_targets)
|
|
test.fail_test()
|
|
|
|
actual_test_targets = set(result['test_targets'])
|
|
if actual_test_targets != test_targets:
|
|
print('actual test_targets:', actual_test_targets,
|
|
'\nexpected test_targets:', test_targets)
|
|
test.fail_test()
|
|
|
|
if matched and result['status'] != found:
|
|
print('expected', found, 'got', result['status'])
|
|
test.fail_test()
|
|
elif not matched and result['status'] != not_found:
|
|
print('expected', not_found, 'got', result['status'])
|
|
test.fail_test()
|
|
|
|
|
|
def EnsureMatchedAll(compile_targets, test_targets=set()):
|
|
result = _ReadOutputFileContents()
|
|
if 'error' in result:
|
|
print('unexpected error', result.get('error'))
|
|
test.fail_test()
|
|
|
|
if 'invalid_targets' in result:
|
|
print('unexpected invalid_targets', result.get('invalid_targets'))
|
|
test.fail_test()
|
|
|
|
if result['status'] != found_all:
|
|
print('expected', found_all, 'got', result['status'])
|
|
test.fail_test()
|
|
|
|
actual_compile_targets = set(result['compile_targets'])
|
|
if actual_compile_targets != compile_targets:
|
|
print('actual compile_targets:', actual_compile_targets,
|
|
'\nexpected compile_targets:', compile_targets)
|
|
test.fail_test()
|
|
|
|
actual_test_targets = set(result['test_targets'])
|
|
if actual_test_targets != test_targets:
|
|
print('actual test_targets:', actual_test_targets,
|
|
'\nexpected test_targets:', test_targets)
|
|
test.fail_test()
|
|
|
|
|
|
def EnsureError(expected_error_string):
|
|
"""Verifies output contains the error string."""
|
|
result = _ReadOutputFileContents()
|
|
if result.get('error', '').find(expected_error_string) == -1:
|
|
print('actual error:', result.get('error', ''), '\nexpected error:',
|
|
expected_error_string)
|
|
test.fail_test()
|
|
|
|
|
|
def EnsureStdoutContains(expected_error_string):
|
|
if test.stdout().find(expected_error_string) == -1:
|
|
print('actual stdout:', test.stdout(), '\nexpected stdout:',
|
|
expected_error_string)
|
|
test.fail_test()
|
|
|
|
|
|
def EnsureInvalidTargets(expected_invalid_targets):
|
|
"""Verifies output contains invalid_targets."""
|
|
result = _ReadOutputFileContents()
|
|
actual_invalid_targets = set(result['invalid_targets'])
|
|
if actual_invalid_targets != expected_invalid_targets:
|
|
print('actual invalid_targets:', actual_invalid_targets,
|
|
'\nexpected :', expected_invalid_targets)
|
|
test.fail_test()
|
|
|
|
|
|
# Two targets, A and B (both static_libraries) and A depends upon B. If a file
|
|
# in B changes, then both A and B are output. It is not strictly necessary that
|
|
# A is compiled in this case, only B.
|
|
_CreateConfigFile(['b.c'], ['all'])
|
|
test.run_gyp('static_library_test.gyp', *CommonArgs())
|
|
EnsureContains(matched=True, compile_targets={'a' ,'b'})
|
|
|
|
# Verifies config_path must be specified.
|
|
test.run_gyp('test.gyp')
|
|
EnsureStdoutContains('Must specify files to analyze via config_path')
|
|
|
|
# Verifies config_path must point to a valid file.
|
|
test.run_gyp('test.gyp', '-Gconfig_path=bogus_file',
|
|
'-Ganalyzer_output_path=analyzer_output')
|
|
EnsureError('Unable to open file bogus_file')
|
|
|
|
# Verify 'invalid_targets' is present when bad target is specified.
|
|
_CreateConfigFile(['exe2.c'], ['bad_target'])
|
|
run_analyzer()
|
|
EnsureInvalidTargets({'bad_target'})
|
|
|
|
# Verifies config_path must point to a valid json file.
|
|
_CreateBogusConfigFile()
|
|
run_analyzer()
|
|
EnsureError('Unable to parse config file test_file')
|
|
|
|
# Trivial test of a source.
|
|
_CreateConfigFile(['foo.c'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe'})
|
|
|
|
# Conditional source that is excluded.
|
|
_CreateConfigFile(['conditional_source.c'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=False)
|
|
|
|
# Conditional source that is included by way of argument.
|
|
_CreateConfigFile(['conditional_source.c'], ['all'])
|
|
run_analyzer('-Dtest_variable=1')
|
|
EnsureContains(matched=True, compile_targets={'exe'})
|
|
|
|
# Two unknown files.
|
|
_CreateConfigFile(['unknown1.c', 'unoknow2.cc'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains()
|
|
|
|
# Two unknown files.
|
|
_CreateConfigFile(['unknown1.c', 'subdir/subdir_sourcex.c'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains()
|
|
|
|
# Included dependency
|
|
_CreateConfigFile(['unknown1.c', 'subdir/subdir_source.c'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe', 'exe3'})
|
|
|
|
# Included inputs to actions.
|
|
_CreateConfigFile(['action_input.c'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe'})
|
|
|
|
# Don't consider outputs.
|
|
_CreateConfigFile(['action_output.c'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=False)
|
|
|
|
# Rule inputs.
|
|
_CreateConfigFile(['rule_input.c'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe'})
|
|
|
|
# Ignore path specified with PRODUCT_DIR.
|
|
_CreateConfigFile(['product_dir_input.c'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=False)
|
|
|
|
# Path specified via a variable.
|
|
_CreateConfigFile(['subdir/subdir_source2.c'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe'})
|
|
|
|
# Verifies paths with // are fixed up correctly.
|
|
_CreateConfigFile(['parent_source.c'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe', 'exe3'})
|
|
|
|
# Verifies relative paths are resolved correctly.
|
|
_CreateConfigFile(['subdir/subdir_source.h'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe'})
|
|
|
|
# Verifies relative paths in inputs are resolved correctly.
|
|
_CreateConfigFile(['rel_path1.h'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe'})
|
|
|
|
# Various permutations when passing in targets.
|
|
_CreateConfigFile(['exe2.c', 'subdir/subdir2b_source.c'],
|
|
['all'], ['exe', 'exe3'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, test_targets={'exe3'},
|
|
compile_targets={'exe2', 'exe3'})
|
|
|
|
_CreateConfigFile(['exe2.c', 'subdir/subdir2b_source.c'], ['all'], ['exe'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe2', 'exe3'})
|
|
|
|
# Verifies duplicates are ignored.
|
|
_CreateConfigFile(['exe2.c', 'subdir/subdir2b_source.c'], ['all'],
|
|
['exe', 'exe'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe2', 'exe3'})
|
|
|
|
_CreateConfigFile(['exe2.c'], ['all'], ['exe'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe2'})
|
|
|
|
_CreateConfigFile(['exe2.c'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe2'})
|
|
|
|
_CreateConfigFile(['subdir/subdir2b_source.c', 'exe2.c'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe2', 'exe3'})
|
|
|
|
_CreateConfigFile(['subdir/subdir2b_source.c'], ['all'], ['exe3'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, test_targets={'exe3'}, compile_targets={'exe3'})
|
|
|
|
_CreateConfigFile(['exe2.c'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe2'})
|
|
|
|
_CreateConfigFile(['foo.c'], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe'})
|
|
|
|
# Assertions when modifying build (gyp/gypi) files, especially when said files
|
|
# are included.
|
|
_CreateConfigFile(['subdir2/d.cc'], ['all'], ['exe', 'exe2', 'foo', 'exe3'])
|
|
run_analyzer2()
|
|
EnsureContains(matched=True, test_targets={'exe', 'foo'},
|
|
compile_targets={'exe', 'foo'})
|
|
|
|
_CreateConfigFile(['subdir2/subdir.includes.gypi'], ['all'],
|
|
['exe', 'exe2', 'foo', 'exe3'])
|
|
run_analyzer2()
|
|
EnsureContains(matched=True, test_targets={'exe', 'foo'},
|
|
compile_targets={'exe', 'foo'})
|
|
|
|
_CreateConfigFile(['subdir2/subdir.gyp'], ['all'],
|
|
['exe', 'exe2', 'foo', 'exe3'])
|
|
run_analyzer2()
|
|
EnsureContains(matched=True, test_targets={'exe', 'foo'},
|
|
compile_targets={'exe', 'foo'})
|
|
|
|
_CreateConfigFile(['test2.includes.gypi'], ['all'],
|
|
['exe', 'exe2', 'foo', 'exe3'])
|
|
run_analyzer2()
|
|
EnsureContains(matched=True, test_targets={'exe', 'exe2', 'exe3'},
|
|
compile_targets={'exe', 'exe2', 'exe3'})
|
|
|
|
# Verify modifying a file included makes all targets dirty.
|
|
_CreateConfigFile(['common.gypi'], ['all'], ['exe', 'exe2', 'foo', 'exe3'])
|
|
run_analyzer2('-Icommon.gypi')
|
|
EnsureMatchedAll({'all', 'exe', 'exe2', 'foo', 'exe3'},
|
|
{'exe', 'exe2', 'foo', 'exe3'})
|
|
|
|
# Assertions from test3.gyp.
|
|
_CreateConfigFile(['d.c', 'f.c'], ['all'], ['a'])
|
|
run_analyzer3()
|
|
EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a', 'b'})
|
|
|
|
_CreateConfigFile(['f.c'], ['all'], ['a'])
|
|
run_analyzer3()
|
|
EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a', 'b'})
|
|
|
|
_CreateConfigFile(['f.c'], ['all'])
|
|
run_analyzer3()
|
|
EnsureContains(matched=True, compile_targets={'a', 'b'})
|
|
|
|
_CreateConfigFile(['c.c', 'e.c'], ['all'])
|
|
run_analyzer3()
|
|
EnsureContains(matched=True, compile_targets={'a', 'b', 'c', 'e'})
|
|
|
|
_CreateConfigFile(['d.c'], ['all'], ['a'])
|
|
run_analyzer3()
|
|
EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a', 'b'})
|
|
|
|
_CreateConfigFile(['a.c'], ['all'], ['a', 'b'])
|
|
run_analyzer3()
|
|
EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a'})
|
|
|
|
_CreateConfigFile(['a.c'], ['all'], ['a', 'b'])
|
|
run_analyzer3()
|
|
EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a'})
|
|
|
|
_CreateConfigFile(['d.c'], ['all'], ['a', 'b'])
|
|
run_analyzer3()
|
|
EnsureContains(matched=True, test_targets={'a', 'b'},
|
|
compile_targets={'a', 'b'})
|
|
|
|
_CreateConfigFile(['f.c'], ['all'], ['a'])
|
|
run_analyzer3()
|
|
EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a', 'b'})
|
|
|
|
_CreateConfigFile(['a.c'], ['all'], ['a'])
|
|
run_analyzer3()
|
|
EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a'})
|
|
|
|
_CreateConfigFile(['a.c'], ['all'])
|
|
run_analyzer3()
|
|
EnsureContains(matched=True, compile_targets={'a'})
|
|
|
|
_CreateConfigFile(['d.c'], ['all'])
|
|
run_analyzer3()
|
|
EnsureContains(matched=True, compile_targets={'a', 'b'})
|
|
|
|
# Assertions around test4.gyp.
|
|
_CreateConfigFile(['f.c'], ['all'])
|
|
run_analyzer4()
|
|
EnsureContains(matched=True, compile_targets={'e', 'f'})
|
|
|
|
_CreateConfigFile(['d.c'], ['all'])
|
|
run_analyzer4()
|
|
EnsureContains(matched=True, compile_targets={'a', 'b', 'c', 'd'})
|
|
|
|
_CreateConfigFile(['i.c'], ['all'])
|
|
run_analyzer4()
|
|
EnsureContains(matched=True, compile_targets={'h', 'i'})
|
|
|
|
# Assertions where 'all' is not supplied in compile_targets.
|
|
|
|
_CreateConfigFile(['exe2.c'], [], ['exe2'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, test_targets={'exe2'}, compile_targets={'exe2'})
|
|
|
|
_CreateConfigFile(['exe20.c'], [], ['exe2'])
|
|
run_analyzer()
|
|
EnsureContains(matched=False)
|
|
|
|
|
|
_CreateConfigFile(['exe2.c', 'exe3.c'], [], ['exe2', 'exe3'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, test_targets={'exe2', 'exe3'},
|
|
compile_targets={'exe2', 'exe3'})
|
|
|
|
_CreateConfigFile(['exe2.c', 'exe3.c'], ['exe3'], ['exe2'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, test_targets={'exe2'},
|
|
compile_targets={'exe2', 'exe3'})
|
|
|
|
_CreateConfigFile(['exe3.c'], ['exe2'], ['exe2'])
|
|
run_analyzer()
|
|
EnsureContains(matched=False)
|
|
|
|
# Assertions with 'all' listed as a test_target.
|
|
_CreateConfigFile(['exe3.c'], [], ['all'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe3', 'all'},
|
|
test_targets={'all'})
|
|
|
|
_CreateConfigFile(['exe2.c'], [], ['all', 'exe2'])
|
|
run_analyzer()
|
|
EnsureContains(matched=True, compile_targets={'exe2', 'all'},
|
|
test_targets={'all', 'exe2'})
|
|
|
|
test.pass_test()
|