diff options
author | Benoit Daloze <eregontp@gmail.com> | 2021-10-05 19:41:44 +0200 |
---|---|---|
committer | Benoit Daloze <eregontp@gmail.com> | 2021-10-05 19:41:44 +0200 |
commit | b9f34062f00d1d2548ca9b6af61a6447c2d0f8e3 (patch) | |
tree | 37c7600088a5e080b2f35794b0923395daf036d0 | |
parent | afcbb501ac17ba2ad5370ada5fd26e8dda9a5aaa (diff) | |
download | ruby-b9f34062f00d1d2548ca9b6af61a6447c2d0f8e3.tar.gz |
Update to ruby/spec@ccf0d85
28 files changed, 692 insertions, 31 deletions
diff --git a/spec/ruby/core/dir/fixtures/common.rb b/spec/ruby/core/dir/fixtures/common.rb index 1a197d7a97..c32b056819 100644 --- a/spec/ruby/core/dir/fixtures/common.rb +++ b/spec/ruby/core/dir/fixtures/common.rb @@ -92,6 +92,7 @@ module DirSpecs special/| special/こんにちは.txt + special/\a ] end end diff --git a/spec/ruby/core/dir/shared/glob.rb b/spec/ruby/core/dir/shared/glob.rb index 89d6b90283..d2824df446 100644 --- a/spec/ruby/core/dir/shared/glob.rb +++ b/spec/ruby/core/dir/shared/glob.rb @@ -80,6 +80,10 @@ describe :dir_glob, shared: true do it "matches regexp special |" do Dir.send(@method, 'special/|').should == ['special/|'] end + + it "matches files with backslashes in their name" do + Dir.glob('special/\\\\{a,b}').should == ['special/\a'] + end end it "matches regexp special ^" do diff --git a/spec/ruby/core/encoding/default_external_spec.rb b/spec/ruby/core/encoding/default_external_spec.rb index e2cb9b02f4..682d49d37c 100644 --- a/spec/ruby/core/encoding/default_external_spec.rb +++ b/spec/ruby/core/encoding/default_external_spec.rb @@ -17,6 +17,14 @@ describe "Encoding.default_external" do Encoding.default_external = Encoding::SHIFT_JIS Encoding.default_external.should == Encoding::SHIFT_JIS end + + ruby_version_is "3.0" do + platform_is :windows do + it 'is UTF-8 by default on Windows' do + Encoding.default_external.should == Encoding::UTF_8 + end + end + end end describe "Encoding.default_external=" do diff --git a/spec/ruby/core/enumerable/shared/collect.rb b/spec/ruby/core/enumerable/shared/collect.rb index 32c1722c75..6df1a616eb 100644 --- a/spec/ruby/core/enumerable/shared/collect.rb +++ b/spec/ruby/core/enumerable/shared/collect.rb @@ -89,5 +89,19 @@ describe :enumerable_collect, shared: true do end.should raise_error(ArgumentError) end + it "calls the each method on sub-classes" do + c = Class.new(Hash) do + def each + ScratchPad << 'in each' + super + end + end + h = c.new + h[1] = 'a' + ScratchPad.record [] + h.send(@method) { |k,v| v } + ScratchPad.recorded.should == ['in each'] + end + it_should_behave_like :enumerable_enumeratorized_with_origin_size end diff --git a/spec/ruby/core/file/utime_spec.rb b/spec/ruby/core/file/utime_spec.rb index 19cb80d5f8..45a51490e4 100644 --- a/spec/ruby/core/file/utime_spec.rb +++ b/spec/ruby/core/file/utime_spec.rb @@ -70,6 +70,15 @@ describe "File.utime" do end end + platform_is_not :windows do + it "sets nanosecond precision" do + t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789r) + File.utime(t, t, @file1) + File.atime(@file1).nsec.should == 123456789 + File.mtime(@file1).nsec.should == 123456789 + end + end + platform_is :linux do platform_is wordsize: 64 do it "allows Time instances in the far future to set mtime and atime (but some filesystems limit it up to 2446-05-10 or 2038-01-19)" do diff --git a/spec/ruby/core/kernel/shared/sprintf.rb b/spec/ruby/core/kernel/shared/sprintf.rb index 6d62a65f7c..84d472b0d1 100644 --- a/spec/ruby/core/kernel/shared/sprintf.rb +++ b/spec/ruby/core/kernel/shared/sprintf.rb @@ -320,6 +320,10 @@ describe :kernel_sprintf, shared: true do @method.call("%s", "abc").should == "abc" end + it "substitutes '' for nil" do + @method.call("%s", nil).should == "" + end + it "converts argument to string with to_s" do obj = mock("string") obj.should_receive(:to_s).and_return("abc") @@ -348,6 +352,28 @@ describe :kernel_sprintf, shared: true do Kernel.format("%-3.3s", "hello").should == "hel" end + it "formats string with width" do + @method.call("%6s", "abc").should == " abc" + @method.call("%6s", "abcdefg").should == "abcdefg" + end + + it "formats string with width and precision" do + @method.call("%4.6s", "abc").should == " abc" + @method.call("%4.6s", "abcdefg").should == "abcdef" + end + + it "formats nli with width" do + @method.call("%6s", nil).should == " " + end + + it "formats nli with precision" do + @method.call("%.6s", nil).should == "" + end + + it "formats nil with width and precision" do + @method.call("%4.6s", nil).should == " " + end + it "formats multibyte string with precision" do Kernel.format("%.2s", "été").should == "ét" end diff --git a/spec/ruby/core/marshal/shared/load.rb b/spec/ruby/core/marshal/shared/load.rb index e04a30c02f..b70bca55bf 100644 --- a/spec/ruby/core/marshal/shared/load.rb +++ b/spec/ruby/core/marshal/shared/load.rb @@ -97,8 +97,8 @@ describe :marshal_load, shared: true do :b, :c, 2, a, false, "ant", ["hi", 10, "hi", "hi", st, [:a, :b, :c]], ] - arr.each do |obj| - obj.should.frozen? + arr.each do |v| + v.should.frozen? end Struct.send(:remove_const, :Brittle) diff --git a/spec/ruby/core/objectspace/garbage_collect_spec.rb b/spec/ruby/core/objectspace/garbage_collect_spec.rb index 1aec3ea072..521eaa8785 100644 --- a/spec/ruby/core/objectspace/garbage_collect_spec.rb +++ b/spec/ruby/core/objectspace/garbage_collect_spec.rb @@ -6,8 +6,8 @@ describe "ObjectSpace.garbage_collect" do -> { ObjectSpace.garbage_collect }.should_not raise_error end - it "doesn't accept any arguments" do - -> { ObjectSpace.garbage_collect(1) }.should raise_error(ArgumentError) + it "accepts keyword arguments" do + ObjectSpace.garbage_collect(full_mark: true, immediate_sweep: true).should == nil end it "ignores the supplied block" do diff --git a/spec/ruby/core/string/lstrip_spec.rb b/spec/ruby/core/string/lstrip_spec.rb index 6b40189500..20e4cdeabd 100644 --- a/spec/ruby/core/string/lstrip_spec.rb +++ b/spec/ruby/core/string/lstrip_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' +require_relative 'shared/strip' describe "String#lstrip" do + it_behaves_like :string_strip, :lstrip + it "returns a copy of self with leading whitespace removed" do " hello ".lstrip.should == "hello " " hello world ".lstrip.should == "hello world " diff --git a/spec/ruby/core/string/partition_spec.rb b/spec/ruby/core/string/partition_spec.rb index 996368d6a4..98311f2be4 100644 --- a/spec/ruby/core/string/partition_spec.rb +++ b/spec/ruby/core/string/partition_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' +require_relative 'shared/partition' describe "String#partition with String" do + it_behaves_like :string_partition, :partition + it "returns an array of substrings based on splitting on the given string" do "hello world".partition("o").should == ["hell", "o", " world"] end diff --git a/spec/ruby/core/string/reverse_spec.rb b/spec/ruby/core/string/reverse_spec.rb index cf4956a528..b45ff2cf6f 100644 --- a/spec/ruby/core/string/reverse_spec.rb +++ b/spec/ruby/core/string/reverse_spec.rb @@ -10,6 +10,22 @@ describe "String#reverse" do "".reverse.should == "" end + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("stressed").reverse.should be_an_instance_of(String) + StringSpecs::MyString.new("m").reverse.should be_an_instance_of(String) + StringSpecs::MyString.new("").reverse.should be_an_instance_of(String) + end + end + + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("stressed").reverse.should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("m").reverse.should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("").reverse.should be_an_instance_of(StringSpecs::MyString) + end + end + ruby_version_is ''...'2.7' do it "taints the result if self is tainted" do "".taint.reverse.should.tainted? @@ -20,7 +36,6 @@ describe "String#reverse" do it "reverses a string with multi byte characters" do "微軟正黑體".reverse.should == "體黑正軟微" end - end describe "String#reverse!" do diff --git a/spec/ruby/core/string/rpartition_spec.rb b/spec/ruby/core/string/rpartition_spec.rb index fc37f8b427..c8f9afaee9 100644 --- a/spec/ruby/core/string/rpartition_spec.rb +++ b/spec/ruby/core/string/rpartition_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' +require_relative 'shared/partition' describe "String#rpartition with String" do + it_behaves_like :string_partition, :rpartition + it "returns an array of substrings based on splitting on the given string" do "hello world".rpartition("o").should == ["hello w", "o", "rld"] end diff --git a/spec/ruby/core/string/rstrip_spec.rb b/spec/ruby/core/string/rstrip_spec.rb index 57e1867956..a1453f91fe 100644 --- a/spec/ruby/core/string/rstrip_spec.rb +++ b/spec/ruby/core/string/rstrip_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' +require_relative 'shared/strip' describe "String#rstrip" do + it_behaves_like :string_strip, :rstrip + it "returns a copy of self with trailing whitespace removed" do " hello ".rstrip.should == " hello" " hello world ".rstrip.should == " hello world" diff --git a/spec/ruby/core/string/scrub_spec.rb b/spec/ruby/core/string/scrub_spec.rb index 5c67ad01bc..4da44a7992 100644 --- a/spec/ruby/core/string/scrub_spec.rb +++ b/spec/ruby/core/string/scrub_spec.rb @@ -1,5 +1,6 @@ # -*- encoding: utf-8 -*- require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "String#scrub with a default replacement" do it "returns self for valid strings" do @@ -19,12 +20,25 @@ describe "String#scrub with a default replacement" do input.scrub.should == "foo" end - it "replaces invalid byte sequences when using ASCII as the input encoding" do xE3x80 = [0xE3, 0x80].pack('CC').force_encoding 'utf-8' input = "abc\u3042#{xE3x80}".force_encoding('ASCII') input.scrub.should == "abc?????" end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("foo").scrub.should be_an_instance_of(String) + input = [0x81].pack('C').force_encoding('utf-8') + StringSpecs::MyString.new(input).scrub.should be_an_instance_of(String) + end + end + + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("foo").scrub.should be_an_instance_of(StringSpecs::MyString) + end + end end describe "String#scrub with a custom replacement" do @@ -65,6 +79,14 @@ describe "String#scrub with a custom replacement" do block.should raise_error(TypeError) end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("foo").scrub("*").should be_an_instance_of(String) + input = [0x81].pack('C').force_encoding('utf-8') + StringSpecs::MyString.new(input).scrub("*").should be_an_instance_of(String) + end + end end describe "String#scrub with a block" do @@ -89,6 +111,14 @@ describe "String#scrub with a block" do replaced.should == "€€" end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("foo").scrub { |b| "*" }.should be_an_instance_of(String) + input = [0x81].pack('C').force_encoding('utf-8') + StringSpecs::MyString.new(input).scrub { |b| "<#{b.unpack("H*")[0]}>" }.should be_an_instance_of(String) + end + end end describe "String#scrub!" do diff --git a/spec/ruby/core/string/shared/partition.rb b/spec/ruby/core/string/shared/partition.rb new file mode 100644 index 0000000000..7dc3d9cc0b --- /dev/null +++ b/spec/ruby/core/string/shared/partition.rb @@ -0,0 +1,36 @@ +require_relative '../../../spec_helper' +require_relative '../fixtures/classes' + +describe :string_partition, shared: true do + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("hello").send(@method, "l").each do |item| + item.should be_an_instance_of(String) + end + + StringSpecs::MyString.new("hello").send(@method, "x").each do |item| + item.should be_an_instance_of(String) + end + + StringSpecs::MyString.new("hello").send(@method, /l./).each do |item| + item.should be_an_instance_of(String) + end + end + end + + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("hello").send(@method, StringSpecs::MyString.new("l")).each do |item| + item.should be_an_instance_of(StringSpecs::MyString) + end + + StringSpecs::MyString.new("hello").send(@method, "x").each do |item| + item.should be_an_instance_of(StringSpecs::MyString) + end + + StringSpecs::MyString.new("hello").send(@method, /l./).each do |item| + item.should be_an_instance_of(StringSpecs::MyString) + end + end + end +end diff --git a/spec/ruby/core/string/shared/strip.rb b/spec/ruby/core/string/shared/strip.rb new file mode 100644 index 0000000000..9c232b4694 --- /dev/null +++ b/spec/ruby/core/string/shared/strip.rb @@ -0,0 +1,20 @@ +require_relative '../../../spec_helper' +require_relative '../fixtures/classes' + +describe :string_strip, shared: true do + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new(" hello ").send(@method).should be_an_instance_of(String) + StringSpecs::MyString.new(" ").send(@method).should be_an_instance_of(String) + StringSpecs::MyString.new("").send(@method).should be_an_instance_of(String) + end + end + + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new(" hello ").send(@method).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new(" ").send(@method).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("").send(@method).should be_an_instance_of(StringSpecs::MyString) + end + end +end diff --git a/spec/ruby/core/string/strip_spec.rb b/spec/ruby/core/string/strip_spec.rb index 463a9fedf3..8517bf2d2a 100644 --- a/spec/ruby/core/string/strip_spec.rb +++ b/spec/ruby/core/string/strip_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' +require_relative 'shared/strip' describe "String#strip" do + it_behaves_like :string_strip, :strip + it "returns a new string with leading and trailing whitespace removed" do " hello ".strip.should == "hello" " hello world ".strip.should == "hello world" diff --git a/spec/ruby/language/defined_spec.rb b/spec/ruby/language/defined_spec.rb index f2da8a9293..38345c3727 100644 --- a/spec/ruby/language/defined_spec.rb +++ b/spec/ruby/language/defined_spec.rb @@ -5,21 +5,25 @@ describe "The defined? keyword for literals" do it "returns 'self' for self" do ret = defined?(self) ret.should == "self" + ret.frozen?.should == true end it "returns 'nil' for nil" do ret = defined?(nil) ret.should == "nil" + ret.frozen?.should == true end it "returns 'true' for true" do ret = defined?(true) ret.should == "true" + ret.frozen?.should == true end it "returns 'false' for false" do ret = defined?(false) ret.should == "false" + ret.frozen?.should == true end describe "for a literal Array" do @@ -27,6 +31,7 @@ describe "The defined? keyword for literals" do it "returns 'expression' if each element is defined" do ret = defined?([Object, Array]) ret.should == "expression" + ret.frozen?.should == true end it "returns nil if one element is not defined" do @@ -45,7 +50,9 @@ end describe "The defined? keyword when called with a method name" do describe "without a receiver" do it "returns 'method' if the method is defined" do - defined?(puts).should == "method" + ret = defined?(puts) + ret.should == "method" + ret.frozen?.should == true end it "returns nil if the method is not defined" do @@ -167,7 +174,9 @@ describe "The defined? keyword for an expression" do end it "returns 'assignment' for assigning a local variable" do - defined?(x = 2).should == "assignment" + ret = defined?(x = 2) + ret.should == "assignment" + ret.frozen?.should == true end it "returns 'assignment' for assigning an instance variable" do @@ -470,7 +479,9 @@ end describe "The defined? keyword for variables" do it "returns 'local-variable' when called with the name of a local variable" do - DefinedSpecs::Basic.new.local_variable_defined.should == "local-variable" + ret = DefinedSpecs::Basic.new.local_variable_defined + ret.should == "local-variable" + ret.frozen?.should == true end it "returns 'local-variable' when called with the name of a local variable assigned to nil" do @@ -486,7 +497,9 @@ describe "The defined? keyword for variables" do end it "returns 'instance-variable' for an instance variable that has been assigned" do - DefinedSpecs::Basic.new.instance_variable_defined.should == "instance-variable" + ret = DefinedSpecs::Basic.new.instance_variable_defined + ret.should == "instance-variable" + ret.frozen?.should == true end it "returns 'instance-variable' for an instance variable that has been assigned to nil" do @@ -502,7 +515,9 @@ describe "The defined? keyword for variables" do end it "returns 'global-variable' for a global variable that has been assigned nil" do - DefinedSpecs::Basic.new.global_variable_defined_as_nil.should == "global-variable" + ret = DefinedSpecs::Basic.new.global_variable_defined_as_nil + ret.should == "global-variable" + ret.frozen?.should == true end # MRI appears to special case defined? for $! and $~ in that it returns @@ -674,7 +689,9 @@ describe "The defined? keyword for variables" do # get to the defined? call so it really has nothing to do with 'defined?'. it "returns 'class variable' when called with the name of a class variable" do - DefinedSpecs::Basic.new.class_variable_defined.should == "class variable" + ret = DefinedSpecs::Basic.new.class_variable_defined + ret.should == "class variable" + ret.frozen?.should == true end it "returns 'local-variable' when called with the name of a block local" do @@ -685,7 +702,9 @@ end describe "The defined? keyword for a simple constant" do it "returns 'constant' when the constant is defined" do - defined?(DefinedSpecs).should == "constant" + ret = defined?(DefinedSpecs) + ret.should == "constant" + ret.frozen?.should == true end it "returns nil when the constant is not defined" do @@ -941,12 +960,26 @@ describe "The defined? keyword for yield" do end it "returns 'yield' if a block is passed to a method not taking a block parameter" do - DefinedSpecs::Basic.new.yield_block.should == "yield" + ret = DefinedSpecs::Basic.new.yield_block + ret.should == "yield" + ret.frozen?.should == true end it "returns 'yield' if a block is passed to a method taking a block parameter" do DefinedSpecs::Basic.new.yield_block_parameter.should == "yield" end + + it "returns 'yield' when called within a block" do + def yielder + yield + end + + def call_defined + yielder { defined?(yield) } + end + + call_defined() { }.should == "yield" + end end describe "The defined? keyword for super" do @@ -972,7 +1005,9 @@ describe "The defined? keyword for super" do end it "returns 'super' when a superclass method exists" do - DefinedSpecs::Super.new.method_no_args.should == "super" + ret = DefinedSpecs::Super.new.method_no_args + ret.should == "super" + ret.frozen?.should == true end it "returns 'super' from a block when a superclass method exists" do diff --git a/spec/ruby/language/predefined_spec.rb b/spec/ruby/language/predefined_spec.rb index 24a8cf2f67..417afea537 100644 --- a/spec/ruby/language/predefined_spec.rb +++ b/spec/ruby/language/predefined_spec.rb @@ -1099,6 +1099,8 @@ The following constants are defined by the Ruby interpreter. DATA IO If the main program file contains the directive __END__, then the constant DATA will be initialized so that reading from it will return lines following __END__ from the source file. +FALSE FalseClass Synonym for false (deprecated, removed in Ruby 3). +NIL NilClass Synonym for nil (deprecated, removed in Ruby 3). RUBY_PLATFORM String The identifier of the platform running this program. This string is in the same form as the platform identifier used by the GNU configure utility (which is not a coincidence). @@ -1116,9 +1118,55 @@ SCRIPT_LINES__ Hash If a constant SCRIPT_LINES__ is defined and ref the value. TOPLEVEL_BINDING Binding A Binding object representing the binding at Ruby’s top level— the level where programs are initially executed. +TRUE TrueClass Synonym for true (deprecated, removed in Ruby 3). =end describe "The predefined global constants" do + describe "TRUE" do + ruby_version_is "3.0" do + it "is no longer defined" do + Object.const_defined?(:TRUE).should == false + end + end + + ruby_version_is ""..."3.0" do + it "includes TRUE" do + Object.const_defined?(:TRUE).should == true + -> { TRUE }.should complain(/constant ::TRUE is deprecated/) + end + end + end + + describe "FALSE" do + ruby_version_is "3.0" do + it "is no longer defined" do + Object.const_defined?(:FALSE).should == false + end + end + + ruby_version_is ""..."3.0" do + it "includes FALSE" do + Object.const_defined?(:FALSE).should == true + -> { FALSE }.should complain(/constant ::FALSE is deprecated/) + end + end + end + + describe "NIL" do + ruby_version_is "3.0" do + it "is no longer defined" do + Object.const_defined?(:NIL).should == false + end + end + + ruby_version_is ""..."3.0" do + it "includes NIL" do + Object.const_defined?(:NIL).should == true + -> { NIL }.should complain(/constant ::NIL is deprecated/) + end + end + end + it "includes STDIN" do Object.const_defined?(:STDIN).should == true end @@ -1146,7 +1194,6 @@ describe "The predefined global constants" do it "includes TOPLEVEL_BINDING" do Object.const_defined?(:TOPLEVEL_BINDING).should == true end - end describe "The predefined global constant" do diff --git a/spec/ruby/library/net/http/http/fixtures/http_server.rb b/spec/ruby/library/net/http/http/fixtures/http_server.rb index 63543b46a9..c1cedbfa76 100644 --- a/spec/ruby/library/net/http/http/fixtures/http_server.rb +++ b/spec/ruby/library/net/http/http/fixtures/http_server.rb @@ -11,29 +11,23 @@ module NetHTTPSpecs class SmallHTTPServer def initialize(bind_address) @server = TCPServer.new(bind_address, 0) - @running = Mutex.new @thread = Thread.new { Thread.current.abort_on_exception = true listen } end + def ip + @server.addr[3] + end + def port @server.addr[1] end def listen - loop do - begin - client = @server.accept - rescue IOError => e - if @running.locked? # close - break - else - raise e - end - end - + until @server.closed? + client = @server.accept handle_client(client) end end @@ -43,6 +37,10 @@ module NetHTTPSpecs until client.closed? request = client.gets("\r\n\r\n") break unless request + if request == "CLOSE" + @server.close + break + end handle_request(client, request) end ensure @@ -95,8 +93,9 @@ module NetHTTPSpecs end def close - @running.lock - @server.close + TCPSocket.open(ip, port) do |socket| + socket.write "CLOSE" + end @thread.join end end diff --git a/spec/ruby/library/rbconfig/rbconfig_spec.rb b/spec/ruby/library/rbconfig/rbconfig_spec.rb index e1fd84de91..b90cc90970 100644 --- a/spec/ruby/library/rbconfig/rbconfig_spec.rb +++ b/spec/ruby/library/rbconfig/rbconfig_spec.rb @@ -42,6 +42,17 @@ describe 'RbConfig::CONFIG' do RUBY end + platform_is_not :windows do + it "['LIBRUBY'] is the same as LIBRUBY_SO if and only if ENABLE_SHARED" do + case RbConfig::CONFIG['ENABLE_SHARED'] + when 'yes' + RbConfig::CONFIG['LIBRUBY'].should == RbConfig::CONFIG['LIBRUBY_SO'] + when 'no' + RbConfig::CONFIG['LIBRUBY'].should_not == RbConfig::CONFIG['LIBRUBY_SO'] + end + end + end + guard -> { RbConfig::TOPDIR } do it "libdir/LIBRUBY_SO is the path to libruby and it exists if and only if ENABLE_SHARED" do libdirname = RbConfig::CONFIG['LIBPATHENV'] == 'PATH' ? 'bindir' : diff --git a/spec/ruby/library/socket/basicsocket/local_address_spec.rb b/spec/ruby/library/socket/basicsocket/local_address_spec.rb new file mode 100644 index 0000000000..0bd60a44cd --- /dev/null +++ b/spec/ruby/library/socket/basicsocket/local_address_spec.rb @@ -0,0 +1,10 @@ +require_relative '../spec_helper' +require_relative '../shared/address' + +describe 'BasicSocket#local_address' do + it_behaves_like :socket_local_remote_address, :local_address, -> socket { + a2 = BasicSocket.for_fd(socket.fileno) + a2.autoclose = false + a2.local_address + } +end diff --git a/spec/ruby/library/socket/basicsocket/remote_address_spec.rb b/spec/ruby/library/socket/basicsocket/remote_address_spec.rb new file mode 100644 index 0000000000..439bf31592 --- /dev/null +++ b/spec/ruby/library/socket/basicsocket/remote_address_spec.rb @@ -0,0 +1,10 @@ +require_relative '../spec_helper' +require_relative '../shared/address' + +describe 'BasicSocket#remote_address' do + it_behaves_like :socket_local_remote_address, :remote_address, -> socket { + a2 = BasicSocket.for_fd(socket.fileno) + a2.autoclose = false + a2.remote_address + } +end diff --git a/spec/ruby/library/socket/shared/address.rb b/spec/ruby/library/socket/shared/address.rb new file mode 100644 index 0000000000..f3be9cfb99 --- /dev/null +++ b/spec/ruby/library/socket/shared/address.rb @@ -0,0 +1,249 @@ +require_relative '../fixtures/classes' + +describe :socket_local_remote_address, shared: true do + describe 'using TCPSocket' do + before :each do + @s = TCPServer.new('127.0.0.1', 0) + @a = TCPSocket.new('127.0.0.1', @s.addr[1]) + @b = @s.accept + @addr = @object.call(@a) + end + + after :each do + [@b, @a, @s].each(&:close) + end + + it 'uses AF_INET as the address family' do + @addr.afamily.should == Socket::AF_INET + end + + it 'uses PF_INET as the protocol family' do + @addr.pfamily.should == Socket::PF_INET + end + + it 'uses SOCK_STREAM as the socket type' do + @addr.socktype.should == Socket::SOCK_STREAM + end + + it 'uses the correct IP address' do + @addr.ip_address.should == '127.0.0.1' + end + + it 'uses the correct port' do + if @method == :local_address + @addr.ip_port.should != @s.addr[1] + else + @addr.ip_port.should == @s.addr[1] + end + end + + it 'equals address of peer socket' do + if @method == :local_address + @addr.to_s.should == @b.remote_address.to_s + else + @addr.to_s.should == @b.local_address.to_s + end + end + + it 'returns an Addrinfo' do + @addr.should be_an_instance_of(Addrinfo) + end + + it 'uses 0 as the protocol' do + @addr.protocol.should == 0 + end + + it 'can be used to connect to the server' do + skip if @method == :local_address + b = @addr.connect + begin + b.remote_address.to_s.should == @addr.to_s + ensure + b.close + end + end + end + + guard -> { SocketSpecs.ipv6_available? } do + describe 'using IPv6' do + before :each do + @s = TCPServer.new('::1', 0) + @a = TCPSocket.new('::1', @s.addr[1]) + @b = @s.accept + @addr = @object.call(@a) + end + + after :each do + [@b, @a, @s].each(&:close) + end + + it 'uses AF_INET6 as the address family' do + @addr.afamily.should == Socket::AF_INET6 + end + + it 'uses PF_INET6 as the protocol family' do + @addr.pfamily.should == Socket::PF_INET6 + end + + it 'uses SOCK_STREAM as the socket type' do + @addr.socktype.should == Socket::SOCK_STREAM + end + + it 'uses the correct IP address' do + @addr.ip_address.should == '::1' + end + + it 'uses the correct port' do + if @method == :local_address + @addr.ip_port.should != @s.addr[1] + else + @addr.ip_port.should == @s.addr[1] + end + end + + it 'equals address of peer socket' do + if @method == :local_address + @addr.to_s.should == @b.remote_address.to_s + else + @addr.to_s.should == @b.local_address.to_s + end + end + + it 'returns an Addrinfo' do + @addr.should be_an_instance_of(Addrinfo) + end + + it 'uses 0 as the protocol' do + @addr.protocol.should == 0 + end + + it 'can be used to connect to the server' do + skip if @method == :local_address + b = @addr.connect + begin + b.remote_address.to_s.should == @addr.to_s + ensure + b.close + end + end + end + end + + with_feature :unix_socket do + describe 'using UNIXSocket' do + before :each do + @path = SocketSpecs.socket_path + @s = UNIXServer.new(@path) + @a = UNIXSocket.new(@path) + @b = @s.accept + @addr = @object.call(@a) + end + + after :each do + [@b, @a, @s].each(&:close) + rm_r(@path) + end + + it 'uses AF_UNIX as the address family' do + @addr.afamily.should == Socket::AF_UNIX + end + + it 'uses PF_UNIX as the protocol family' do + @addr.pfamily.should == Socket::PF_UNIX + end + + it 'uses SOCK_STREAM as the socket type' do + @addr.socktype.should == Socket::SOCK_STREAM + end + + it 'uses the correct socket path' do + if @method == :local_address + @addr.unix_path.should == "" + else + @addr.unix_path.should == @path + end + end + + it 'equals address of peer socket' do + if @method == :local_address + @addr.to_s.should == @b.remote_address.to_s + else + @addr.to_s.should == @b.local_address.to_s + end + end + + it 'returns an Addrinfo' do + @addr.should be_an_instance_of(Addrinfo) + end + + it 'uses 0 as the protocol' do + @addr.protocol.should == 0 + end + + it 'can be used to connect to the server' do + skip if @method == :local_address + b = @addr.connect + begin + b.remote_address.to_s.should == @addr.to_s + ensure + b.close + end + end + end + end + + describe 'using UDPSocket' do + before :each do + @s = UDPSocket.new + @s.bind("127.0.0.1", 0) + @a = UDPSocket.new + @a.connect("127.0.0.1", @s.addr[1]) + @addr = @object.call(@a) + end + + after :each do + [@a, @s].each(&:close) + end + + it 'uses the correct address family' do + @addr.afamily.should == Socket::AF_INET + end + + it 'uses the correct protocol family' do + @addr.pfamily.should == Socket::PF_INET + end + + it 'uses SOCK_DGRAM as the socket type' do + @addr.socktype.should == Socket::SOCK_DGRAM + end + + it 'uses the correct IP address' do + @addr.ip_address.should == '127.0.0.1' + end + + it 'uses the correct port' do + if @method == :local_address + @addr.ip_port.should != @s.addr[1] + else + @addr.ip_port.should == @s.addr[1] + end + end + + it 'returns an Addrinfo' do + @addr.should be_an_instance_of(Addrinfo) + end + + it 'uses 0 as the protocol' do + @addr.protocol.should == 0 + end + + it 'can be used to connect to the peer' do + b = @addr.connect + begin + b.remote_address.to_s.should == @addr.to_s + ensure + b.close + end + end + end +end diff --git a/spec/ruby/library/stringio/ungetbyte_spec.rb b/spec/ruby/library/stringio/ungetbyte_spec.rb index 701463e621..eb1cc55220 100644 --- a/spec/ruby/library/stringio/ungetbyte_spec.rb +++ b/spec/ruby/library/stringio/ungetbyte_spec.rb @@ -1,6 +1,42 @@ +# frozen_string_literal: false require_relative '../../spec_helper' require 'stringio' describe "StringIO#ungetbyte" do - it "needs to be reviewed for spec completeness" + it "ungets a single byte from a string starting with a single byte character" do + str = 'This is a simple string.' + io = StringIO.new("#{str}") + c = io.getc + c.should == 'T' + io.ungetbyte(83) + io.string.should == 'Shis is a simple string.' + end + + it "ungets a single byte from a string in the middle of a multibyte characte" do + str = "\u01a9" + io = StringIO.new(str) + b = io.getbyte + b.should == 0xc6 # First byte of UTF-8 encoding of \u01a9 + io.ungetbyte(0xce) # First byte of UTF-8 encoding of \u03a9 + io.string.should == "\u03a9" + end + + it "constrains the value of a numeric argument to a single byte" do + str = 'This is a simple string.' + io = StringIO.new("#{str}") + c = io.getc + c.should == 'T' + io.ungetbyte(83 | 0xff00) + io.string.should == 'Shis is a simple string.' + end + + it "ungets the bytes of a string if given a string as an arugment" do + str = "\u01a9" + io = StringIO.new(str) + b = io.getbyte + b.should == 0xc6 # First byte of UTF-8 encoding of \u01a9 + io.ungetbyte("\u01a9") + io.string.bytes.should == [198, 169, 169] + end + end diff --git a/spec/ruby/library/stringscanner/check_spec.rb b/spec/ruby/library/stringscanner/check_spec.rb index c7f788f0b3..21da785515 100644 --- a/spec/ruby/library/stringscanner/check_spec.rb +++ b/spec/ruby/library/stringscanner/check_spec.rb @@ -13,4 +13,15 @@ describe "StringScanner#check" do @s.check(/is/).should == nil @s.matched.should == nil end + + ruby_version_is "2.7" do + it "treats String as the pattern itself" do + @s.check("This").should == "This" + @s.matched.should == "This" + @s.pos.should == 0 + @s.check(/is/).should == nil + @s.matched.should == nil + end + end + end diff --git a/spec/ruby/optional/capi/ext/string_spec.c b/spec/ruby/optional/capi/ext/string_spec.c index c3fa53c5a7..099363c951 100644 --- a/spec/ruby/optional/capi/ext/string_spec.c +++ b/spec/ruby/optional/capi/ext/string_spec.c @@ -471,6 +471,32 @@ static VALUE string_spec_rb_sprintf4(VALUE self, VALUE str) { return rb_sprintf("Result: %+" PRIsVALUE ".", str); } +static VALUE string_spec_rb_sprintf5(VALUE self, VALUE width, VALUE precision, VALUE str) { + return rb_sprintf("Result: %*.*s.", FIX2INT(width), FIX2INT(precision), RSTRING_PTR(str)); +} + +static VALUE string_spec_rb_sprintf6(VALUE self, VALUE width, VALUE precision, VALUE str) { + return rb_sprintf("Result: %*.*" PRIsVALUE ".", FIX2INT(width), FIX2INT(precision), str); +} + +static VALUE string_spec_rb_sprintf7(VALUE self, VALUE str, VALUE obj) { + VALUE results = rb_ary_new(); + rb_ary_push(results, rb_sprintf(RSTRING_PTR(str), obj)); + char cstr[256]; + int len = snprintf(cstr, 256, RSTRING_PTR(str), obj); + rb_ary_push(results, rb_str_new(cstr, len)); + return results; +} + +static VALUE string_spec_rb_sprintf8(VALUE self, VALUE str, VALUE num) { + VALUE results = rb_ary_new(); + rb_ary_push(results, rb_sprintf(RSTRING_PTR(str), FIX2LONG(num))); + char cstr[256]; + int len = snprintf(cstr, 256, RSTRING_PTR(str), FIX2LONG(num)); + rb_ary_push(results, rb_str_new(cstr, len)); + return results; +} + PRINTF_ARGS(static VALUE string_spec_rb_vsprintf_worker(char* fmt, ...), 1, 2); static VALUE string_spec_rb_vsprintf_worker(char* fmt, ...) { va_list varargs; @@ -628,6 +654,10 @@ void Init_string_spec(void) { rb_define_method(cls, "rb_sprintf2", string_spec_rb_sprintf2, 3); rb_define_method(cls, "rb_sprintf3", string_spec_rb_sprintf3, 1); rb_define_method(cls, "rb_sprintf4", string_spec_rb_sprintf4, 1); + rb_define_method(cls, "rb_sprintf5", string_spec_rb_sprintf5, 3); + rb_define_method(cls, "rb_sprintf6", string_spec_rb_sprintf6, 3); + rb_define_method(cls, "rb_sprintf7", string_spec_rb_sprintf7, 2); + rb_define_method(cls, "rb_sprintf8", string_spec_rb_sprintf8, 2); rb_define_method(cls, "rb_vsprintf", string_spec_rb_vsprintf, 4); rb_define_method(cls, "rb_str_equal", string_spec_rb_str_equal, 2); rb_define_method(cls, "rb_usascii_str_new", string_spec_rb_usascii_str_new, 2); diff --git a/spec/ruby/optional/capi/string_spec.rb b/spec/ruby/optional/capi/string_spec.rb index 3c5b7fe4e0..5575ade07b 100644 --- a/spec/ruby/optional/capi/string_spec.rb +++ b/spec/ruby/optional/capi/string_spec.rb @@ -1055,6 +1055,51 @@ end s = 'Result: true.' @s.rb_sprintf4(true.class).should == s end + + it "truncates a string to a supplied precision if that is shorter than the string" do + s = 'Result: Hel.' + @s.rb_sprintf5(0, 3, "Hello").should == s + end + + it "does not truncates a string to a supplied precision if that is longer than the string" do + s = 'Result: Hello.' + @s.rb_sprintf5(0, 8, "Hello").should == s + end + + it "pads a string to a supplied width if that is longer than the string" do + s = 'Result: Hello.' + @s.rb_sprintf5(8, 5, "Hello").should == s + end + + it "truncates a VALUE string to a supplied precision if that is shorter than the VALUE string" do + s = 'Result: Hel.' + @s.rb_sprintf6(0, 3, "Hello").should == s + end + + it "does not truncates a VALUE string to a supplied precision if that is longer than the VALUE string" do + s = 'Result: Hello.' + @s.rb_sprintf6(0, 8, "Hello").should == s + end + + it "pads a VALUE string to a supplied width if that is longer than the VALUE string" do + s = 'Result: Hello.' + @s.rb_sprintf6(8, 5, "Hello").should == s + end + + it "can format a nil VALUE as a pointer and gives the same output as sprintf in C" do + res = @s.rb_sprintf7("%p", nil); + res[0].should == res[1] + end + + it "can format a string VALUE as a pointer and gives the same output as sprintf in C" do + res = @s.rb_sprintf7("%p", "Hello") + res[0].should == res[1] + end + + it "can format a raw number a pointer and gives the same output as sprintf in C" do + res = @s.rb_sprintf7("%p", 0x223643); + res[0].should == res[1] + end end describe "rb_vsprintf" do |