systemu 2.4.2 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -4,7 +4,8 @@ NAME
4
4
 
5
5
  SYNOPSIS
6
6
 
7
- univeral capture of stdout and stderr and handling of child process pid for windows, *nix, etc.
7
+ universal capture of stdout and stderr and handling of child process pid for
8
+ windows, *nix, etc.
8
9
 
9
10
  URIS
10
11
 
data/lib/systemu.rb CHANGED
@@ -1,4 +1,5 @@
1
- # vim: ts=2:sw=2:sts=2:et:fdm=marker
1
+ # encoding: utf-8
2
+
2
3
  require 'tmpdir'
3
4
  require 'socket'
4
5
  require 'fileutils'
@@ -13,7 +14,7 @@ class SystemUniversal
13
14
  #
14
15
  # constants
15
16
  #
16
- SystemUniversal::VERSION = '2.4.2' unless SystemUniversal.send(:const_defined?, :VERSION)
17
+ SystemUniversal::VERSION = '2.5.0' unless SystemUniversal.send(:const_defined?, :VERSION)
17
18
  def SystemUniversal.version() SystemUniversal::VERSION end
18
19
  def version() SystemUniversal::VERSION end
19
20
  #
@@ -76,7 +77,7 @@ class SystemUniversal
76
77
  line = pipe.gets
77
78
  case line
78
79
  when %r/^pid: \d+$/
79
- cid = Integer line[%r/\d+/]
80
+ cid = Integer line[%r/\d+/]
80
81
  else
81
82
  begin
82
83
  buf = pipe.read
@@ -120,12 +121,12 @@ class SystemUniversal
120
121
  SystemUniversal.quote(*args, &block)
121
122
  end
122
123
 
123
- def new_thread cid, block
124
+ def new_thread cid, block
124
125
  q = Queue.new
125
- Thread.new(cid) do |cid|
126
- current = Thread.current
126
+ Thread.new(cid) do |cid|
127
+ current = Thread.current
127
128
  current.abort_on_exception = true
128
- q.push current
129
+ q.push current
129
130
  block.call cid
130
131
  end
131
132
  q.pop
@@ -150,10 +151,10 @@ class SystemUniversal
150
151
  c['argv'] = @argv
151
152
  c['env'] = @env
152
153
  c['cwd'] = @cwd
153
- c['stdin'] = stdin
154
- c['stdout'] = stdout
155
- c['stderr'] = stderr
156
- c['program'] = program
154
+ c['stdin'] = stdin
155
+ c['stdout'] = stdout
156
+ c['stderr'] = stderr
157
+ c['program'] = program
157
158
  open(config, 'w'){|f| Marshal.dump(c, f)}
158
159
 
159
160
  open(program, 'w'){|f| f.write child_program(config)}
@@ -171,6 +172,8 @@ class SystemUniversal
171
172
 
172
173
  def child_program config
173
174
  <<-program
175
+ # encoding: utf-8
176
+
174
177
  PIPE = STDOUT.dup
175
178
  begin
176
179
  config = Marshal.load(IO.read('#{ config }'))
@@ -190,7 +193,7 @@ class SystemUniversal
190
193
  STDERR.reopen stderr
191
194
 
192
195
  PIPE.puts "pid: \#{ Process.pid }"
193
- PIPE.flush ### the process is ready yo!
196
+ PIPE.flush ### the process is ready yo!
194
197
  PIPE.close
195
198
 
196
199
  exec *argv
@@ -221,9 +224,9 @@ class SystemUniversal
221
224
  tmp = File.join d, "systemu_#{ @host }_#{ @ppid }_#{ @pid }_#{ rand }_#{ i += 1 }"
222
225
 
223
226
  begin
224
- Dir.mkdir tmp
227
+ Dir.mkdir tmp
225
228
  rescue Errno::EEXIST
226
- raise if i >= max
229
+ raise if i >= max
227
230
  next
228
231
  end
229
232
 
@@ -232,7 +235,7 @@ class SystemUniversal
232
235
  begin
233
236
  b.call tmp
234
237
  ensure
235
- FileUtils.rm_rf tmp unless SystemU.turd
238
+ FileUtils.rm_rf tmp unless SystemU.turd
236
239
  end
