blob: 71231135dcbb77a23f04940fe13528b75024610f [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')
Colin Cross27df5312015-11-09 13:39:14 -080046 files.delete('env.sh')
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +090047 files.delete('ninja.sh')
Shinichiro Hamaji65489db2015-06-29 20:44:26 +090048 files.delete('gmon.out')
Shinichiro Hamaji91571ac2015-09-07 18:24:00 +090049 files.delete('submake')
Shinichiro Hamajib674d582015-04-28 03:40:57 +090050 files.reject!{|f|f =~ /\.json$/}
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +090051 files.reject!{|f|f =~ /^kati\.*/}
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090052 files
53end
54
55def cleanup
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +090056 (get_output_filenames + Dir.glob('.*')).each do |fname|
57 next if fname == '.' || fname == '..'
Shinichiro Hamajic6713602015-04-01 01:03:34 +090058 FileUtils.rm_rf fname
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090059 end
60end
61
Shinichiro Hamaji74a66002015-04-27 16:42:30 +090062def move_circular_dep(l)
63 # We don't care when circular dependency detection happens.
64 circ = ''
65 while l.sub!(/Circular .* dropped\.\n/, '') do
66 circ += $&
67 end
68 circ + l
69end
70
Shinichiro Hamajic6713602015-04-01 01:03:34 +090071expected_failures = []
72unexpected_passes = []
73failures = []
74passes = []
75
Shinichiro Hamajiec42b4e2015-05-14 16:20:03 +090076if !ARGV.empty?
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +090077 test_files = ARGV.map do |test|
78 "testcase/#{File.basename(test)}"
Shinichiro Hamajiec42b4e2015-05-14 16:20:03 +090079 end
80else
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +090081 test_files = Dir.glob('testcase/*.mk').sort
82 test_files += Dir.glob('testcase/*.sh').sort
Shinichiro Hamajiec42b4e2015-05-14 16:20:03 +090083end
84
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +090085def run_in_testdir(test_filename)
86 c = File.read(test_filename)
87 name = File.basename(test_filename)
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090088 dir = "out/#{name}"
Shinichiro Hamaji52e42032015-03-31 23:20:13 +090089
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090090 FileUtils.mkdir_p(dir)
Shinichiro Hamaji52e42032015-03-31 23:20:13 +090091 Dir.glob("#{dir}/*").each do |fname|
92 FileUtils.rm_rf(fname)
93 end
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090094
95 Dir.chdir(dir) do
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +090096 yield name
97 end
98end
99
Shinichiro Hamaji86e11332015-07-28 15:24:17 +0900100def normalize_ninja_log(log, mk)
Colin Crossdf110442015-10-02 11:06:49 -0700101 log.gsub!(/^NINJACMD: .*\n/, '')
Shinichiro Hamajicecc3582015-07-28 15:56:59 +0900102 log.gsub!(/^ninja: no work to do\.\n/, '')
Fumitoshi Ukai786846d2015-07-28 18:08:47 +0900103 log.gsub!(/^ninja: error: (.*, needed by .*),.*/,
104 '*** No rule to make target \\1.')
Dan Willemsenf3a4ced2015-08-25 14:22:35 -0700105 log.gsub!(/^ninja: warning: multiple rules generate (.*)\. builds involving this target will not be correct.*$/,
Shinichiro Hamaji3c60c122015-10-05 16:26:38 +0900106 'ninja: warning: multiple rules generate \\1.')
Shinichiro Hamaji86e11332015-07-28 15:24:17 +0900107 if mk =~ /err_error_in_recipe.mk/
108 # This test expects ninja fails. Strip ninja specific error logs.
109 log.gsub!(/^FAILED: .*\n/, '')
110 log.gsub!(/^ninja: .*\n/, '')
111 end
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +0900112 log
113end
114
Dan Willemsenf3a4ced2015-08-25 14:22:35 -0700115def normalize_make_log(expected, mk, via_ninja)
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900116 expected.gsub!(/^make(?:\[\d+\])?: (Entering|Leaving) directory.*\n/, '')
117 expected.gsub!(/^make(?:\[\d+\])?: /, '')
118 expected = move_circular_dep(expected)
119
120 # Normalizations for old/new GNU make.
121 expected.gsub!(/[`'"]/, '"')
122 expected.gsub!(/ (?:commands|recipe) for target /,
123 ' commands for target ')
124 expected.gsub!(/ (?:commands|recipe) commences /,
125 ' commands commence ')
126 expected.gsub!(' (did you mean TAB instead of 8 spaces?)', '')
127 expected.gsub!('Extraneous text after', 'extraneous text after')
128 # Not sure if this is useful.
129 expected.gsub!(/\s+Stop\.$/, '')
130 # GNU make 4.0 has this output.
131 expected.gsub!(/Makefile:\d+: commands for target ".*?" failed\n/, '')
132 # We treat some warnings as errors.
Shinichiro Hamaji3498f342015-08-11 14:23:12 +0900133 expected.gsub!(/^\/bin\/sh: line 0: /, '')
Dan Willemsenf3a4ced2015-08-25 14:22:35 -0700134 # We print out some ninja warnings in some tests to match what we expect
135 # ninja to produce. Remove them if we're not testing ninja.
136 if !via_ninja
137 expected.gsub!(/^ninja: warning: .*\n/, '')
138 end
Shinichiro Hamajib7be8f12015-10-05 16:29:58 +0900139 # Normalization for "include foo" with C++ kati.
140 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 +0900141
142 expected
143end
144
145def normalize_kati_log(output)
146 output = move_circular_dep(output)
147 # kati specific log messages.
148 output.gsub!(/^\*kati\*.*\n/, '')
Fumitoshi Ukaia43b96f2015-07-17 19:54:21 +0900149 output.gsub!(/^c?kati: /, '')
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900150 output.gsub!(/[`'"]/, '"')
Fumitoshi Ukai08c1e942015-07-15 16:38:07 +0900151 output.gsub!(/\/bin\/sh: ([^:]*): command not found/,
152 "\\1: Command not found")
Shinichiro Hamajia06bee92015-08-05 17:13:05 +0900153 output.gsub!(/.*: warning for parse error in an unevaluated line: .*\n/, '')
Shinichiro Hamaji3498f342015-08-11 14:23:12 +0900154 output.gsub!(/^FindEmulator: /, '')
Fumitoshi Ukai2c6eff62015-08-11 17:50:56 +0900155 output.gsub!(/^\/bin\/sh: line 0: /, '')
Fumitoshi Ukaib0ede7d2015-07-29 10:19:05 +0900156 output.gsub!(/ (\.\/+)+kati\.\S+/, '') # kati log files in find_command.mk
157 output.gsub!(/ (\.\/+)+test\S+.json/, '') # json files in find_command.mk
Shinichiro Hamajib7be8f12015-10-05 16:29:58 +0900158 # Normalization for "include foo" with Go kati.
159 output.gsub!(/(: )open (\S+): n(o such file or directory)\nNOTE:.*/,
160 "\\1\\2: N\\3")
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900161 output
162end
163
164run_make_test = proc do |mk|
165 c = File.read(mk)
Shinichiro Hamaji6a492922015-07-27 19:37:20 +0900166 expected_failure = false
Fumitoshi Ukaibfabe632015-07-28 15:26:56 +0900167 if c =~ /\A# TODO(?:\(([-a-z|]+)\))?/
Shinichiro Hamaji6a492922015-07-27 19:37:20 +0900168 if $1
169 todos = $1.split('|')
170 if todos.include?('go') && !ckati
171 expected_failure = true
172 end
173 if todos.include?('c') && ckati
174 expected_failure = true
175 end
Fumitoshi Ukaibfabe632015-07-28 15:26:56 +0900176 if todos.include?('go-ninja') && !ckati && via_ninja
177 expected_failure = true
178 end
179 if todos.include?('c-ninja') && ckati && via_ninja
180 expected_failure = true
181 end
Shinichiro Hamaji6a492922015-07-27 19:37:20 +0900182 if todos.include?('ninja') && via_ninja
183 expected_failure = true
184 end
185 else
186 expected_failure = true
Shinichiro Hamajie919d002015-06-26 01:15:55 +0900187 end
188 end
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900189
190 run_in_testdir(mk) do |name|
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900191 File.open("Makefile", 'w') do |ofile|
192 ofile.print(c)
193 end
Shinichiro Hamaji91571ac2015-09-07 18:24:00 +0900194 File.symlink('../../testcase/submake', 'submake')
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900195
196 expected = ''
197 output = ''
198
Shinichiro Hamaji491e73f2015-04-07 12:41:59 +0900199 testcases = c.scan(/^test\d*/).sort.uniq
Shinichiro Hamaji497754d2015-03-31 02:02:11 +0900200 if testcases.empty?
201 testcases = ['']
202 end
Shinichiro Hamajie5be0142015-03-30 19:26:01 +0900203
Shinichiro Hamajib6a04542015-09-09 17:37:41 +0900204 is_silent_test = mk =~ /\/submake_/
205
Shinichiro Hamajie5be0142015-03-30 19:26:01 +0900206 cleanup
207 testcases.each do |tc|
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +0900208 cmd = 'make'
Shinichiro Hamajib6a04542015-09-09 17:37:41 +0900209 if via_ninja || is_silent_test
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +0900210 cmd += ' -s'
211 end
212 cmd += " #{tc} 2>&1"
213 res = `#{cmd}`
Dan Willemsenf3a4ced2015-08-25 14:22:35 -0700214 res = normalize_make_log(res, mk, via_ninja)
Shinichiro Hamaji74a66002015-04-27 16:42:30 +0900215 expected += "=== #{tc} ===\n" + res
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900216 expected_files = get_output_filenames
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900217 expected += "\n=== FILES ===\n#{expected_files * "\n"}\n"
Shinichiro Hamajie5be0142015-03-30 19:26:01 +0900218 end
219
220 cleanup
221 testcases.each do |tc|
Shinichiro Hamajic48d9ce2015-04-28 03:47:39 +0900222 json = "#{tc.empty? ? 'test' : tc}"
Fumitoshi Ukai0547db62015-07-29 16:20:59 +0900223 cmd = "../../kati -save_json=#{json}.json -log_dir=. --use_find_emulator"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900224 if ckati
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +0900225 cmd = "../../ckati --use_find_emulator"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900226 end
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +0900227 if via_ninja
228 cmd += ' --ninja'
229 end
Shinichiro Hamaji85620572015-10-03 11:25:15 +0900230 if gen_all_targets
231 if !ckati || !via_ninja
232 raise "-a should be used with -c -n"
233 end
234 cmd += ' --gen_all_targets'
235 end
Shinichiro Hamajib6a04542015-09-09 17:37:41 +0900236 if is_silent_test
237 cmd += ' -s'
238 end
Shinichiro Hamaji6ff74ce2015-10-03 11:58:35 +0900239 if !gen_all_targets || mk =~ /makecmdgoals/
240 cmd += " #{tc}"
241 end
242 cmd += " 2>&1"
Shinichiro Hamajib674d582015-04-28 03:40:57 +0900243 res = IO.popen(cmd, 'r:binary', &:read)
Fumitoshi Ukai39837dd2015-07-28 12:25:56 +0900244 if via_ninja && File.exist?('build.ninja') && File.exists?('ninja.sh')
Shinichiro Hamaji85620572015-10-03 11:25:15 +0900245 cmd = './ninja.sh -j1 -v'
246 if gen_all_targets
247 cmd += " #{tc}"
248 end
249 cmd += ' 2>&1'
250 log = IO.popen(cmd, 'r:binary', &:read)
Shinichiro Hamaji86e11332015-07-28 15:24:17 +0900251 res += normalize_ninja_log(log, mk)
Shinichiro Hamaji8ac81712015-07-16 09:15:54 +0900252 end
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900253 res = normalize_kati_log(res)
Shinichiro Hamaji42f42e12015-04-13 14:26:45 +0900254 output += "=== #{tc} ===\n" + res
Shinichiro Hamajie5be0142015-03-30 19:26:01 +0900255 output_files = get_output_filenames
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900256 output += "\n=== FILES ===\n#{output_files * "\n"}\n"
257 end
258
259 File.open('out.make', 'w'){|ofile|ofile.print(expected)}
260 File.open('out.kati', 'w'){|ofile|ofile.print(output)}
261
Shinichiro Hamaji74c832f2015-04-09 14:54:39 +0900262 if expected =~ /FAIL/
263 puts %Q(#{name} has a string "FAIL" in its expectation)
264 exit 1
265 end
266
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900267 if expected != output
Shinichiro Hamaji91b105c2015-03-30 18:39:05 +0900268 if expected_failure
269 puts "#{name}: FAIL (expected)"
Shinichiro Hamajic6713602015-04-01 01:03:34 +0900270 expected_failures << name
Shinichiro Hamaji91b105c2015-03-30 18:39:05 +0900271 else
272 puts "#{name}: FAIL"
Shinichiro Hamajic6713602015-04-01 01:03:34 +0900273 failures << name
Shinichiro Hamaji91b105c2015-03-30 18:39:05 +0900274 end
Shinichiro Hamaji7f3a8702015-09-11 15:37:02 +0900275 if !expected_failure || show_failing
Shinichiro Hamaji221a16b2015-09-10 12:40:14 +0900276 puts `diff -u out.make out.kati`
277 end
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900278 else
Shinichiro Hamaji91b105c2015-03-30 18:39:05 +0900279 if expected_failure
280 puts "#{name}: PASS (unexpected)"
Shinichiro Hamajic6713602015-04-01 01:03:34 +0900281 unexpected_passes << name
Shinichiro Hamaji91b105c2015-03-30 18:39:05 +0900282 else
283 puts "#{name}: PASS"
Shinichiro Hamajic6713602015-04-01 01:03:34 +0900284 passes << name
Shinichiro Hamaji91b105c2015-03-30 18:39:05 +0900285 end
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900286 end
Shinichiro Hamajic48d9ce2015-04-28 03:47:39 +0900287
Shinichiro Hamajie666ac82015-04-28 04:18:13 +0900288 if name !~ /^err_/ && test_serialization && !expected_failure
Shinichiro Hamajic48d9ce2015-04-28 03:47:39 +0900289 testcases.each do |tc|
290 json = "#{tc.empty? ? 'test' : tc}"
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900291 cmd = "../../kati -save_json=#{json}_2.json -load_json=#{json}.json -n -log_dir=. #{tc} 2>&1"
Shinichiro Hamajic48d9ce2015-04-28 03:47:39 +0900292 res = IO.popen(cmd, 'r:binary', &:read)
293 if !File.exist?("#{json}.json") || !File.exist?("#{json}_2.json")
294 puts "#{name}##{json}: Serialize failure (not exist)"
Shinichiro Hamaji9f4f5d32015-04-28 03:53:49 +0900295 puts res
Shinichiro Hamajic48d9ce2015-04-28 03:47:39 +0900296 else
297 json1 = File.read("#{json}.json")
298 json2 = File.read("#{json}_2.json")
299 if json1 != json2
300 puts "#{name}##{json}: Serialize failure"
Shinichiro Hamaji9f4f5d32015-04-28 03:53:49 +0900301 puts res
Shinichiro Hamajic48d9ce2015-04-28 03:47:39 +0900302 end
303 end
304 end
305 end
Fumitoshi Ukai119dc912015-03-30 16:52:41 +0900306 end
307end
Shinichiro Hamajic6713602015-04-01 01:03:34 +0900308
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900309run_shell_test = proc do |sh|
Shinichiro Hamaji09796ef2015-07-30 17:08:29 +0900310 is_ninja_test = sh =~ /\/ninja_/
311 if is_ninja_test && (!ckati || !via_ninja)
312 next
313 end
314
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900315 run_in_testdir(sh) do |name|
316 cleanup
317 cmd = "sh ../../#{sh} make"
Shinichiro Hamaji09796ef2015-07-30 17:08:29 +0900318 if is_ninja_test
319 cmd += ' -s'
320 end
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900321 expected = IO.popen(cmd, 'r:binary', &:read)
322 cleanup
Shinichiro Hamaji09796ef2015-07-30 17:08:29 +0900323
324 if is_ninja_test
325 if ckati
Shinichiro Hamajia88c1c22015-07-31 12:29:48 +0900326 cmd = "sh ../../#{sh} ../../ckati --ninja --regen"
Shinichiro Hamaji09796ef2015-07-30 17:08:29 +0900327 else
328 next
329 end
330 else
331 if ckati
332 cmd = "sh ../../#{sh} ../../ckati"
333 else
334 cmd = "sh ../../#{sh} ../../kati --use_cache -log_dir=."
335 end
336 end
337
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900338 output = IO.popen(cmd, 'r:binary', &:read)
339
Dan Willemsenf3a4ced2015-08-25 14:22:35 -0700340 expected = normalize_make_log(expected, sh, is_ninja_test)
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900341 output = normalize_kati_log(output)
Shinichiro Hamaji09796ef2015-07-30 17:08:29 +0900342 if is_ninja_test
343 output = normalize_ninja_log(output, sh)
Shinichiro Hamaji59956602015-08-11 15:35:55 +0900344 output.gsub!(/No need to regenerate ninja file\n/, '')
Shinichiro Hamaji09796ef2015-07-30 17:08:29 +0900345 end
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900346 File.open('out.make', 'w'){|ofile|ofile.print(expected)}
347 File.open('out.kati', 'w'){|ofile|ofile.print(output)}
348
349 if expected != output
350 puts "#{name}: FAIL"
Shinichiro Hamaji39e62402015-05-20 19:34:58 +0900351 puts `diff -u out.make out.kati`
Shinichiro Hamajia9bda7a2015-05-20 17:50:42 +0900352 failures << name
353 else
354 puts "#{name}: PASS"
355 passes << name
356 end
357 end
358end
359
360test_files.each do |test|
361 if /\.mk$/ =~ test
362 run_make_test.call(test)
363 elsif /\.sh$/ =~ test
364 run_shell_test.call(test)
365 else
366 raise "Unknown test type: #{test}"
367 end
368end
369
Shinichiro Hamajic6713602015-04-01 01:03:34 +0900370puts
371
372if !expected_failures.empty?
373 puts "=== Expected failures ==="
374 expected_failures.each do |n|
375 puts n
376 end
377end
378
379if !unexpected_passes.empty?
380 puts "=== Unexpected passes ==="
381 unexpected_passes.each do |n|
382 puts n
383 end
384end
385
386if !failures.empty?
387 puts "=== Failures ==="
388 failures.each do |n|
389 puts n
390 end
391end
392
393puts
394
395if !unexpected_passes.empty? || !failures.empty?
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900396 puts "FAIL! (#{failures.size + unexpected_passes.size} fails #{passes.size} passes)"
Shinichiro Hamaji680e98b2015-10-05 17:30:43 +0900397 exit 1
Shinichiro Hamajic6713602015-04-01 01:03:34 +0900398else
399 puts 'PASS!'
400end