[rubygems/rubygems] Use a constant empty tar header to avoid extra allocations
[ruby.git] / test / test_open3.rb
blob19277c8a66eca6f64c3f4a86f3ebe29729cd3cbf
1 # frozen_string_literal: true
3 require 'test/unit'
4 require 'open3'
6 class TestOpen3 < Test::Unit::TestCase
7   RUBY = EnvUtil.rubybin
9   def test_exit_status
10     Open3.popen3(RUBY, '-e', 'exit true') {|i,o,e,t|
11       assert_equal(true, t.value.success?)
12     }
13     Open3.popen3(RUBY, '-e', 'exit false') {|i,o,e,t|
14       assert_equal(false, t.value.success?)
15     }
16   end
18   def test_stdin
19     Open3.popen3(RUBY, '-e', 'exit STDIN.gets.chomp == "t"') {|i,o,e,t|
20       i.puts 't'
21       assert_equal(true, t.value.success?)
22     }
23     Open3.popen3(RUBY, '-e', 'exit STDIN.gets.chomp == "t"') {|i,o,e,t|
24       i.puts 'f'
25       assert_equal(false, t.value.success?)
26     }
27   end
29   def test_stdout
30     Open3.popen3(RUBY, '-e', 'STDOUT.print "foo"') {|i,o,e,t|
31       assert_equal("foo", o.read)
32     }
33   end
35   def test_stderr
36     Open3.popen3(RUBY, '-e', 'STDERR.print "bar"') {|i,o,e,t|
37       assert_equal("bar", e.read)
38     }
39   end
41   def test_block
42     r = Open3.popen3(RUBY, '-e', 'STDOUT.print STDIN.read') {|i,o,e,t|
43       i.print "baz"
44       i.close
45       assert_equal("baz", o.read)
46       "qux"
47     }
48     assert_equal("qux", r)
49   end
51   def test_noblock
52     i,o,e,t = Open3.popen3(RUBY, '-e', 'STDOUT.print STDIN.read')
53     i.print "baz"
54     i.close
55     assert_equal("baz", o.read)
56   ensure
57     i.close
58     o.close
59     e.close
60     t.join
61   end
63   def test_commandline
64     commandline = "echo quux\n"
65     Open3.popen3(commandline) {|i,o,e,t|
66       assert_equal("quux\n", o.read)
67     }
68   end
70   def test_pid
71     Open3.popen3(RUBY, '-e', 'print $$') {|i,o,e,t|
72       pid = o.read.to_i
73       assert_equal(pid, t[:pid])
74       assert_equal(pid, t.pid)
75     }
76   end
78   def test_env
79     Open3.popen3({'A' => 'B', 'C' => 'D'}, RUBY, '-e' 'p ENV["A"]') do |i, out, err, thr|
80       output = out.read
81       assert_equal("\"B\"\n", output)
82     end
83   end
85   def test_numeric_file_descriptor2
86     with_pipe {|r, w|
87       Open3.popen2(RUBY, '-e', 'STDERR.puts "foo"', 2 => w) {|i,o,t|
88         assert_equal("foo\n", r.gets)
89       }
90     }
91   end
93   def test_numeric_file_descriptor3
94     omit "passing FDs bigger than 2 is not supported on Windows" if /mswin|mingw/ =~ RbConfig::CONFIG['host_os']
95     with_pipe {|r, w|
96       Open3.popen3(RUBY, '-e', 'IO.open(3).puts "foo"', 3 => w) {|i,o,e,t|
97         assert_equal("foo\n", r.gets, "[GH-808] [ruby-core:67347] [Bug #10699]")
98       }
99     }
100   end
102   def with_pipe
103     r, w = IO.pipe
104     yield r, w
105   ensure
106     r.close
107     w.close
108   end
110   def with_reopen(io, arg)
111     old = io.dup
112     io.reopen(arg)
113     yield old
114   ensure
115     io.reopen(old)
116     old.close
117   end
119   def test_popen2
120     with_pipe {|r, w|
121       with_reopen(STDERR, w) {|old|
122         w.close
123         Open3.popen2(RUBY, '-e', 's=STDIN.read; STDOUT.print s+"o"; STDERR.print s+"e"') {|i,o,t|
124           assert_kind_of(Thread, t)
125           i.print "z"
126           i.close
127           STDERR.reopen(old)
128           assert_equal("zo", o.read)
129           assert_equal("ze", r.read)
130         }
131       }
132     }
133   end
135   def test_popen2e
136     with_pipe {|r, w|
137       with_reopen(STDERR, w) {|old|
138         w.close
139         Open3.popen2e(RUBY, '-e', 's=STDIN.read; STDOUT.print s+"o"; STDOUT.flush; STDERR.print s+"e"') {|i,o,t|
140           assert_kind_of(Thread, t)
141           i.print "y"
142           i.close
143           STDERR.reopen(old)
144           assert_equal("yoye", o.read)
145           assert_equal("", r.read)
146         }
147       }
148     }
149   end
151   def test_popen2e_noblock
152     i, o, t = Open3.popen2e(RUBY, '-e', 'STDOUT.print STDIN.read')
153     i.print "baz"
154     i.close
155     assert_equal("baz", o.read)
156   ensure
157     i.close
158     o.close
159     t.join
160   end
162   def test_capture3
163     o, e, s = Open3.capture3(RUBY, '-e', 'i=STDIN.read; print i+"o"; STDOUT.flush; STDERR.print i+"e"', :stdin_data=>"i")
164     assert_equal("io", o)
165     assert_equal("ie", e)
166     assert(s.success?)
167   end
169   def test_capture3_stdin_data_io
170     IO.pipe {|r, w|
171       w.write "i"
172       w.close
173       o, e, s = Open3.capture3(RUBY, '-e', 'i=STDIN.read; print i+"o"; STDOUT.flush; STDERR.print i+"e"', :stdin_data=>r)
174       assert_equal("io", o)
175       assert_equal("ie", e)
176       assert(s.success?)
177     }
178   end
180   def test_capture3_flip
181     o, e, s = Open3.capture3(RUBY, '-e', 'STDOUT.sync=true; 1000.times { print "o"*1000; STDERR.print "e"*1000 }')
182     assert_equal("o"*1000000, o)
183     assert_equal("e"*1000000, e)
184     assert(s.success?)
185   end
187   def test_capture2
188     o, s = Open3.capture2(RUBY, '-e', 'i=STDIN.read; print i+"o"', :stdin_data=>"i")
189     assert_equal("io", o)
190     assert(s.success?)
191   end
193   def test_capture2_stdin_data_io
194     IO.pipe {|r, w|
195       w.write "i"
196       w.close
197       o, s = Open3.capture2(RUBY, '-e', 'i=STDIN.read; print i+"o"', :stdin_data=>r)
198       assert_equal("io", o)
199       assert(s.success?)
200     }
201   end
203   def test_capture2e
204     oe, s = Open3.capture2e(RUBY, '-e', 'i=STDIN.read; print i+"o"; STDOUT.flush; STDERR.print i+"e"', :stdin_data=>"i")
205     assert_equal("ioie", oe)
206     assert(s.success?)
207   end
209   def test_capture2e_stdin_data_io
210     IO.pipe {|r, w|
211       w.write "i"
212       w.close
213       oe, s = Open3.capture2e(RUBY, '-e', 'i=STDIN.read; print i+"o"; STDOUT.flush; STDERR.print i+"e"', :stdin_data=>r)
214       assert_equal("ioie", oe)
215       assert(s.success?)
216     }
217   end
219   def test_capture3_stdin_data
220     o, e, s = Open3.capture3(RUBY, '-e', '', :stdin_data=>"z"*(1024*1024))
221     assert_equal("", o)
222     assert_equal("", e)
223     assert(s.success?)
224   end
226   def test_capture2_stdin_data
227     o, s = Open3.capture2(RUBY, '-e', '', :stdin_data=>"z"*(1024*1024))
228     assert_equal("", o)
229     assert(s.success?)
230   end
232   def test_capture2e_stdin_data
233     oe, s = Open3.capture2e(RUBY, '-e', '', :stdin_data=>"z"*(1024*1024))
234     assert_equal("", oe)
235     assert(s.success?)
236   end
238   def test_pipeline_rw
239     Open3.pipeline_rw([RUBY, '-e', 'print STDIN.read + "1"'],
240                       [RUBY, '-e', 'print STDIN.read + "2"']) {|i,o,ts|
241       assert_kind_of(IO, i)
242       assert_kind_of(IO, o)
243       assert_kind_of(Array, ts)
244       assert_equal(2, ts.length)
245       ts.each {|t| assert_kind_of(Thread, t) }
246       i.print "0"
247       i.close
248       assert_equal("012", o.read)
249       ts.each {|t|
250         assert(t.value.success?)
251       }
252     }
253   end
255   def test_pipeline_r
256     Open3.pipeline_r([RUBY, '-e', 'print "1"'],
257                      [RUBY, '-e', 'print STDIN.read + "2"']) {|o,ts|
258       assert_kind_of(IO, o)
259       assert_kind_of(Array, ts)
260       assert_equal(2, ts.length)
261       ts.each {|t| assert_kind_of(Thread, t) }
262       assert_equal("12", o.read)
263       ts.each {|t|
264         assert(t.value.success?)
265       }
266     }
267   end
269   def test_pipeline_w
270     command = [RUBY, '-e', 's=STDIN.read; print s[1..-1]; exit s[0] == ?t']
271     str = 'ttftff'
272     Open3.pipeline_w(*[command]*str.length) {|i,ts|
273       assert_kind_of(IO, i)
274       assert_kind_of(Array, ts)
275       assert_equal(str.length, ts.length)
276       ts.each {|t| assert_kind_of(Thread, t) }
277       i.print str
278       i.close
279       ts.each_with_index {|t, ii|
280         assert_equal(str[ii] == ?t, t.value.success?)
281       }
282     }
283   end
285   def test_pipeline_start
286     command = [RUBY, '-e', 's=STDIN.read; print s[1..-1]; exit s[0] == ?t']
287     str = 'ttftff'
288     Open3.pipeline_start([RUBY, '-e', 'print ARGV[0]', str],
289                          *([command]*str.length)) {|ts|
290       assert_kind_of(Array, ts)
291       assert_equal(str.length+1, ts.length)
292       ts.each {|t| assert_kind_of(Thread, t) }
293       ts.each_with_index {|t, i|
294         if i == 0
295           assert(t.value.success?)
296         else
297           assert_equal(str[i-1] == ?t, t.value.success?)
298         end
299       }
300     }
301   end
303   def test_pipeline_start_noblock
304     ts = Open3.pipeline_start([RUBY, '-e', ''])
305     assert_kind_of(Array, ts)
306     assert_equal(1, ts.length)
307     ts.each {|t| assert_kind_of(Thread, t) }
308     t = ts[0]
309     assert(t.value.success?)
310   end
312   def test_pipeline
313     command = [RUBY, '-e', 's=STDIN.read; print s[1..-1]; exit s[0] == ?t']
314     str = 'ttftff'
315     ss = Open3.pipeline([RUBY, '-e', 'print ARGV[0]', str],
316                         *([command]*str.length))
317     assert_kind_of(Array, ss)
318     assert_equal(str.length+1, ss.length)
319     ss.each {|s| assert_kind_of(Process::Status, s) }
320     ss.each_with_index {|s, i|
321       if i == 0
322         assert(s.success?)
323       else
324         assert_equal(str[i-1] == ?t, s.success?)
325       end
326     }
327   end
329   def test_integer_and_symbol_key
330     command = [RUBY, '-e', 'puts "test_integer_and_symbol_key"']
331     out, status = Open3.capture2(*command, :chdir => '.', 2 => IO::NULL)
332     assert_equal("test_integer_and_symbol_key\n", out)
333     assert_predicate(status, :success?)
334   end