237
240
  else
238
241
  tmp
@@ -260,36 +263,39 @@ end
260
263
  if defined? JRUBY_VERSION
261
264
  require 'jruby'
262
265
  java_import org.jruby.RubyProcess
263
-
266
+
264
267
  class SystemUniversal
265
268
  def systemu
266
269
  split_argv = JRuby::PathHelper.smart_split_command @argv
267
270
  process = java.lang.Runtime.runtime.exec split_argv.to_java(:string)
268
-
271
+
269
272
  stdout, stderr = [process.input_stream, process.error_stream].map do |stream|
270
273
  StreamReader.new(stream)
271
274
  end
272
275
 
273
276
  exit_code = process.wait_for
277
+ field = process.get_class.get_declared_field("pid")
278
+ field.set_accessible(true)
279
+ pid = field.get(process)
274
280
  [
275
- RubyProcess::RubyStatus.new_process_status(JRuby.runtime, exit_code),
276
- stdout.join,
281
+ RubyProcess::RubyStatus.new_process_status(JRuby.runtime, exit_code, pid),
282
+ stdout.join,
277
283
  stderr.join
278
284
  ]
279
285
  end
280
-
286
+
281
287
  class StreamReader
282
288
  def initialize(stream)
283
289
  @data = ""
284
290
  @thread = Thread.new do
285
291
  reader = java.io.BufferedReader.new java.io.InputStreamReader.new(stream)
286
-
292
+
287
293
  while line = reader.read_line
288
294
  @data << line << "\n"
289
295
  end
290
296
  end
291
297
  end
292
-
298
+
293
299
  def join
294
300
  @thread.join
295
301
  @data
@@ -297,7 +303,7 @@ if defined? JRUBY_VERSION
297
303
  end
298
304
  end
299
305
  end
300
-
306
+
301
307
 
302
308
 
303
309
  SystemU = SystemUniversal unless defined? SystemU
@@ -333,20 +339,20 @@ if $0 == __FILE__
333
339
  # sleep
334
340
  #
335
341
  sleep = %q( ruby -e" p(sleep(1)) " )
336
- status, stdout, stderr = systemu sleep
342
+ status, stdout, stderr = systemu sleep
337
343
  p [status, stdout, stderr]
338
344
 
339
345
  sleep = %q( ruby -e" p(sleep(42)) " )
340
346
  status, stdout, stderr = systemu(sleep){|cid| Process.kill 9, cid}
341
347
  p [status, stdout, stderr]
342
348
  #
343
- # env
349
+ # env
344
350
  #
345
351
  env = %q( ruby -e" p ENV['A'] " )
346
- status, stdout, stderr = systemu env, :env => {'A' => 42}
352
+ status, stdout, stderr = systemu env, :env => {'A' => 42}
347
353
  p [status, stdout, stderr]
348
354
  #
349
- # cwd
355
+ # cwd
350
356
  #
351
357
  env = %q( ruby -e" p Dir.pwd " )
352
358
  status, stdout, stderr = systemu env, :cwd => Dir.tmpdir
data/systemu.gemspec CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  Gem::Specification::new do |spec|
5
5
  spec.name = "systemu"
6
- spec.version = "2.4.2"
6
+ spec.version = "2.5.0"
7
7
  spec.platform = Gem::Platform::RUBY
8
8
  spec.summary = "systemu"
9
9
  spec.description = "description: systemu kicks the ass"
@@ -22,7 +22,10 @@ Gem::Specification::new do |spec|
22
22
  "samples/d.rb",
23
23
  "samples/e.rb",
24
24
  "samples/f.rb",
25
- "systemu.gemspec"]
25
+ "systemu.gemspec",
26
+ "test",
27
+ "test/systemu_test.rb",
28
+ "test/testing.rb"]
26
29
 
27
30
  spec.executables = []
28
31
 
