rubygems-test 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
data/lib/open4.rb ADDED
@@ -0,0 +1,401 @@
1
+ # vim: ts=2:sw=2:sts=2:et:fdm=marker
2
+ require 'fcntl'
3
+ require 'timeout'
4
+ require 'thread'
5
+
6
+ module Open4
7
+ #--{{{
8
+ VERSION = '1.0.1'
9
+ def self.version() VERSION end
10
+
11
+ class Error < ::StandardError; end
12
+
13
+ def popen4(*cmd, &b)
14
+ #--{{{
15
+ pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe
16
+
17
+ verbose = $VERBOSE
18
+ begin
19
+ $VERBOSE = nil
20
+ ps.first.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
21
+ ps.last.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
22
+
23
+ cid = fork {
24
+ pw.last.close
25
+ STDIN.reopen pw.first
26
+ pw.first.close
27
+
28
+ pr.first.close
29
+ STDOUT.reopen pr.last
30
+ pr.last.close
31
+
32
+ pe.first.close
33
+ STDERR.reopen pe.last
34
+ pe.last.close
35
+
36
+ STDOUT.sync = STDERR.sync = true
37
+
38
+ begin
39
+ exec(*cmd)
40
+ raise 'forty-two'
41
+ rescue Exception => e
42
+ Marshal.dump(e, ps.last)
43
+ ps.last.flush
44
+ end
45
+ ps.last.close unless (ps.last.closed?)
46
+ exit!
47
+ }
48
+ ensure
49
+ $VERBOSE = verbose
50
+ end
51
+
52
+ [pw.first, pr.last, pe.last, ps.last].each{|fd| fd.close}
53
+
54
+ begin
55
+ e = Marshal.load ps.first
56
+ raise(Exception === e ? e : "unknown failure!")
57
+ rescue EOFError # If we get an EOF error, then the exec was successful
58
+ 42
59
+ ensure
60
+ ps.first.close
61
+ end
62
+
63
+ pw.last.sync = true
64
+
65
+ pi = [pw.last, pr.first, pe.first]
66
+
67
+ if b
68
+ begin
69
+ b[cid, *pi]
70
+ Process.waitpid2(cid).last
71
+ ensure
72
+ pi.each{|fd| fd.close unless fd.closed?}
73
+ end
74
+ else
75
+ [cid, pw.last, pr.first, pe.first]
76
+ end
77
+ #--}}}
78
+ end
79
+ alias open4 popen4
80
+ module_function :popen4
81
+ module_function :open4
82
+
83
+ class SpawnError < Error
84
+ #--{{{
85
+ attr 'cmd'
86
+ attr 'status'
87
+ attr 'signals'
88
+ def exitstatus
89
+ @status.exitstatus
90
+ end
91
+ def initialize cmd, status
92
+ @cmd, @status = cmd, status
93
+ @signals = {}
94
+ if status.signaled?
95
+ @signals['termsig'] = status.termsig
96
+ @signals['stopsig'] = status.stopsig
97
+ end
98
+ sigs = @signals.map{|k,v| "#{ k }:#{ v.inspect }"}.join(' ')
99
+ super "cmd <#{ cmd }> failed with status <#{ exitstatus.inspect }> signals <#{ sigs }>"
100
+ end
101
+ #--}}}
102
+ end
103
+
104
+ class ThreadEnsemble
105
+ #--{{{
106
+ attr 'threads'
107
+
108
+ def initialize cid
109
+ @cid, @threads, @argv, @done, @running = cid, [], [], Queue.new, false
110
+ @killed = false
111
+ end
112
+
113
+ def add_thread *a, &b
114
+ @running ? raise : (@argv << [a, b])
115
+ end
116
+
117
+ #
118
+ # take down process more nicely
119
+ #
120
+ def killall
121
+ c = Thread.critical
122
+ return nil if @killed
123
+ Thread.critical = true
124
+ (@threads - [Thread.current]).each{|t| t.kill rescue nil}
125
+ @killed = true
126
+ ensure
127
+ Thread.critical = c
128
+ end
129
+
130
+ def run
131
+ @running = true
132
+
133
+ begin
134
+ @argv.each do |a, b|
135
+ @threads << Thread.new(*a) do |*a|
136
+ begin
137
+ b[*a]
138
+ ensure
139
+ killall rescue nil if $!
140
+ @done.push Thread.current
141
+ end
142
+ end
143
+ end
144
+ rescue
145
+ killall
146
+ raise
147
+ ensure
148
+ all_done
149
+ end
150
+
151
+ @threads.map{|t| t.value}
152
+ end
153
+
154
+ def all_done
155
+ @threads.size.times{ @done.pop }
156
+ end
157
+ #--}}}
158
+ end
159
+
160
+ def to timeout = nil
161
+ #--{{{
162
+ Timeout.timeout(timeout){ yield }
163
+ #--}}}
164
+ end
165
+ module_function :to
166
+
167
+ def new_thread *a, &b
168
+ #--{{{
169
+ cur = Thread.current
170
+ Thread.new(*a) do |*a|
171
+ begin
172
+ b[*a]
173
+ rescue Exception => e
174
+ cur.raise e
175
+ end
176
+ end
177
+ #--}}}
178
+ end
179
+ module_function :new_thread
180
+
181
+ def getopts opts = {}
182
+ #--{{{
183
+ lambda do |*args|
184
+ keys, default, ignored = args
185
+ catch('opt') do
186
+ [keys].flatten.each do |key|
187
+ [key, key.to_s, key.to_s.intern].each do |key|
188
+ throw 'opt', opts[key] if opts.has_key?(key)
189
+ end
190
+ end
191
+ default
192
+ end
193
+ end
194
+ #--}}}
195
+ end
196
+ module_function :getopts
197
+
198
+ def relay src, dst = nil, t = nil
199
+ #--{{{
200
+ send_dst =
201
+ if dst.respond_to?(:call)
202
+ lambda{|buf| dst.call(buf)}
203
+ else
204
+ lambda{|buf| dst << buf}
205
+ end
206
+
207
+ unless src.nil?
208
+ if src.respond_to? :gets
209
+ while buf = to(t){ src.gets }
210
+ send_dst[buf]
211
+ end
212
+
213
+ elsif src.respond_to? :each
214
+ q = Queue.new
215
+ th = nil
216
+
217
+ timer_set = lambda do |t|
218
+ th = new_thread{ to(t){ q.pop } }
219
+ end
220
+
221
+ timer_cancel = lambda do |t|
222
+ th.kill if th rescue nil
223
+ end
224
+
225
+ timer_set[t]
226
+ begin
227
+ src.each do |buf|
228
+ timer_cancel[t]
229
+ send_dst[buf]
230
+ timer_set[t]
231
+ end
232
+ ensure
233
+ timer_cancel[t]
234
+ end
235
+
236
+ elsif src.respond_to? :read
237
+ buf = to(t){ src.read }
238
+ send_dst[buf]
239
+
240
+ else
241
+ buf = to(t){ src.to_s }
242
+ send_dst[buf]
243
+ end
244
+ end
245
+ #--}}}
246
+ end
247
+ module_function :relay
248
+
249
+ def spawn arg, *argv
250
+ #--{{{
251
+ argv.unshift(arg)
252
+ opts = ((argv.size > 1 and Hash === argv.last) ? argv.pop : {})
253
+ argv.flatten!
254
+ cmd = argv.join(' ')
255
+
256
+
257
+ getopt = getopts opts
258
+
259
+ ignore_exit_failure = getopt[ 'ignore_exit_failure', getopt['quiet', false] ]
260
+ ignore_exec_failure = getopt[ 'ignore_exec_failure', !getopt['raise', true] ]
261
+ exitstatus = getopt[ %w( exitstatus exit_status status ) ]
262
+ stdin = getopt[ %w( stdin in i 0 ) << 0 ]
263
+ stdout = getopt[ %w( stdout out o 1 ) << 1 ]
264
+ stderr = getopt[ %w( stderr err e 2 ) << 2 ]
265
+ pid = getopt[ 'pid' ]
266
+ timeout = getopt[ %w( timeout spawn_timeout ) ]
267
+ stdin_timeout = getopt[ %w( stdin_timeout ) ]
268
+ stdout_timeout = getopt[ %w( stdout_timeout io_timeout ) ]
269
+ stderr_timeout = getopt[ %w( stderr_timeout ) ]
270
+ status = getopt[ %w( status ) ]
271
+ cwd = getopt[ %w( cwd dir ) ]
272
+
273
+ exitstatus =
274
+ case exitstatus
275
+ when TrueClass, FalseClass
276
+ ignore_exit_failure = true if exitstatus
277
+ [0]
278
+ else
279
+ [*(exitstatus || 0)].map{|i| Integer i}
280
+ end
281
+
282
+ stdin ||= '' if stdin_timeout
283
+ stdout ||= '' if stdout_timeout
284
+ stderr ||= '' if stderr_timeout
285
+
286
+ started = false
287
+
288
+ status =
289
+ begin
290
+ chdir(cwd) do
291
+ Timeout::timeout(timeout) do
292
+ popen4(*argv) do |c, i, o, e|
293
+ started = true
294
+
295
+ %w( replace pid= << push update ).each do |msg|
296
+ break(pid.send(msg, c)) if pid.respond_to? msg
297
+ end
298
+
299
+ te = ThreadEnsemble.new c
300
+
301
+ te.add_thread(i, stdin) do |i, stdin|
302
+ relay stdin, i, stdin_timeout
303
+ i.close rescue nil
304
+ end
305
+
306
+ te.add_thread(o, stdout) do |o, stdout|
307
+ relay o, stdout, stdout_timeout
308
+ end
309
+
310
+ te.add_thread(e, stderr) do |o, stderr|
311
+ relay e, stderr, stderr_timeout
312
+ end
313
+
314
+ te.run
315
+ end
316
+ end
317
+ end
318
+ rescue
319
+ raise unless(not started and ignore_exec_failure)
320
+ end
321
+
322
+ raise SpawnError.new(cmd, status) unless
323
+ (ignore_exit_failure or (status.nil? and ignore_exec_failure) or exitstatus.include?(status.exitstatus))
324
+
325
+ status
326
+ #--}}}
327
+ end
328
+ module_function :spawn
329
+
330
+ def chdir cwd, &block
331
+ return(block.call Dir.pwd) unless cwd
332
+ Dir.chdir cwd, &block
333
+ end
334
+ module_function :chdir
335
+
336
+ def background arg, *argv
337
+ #--{{{
338
+ require 'thread'
339
+ q = Queue.new
340
+ opts = { 'pid' => q, :pid => q }
341
+ case argv.last
342
+ when Hash
343
+ argv.last.update opts
344
+ else
345
+ argv.push opts
346
+ end
347
+ thread = Thread.new(arg, argv){|arg, argv| spawn arg, *argv}
348
+ sc = class << thread; self; end
349
+ sc.module_eval {
350
+ define_method(:pid){ @pid ||= q.pop }
351
+ define_method(:spawn_status){ @spawn_status ||= value }
352
+ define_method(:exitstatus){ @exitstatus ||= spawn_status.exitstatus }
353
+ }
354
+ thread
355
+ #--}}}
356
+ end
357
+ alias bg background
358
+ module_function :background
359
+ module_function :bg
360
+
361
+ def maim pid, opts = {}
362
+ #--{{{
363
+ getopt = getopts opts
364
+ sigs = getopt[ 'signals', %w(SIGTERM SIGQUIT SIGKILL) ]
365
+ suspend = getopt[ 'suspend', 4 ]
366
+ pid = Integer pid
367
+ existed = false
368
+ sigs.each do |sig|
369
+ begin
370
+ Process.kill sig, pid
371
+ existed = true
372
+ rescue Errno::ESRCH
373
+ return(existed ? nil : true)
374
+ end
375
+ return true unless alive? pid
376
+ sleep suspend
377
+ return true unless alive? pid
378
+ end
379
+ return(not alive?(pid))
380
+ #--}}}
381
+ end
382
+ module_function :maim
383
+
384
+ def alive pid
385
+ #--{{{
386
+ pid = Integer pid
387
+ begin
388
+ Process.kill 0, pid
389
+ true
390
+ rescue Errno::ESRCH
391
+ false
392
+ end
393
+ #--}}}
394
+ end
395
+ alias alive? alive
396
+ module_function :alive
397
+ module_function :'alive?'
398
+ #--}}}
399
+ end
400
+
401
+ def open4(*cmd, &b) cmd.size == 0 ? Open4 : Open4::popen4(*cmd, &b) end
@@ -7,7 +7,6 @@ require 'fileutils'
7
7
  require 'pathname'
