~ubuntu-branches/ubuntu/quantal/ruby1.9.1/quantal

« back to all changes in this revision

Viewing changes to .pc/110829-freebsd_assert_normal_exit.patch/bootstraptest/runner.rb

  • Committer: Bazaar Package Importer
  • Author(s): Lucas Nussbaum
  • Date: 2011-09-24 19:16:17 UTC
  • mfrom: (1.1.8 upstream) (13.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20110924191617-o1qz4rcmqjot8zuy
Tags: 1.9.3~rc1-1
* New upstream release: 1.9.3 RC1.
  + Includes load.c fixes. Closes: #639959.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"exec" "${RUBY-ruby}" "-x" "$0" "$@"; true # -*- mode: ruby; coding: utf-8 -*-
 
2
#!./ruby
 
3
# $Id: runner.rb 32088 2011-06-14 14:17:42Z akr $
 
4
 
 
5
# NOTE:
 
6
# Never use optparse in this file.
 
7
# Never use test/unit in this file.
 
8
# Never use Ruby extensions in this file.
 
9
 
 
10
begin
 
11
  require 'fileutils'
 
12
  require 'tmpdir'
 
13
rescue LoadError
 
14
  $:.unshift File.join(File.dirname(__FILE__), '../lib')
 
15
  retry
 
16
end
 
17
 
 
18
if !Dir.respond_to?(:mktmpdir)
 
19
  # copied from lib/tmpdir.rb
 
20
  def Dir.mktmpdir(prefix_suffix=nil, tmpdir=nil)
 
21
    case prefix_suffix
 
22
    when nil
 
23
      prefix = "d"
 
24
      suffix = ""
 
25
    when String
 
26
      prefix = prefix_suffix
 
27
      suffix = ""
 
28
    when Array
 
29
      prefix = prefix_suffix[0]
 
30
      suffix = prefix_suffix[1]
 
31
    else
 
32
      raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}"
 
33
    end
 
34
    tmpdir ||= Dir.tmpdir
 
35
    t = Time.now.strftime("%Y%m%d")
 
36
    n = nil
 
37
    begin
 
38
      path = "#{tmpdir}/#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}"
 
39
      path << "-#{n}" if n
 
40
      path << suffix
 
41
      Dir.mkdir(path, 0700)
 
42
    rescue Errno::EEXIST
 
43
      n ||= 0
 
44
      n += 1
 
45
      retry
 
46
    end
 
47
 
 
48
    if block_given?
 
49
      begin
 
50
        yield path
 
51
      ensure
 
52
        FileUtils.remove_entry_secure path
 
53
      end
 
54
    else
 
55
      path
 
56
    end
 
57
  end
 
58
end
 
59
 
 
60
def main
 
61
  @ruby = File.expand_path('miniruby')
 
62
  @verbose = false
 
63
  $stress = false
 
64
  dir = nil
 
65
  quiet = false
 
66
  tests = nil
 
67
  ARGV.delete_if {|arg|
 
68
    case arg
 
69
    when /\A--ruby=(.*)/
 
70
      @ruby = $1
 
71
      @ruby.gsub!(/^([^ ]*)/){File.expand_path($1)}
 
72
      @ruby.gsub!(/(\s+-I\s*)((?!(?:\.\/)*-(?:\s|\z))\S+)/){$1+File.expand_path($2)}
 
73
      @ruby.gsub!(/(\s+-r\s*)(\.\.?\/\S+)/){$1+File.expand_path($2)}
 
74
      true
 
75
    when /\A--sets=(.*)/
 
76
      tests = Dir.glob("#{File.dirname($0)}/test_{#{$1}}*.rb").sort
 
77
      puts tests.map {|path| File.basename(path) }.inspect
 
78
      true
 
79
    when /\A--dir=(.*)/
 
80
      dir = $1
 
81
      true
 
82
    when /\A(--stress|-s)/
 
83
      $stress = true
 
84
    when /\A(-q|--q(uiet))\z/
 
85
      quiet = true
 
86
      true
 
87
    when /\A(-v|--v(erbose))\z/
 
88
      @verbose = true
 
89
    when /\A(-h|--h(elp)?)\z/
 
90
      puts(<<-End)
 
91
Usage: #{File.basename($0, '.*')} --ruby=PATH [--sets=NAME,NAME,...]
 
92
        --sets=NAME,NAME,...        Name of test sets.
 
93
        --dir=DIRECTORY             Working directory.
 
94
                                    default: /tmp/bootstraptestXXXXX.tmpwd
 
95
    -s, --stress                    stress test.
 
96
    -v, --verbose                   Output test name before exec.
 
97
    -q, --quiet                     Don\'t print header message.
 
98
    -h, --help                      Print this message and quit.
 
99
End
 
100
      exit true
 
101
    else
 
102
      false
 
103
    end
 
104
  }
 
105
  if tests and not ARGV.empty?
 
106
    $stderr.puts "--tests and arguments are exclusive"
 
107
    exit false
 
108
  end
 
109
  tests ||= ARGV
 
110
  tests = Dir.glob("#{File.dirname($0)}/test_*.rb").sort if tests.empty?
 
111
  pathes = tests.map {|path| File.expand_path(path) }
 
112
 
 
113
  unless quiet
 
114
    puts Time.now
 
115
    if defined?(RUBY_DESCRIPTION)
 
116
      puts "Driver is #{RUBY_DESCRIPTION}"
 
117
    elsif defined?(RUBY_PATCHLEVEL)
 
118
      puts "Driver is ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}#{RUBY_PLATFORM}) [#{RUBY_PLATFORM}]"
 
119
    else
 
120
      puts "Driver is ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
 
121
    end
 
122
    puts "Target is #{`#{@ruby} -v`.chomp}"
 
123
    puts
 
124
    $stdout.flush
 
125
  end
 
126
 
 
127
  in_temporary_working_directory(dir) {
 
128
    exec_test pathes
 
129
  }
 
130
end
 
131
 
 
132
def exec_test(pathes)
 
133
  @count = 0
 
134
  @error = 0
 
135
  @errbuf = []
 
136
  @location = nil
 
137
  pathes.each do |path|
 
138
    $stderr.print "\n#{File.basename(path)} "
 
139
    $stderr.puts if @verbose
 
140
    load File.expand_path(path)
 
141
  end
 
142
  $stderr.puts
 
143
  if @error == 0
 
144
    if @count == 0
 
145
      $stderr.puts "No tests, no problem"
 
146
    else
 
147
      $stderr.puts "PASS all #{@count} tests"
 
148
    end
 
149
    exit true
 
150
  else
 
151
    @errbuf.each do |msg|
 
152
      $stderr.puts msg
 
153
    end
 
154
    $stderr.puts "FAIL #{@error}/#{@count} tests failed"
 
155
    exit false
 
156
  end
 
157
end
 
158
 
 
159
def show_progress(message = '')
 
160
  if @verbose
 
161
    $stderr.print "\##{@count} #{@location} "
 
162
  end
 
163
  faildesc = yield
 
164
  if !faildesc
 
165
    $stderr.print '.'
 
166
    $stderr.puts if @verbose
 
167
  else
 
168
    $stderr.print 'F'
 
169
    $stderr.puts if @verbose
 
170
    error faildesc, message
 
171
  end
 
172
rescue Exception => err
 
173
  $stderr.print 'E'
 
174
  $stderr.puts if @verbose
 
175
  error err.message, message
 
176
end
 
177
 
 
178
def assert_check(testsrc, message = '', opt = '')
 
179
  show_progress(message) {
 
180
    result = get_result_string(testsrc, opt)
 
181
    check_coredump
 
182
    yield(result)
 
183
  }
 
184
end
 
185
 
 
186
def assert_equal(expected, testsrc, message = '')
 
187
  newtest
 
188
  assert_check(testsrc, message) {|result|
 
189
    if expected == result
 
190
      nil
 
191
    else
 
192
      desc = "#{result.inspect} (expected #{expected.inspect})"
 
193
      pretty(testsrc, desc, result)
 
194
    end
 
195
  }
 
196
end
 
197
 
 
198
def assert_match(expected_pattern, testsrc, message = '')
 
199
  newtest
 
200
  assert_check(testsrc, message) {|result|
 
201
    if expected_pattern =~ result
 
202
      nil
 
203
    else
 
204
      desc = "#{expected_pattern.inspect} expected to be =~\n#{result.inspect}"
 
205
      pretty(testsrc, desc, result)
 
206
    end
 
207
  }
 
208
end
 
209
 
 
210
def assert_not_match(unexpected_pattern, testsrc, message = '')
 
211
  newtest
 
212
  assert_check(testsrc, message) {|result|
 
213
    if unexpected_pattern !~ result
 
214
      nil
 
215
    else
 
216
      desc = "#{unexpected_pattern.inspect} expected to be !~\n#{result.inspect}"
 
217
      pretty(testsrc, desc, result)
 
218
    end
 
219
  }
 
220
end
 
221
 
 
222
def assert_valid_syntax(testsrc, message = '')
 
223
  newtest
 
224
  assert_check(testsrc, message, '-c') {|result|
 
225
    result if /Syntax OK/ !~ result
 
226
  }
 
227
end
 
228
 
 
229
def assert_normal_exit(testsrc, *rest)
 
230
  newtest
 
231
  opt = {}
 
232
  opt = rest.pop if Hash === rest.last
 
233
  message, ignore_signals = rest
 
234
  message ||= ''
 
235
  timeout = opt[:timeout]
 
