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