8
8
  require 'rbconfig'
9
9
  require 'yaml'
10
- require 'open3'
11
10
  require 'net/http'
12
11
  require 'uri'
13
12
  require 'ostruct'
@@ -174,7 +173,7 @@ class Gem::Commands::TestCommand < Gem::Command
174
173
  :release => spec.version.release.to_s,
175
174
  :prerelease => spec.version.prerelease?
176
175
  },
177
- :platform => spec.platform,
176
+ :platform => (Kernel.const_get("RUBY_ENGINE") rescue "ruby"),
178
177
  :ruby_version => RUBY_VERSION,
179
178
  :result => result,
180
179
  :test_output => output
@@ -195,7 +194,7 @@ class Gem::Commands::TestCommand < Gem::Command
195
194
  exit_status = nil
196
195
 
197
196
  if spec.files.include?(".gemtest")
198
- open_proc = proc do |stdin, stdout, stderr, thr|
197
+ open_proc = proc do |pid, stdin, stdout, stderr|
199
198
  loop do
200
199
  if stdout.eof? and stderr.eof?
201
200
  break
@@ -205,28 +204,32 @@ class Gem::Commands::TestCommand < Gem::Command
205
204
 
206
205
  handles, _, _ = IO.select([stdout, stderr].reject { |x| x.closed? || x.eof? }, nil, nil, 0.1)
