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