blob: f903310d94d4fe6ebdae8462feb63a80ba2bff35 [file] [log] [blame]
Fumitoshi Ukai119dc912015-03-30 16:52:41 +09001#!/usr/bin/env ruby
Shinichiro Hamajib69bf8a2015-06-10 14:52:06 +09002#
3# Copyright 2015 Google Inc. All rights reserved
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090016
17require 'fileutils'
18
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +090019while true
20 if ARGV[0] == '-s'
21 test_serialization = true
22 ARGV.shift
23 elsif ARGV[0] == '-c'
24 ckati = true
25 ARGV.shift
26 ENV['KATI_VARIANT'] = 'c'
27 elsif ARGV[0] == '-n'
28 via_ninja = true
29 ARGV.shift
Colin Crossdf110442015-10-02 11:06:49 -070030 ENV['NINJA_STATUS'] = 'NINJACMD: '
Shinichiro Hamaji85620572015-10-03 11:25:15 +090031 elsif ARGV[0] == '-a'
32 gen_all_targets = true
33 ARGV.shift
Shinichiro Hamaji221a16b2015-09-10 12:40:14 +090034 elsif ARGV[0] == '-v'
35 show_failing = true
36 ARGV.shift
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +090037 else
38 break
39 end
Shinichiro Hamaji9f4f5d32015-04-28 03:53:49 +090040end
41
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090042def get_output_filenames
43 files = Dir.glob('*')
44 files.delete('Makefile')
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +090045 files.delete('build.ninja')
46 files.delete('ninja.sh')
Shinichiro Hamaji65489db2015-06-29 20:44:26 +090047 files.delete('gmon.out')
Shinichiro Hamaji91571ac2015-09-07 18:24:00 +090048 files.delete('submake')
Shinichiro Hamajib674d582015-04-28 03:40:57 +090049 files.reject!{|f|f =~ /\.json$/}
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +090050 files.reject!{|f|f =~ /^kati\.*/}
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090051 files
52end
53
54def cleanup
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +090055 (get_output_filenames + Dir.glob('.*')).each do |fname|
56 next if fname == '.' || fname == '..'
Shinichiro Hamajic6713602015-04-01 01:03:34 +090057 FileUtils.rm_rf fname
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090058 end
59end
60
Shinichiro Hamaji74a66002015-04-27 16:42:30 +090061def move_circular_dep(l)
62 # We don't care when circular dependency detection happens.
63 circ = ''
64 while l.sub!(/Circular .* dropped\.\n/, '') do
65 circ += $&
66 end
67 circ + l
68end
69
Shinichiro Hamajic6713602015-04-01 01:03:34 +090070expected_failures = []
71unexpected_passes = []
72failures = []
73passes = []
74
Shinichiro Hamajiec42b4e2015-05-14 16:20:03 +090075if !ARGV.empty?
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +090076 test_files = ARGV.map do |test|
77 "testcase/#{File.basename(test)}"
Shinichiro Hamajiec42b4e2015-05-14 16:20:03 +090078 end
79else
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +090080 test_files = Dir.glob('testcase/*.mk').sort
81 test_files += Dir.glob('testcase/*.sh').sort
Shinichiro Hamajiec42b4e2015-05-14 16:20:03 +090082end
83
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +090084def run_in_testdir(test_filename)
85 c = File.read(test_filename)
86 name = File.basename(test_filename)
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090087 dir = "out/#{name}"
Shinichiro Hamaji52e42032015-03-31 23:20:13 +090088
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090089 FileUtils.mkdir_p(dir)
Shinichiro Hamaji52e42032015-03-31 23:20:13 +090090 Dir.glob("#{dir}/*").each do |fname|
91 FileUtils.rm_rf(fname)
92 end
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090093
94 Dir.chdir(dir) do
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +090095 yield name
96 end
97end
98
Shinichiro Hamaji86e11332015-07-28 15:24:17 +090099def normalize_ninja_log(log, mk)
Colin Crossdf110442015-10-02 11:06:49 -0700100 log.gsub!(/^NINJACMD: .*\n/, '')
Shinichiro Hamajicecc3582015-07-28 15:56:59 +0900101 log.gsub!(/^ninja: no work to do\.\n/, '')
Fumitoshi Ukai786846d2015-07-28 18:08:47 +0900102 log.gsub!(/^ninja: error: (.*, needed by .*),.*/,
103 '*** No rule to make target \\1.')
Dan Willemsenf3a4ced2015-08-25 14:22:35 -0700104 log.gsub!(/^ninja: warning: multiple rules generate (.*)\. builds involving this target will not be correct.*$/,
Shinichiro Hamaji3c60c122015-10-05 16:26:38 +0900105 'ninja: warning: multiple rules generate \\1.')
Shinichiro Hamaji86e11332015-07-28 15:24:17 +0900106 if mk =~ /err_error_in_recipe.mk/
107 # This test expects ninja fails. Strip ninja specific error logs.
108 log.gsub!(/^FAILED: .*\n/, '')
109 log.gsub!(/^ninja: .*\n/, '')
110 end
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +0900111 log
112end
113
Dan Willemsenf3a4ced2015-08-25 14:22:35 -0700114def normalize_make_log(expected, mk, via_ninja)
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900115 expected.gsub!(/^make(?:\[\d+\])?: (Entering|Leaving) directory.*\n/, '')
116 expected.gsub!(/^make(?:\[\d+\])?: /, '')
117 expected = move_circular_dep(expected)
118
119 # Normalizations for old/new GNU make.
120 expected.gsub!(/[`'"]/, '"')
121 expected.gsub!(/ (?:commands|recipe) for target /,
122 ' commands for target ')
123 expected.gsub!(/ (?:commands|recipe) commences /,
124 ' commands commence ')
125 expected.gsub!(' (did you mean TAB instead of 8 spaces?)', '')
126 expected.gsub!('Extraneous text after', 'extraneous text after')
127 # Not sure if this is useful.
128 expected.gsub!(/\s+Stop\.$/, '')
129 # GNU make 4.0 has this output.
130 expected.gsub!(/Makefile:\d+: commands for target ".*?" failed\n/, '')
131 # We treat some warnings as errors.
Shinichiro Hamaji3498f342015-08-11 14:23:12 +0900132 expected.gsub!(/^\/bin\/sh: line 0: /, '')
Dan Willemsenf3a4ced2015-08-25 14:22:35 -0700133 # We print out some ninja warnings in some tests to match what we expect
134 # ninja to produce. Remove them if we're not testing ninja.
135 if !via_ninja
136 expected.gsub!(/^ninja: warning: .*\n/, '')
137 end
Shinichiro Hamajib7be8f12015-10-05 16:29:58 +0900138 # Normalization for "include foo" with C++ kati.
139 expected.gsub!(/(: )(\S+): (No such file or directory)\n\*\*\* No rule to make target "\2"./, '\1\2: \3')
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900140
141 expected
142end
143
144def normalize_kati_log(output)
145 output = move_circular_dep(output)
146 # kati specific log messages.
147 output.gsub!(/^\*kati\*.*\n/, '')
Fumitoshi Ukaia43b96f2015-07-17 19:54:21 +0900148 output.gsub!(/^c?kati: /, '')
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900149 output.gsub!(/[`'"]/, '"')
Fumitoshi Ukai08c1e942015-07-15 16:38:07 +0900150 output.gsub!(/\/bin\/sh: ([^:]*): command not found/,
151 "\\1: Command not found")
Shinichiro Hamajia06bee92015-08-05 17:13:05 +0900152 output.gsub!(/.*: warning for parse error in an unevaluated line: .*\n/, '')
Shinichiro Hamaji3498f342015-08-11 14:23:12 +0900153 output.gsub!(/^FindEmulator: /, '')
Fumitoshi Ukai2c6eff62015-08-11 17:50:56 +0900154 output.gsub!(/^\/bin\/sh: line 0: /, '')
Fumitoshi Ukaib0ede7d2015-07-29 10:19:05 +0900155 output.gsub!(/ (\.\/+)+kati\.\S+/, '') # kati log files in find_command.mk
156 output.gsub!(/ (\.\/+)+test\S+.json/, '') # json files in find_command.mk
Shinichiro Hamajib7be8f12015-10-05 16:29:58 +0900157 # Normalization for "include foo" with Go kati.
158 output.gsub!(/(: )open (\S+): n(o such file or directory)\nNOTE:.*/,
159 "\\1\\2: N\\3")
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900160 output
161end
162
163run_make_test = proc do |mk|
164 c = File.read(mk)
Shinichiro Hamaji6a492922015-07-27 19:37:20 +0900165 expected_failure = false
Fumitoshi Ukaibfabe632015-07-28 15:26:56 +0900166 if c =~ /\A# TODO(?:\(([-a-z|]+)\))?/
Shinichiro Hamaji6a492922015-07-27 19:37:20 +0900167 if $1
168 todos = $1.split('|')
169 if todos.include?('go') && !ckati
170 expected_failure = true
171 end
172 if todos.include?('c') && ckati
173 expected_failure = true
174 end
Fumitoshi Ukaibfabe632015-07-28 15:26:56 +0900175 if todos.include?('go-ninja') && !ckati && via_ninja
176 expected_failure = true
177 end
178 if todos.include?('c-ninja') && ckati && via_ninja
179 expected_failure = true
180 end
Shinichiro Hamaji6a492922015-07-27 19:37:20 +0900181 if todos.include?('ninja') && via_ninja
182 expected_failure = true
183 end
184 else
185 expected_failure = true
Shinichiro Hamajie919d002015-06-26 01:15:55 +0900186 end
187 end
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900188
189 run_in_testdir(mk) do |name|
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900190 File.open("Makefile", 'w') do |ofile|
191 ofile.print(c)
192 end
Shinichiro Hamaji91571ac2015-09-07 18:24:00 +0900193 File.symlink('../../testcase/submake', 'submake')
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900194
195 expected = ''
196 output = ''
197
Shinichiro Hamaji491e73f2015-04-07 12:41:59 +0900198 testcases = c.scan(/^test\d*/).sort.uniq
Shinichiro Hamaji497754d2015-03-31 02:02:11 +0900199 if testcases.empty?
200 testcases = ['']
201 end
Shinichiro Hamajie5be0142015-03-30 19:26:01 +0900202
Shinichiro Hamajib6a04542015-09-09 17:37:41 +0900203 is_silent_test = mk =~ /\/submake_/
204
Shinichiro Hamajie5be0142015-03-30 19:26:01 +0900205 cleanup
206 testcases.each do |tc|
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +0900207 cmd = 'make'
Shinichiro Hamajib6a04542015-09-09 17:37:41 +0900208 if via_ninja || is_silent_test
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +0900209 cmd += ' -s'
210 end
211 cmd += " #{tc} 2>&1"
212 res = `#{cmd}`
Dan Willemsenf3a4ced2015-08-25 14:22:35 -0700213 res = normalize_make_log(res, mk, via_ninja)
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900214 expected += "=== #{tc} ===\n" + res
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900215 expected_files = get_output_filenames
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900216 expected += "\n=== FILES ===\n#{expected_files * "\n"}\n"
Shinichiro Hamajie5be0142015-03-30 19:26:01 +0900217 end
218
219 cleanup
220 testcases.each do |tc|
Shinichiro Hamajic48d9ce2015-04-28 03:47:39 +0900221 json = "#{tc.empty? ? 'test' : tc}"
Fumitoshi Ukai0547db62015-07-29 16:20:59 +0900222 cmd = "../../kati -save_json=#{json}.json -log_dir=. --use_find_emulator"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900223 if ckati
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +0900224 cmd = "../../ckati --use_find_emulator"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900225 end
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +0900226 if via_ninja
227 cmd += ' --ninja'
228 end
Shinichiro Hamaji85620572015-10-03 11:25:15 +0900229 if gen_all_targets
230 if !ckati || !via_ninja
231 raise "-a should be used with -c -n"
232 end
233 cmd += ' --gen_all_targets'
234 end
Shinichiro Hamajib6a04542015-09-09 17:37:41 +0900235 if is_silent_test
236 cmd += ' -s'
237 end
Shinichiro Hamaji6ff74ce2015-10-03 11:58:35 +0900238 if !gen_all_targets || mk =~ /makecmdgoals/
239 cmd += " #{tc}"
240 end
241 cmd += " 2>&1"
Shinichiro Hamajib674d582015-04-28 03:40:57 +0900242 res = IO.popen(cmd, 'r:binary', &:read)
Fumitoshi Ukai39837dd2015-07-28 12:25:56 +0900243 if via_ninja && File.exist?('build.ninja') && File.exists?('ninja.sh')
Shinichiro Hamaji85620572015-10-03 11:25:15 +0900244 cmd = './ninja.sh -j1 -v'
245 if gen_all_targets
246 cmd += " #{tc}"
247 end
248 cmd += ' 2>&1'
249 log = IO.popen(cmd, 'r:binary', &:read)
Shinichiro Hamaji86e11332015-07-28 15:24:17 +0900250 res += normalize_ninja_log(log, mk)
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +0900251 end
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900252 res = normalize_kati_log(res)
Shinichiro Hamaji42f42e12015-04-13 14:26:45 +0900253 output += "=== #{tc} ===\n" + res
Shinichiro Hamajie5be0142015-03-30 19:26:01 +0900254 output_files = get_output_filenames
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900255 output += "\n=== FILES ===\n#{output_files * "\n"}\n"
256 end
257
258 File.open('out.make', 'w'){|ofile|ofile.print(expected)}
259 File.open('out.kati', 'w'){|ofile|ofile.print(output)}
260
Shinichiro Hamaji74c832f2015-04-09 14:54:39 +0900261 if expected =~ /FAIL/
262 puts %Q(#{name} has a string "FAIL" in its expectation)
263 exit 1
264 end
265
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900266 if expected != output
Shinichiro Hamaji91b105c2015-03-30 18:39:05 +0900267 if expected_failure
268 puts "#{name}: FAIL (expected)"
Shinichiro Hamajic6713602015-04-01 01:03:34 +0900269 expected_failures << name
Shinichiro Hamaji91b105c2015-03-30 18:39:05 +0900270 else
271 puts "#{name}: FAIL"
Shinichiro Hamajic6713602015-04-01 01:03:34 +0900272 failures << name
Shinichiro Hamaji91b105c2015-03-30 18:39:05 +0900273 end
Shinichiro Hamaji7f3a8702015-09-11 15:37:02 +0900274 if !expected_failure || show_failing
Shinichiro Hamaji221a16b2015-09-10 12:40:14 +0900275 puts `diff -u out.make out.kati`
276 end
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900277 else
Shinichiro Hamaji91b105c2015-03-30 18:39:05 +0900278 if expected_failure
279 puts "#{name}: PASS (unexpected)"
Shinichiro Hamajic6713602015-04-01 01:03:34 +0900280 unexpected_passes << name
Shinichiro Hamaji91b105c2015-03-30 18:39:05 +0900281 else
282 puts "#{name}: PASS"
Shinichiro Hamajic6713602015-04-01 01:03:34 +0900283 passes << name
Shinichiro Hamaji91b105c2015-03-30 18:39:05 +0900284 end
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900285 end
Shinichiro Hamajic48d9ce2015-04-28 03:47:39 +0900286
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900287 if name !~ /^err_/ && test_serialization && !expected_failure
Shinichiro Hamajic48d9ce2015-04-28 03:47:39 +0900288 testcases.each do |tc|
289 json = "#{tc.empty? ? 'test' : tc}"
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900290 cmd = "../../kati -save_json=#{json}_2.json -load_json=#{json}.json -n -log_dir=. #{tc} 2>&1"
Shinichiro Hamajic48d9ce2015-04-28 03:47:39 +0900291 res = IO.popen(cmd, 'r:binary', &:read)
292 if !File.exist?("#{json}.json") || !File.exist?("#{json}_2.json")
293 puts "#{name}##{json}: Serialize failure (not exist)"
Shinichiro Hamaji9f4f5d32015-04-28 03:53:49 +0900294 puts res
Shinichiro Hamajic48d9ce2015-04-28 03:47:39 +0900295 else
296 json1 = File.read("#{json}.json")
297 json2 = File.read("#{json}_2.json")
298 if json1 != json2
299 puts "#{name}##{json}: Serialize failure"
Shinichiro Hamaji9f4f5d32015-04-28 03:53:49 +0900300 puts res
Shinichiro Hamajic48d9ce2015-04-28 03:47:39 +0900301 end
302 end
303 end
304 end
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900305 end
306end
Shinichiro Hamajic6713602015-04-01 01:03:34 +0900307
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900308run_shell_test = proc do |sh|
Shinichiro Hamaji09796ef2015-07-30 17:08:29 +0900309 is_ninja_test = sh =~ /\/ninja_/
310 if is_ninja_test && (!ckati || !via_ninja)
311 next
312 end
313
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900314 run_in_testdir(sh) do |name|
315 cleanup
316 cmd = "sh ../../#{sh} make"
Shinichiro Hamaji09796ef2015-07-30 17:08:29 +0900317 if is_ninja_test
318 cmd += ' -s'
319 end
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900320 expected = IO.popen(cmd, 'r:binary', &:read)
321 cleanup
Shinichiro Hamaji09796ef2015-07-30 17:08:29 +0900322
323 if is_ninja_test
324 if ckati
Shinichiro Hamajia88c1c22015-07-31 12:29:48 +0900325 cmd = "sh ../../#{sh} ../../ckati --ninja --regen"
Shinichiro Hamaji09796ef2015-07-30 17:08:29 +0900326 else
327 next
328 end
329 else
330 if ckati
331 cmd = "sh ../../#{sh} ../../ckati"
332 else
333 cmd = "sh ../../#{sh} ../../kati --use_cache -log_dir=."
334 end
335 end
336
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900337 output = IO.popen(cmd, 'r:binary', &:read)
338
Dan Willemsenf3a4ced2015-08-25 14:22:35 -0700339 expected = normalize_make_log(expected, sh, is_ninja_test)
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900340 output = normalize_kati_log(output)
Shinichiro Hamaji09796ef2015-07-30 17:08:29 +0900341 if is_ninja_test
342 output = normalize_ninja_log(output, sh)
Shinichiro Hamaji59956602015-08-11 15:35:55 +0900343 output.gsub!(/No need to regenerate ninja file\n/, '')
Shinichiro Hamaji09796ef2015-07-30 17:08:29 +0900344 end
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900345 File.open('out.make', 'w'){|ofile|ofile.print(expected)}
346 File.open('out.kati', 'w'){|ofile|ofile.print(output)}
347
348 if expected != output
349 puts "#{name}: FAIL"
Shinichiro Hamaji39e62402015-05-20 19:34:58 +0900350 puts `diff -u out.make out.kati`
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900351 failures << name
352 else
353 puts "#{name}: PASS"
354 passes << name
355 end
356 end
357end
358
359test_files.each do |test|
360 if /\.mk$/ =~ test
361 run_make_test.call(test)
362 elsif /\.sh$/ =~ test
363 run_shell_test.call(test)
364 else
365 raise "Unknown test type: #{test}"
366 end
367end
368
Shinichiro Hamajic6713602015-04-01 01:03:34 +0900369puts
370
371if !expected_failures.empty?
372 puts "=== Expected failures ==="
373 expected_failures.each do |n|
374 puts n
375 end
376end
377
378if !unexpected_passes.empty?
379 puts "=== Unexpected passes ==="
380 unexpected_passes.each do |n|
381 puts n
382 end
383end
384
385if !failures.empty?
386 puts "=== Failures ==="
387 failures.each do |n|
388 puts n
389 end
390end
391
392puts
393
394if !unexpected_passes.empty? || !failures.empty?
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900395 puts "FAIL! (#{failures.size + unexpected_passes.size} fails #{passes.size} passes)"
Shinichiro Hamajic6713602015-04-01 01:03:34 +0900396else
397 puts 'PASS!'
398end