207
206
 
208
- begin
209
- handles.each { |io| io.readpartial(16384, buf) } if handles
210
- rescue EOFError, IOError
211
- next
212
- end
207
+ handles.each do |io|
208
+ begin
209
+ io.readpartial(16384, buf)
210
+ rescue EOFError, IOError
211
+ next
212
+ end
213
+ end if handles
213
214
 
214
215
  output += buf
215
216
 
216
217
  print buf
217
218
  end
219
+ end
218
220
 
219
- unless RUBY_VERSION =~ /^1.8/
220
- exit_status = thr.value
221
+ # jruby stuffs it under IO, so we'll use that if it's available
222
+ # XXX I'm fairly sure that JRuby's gems don't support plugins, so this is
223
+ # left untested.
224
+ klass =
225
+ if IO.respond_to?(:open4)
226
+ IO
227
+ else
228
+ require 'open4'
229
+ Open4
221
230
  end
222
- end
223
231
 
224
- if RUBY_VERSION =~ /^1.8/
225
- Open3.popen3(rake_path, "test", '--trace', &open_proc)
226
- exit_status = $?
227
- else
228
- Open3.popen3(rake_path, "test", '--trace', &open_proc)
229
- end
232
+ exit_status = klass.popen4(rake_path, "test", '--trace', &open_proc)
230
233
 
231
234
  if config["upload_results"] or
232
235
  (!config.has_key?("upload_results") and ask_yes_no("Upload these results to rubygems.org?", true))
@@ -239,7 +242,7 @@ class Gem::Commands::TestCommand < Gem::Command
239
242
 
240
243
  FileUtils.chdir(pwd)
241
244
 
242
- raise Gem::TestError
245
+ raise Gem::TestError, "something"
243
246
  end
244
247
  else
245
248
  alert_warning "This gem has no tests! Please contact the author to gain testing and reporting!"
data/test/test_execute.rb CHANGED
@@ -78,11 +78,10 @@ class TestExecute < Test::Unit::TestCase
78
78
  :release => spec.version.release.to_s,
79
79
  :prerelease => spec.version.prerelease?
80
80
  },
81
- :platform => spec.platform,
81
+ :platform => (Kernel.const_get("RUBY_ENGINE") rescue "ruby"),
82
82
  :test_output => output
83
83
  }
84
84
 
85
-
86
85
  assert_equal YAML.load(@test.gather_results(spec, output, true)), hash
87
86
  end
88
87
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 2
9
- version: 0.1.2
8
+ - 3
9
+ version: 0.1.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Erik Hollensbe
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-16 00:00:00 -05:00
18
+ date: 2010-12-17 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -47,6 +47,7 @@ files:
47
47
  - gems/template.gemspec
48
48
  - gems/test-gem-0.0.0.gem
49
49
  - gems/test/test_pass.rb
50
+ - lib/open4.rb
50
51
  - lib/rubygems/commands/test_command.rb
51
52
  - lib/rubygems/on_install_test.rb
52
53
  - lib/rubygems_plugin.rb