@@ -0,0 +1,64 @@
1
+
2
+ Testing SystemU do
3
+
4
+ ##
5
+ #
6
+ testing 'that simple usage works' do
7
+ status, stdout, stderr = assert{ systemu :bin/:ls }
8
+ assert{ status == 0 }
9
+ assert{ stdout['lib'] }
10
+ assert{ stderr.strip.empty? }
11
+ end
12
+
13
+ testing 'program with stdin' do
14
+ stdin = '42'
15
+ status, stdout, stderr = assert{ systemu :bin/:cat, :stdin => stdin }
16
+ assert{ status == 0 }
17
+ assert{ stdout == stdin }
18
+ end
19
+
20
+ end
21
+
22
+
23
+
24
+
25
+
26
+ BEGIN {
27
+
28
+ # silly hax to build commands we can shell out to on any platform. since
29
+ # tests might run on windoze we assume only that 'ruby' is available and build
30
+ # other command-line programs from it.
31
+ #
32
+ module Kernel
33
+ private
34
+ def bin(which, options = {}, &block)
35
+ case which.to_s
36
+ when 'ls'
37
+ %| ruby -e'puts Dir.glob("*").sort' |
38
+
39
+ when 'cat'
40
+ %| ruby -e'STDOUT.write(ARGF.read)' |
41
+
42
+ when 'find'
43
+ %| ruby -e'puts Dir.glob("**/**").sort' |
44
+ end
45
+ end
46
+ end
47
+
48
+ # just let's us write: :bin/:ls
49
+ #
50
+ class Symbol
51
+ def / other, options = {}, &block
52
+ eval "#{ self }(:#{ other }, options, &block)"
53
+ end
54
+ end
55
+
56
+ testdir = File.dirname(File.expand_path(__FILE__))
57
+ rootdir = File.dirname(testdir)
58
+ libdir = File.join(rootdir, 'lib')
59
+ require File.join(libdir, 'systemu')
60
+ require File.join(testdir, 'testing')
61
+
62
+
63
+ Dir.chdir(rootdir)
64
+ }
data/test/testing.rb ADDED
@@ -0,0 +1,195 @@
1
+ require 'test/unit'
2
+
3
+ testdir = File.expand_path(File.dirname(__FILE__))
4
+ rootdir = File.dirname(testdir)
5
+ libdir = File.join(rootdir, 'lib')
6
+
7
+ STDOUT.sync = true
8
+
9
+ $:.unshift(testdir) unless $:.include?(testdir)
10
+ $:.unshift(libdir) unless $:.include?(libdir)
11
+ $:.unshift(rootdir) unless $:.include?(rootdir)
12
+
13
+ class Testing
14
+ class Slug < ::String
15
+ def Slug.for(*args)
16
+ string = args.flatten.compact.join('-')
17
+ words = string.to_s.scan(%r/\w+/)
18
+ words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''}
19
+ words.delete_if{|word| word.nil? or word.strip.empty?}
20
+ new(words.join('-').downcase)
21
+ end
22
+ end
23
+
24
+ class Context
25
+ attr_accessor :name
26
+
27
+ def initialize(name, *args)
28
+ @name = name
29
+ end
30
+
31
+ def to_s
32
+ Slug.for(name)
33
+ end
34
+ end
35
+ end
36
+
37
+ def Testing(*args, &block)
38
+ Class.new(::Test::Unit::TestCase) do
39
+
40
+ ## class methods
41
+ #
42
+ class << self
43
+ def contexts
44
+ @contexts ||= []
45
+ end
46
+
47
+ def context(*args, &block)
48
+ return contexts.last if(args.empty? and block.nil?)
49
+
50
+ context = Testing::Context.new(*args)
51
+ contexts.push(context)
52
+
53
+ begin
54
+ block.call(context)
55
+ ensure
56
+ contexts.pop
57
+ end
58
+ end
59
+
60
+ def slug_for(*args)
61
+ string = [context, args].flatten.compact.join('-')
62
+ words = string.to_s.scan(%r/\w+/)
63
+ words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''}
64
+ words.delete_if{|word| word.nil? or word.strip.empty?}
65
+ words.join('-').downcase.sub(/_$/, '')
66
+ end
67
+
68
+ def name() const_get(:Name) end
69
+
70
+ def testno()
71
+ '%05d' % (@testno ||= 0)
72
+ ensure
73
+ @testno += 1
74
+ end
75
+
76
+ def testing(*args, &block)
77
+ method = ["test", testno, slug_for(*args)].delete_if{|part| part.empty?}.join('_')
78
+ define_method(method, &block)
79
+ end
80
+
81
+ def test(*args, &block)
82
+ testing(*args, &block)
83
+ end
84
+
85
+ def setup(&block)
86
+ define_method(:setup, &block) if block
87
+ end
88
+
89
+ def teardown(&block)
90
+ define_method(:teardown, &block) if block
91
+ end
92
+
93
+ def prepare(&block)
94
+ @prepare ||= []
95
+ @prepare.push(block) if block
96
+ @prepare
97
+ end
98
+
99
+ def cleanup(&block)
100
+ @cleanup ||= []
101
+ @cleanup.push(block) if block
102
+ @cleanup
103
+ end
104
+ end
105
+
106
+ ## configure the subclass!
107
+ #
108
+ const_set(:Testno, '0')
109
+ slug = slug_for(*args).gsub(%r/-/,'_')
110
+ name = ['TESTING', '%03d' % const_get(:Testno), slug].delete_if{|part| part.empty?}.join('_')
111
+ name = name.upcase!
112
+ const_set(:Name, name)
113
+ const_set(:Missing, Object.new.freeze)
114
+
115
+ ## instance methods
116
+ #
117
+ alias_method('__assert__', 'assert')
118
+
119
+ def assert(*args, &block)
120
+ if args.size == 1 and args.first.is_a?(Hash)
121
+ options = args.first
122
+ expected = getopt(:expected, options){ missing }
123
+ actual = getopt(:actual, options){ missing }
124
+ if expected == missing and actual == missing
125
+ actual, expected, *ignored = options.to_a.flatten
126
+ end
127
+ expected = expected.call() if expected.respond_to?(:call)
128
+ actual = actual.call() if actual.respond_to?(:call)
129
+ assert_equal(expected, actual)
130
+ end
131
+
132
+ if block
133
+ label = "assert(#{ args.join(' ') })"
134
+ result = nil
135
+ assert_nothing_raised{ result = block.call }
136
+ __assert__(result, label)
137
+ result
138
+ else
139
+ result = args.shift
140
+ label = "assert(#{ args.join(' ') })"
141
+ __assert__(result, label)
142
+ result
143
+ end
144
+ end
145
+
146
+ def missing
147
+ self.class.const_get(:Missing)
148
+ end
149
+
150
+ def getopt(opt, hash, options = nil, &block)
151
+ [opt.to_s, opt.to_s.to_sym].each do |key|
152
+ return hash[key] if hash.has_key?(key)
153
+ end
154
+ default =
155
+ if block
156
+ block.call
157
+ else
158
+ options.is_a?(Hash) ? options[:default] : nil
159
+ end
160
+ return default
161
+ end
162
+
163
+ def subclass_of exception
164
+ class << exception
165
+ def ==(other) super or self > other end
166
+ end
167
+ exception
168
+ end
169
+
170
+ ##
171
+ #
172
+ module_eval(&block)
173
+
174
+ self.setup()
175
+ self.prepare.each{|b| b.call()}
176
+
177
+ at_exit{
178
+ self.teardown()
179
+ self.cleanup.each{|b| b.call()}
180
+ }
181
+
182
+ self
183
+ end
184
+ end
185
+
186
+
187
+ if $0 == __FILE__
188
+
189
+ Testing 'Testing' do
190
+ testing('foo'){ assert true }
191
+ test{ assert true }
192
+ p instance_methods.grep(/test/)
193
+ end
194
+
195
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: systemu
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.2
4
+ version: 2.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-12 00:00:00.000000000 Z
12
+ date: 2012-03-13 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: ! 'description: systemu kicks the ass'
15
15
  email: ara.t.howard@gmail.com
@@ -29,6 +29,8 @@ files:
29
29
  - samples/e.rb
30
30
  - samples/f.rb
31
31
  - systemu.gemspec
32
+ - test/systemu_test.rb
33
+ - test/testing.rb
32
34
  homepage: https://github.com/ahoward/systemu
33
35
  licenses: []
34
36
  post_install_message: