Created
January 29, 2016 15:51
-
-
Save ahmadsherif/998858e65899716edd7d to your computer and use it in GitHub Desktop.
ARGF#read_nonblock
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/kernel/common/argf.rb b/kernel/common/argf.rb | |
index c9f80dd..c710116 100644 | |
--- a/kernel/common/argf.rb | |
+++ b/kernel/common/argf.rb | |
@@ -402,6 +402,33 @@ module Rubinius | |
alias_method :to_a, :readlines | |
+ def read_nonblock(maxlen, output=nil, opts={}) | |
+ if output.is_a?(Hash) | |
+ opts = output | |
+ output = nil | |
+ end | |
+ | |
+ output ||= default_value | |
+ | |
+ unless advance! | |
+ output.clear | |
+ raise EOFError, "ARGF at end" | |
+ end | |
+ | |
+ begin | |
+ ret = @stream.read_nonblock(maxlen, output, opts) | |
+ return ret unless ret.is_a?(Hash) | |
+ rescue EOFError => e | |
+ raise e if @use_stdin_only | |
+ | |
+ @stream.close | |
+ @advance = true | |
+ advance! or raise e | |
+ end | |
+ | |
+ return output | |
+ end | |
+ | |
def readpartial(maxlen, output=nil) | |
output ||= default_value | |
diff --git a/spec/custom/helpers/ruby_exe_pipe.rb b/spec/custom/helpers/ruby_exe_pipe.rb | |
new file mode 100644 | |
index 0000000..6ac99d0 | |
--- /dev/null | |
+++ b/spec/custom/helpers/ruby_exe_pipe.rb | |
@@ -0,0 +1,9 @@ | |
+class Object | |
+ def ruby_exe_pipe(code, opts={}) | |
+ pipe_mode = opts.delete(:pipe_mode) || 'r' | |
+ f = IO.popen(ruby_cmd(code, opts), pipe_mode) | |
+ yield f | |
+ ensure | |
+ f.close if f && !f.closed? | |
+ end | |
+end | |
diff --git a/spec/custom/mspec.rb b/spec/custom/mspec.rb | |
index ee009a1..229d6b2 100644 | |
--- a/spec/custom/mspec.rb | |
+++ b/spec/custom/mspec.rb | |
@@ -13,3 +13,4 @@ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' | |
end | |
require 'spec/custom/utils/script' | |
+require 'spec/custom/helpers/ruby_exe_pipe' | |
diff --git a/spec/ruby/core/argf/read_nonblock_spec.rb b/spec/ruby/core/argf/read_nonblock_spec.rb | |
new file mode 100644 | |
index 0000000..7a53161 | |
--- /dev/null | |
+++ b/spec/ruby/core/argf/read_nonblock_spec.rb | |
@@ -0,0 +1,78 @@ | |
+require File.expand_path('../../../spec_helper', __FILE__) | |
+require File.expand_path('../shared/read', __FILE__) | |
+require File.expand_path('../shared/readpartial', __FILE__) | |
+ | |
+describe "ARGF.read_nonblock" do | |
+ it_behaves_like :argf_read, :read_nonblock | |
+ it_behaves_like :argf_readpartial, :read_nonblock | |
+ | |
+ context "when ARGF is not readable yet" do | |
+ context "when exception option is not passed" do | |
+ it "raises an IO::WaitReadable exception if ARGF is not readable yet" do | |
+ output = ruby_exe <<-STR, escape: true | |
+ begin | |
+ ARGF.read_nonblock(1) | |
+ rescue IO::WaitReadable => e | |
+ print "IO::WaitReadable raised" | |
+ end | |
+ STR | |
+ output.should == "IO::WaitReadable raised" | |
+ end | |
+ end | |
+ | |
+ context "when exception option is set to false" do | |
+ it "returns :wait_readable" do | |
+ ruby_exe("print ARGF.read_nonblock(1, exception: false).inspect").should == ":wait_readable" | |
+ end | |
+ end | |
+ end | |
+ | |
+ context "when there is nothing more to read" do | |
+ context "when exception option is not passed" do | |
+ it "raises EOFError when there is nothing more to read" do | |
+ ruby_exe_pipe(<<-STR, escape: true, pipe_mode: "r+") do |f| | |
+ $stdout.sync | |
+ begin | |
+ ARGF.read_nonblock(1) | |
+ rescue EOFError | |
+ print "EOFError raised" | |
+ end | |
+ STR | |
+ f.close_write | |
+ f.read.should == "EOFError raised" | |
+ end | |
+ end | |
+ end | |
+ | |
+ context "when exception option is set to false" do | |
+ it "returns nil" do | |
+ ruby_exe_pipe(<<-STR, escape: true, pipe_mode: "r+") do |f| | |
+ $stdout.sync | |
+ print ARGF.read_nonblock(1, exception: false).inspect | |
+ STR | |
+ f.close_write | |
+ f.read.should == "nil" | |
+ end | |
+ end | |
+ end | |
+ end | |
+ | |
+ it "reads a maximum number of bytes once it is ready for reading" do | |
+ ruby_exe_pipe("print ARGF.read_nonblock(1)", escape: true, pipe_mode: "r+") do |f| | |
+ f.write("a") | |
+ f.read(1).should == "a" | |
+ end | |
+ end | |
+ | |
+ context "when exception option is set to false" do | |
+ it "raises an EOFError if the exception was raised while reading the last file" do | |
+ argv [@file1_name, @file2_name] do | |
+ ARGF.send(@method, @file1.size) | |
+ ARGF.send(@method, 1) | |
+ ARGF.send(@method, @file2.size) | |
+ ARGF.send(@method, 1, exception: false).should be_nil | |
+ lambda { ARGF.send(@method, 1, exception: false) }.should raise_error(EOFError) | |
+ end | |
+ end | |
+ end | |
+end | |
diff --git a/spec/ruby/core/argf/readpartial_spec.rb b/spec/ruby/core/argf/readpartial_spec.rb | |
index bd3f8d9..237956b 100644 | |
--- a/spec/ruby/core/argf/readpartial_spec.rb | |
+++ b/spec/ruby/core/argf/readpartial_spec.rb | |
@@ -1,75 +1,8 @@ | |
require File.expand_path('../../../spec_helper', __FILE__) | |
require File.expand_path('../shared/read', __FILE__) | |
+require File.expand_path('../shared/readpartial', __FILE__) | |
describe "ARGF.readpartial" do | |
it_behaves_like :argf_read, :readpartial | |
- | |
- before :each do | |
- @file1_name = fixture __FILE__, "file1.txt" | |
- @file2_name = fixture __FILE__, "file2.txt" | |
- @stdin_name = fixture __FILE__, "stdin.txt" | |
- | |
- @file1 = File.read @file1_name | |
- @file2 = File.read @file2_name | |
- @stdin = File.read @stdin_name | |
- end | |
- | |
- it "raises an ArgumentError if called without a maximum read length" do | |
- argv [@file1_name] do | |
- lambda { ARGF.readpartial }.should raise_error(ArgumentError) | |
- end | |
- end | |
- | |
- it "reads maximum number of bytes from one file at a time" do | |
- argv [@file1_name, @file2_name] do | |
- len = @file1.size + @file2.size | |
- ARGF.readpartial(len).should == @file1 | |
- end | |
- end | |
- | |
- it "clears output buffer even if EOFError is raised because ARGF is at end" do | |
- begin | |
- output = "to be cleared" | |
- | |
- argv [@file1_name] do | |
- ARGF.read | |
- ARGF.readpartial(1, output) | |
- end | |
- rescue EOFError | |
- output.should == "" | |
- end | |
- end | |
- | |
- it "reads maximum number of bytes from one file at a time" do | |
- argv [@file1_name, @file2_name] do | |
- len = @file1.size + @file2.size | |
- ARGF.readpartial(len).should == @file1 | |
- end | |
- end | |
- | |
- it "returns an empty string if EOFError is raised while reading any but the last file" do | |
- argv [@file1_name, @file2_name] do | |
- ARGF.readpartial(@file1.size) | |
- ARGF.readpartial(1).should == "" | |
- end | |
- end | |
- | |
- it "raises an EOFError if the exception was raised while reading the last file" do | |
- argv [@file1_name, @file2_name] do | |
- ARGF.readpartial(@file1.size) | |
- ARGF.readpartial(1) | |
- ARGF.readpartial(@file2.size) | |
- lambda { ARGF.readpartial(1) }.should raise_error(EOFError) | |
- lambda { ARGF.readpartial(1) }.should raise_error(EOFError) | |
- end | |
- end | |
- | |
- it "raises an EOFError if the exception was raised while reading STDIN" do | |
- ruby_str = <<-STR | |
- print ARGF.readpartial(#{@stdin.size}) | |
- ARGF.readpartial(1) rescue print $!.class | |
- STR | |
- stdin = ruby_exe(ruby_str, args: "< #{@stdin_name}", escape: true) | |
- stdin.should == @stdin + "EOFError" | |
- end | |
+ it_behaves_like :argf_readpartial, :readpartial | |
end | |
diff --git a/spec/ruby/core/argf/shared/readpartial.rb b/spec/ruby/core/argf/shared/readpartial.rb | |
new file mode 100644 | |
index 0000000..bd777c1 | |
--- /dev/null | |
+++ b/spec/ruby/core/argf/shared/readpartial.rb | |
@@ -0,0 +1,70 @@ | |
+describe :argf_readpartial, shared: true do | |
+ before :each do | |
+ @file1_name = fixture __FILE__, "file1.txt" | |
+ @file2_name = fixture __FILE__, "file2.txt" | |
+ @stdin_name = fixture __FILE__, "stdin.txt" | |
+ | |
+ @file1 = File.read @file1_name | |
+ @file2 = File.read @file2_name | |
+ @stdin = File.read @stdin_name | |
+ end | |
+ | |
+ it "raises an ArgumentError if called without a maximum read length" do | |
+ argv [@file1_name] do | |
+ lambda { ARGF.send(@method) }.should raise_error(ArgumentError) | |
+ end | |
+ end | |
+ | |
+ it "reads maximum number of bytes from one file at a time" do | |
+ argv [@file1_name, @file2_name] do | |
+ len = @file1.size + @file2.size | |
+ ARGF.send(@method, len).should == @file1 | |
+ end | |
+ end | |
+ | |
+ it "clears output buffer even if EOFError is raised because ARGF is at end" do | |
+ begin | |
+ output = "to be cleared" | |
+ | |
+ argv [@file1_name] do | |
+ ARGF.read | |
+ ARGF.send(@method, 1, output) | |
+ end | |
+ rescue EOFError | |
+ output.should == "" | |
+ end | |
+ end | |
+ | |
+ it "reads maximum number of bytes from one file at a time" do | |
+ argv [@file1_name, @file2_name] do | |
+ len = @file1.size + @file2.size | |
+ ARGF.send(@method, len).should == @file1 | |
+ end | |
+ end | |
+ | |
+ it "returns an empty string if EOFError is raised while reading any but the last file" do | |
+ argv [@file1_name, @file2_name] do | |
+ ARGF.send(@method, @file1.size) | |
+ ARGF.send(@method, 1).should == "" | |
+ end | |
+ end | |
+ | |
+ it "raises an EOFError if the exception was raised while reading the last file" do | |
+ argv [@file1_name, @file2_name] do | |
+ ARGF.send(@method, @file1.size) | |
+ ARGF.send(@method, 1) | |
+ ARGF.send(@method, @file2.size) | |
+ lambda { ARGF.send(@method, 1) }.should raise_error(EOFError) | |
+ lambda { ARGF.send(@method, 1) }.should raise_error(EOFError) | |
+ end | |
+ end | |
+ | |
+ it "raises an EOFError if the exception was raised while reading STDIN" do | |
+ ruby_str = <<-STR | |
+ print ARGF.#{@method}(#{@stdin.size}) | |
+ ARGF.#{@method}(1) rescue print $!.class | |
+ STR | |
+ stdin = ruby_exe(ruby_str, args: "< #{@stdin_name}", escape: true) | |
+ stdin.should == @stdin + "EOFError" | |
+ end | |
+end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment