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