1#!/usr/bin/env python 2# Copyright (c) 2014 Google Inc. 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. 5 6"""Tests for analyzer 7""" 8 9from __future__ import print_function 10 11import json 12import TestGyp 13 14found = 'Found dependency' 15found_all = 'Found dependency (all)' 16not_found = 'No dependencies' 17 18 19def _CreateConfigFile(files, additional_compile_targets, test_targets=[]): 20 """Creates the analyzer config file, which is used as the input to analyzer. 21 See description of analyzer.py for description of the arguments.""" 22 f = open('test_file', 'w') 23 to_write = {'files': files, 24 'test_targets': test_targets, 25 'additional_compile_targets': additional_compile_targets } 26 json.dump(to_write, f) 27 f.close() 28 29 30def _CreateBogusConfigFile(): 31 f = open('test_file','w') 32 f.write('bogus') 33 f.close() 34 35 36def _ReadOutputFileContents(): 37 f = open('analyzer_output', 'r') 38 result = json.load(f) 39 f.close() 40 return result 41 42 43# NOTE: this would be clearer if it subclassed TestGypCustom, but that trips 44# over a bug in pylint (E1002). 45test = TestGyp.TestGypCustom(format='analyzer') 46 47def CommonArgs(): 48 return ('-Gconfig_path=test_file', 49 '-Ganalyzer_output_path=analyzer_output') 50 51 52def run_analyzer(*args, **kw): 53 """Runs the test specifying a particular config and output path.""" 54 args += CommonArgs() 55 test.run_gyp('test.gyp', *args, **kw) 56 57 58def run_analyzer2(*args, **kw): 59 """Same as run_analyzer(), but passes in test2.gyp instead of test.gyp.""" 60 args += CommonArgs() 61 test.run_gyp('test2.gyp', *args, **kw) 62 63 64def run_analyzer3(*args, **kw): 65 """Same as run_analyzer(), but passes in test3.gyp instead of test.gyp.""" 66 args += CommonArgs() 67 test.run_gyp('test3.gyp', *args, **kw) 68 69 70def run_analyzer4(*args, **kw): 71 """Same as run_analyzer(), but passes in test3.gyp instead of test.gyp.""" 72 args += CommonArgs() 73 test.run_gyp('test4.gyp', *args, **kw) 74 75 76def EnsureContains(matched=False, compile_targets=set(), test_targets=set()): 77 """Verifies output contains |compile_targets|.""" 78 result = _ReadOutputFileContents() 79 if 'error' in result: 80 print('unexpected error', result.get('error')) 81 test.fail_test() 82 83 if 'invalid_targets' in result: 84 print('unexpected invalid_targets', result.get('invalid_targets')) 85 test.fail_test() 86 87 actual_compile_targets = set(result['compile_targets']) 88 if actual_compile_targets != compile_targets: 89 print('actual compile_targets:', actual_compile_targets, 90 '\nexpected compile_targets:', compile_targets) 91 test.fail_test() 92 93 actual_test_targets = set(result['test_targets']) 94 if actual_test_targets != test_targets: 95 print('actual test_targets:', actual_test_targets, 96 '\nexpected test_targets:', test_targets) 97 test.fail_test() 98 99 if matched and result['status'] != found: 100 print('expected', found, 'got', result['status']) 101 test.fail_test() 102 elif not matched and result['status'] != not_found: 103 print('expected', not_found, 'got', result['status']) 104 test.fail_test() 105 106 107def EnsureMatchedAll(compile_targets, test_targets=set()): 108 result = _ReadOutputFileContents() 109 if 'error' in result: 110 print('unexpected error', result.get('error')) 111 test.fail_test() 112 113 if 'invalid_targets' in result: 114 print('unexpected invalid_targets', result.get('invalid_targets')) 115 test.fail_test() 116 117 if result['status'] != found_all: 118 print('expected', found_all, 'got', result['status']) 119 test.fail_test() 120 121 actual_compile_targets = set(result['compile_targets']) 122 if actual_compile_targets != compile_targets: 123 print('actual compile_targets:', actual_compile_targets, 124 '\nexpected compile_targets:', compile_targets) 125 test.fail_test() 126 127 actual_test_targets = set(result['test_targets']) 128 if actual_test_targets != test_targets: 129 print('actual test_targets:', actual_test_targets, 130 '\nexpected test_targets:', test_targets) 131 test.fail_test() 132 133 134def EnsureError(expected_error_string): 135 """Verifies output contains the error string.""" 136 result = _ReadOutputFileContents() 137 if result.get('error', '').find(expected_error_string) == -1: 138 print('actual error:', result.get('error', ''), '\nexpected error:', 139 expected_error_string) 140 test.fail_test() 141 142 143def EnsureStdoutContains(expected_error_string): 144 if test.stdout().find(expected_error_string) == -1: 145 print('actual stdout:', test.stdout(), '\nexpected stdout:', 146 expected_error_string) 147 test.fail_test() 148 149 150def EnsureInvalidTargets(expected_invalid_targets): 151 """Verifies output contains invalid_targets.""" 152 result = _ReadOutputFileContents() 153 actual_invalid_targets = set(result['invalid_targets']) 154 if actual_invalid_targets != expected_invalid_targets: 155 print('actual invalid_targets:', actual_invalid_targets, 156 '\nexpected :', expected_invalid_targets) 157 test.fail_test() 158 159 160# Two targets, A and B (both static_libraries) and A depends upon B. If a file 161# in B changes, then both A and B are output. It is not strictly necessary that 162# A is compiled in this case, only B. 163_CreateConfigFile(['b.c'], ['all']) 164test.run_gyp('static_library_test.gyp', *CommonArgs()) 165EnsureContains(matched=True, compile_targets={'a' ,'b'}) 166 167# Verifies config_path must be specified. 168test.run_gyp('test.gyp') 169EnsureStdoutContains('Must specify files to analyze via config_path') 170 171# Verifies config_path must point to a valid file. 172test.run_gyp('test.gyp', '-Gconfig_path=bogus_file', 173 '-Ganalyzer_output_path=analyzer_output') 174EnsureError('Unable to open file bogus_file') 175 176# Verify 'invalid_targets' is present when bad target is specified. 177_CreateConfigFile(['exe2.c'], ['bad_target']) 178run_analyzer() 179EnsureInvalidTargets({'bad_target'}) 180 181# Verifies config_path must point to a valid json file. 182_CreateBogusConfigFile() 183run_analyzer() 184EnsureError('Unable to parse config file test_file') 185 186# Trivial test of a source. 187_CreateConfigFile(['foo.c'], ['all']) 188run_analyzer() 189EnsureContains(matched=True, compile_targets={'exe'}) 190 191# Conditional source that is excluded. 192_CreateConfigFile(['conditional_source.c'], ['all']) 193run_analyzer() 194EnsureContains(matched=False) 195 196# Conditional source that is included by way of argument. 197_CreateConfigFile(['conditional_source.c'], ['all']) 198run_analyzer('-Dtest_variable=1') 199EnsureContains(matched=True, compile_targets={'exe'}) 200 201# Two unknown files. 202_CreateConfigFile(['unknown1.c', 'unoknow2.cc'], ['all']) 203run_analyzer() 204EnsureContains() 205 206# Two unknown files. 207_CreateConfigFile(['unknown1.c', 'subdir/subdir_sourcex.c'], ['all']) 208run_analyzer() 209EnsureContains() 210 211# Included dependency 212_CreateConfigFile(['unknown1.c', 'subdir/subdir_source.c'], ['all']) 213run_analyzer() 214EnsureContains(matched=True, compile_targets={'exe', 'exe3'}) 215 216# Included inputs to actions. 217_CreateConfigFile(['action_input.c'], ['all']) 218run_analyzer() 219EnsureContains(matched=True, compile_targets={'exe'}) 220 221# Don't consider outputs. 222_CreateConfigFile(['action_output.c'], ['all']) 223run_analyzer() 224EnsureContains(matched=False) 225 226# Rule inputs. 227_CreateConfigFile(['rule_input.c'], ['all']) 228run_analyzer() 229EnsureContains(matched=True, compile_targets={'exe'}) 230 231# Ignore path specified with PRODUCT_DIR. 232_CreateConfigFile(['product_dir_input.c'], ['all']) 233run_analyzer() 234EnsureContains(matched=False) 235 236# Path specified via a variable. 237_CreateConfigFile(['subdir/subdir_source2.c'], ['all']) 238run_analyzer() 239EnsureContains(matched=True, compile_targets={'exe'}) 240 241# Verifies paths with // are fixed up correctly. 242_CreateConfigFile(['parent_source.c'], ['all']) 243run_analyzer() 244EnsureContains(matched=True, compile_targets={'exe', 'exe3'}) 245 246# Verifies relative paths are resolved correctly. 247_CreateConfigFile(['subdir/subdir_source.h'], ['all']) 248run_analyzer() 249EnsureContains(matched=True, compile_targets={'exe'}) 250 251# Verifies relative paths in inputs are resolved correctly. 252_CreateConfigFile(['rel_path1.h'], ['all']) 253run_analyzer() 254EnsureContains(matched=True, compile_targets={'exe'}) 255 256# Various permutations when passing in targets. 257_CreateConfigFile(['exe2.c', 'subdir/subdir2b_source.c'], 258 ['all'], ['exe', 'exe3']) 259run_analyzer() 260EnsureContains(matched=True, test_targets={'exe3'}, 261 compile_targets={'exe2', 'exe3'}) 262 263_CreateConfigFile(['exe2.c', 'subdir/subdir2b_source.c'], ['all'], ['exe']) 264run_analyzer() 265EnsureContains(matched=True, compile_targets={'exe2', 'exe3'}) 266 267# Verifies duplicates are ignored. 268_CreateConfigFile(['exe2.c', 'subdir/subdir2b_source.c'], ['all'], 269 ['exe', 'exe']) 270run_analyzer() 271EnsureContains(matched=True, compile_targets={'exe2', 'exe3'}) 272 273_CreateConfigFile(['exe2.c'], ['all'], ['exe']) 274run_analyzer() 275EnsureContains(matched=True, compile_targets={'exe2'}) 276 277_CreateConfigFile(['exe2.c'], ['all']) 278run_analyzer() 279EnsureContains(matched=True, compile_targets={'exe2'}) 280 281_CreateConfigFile(['subdir/subdir2b_source.c', 'exe2.c'], ['all']) 282run_analyzer() 283EnsureContains(matched=True, compile_targets={'exe2', 'exe3'}) 284 285_CreateConfigFile(['subdir/subdir2b_source.c'], ['all'], ['exe3']) 286run_analyzer() 287EnsureContains(matched=True, test_targets={'exe3'}, compile_targets={'exe3'}) 288 289_CreateConfigFile(['exe2.c'], ['all']) 290run_analyzer() 291EnsureContains(matched=True, compile_targets={'exe2'}) 292 293_CreateConfigFile(['foo.c'], ['all']) 294run_analyzer() 295EnsureContains(matched=True, compile_targets={'exe'}) 296 297# Assertions when modifying build (gyp/gypi) files, especially when said files 298# are included. 299_CreateConfigFile(['subdir2/d.cc'], ['all'], ['exe', 'exe2', 'foo', 'exe3']) 300run_analyzer2() 301EnsureContains(matched=True, test_targets={'exe', 'foo'}, 302 compile_targets={'exe', 'foo'}) 303 304_CreateConfigFile(['subdir2/subdir.includes.gypi'], ['all'], 305 ['exe', 'exe2', 'foo', 'exe3']) 306run_analyzer2() 307EnsureContains(matched=True, test_targets={'exe', 'foo'}, 308 compile_targets={'exe', 'foo'}) 309 310_CreateConfigFile(['subdir2/subdir.gyp'], ['all'], 311 ['exe', 'exe2', 'foo', 'exe3']) 312run_analyzer2() 313EnsureContains(matched=True, test_targets={'exe', 'foo'}, 314 compile_targets={'exe', 'foo'}) 315 316_CreateConfigFile(['test2.includes.gypi'], ['all'], 317 ['exe', 'exe2', 'foo', 'exe3']) 318run_analyzer2() 319EnsureContains(matched=True, test_targets={'exe', 'exe2', 'exe3'}, 320 compile_targets={'exe', 'exe2', 'exe3'}) 321 322# Verify modifying a file included makes all targets dirty. 323_CreateConfigFile(['common.gypi'], ['all'], ['exe', 'exe2', 'foo', 'exe3']) 324run_analyzer2('-Icommon.gypi') 325EnsureMatchedAll({'all', 'exe', 'exe2', 'foo', 'exe3'}, 326 {'exe', 'exe2', 'foo', 'exe3'}) 327 328# Assertions from test3.gyp. 329_CreateConfigFile(['d.c', 'f.c'], ['all'], ['a']) 330run_analyzer3() 331EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a', 'b'}) 332 333_CreateConfigFile(['f.c'], ['all'], ['a']) 334run_analyzer3() 335EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a', 'b'}) 336 337_CreateConfigFile(['f.c'], ['all']) 338run_analyzer3() 339EnsureContains(matched=True, compile_targets={'a', 'b'}) 340 341_CreateConfigFile(['c.c', 'e.c'], ['all']) 342run_analyzer3() 343EnsureContains(matched=True, compile_targets={'a', 'b', 'c', 'e'}) 344 345_CreateConfigFile(['d.c'], ['all'], ['a']) 346run_analyzer3() 347EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a', 'b'}) 348 349_CreateConfigFile(['a.c'], ['all'], ['a', 'b']) 350run_analyzer3() 351EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a'}) 352 353_CreateConfigFile(['a.c'], ['all'], ['a', 'b']) 354run_analyzer3() 355EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a'}) 356 357_CreateConfigFile(['d.c'], ['all'], ['a', 'b']) 358run_analyzer3() 359EnsureContains(matched=True, test_targets={'a', 'b'}, 360 compile_targets={'a', 'b'}) 361 362_CreateConfigFile(['f.c'], ['all'], ['a']) 363run_analyzer3() 364EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a', 'b'}) 365 366_CreateConfigFile(['a.c'], ['all'], ['a']) 367run_analyzer3() 368EnsureContains(matched=True, test_targets={'a'}, compile_targets={'a'}) 369 370_CreateConfigFile(['a.c'], ['all']) 371run_analyzer3() 372EnsureContains(matched=True, compile_targets={'a'}) 373 374_CreateConfigFile(['d.c'], ['all']) 375run_analyzer3() 376EnsureContains(matched=True, compile_targets={'a', 'b'}) 377 378# Assertions around test4.gyp. 379_CreateConfigFile(['f.c'], ['all']) 380run_analyzer4() 381EnsureContains(matched=True, compile_targets={'e', 'f'}) 382 383_CreateConfigFile(['d.c'], ['all']) 384run_analyzer4() 385EnsureContains(matched=True, compile_targets={'a', 'b', 'c', 'd'}) 386 387_CreateConfigFile(['i.c'], ['all']) 388run_analyzer4() 389EnsureContains(matched=True, compile_targets={'h', 'i'}) 390 391# Assertions where 'all' is not supplied in compile_targets. 392 393_CreateConfigFile(['exe2.c'], [], ['exe2']) 394run_analyzer() 395EnsureContains(matched=True, test_targets={'exe2'}, compile_targets={'exe2'}) 396 397_CreateConfigFile(['exe20.c'], [], ['exe2']) 398run_analyzer() 399EnsureContains(matched=False) 400 401 402_CreateConfigFile(['exe2.c', 'exe3.c'], [], ['exe2', 'exe3']) 403run_analyzer() 404EnsureContains(matched=True, test_targets={'exe2', 'exe3'}, 405 compile_targets={'exe2', 'exe3'}) 406 407_CreateConfigFile(['exe2.c', 'exe3.c'], ['exe3'], ['exe2']) 408run_analyzer() 409EnsureContains(matched=True, test_targets={'exe2'}, 410 compile_targets={'exe2', 'exe3'}) 411 412_CreateConfigFile(['exe3.c'], ['exe2'], ['exe2']) 413run_analyzer() 414EnsureContains(matched=False) 415 416# Assertions with 'all' listed as a test_target. 417_CreateConfigFile(['exe3.c'], [], ['all']) 418run_analyzer() 419EnsureContains(matched=True, compile_targets={'exe3', 'all'}, 420 test_targets={'all'}) 421 422_CreateConfigFile(['exe2.c'], [], ['all', 'exe2']) 423run_analyzer() 424EnsureContains(matched=True, compile_targets={'exe2', 'all'}, 425 test_targets={'all', 'exe2'}) 426 427test.pass_test() 428