236
  show_progress(message) {
 
237
    faildesc = nil
 
238
    filename = make_srcfile(testsrc)
 
239
    old_stderr = $stderr.dup
 
240
    timeout_signaled = false
 
241
    begin
 
242
      $stderr.reopen("assert_normal_exit.log", "w")
 
243
      io = IO.popen("#{@ruby} -W0 #{filename}")
 
244
      pid = io.pid
 
245
      th = Thread.new {
 
246
        io.read
 
247
        io.close
 
248
        $?
 
249
      }
 
250
      if !th.join(timeout)
 
251
        Process.kill :KILL, pid
 
252
        timeout_signaled = true
 
253
      end
 
254
      status = th.value
 
255
    ensure
 
256
      $stderr.reopen(old_stderr)
 
257
      old_stderr.close
 
258
    end
 
259
    if status.signaled?
 
260
      signo = status.termsig
 
261
      signame = Signal.list.invert[signo]
 
262
      unless ignore_signals and ignore_signals.include?(signame)
 
263
        sigdesc = "signal #{signo}"
 
264
        if signame
 
265
          sigdesc = "SIG#{signame} (#{sigdesc})"
 
266
        end
 
267
        if timeout_signaled
 
268
          sigdesc << " (timeout)"
 
269
        end
 
270
        faildesc = pretty(testsrc, "killed by #{sigdesc}", nil)
 
271
        stderr_log = File.read("assert_normal_exit.log")
 
272
        if !stderr_log.empty?
 
273
          faildesc << "\n" if /\n\z/ !~ faildesc
 
274
          stderr_log << "\n" if /\n\z/ !~ stderr_log
 
275
          stderr_log.gsub!(/^.*\n/) { '| ' + $& }
 
276
          faildesc << stderr_log
 
277
        end
 
278
      end
 
279
    end
 
280
    faildesc
 
281
  }
 
282
end
 
283
 
 
284
def assert_finish(timeout_seconds, testsrc, message = '')
 
285
  newtest
 
286
  show_progress(message) {
 
287
    faildesc = nil
 
288
    filename = make_srcfile(testsrc)
 
289
    io = IO.popen("#{@ruby} -W0 #{filename}")
 
290
    pid = io.pid
 
291
    waited = false
 
292
    tlimit = Time.now + timeout_seconds
 
293
    while Time.now < tlimit
 
294
      if Process.waitpid pid, Process::WNOHANG
 
295
        waited = true
 
296
        break
 
297
      end
 
298
      sleep 0.1
 
299
    end
 
300
    if !waited
 
301
      Process.kill(:KILL, pid)
 
302
      Process.waitpid pid
 
303
      faildesc = pretty(testsrc, "not finished in #{timeout_seconds} seconds", nil)
 
304
    end
 
305
    io.close
 
306
    faildesc
 
307
  }
 
308
end
 
309
 
 
310
def flunk(message = '')
 
311
  newtest
 
312
  show_progress('') { message }
 
313
end
 
314
 
 
315
def pretty(src, desc, result)
 
316
  src = src.sub(/\A.*\n/, '')
 
317
  (/\n/ =~ src ? "\n#{adjust_indent(src)}" : src) + "  #=> #{desc}"
 
318
end
 
319
 
 
320
INDENT = 27
 
321
 
 
322
def adjust_indent(src)
 
323
  untabify(src).gsub(/^ {#{INDENT}}/o, '').gsub(/^/, '   ')
 
324
end
 
325
 
 
326
def untabify(str)
 
327
  str.gsub(/^\t+/) {' ' * (8 * $&.size) }
 
328
end
 
329
 
 
330
def make_srcfile(src)
 
331
  filename = 'bootstraptest.tmp.rb'
 
332
  File.open(filename, 'w') {|f|
 
333
    f.puts "GC.stress = true" if $stress
 
334
    f.puts "print(begin; #{src}; end)"
 
335
  }
 
336
  filename
 
337
end
 
338
 
 
339
def get_result_string(src, opt = '')
 
340
  if @ruby
 
341
    filename = make_srcfile(src)
 
342
    begin
 
343
      `#{@ruby} -W0 #{opt} #{filename}`
 
344
    ensure
 
345
      raise CoreDumpError, "core dumped" if $? and $?.coredump?
 
346
    end
 
347
  else
 
348
    eval(src).to_s
 
349
  end
 
350
end
 
351
 
 
352
def newtest
 
353
  @location = File.basename(caller(2).first)
 
354
  @count += 1
 
355
  cleanup_coredump
 
356
end
 
357
 
 
358
def error(msg, additional_message)
 
359
  @errbuf.push "\##{@count} #{@location}: #{msg}  #{additional_message}"
 
360
  @error += 1
 
361
end
 
362
 
 
363
def in_temporary_working_directory(dir)
 
364
  if dir
 
365
    Dir.mkdir dir
 
366
    Dir.chdir(dir) {
 
367
      yield
 
368
    }
 
369
  else
 
370
    Dir.mktmpdir(["bootstraptest", ".tmpwd"]) {|d|
 
371
      Dir.chdir(d) {
 
372
        yield
 
373
      }
 
374
    }
 
375
  end
 
376
end
 
377
 
 
378
def cleanup_coredump
 
379
  FileUtils.rm_f 'core'
 
380
  FileUtils.rm_f Dir.glob('core.*')
 
381
  FileUtils.rm_f @ruby+'.stackdump' if @ruby
 
382
end
 
383
 
 
384
class CoreDumpError < StandardError; end
 
385
 
 
386
def check_coredump
 
387
  if File.file?('core') or not Dir.glob('core.*').empty? or
 
388
      (@ruby and File.exist?(@ruby+'.stackdump'))
 
389
    raise CoreDumpError, "core dumped"
 
390
  end
 
391
end
 
392
 
 
393
main