From c9213aa864fb8527388679c21f1ea8ce129e2f1a Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 2 May 2020 16:03:14 +0200 Subject: Update to ruby/spec@d394dfd --- spec/ruby/core/enumerator/next_spec.rb | 11 +++ spec/ruby/core/exception/key_error_spec.rb | 6 ++ spec/ruby/core/file/join_spec.rb | 9 +++ spec/ruby/core/file/stat_spec.rb | 5 +- spec/ruby/core/io/copy_stream_spec.rb | 40 ++++++++++ spec/ruby/core/io/fixtures/classes.rb | 4 +- spec/ruby/core/io/fixtures/copy_in_out.rb | 2 + spec/ruby/core/kernel/require_relative_spec.rb | 10 +++ spec/ruby/core/module/using_spec.rb | 90 ++++++++++++++++++++++ .../ruby/core/objectspace/weakmap/each_key_spec.rb | 11 +++ .../core/objectspace/weakmap/each_pair_spec.rb | 11 +++ spec/ruby/core/objectspace/weakmap/each_spec.rb | 11 +++ .../core/objectspace/weakmap/each_value_spec.rb | 11 +++ .../objectspace/weakmap/element_reference_spec.rb | 24 ++++++ .../core/objectspace/weakmap/element_set_spec.rb | 61 +++++++++++++++ spec/ruby/core/objectspace/weakmap/include_spec.rb | 6 ++ spec/ruby/core/objectspace/weakmap/inspect_spec.rb | 25 ++++++ spec/ruby/core/objectspace/weakmap/key_spec.rb | 6 ++ spec/ruby/core/objectspace/weakmap/keys_spec.rb | 6 ++ spec/ruby/core/objectspace/weakmap/length_spec.rb | 6 ++ spec/ruby/core/objectspace/weakmap/member_spec.rb | 6 ++ spec/ruby/core/objectspace/weakmap/shared/each.rb | 10 +++ .../core/objectspace/weakmap/shared/include.rb | 34 ++++++++ .../core/objectspace/weakmap/shared/members.rb | 14 ++++ spec/ruby/core/objectspace/weakmap/shared/size.rb | 14 ++++ spec/ruby/core/objectspace/weakmap/size_spec.rb | 6 ++ spec/ruby/core/objectspace/weakmap/values_spec.rb | 6 ++ spec/ruby/core/objectspace/weakmap_spec.rb | 12 +++ spec/ruby/core/process/clock_getres_spec.rb | 4 +- spec/ruby/core/time/shared/to_i.rb | 7 ++ spec/ruby/core/tracepoint/inspect_spec.rb | 22 ++++-- spec/ruby/language/string_spec.rb | 11 +++ spec/ruby/library/matrix/unitary_spec.rb | 5 +- .../library/net/http/http/fixtures/http_server.rb | 12 ++- spec/ruby/library/rbconfig/rbconfig_spec.rb | 16 ++++ spec/ruby/optional/capi/class_spec.rb | 66 +++++++++++++++- spec/ruby/optional/capi/ext/class_spec.c | 24 ++++++ spec/ruby/optional/capi/ext/rbasic_spec.c | 71 +++++++++++++++++ spec/ruby/optional/capi/ext/symbol_spec.c | 5 ++ spec/ruby/optional/capi/ext/tracepoint_spec.c | 49 ++++++++++++ spec/ruby/optional/capi/rbasic_spec.rb | 22 ++++++ spec/ruby/optional/capi/shared/rbasic.rb | 81 +++++++++++++++++++ spec/ruby/optional/capi/symbol_spec.rb | 16 ++++ spec/ruby/optional/capi/tracepoint_spec.rb | 56 ++++++++++++++ 44 files changed, 904 insertions(+), 20 deletions(-) create mode 100644 spec/ruby/core/io/fixtures/copy_in_out.rb create mode 100644 spec/ruby/core/objectspace/weakmap/each_key_spec.rb create mode 100644 spec/ruby/core/objectspace/weakmap/each_pair_spec.rb create mode 100644 spec/ruby/core/objectspace/weakmap/each_spec.rb create mode 100644 spec/ruby/core/objectspace/weakmap/each_value_spec.rb create mode 100644 spec/ruby/core/objectspace/weakmap/element_reference_spec.rb create mode 100644 spec/ruby/core/objectspace/weakmap/element_set_spec.rb create mode 100644 spec/ruby/core/objectspace/weakmap/include_spec.rb create mode 100644 spec/ruby/core/objectspace/weakmap/inspect_spec.rb create mode 100644 spec/ruby/core/objectspace/weakmap/key_spec.rb create mode 100644 spec/ruby/core/objectspace/weakmap/keys_spec.rb create mode 100644 spec/ruby/core/objectspace/weakmap/length_spec.rb create mode 100644 spec/ruby/core/objectspace/weakmap/member_spec.rb create mode 100644 spec/ruby/core/objectspace/weakmap/shared/each.rb create mode 100644 spec/ruby/core/objectspace/weakmap/shared/include.rb create mode 100644 spec/ruby/core/objectspace/weakmap/shared/members.rb create mode 100644 spec/ruby/core/objectspace/weakmap/shared/size.rb create mode 100644 spec/ruby/core/objectspace/weakmap/size_spec.rb create mode 100644 spec/ruby/core/objectspace/weakmap/values_spec.rb create mode 100644 spec/ruby/core/objectspace/weakmap_spec.rb create mode 100644 spec/ruby/optional/capi/ext/rbasic_spec.c create mode 100644 spec/ruby/optional/capi/ext/tracepoint_spec.c create mode 100644 spec/ruby/optional/capi/rbasic_spec.rb create mode 100644 spec/ruby/optional/capi/shared/rbasic.rb create mode 100644 spec/ruby/optional/capi/tracepoint_spec.rb diff --git a/spec/ruby/core/enumerator/next_spec.rb b/spec/ruby/core/enumerator/next_spec.rb index 3e9ed8b015..a5e01a399d 100644 --- a/spec/ruby/core/enumerator/next_spec.rb +++ b/spec/ruby/core/enumerator/next_spec.rb @@ -24,4 +24,15 @@ describe "Enumerator#next" do @enum.rewind @enum.next.should == 1 end + + it "restarts the enumerator if an exception terminated a previous iteration" do + exception = StandardError.new + enum = Enumerator.new do + raise exception + end + + result = 2.times.map { enum.next rescue $! } + + result.should == [exception, exception] + end end diff --git a/spec/ruby/core/exception/key_error_spec.rb b/spec/ruby/core/exception/key_error_spec.rb index ad280279d8..71bf2b46ff 100644 --- a/spec/ruby/core/exception/key_error_spec.rb +++ b/spec/ruby/core/exception/key_error_spec.rb @@ -10,6 +10,12 @@ describe "KeyError" do error.receiver.should == receiver error.key.should == key + + error = KeyError.new("message", receiver: receiver, key: key) + + error.message.should == "message" + error.receiver.should == receiver + error.key.should == key end end end diff --git a/spec/ruby/core/file/join_spec.rb b/spec/ruby/core/file/join_spec.rb index f1eab02de0..0feedbae93 100644 --- a/spec/ruby/core/file/join_spec.rb +++ b/spec/ruby/core/file/join_spec.rb @@ -136,4 +136,13 @@ describe "File.join" do File.join(bin).should == "bin" File.join("usr", bin).should == "usr/bin" end + + it "raises errors for null bytes" do + -> { File.join("\x00x", "metadata.gz") }.should raise_error(ArgumentError) { |e| + e.message.should == 'string contains null byte' + } + -> { File.join("metadata.gz", "\x00x") }.should raise_error(ArgumentError) { |e| + e.message.should == 'string contains null byte' + } + end end diff --git a/spec/ruby/core/file/stat_spec.rb b/spec/ruby/core/file/stat_spec.rb index 76b0becbf0..275eae36d5 100644 --- a/spec/ruby/core/file/stat_spec.rb +++ b/spec/ruby/core/file/stat_spec.rb @@ -43,10 +43,11 @@ platform_is_not :windows do end it "returns an error when given missing non-ASCII path" do - missing_path = "/missingfilepath\xE3E4".force_encoding("ASCII-8BIT") + missing_path = "/missingfilepath\xE3E4".b -> { File.stat(missing_path) - }.should raise_error(Errno::ENOENT) { |e| + }.should raise_error(SystemCallError) { |e| + [Errno::ENOENT, Errno::EILSEQ].should include(e.class) e.message.should include(missing_path) } end diff --git a/spec/ruby/core/io/copy_stream_spec.rb b/spec/ruby/core/io/copy_stream_spec.rb index c541e96e14..df9c5c7390 100644 --- a/spec/ruby/core/io/copy_stream_spec.rb +++ b/spec/ruby/core/io/copy_stream_spec.rb @@ -279,4 +279,44 @@ describe "IO.copy_stream" do end end + + + describe "with a destination that does partial reads" do + before do + @from_out, @from_in = IO.pipe + @to_out, @to_in = IO.pipe + end + + after do + [@from_out, @from_in, @to_out, @to_in].each {|io| io.close rescue nil} + end + + it "calls #write repeatedly on the destination Object" do + @from_in.write "1234" + @from_in.close + + th = Thread.new do + IO.copy_stream(@from_out, @to_in) + end + + copied = "" + 4.times do + copied += @to_out.read(1) + end + + th.join + + copied.should == "1234" + end + + end +end + +describe "IO.copy_stream" do + it "does not use buffering when writing to STDOUT" do + IO.popen([*ruby_exe, fixture(__FILE__ , "copy_in_out.rb")], "r+") do |io| + io.write("bar") + io.read(3).should == "bar" + end + end end diff --git a/spec/ruby/core/io/fixtures/classes.rb b/spec/ruby/core/io/fixtures/classes.rb index 460dd62387..5cc42c9b44 100644 --- a/spec/ruby/core/io/fixtures/classes.rb +++ b/spec/ruby/core/io/fixtures/classes.rb @@ -164,7 +164,7 @@ module IOSpecs @io = io end - def read(size, buf=nil) + def read(size, buf) @io.read size, buf end @@ -178,7 +178,7 @@ module IOSpecs @io = io end - def readpartial(size, buf=nil) + def readpartial(size, buf) @io.readpartial size, buf end diff --git a/spec/ruby/core/io/fixtures/copy_in_out.rb b/spec/ruby/core/io/fixtures/copy_in_out.rb new file mode 100644 index 0000000000..b9d4085a47 --- /dev/null +++ b/spec/ruby/core/io/fixtures/copy_in_out.rb @@ -0,0 +1,2 @@ +STDOUT.sync = false +IO.copy_stream(STDIN, STDOUT) diff --git a/spec/ruby/core/kernel/require_relative_spec.rb b/spec/ruby/core/kernel/require_relative_spec.rb index b292a46c63..d4146eb3c8 100644 --- a/spec/ruby/core/kernel/require_relative_spec.rb +++ b/spec/ruby/core/kernel/require_relative_spec.rb @@ -90,6 +90,16 @@ describe "Kernel#require_relative with a relative path" do ScratchPad.recorded.should == [] end + it "raises a LoadError that includes the missing path" do + missing_path = "#{@dir}/nonexistent.rb" + expanded_missing_path = File.expand_path(missing_path, File.dirname(__FILE__)) + -> { require_relative(missing_path) }.should raise_error(LoadError) { |e| + e.message.should include(expanded_missing_path) + e.path.should == expanded_missing_path + } + ScratchPad.recorded.should == [] + end + it "raises a LoadError if basepath does not exist" do -> { eval("require_relative('#{@dir}/nonexistent.rb')") }.should raise_error(LoadError) end diff --git a/spec/ruby/core/module/using_spec.rb b/spec/ruby/core/module/using_spec.rb index 533d87d080..4781b99bb7 100644 --- a/spec/ruby/core/module/using_spec.rb +++ b/spec/ruby/core/module/using_spec.rb @@ -243,6 +243,96 @@ describe "Module#using" do mod.call_foo(c).should == "foo from refinement" end + it "is active for module defined via Module.new {}" do + refinement = Module.new do + refine Integer do + def foo; "foo from refinement"; end + end + end + + result = nil + + Module.new do + using refinement + + Module.new do + result = 1.foo + end + end + + result.should == "foo from refinement" + end + + it "is active for class defined via Class.new {}" do + refinement = Module.new do + refine Integer do + def foo; "foo from refinement"; end + end + end + + result = nil + + Module.new do + using refinement + + Class.new do + result = 1.foo + end + end + + result.should == "foo from refinement" + end + + it "is active for block called via instance_exec" do + refinement = Module.new do + refine Integer do + def foo; "foo from refinement"; end + end + end + + c = Class.new do + using refinement + + def abc + block = -> { + 1.foo + } + + self.instance_exec(&block) + end + end + + c.new.abc.should == "foo from refinement" + end + + it "is active for block called via instance_eval" do + refinement = Module.new do + refine String do + def foo; "foo from refinement"; end + end + end + + c = Class.new do + using refinement + + def initialize + @a = "1703" + + @a.instance_eval do + def abc + "#{self}: #{self.foo}" + end + end + end + + def abc + @a.abc + end + end + + c.new.abc.should == "1703: foo from refinement" + end + it "is not active if `using` call is not evaluated" do result = nil diff --git a/spec/ruby/core/objectspace/weakmap/each_key_spec.rb b/spec/ruby/core/objectspace/weakmap/each_key_spec.rb new file mode 100644 index 0000000000..df971deeb9 --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/each_key_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../../spec_helper' +require_relative 'shared/members' +require_relative 'shared/each' + +describe "ObjectSpace::WeakMap#each_key" do + it_behaves_like :weakmap_members, -> map { a = []; map.each_key{ |k| a << k }; a }, %w[A B] +end + +describe "ObjectSpace::WeakMap#each_key" do + it_behaves_like :weakmap_each, :each_key +end diff --git a/spec/ruby/core/objectspace/weakmap/each_pair_spec.rb b/spec/ruby/core/objectspace/weakmap/each_pair_spec.rb new file mode 100644 index 0000000000..ea29edbd2f --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/each_pair_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../../spec_helper' +require_relative 'shared/members' +require_relative 'shared/each' + +describe "ObjectSpace::WeakMap#each_pair" do + it_behaves_like :weakmap_members, -> map { a = []; map.each_pair{ |k,v| a << "#{k}#{v}" }; a }, %w[Ax By] +end + +describe "ObjectSpace::WeakMap#each_key" do + it_behaves_like :weakmap_each, :each_pair +end diff --git a/spec/ruby/core/objectspace/weakmap/each_spec.rb b/spec/ruby/core/objectspace/weakmap/each_spec.rb new file mode 100644 index 0000000000..46fcb66a6f --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/each_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../../spec_helper' +require_relative 'shared/members' +require_relative 'shared/each' + +describe "ObjectSpace::WeakMap#each" do + it_behaves_like :weakmap_members, -> map { a = []; map.each{ |k,v| a << "#{k}#{v}" }; a }, %w[Ax By] +end + +describe "ObjectSpace::WeakMap#each_key" do + it_behaves_like :weakmap_each, :each +end diff --git a/spec/ruby/core/objectspace/weakmap/each_value_spec.rb b/spec/ruby/core/objectspace/weakmap/each_value_spec.rb new file mode 100644 index 0000000000..65a1a7f6fe --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/each_value_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../../spec_helper' +require_relative 'shared/members' +require_relative 'shared/each' + +describe "ObjectSpace::WeakMap#each_value" do + it_behaves_like :weakmap_members, -> map { a = []; map.each_value{ |k| a << k }; a }, %w[x y] +end + +describe "ObjectSpace::WeakMap#each_key" do + it_behaves_like :weakmap_each, :each_value +end diff --git a/spec/ruby/core/objectspace/weakmap/element_reference_spec.rb b/spec/ruby/core/objectspace/weakmap/element_reference_spec.rb new file mode 100644 index 0000000000..cb3174cbfa --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/element_reference_spec.rb @@ -0,0 +1,24 @@ +require_relative '../../../spec_helper' + +describe "ObjectSpace::WeakMap#[]" do + it "is faithful to the map's content" do + map = ObjectSpace::WeakMap.new + key1, key2 = %w[a b].map(&:upcase) + ref1, ref2 = %w[x y] + map[key1] = ref1 + map[key1].should == ref1 + map[key1] = ref1 + map[key1].should == ref1 + map[key2] = ref2 + map[key1].should == ref1 + map[key2].should == ref2 + end + + it "matches using identity semantics" do + map = ObjectSpace::WeakMap.new + key1, key2 = %w[a a].map(&:upcase) + ref = "x" + map[key1] = ref + map[key2].should == nil + end +end diff --git a/spec/ruby/core/objectspace/weakmap/element_set_spec.rb b/spec/ruby/core/objectspace/weakmap/element_set_spec.rb new file mode 100644 index 0000000000..2b53650148 --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/element_set_spec.rb @@ -0,0 +1,61 @@ +require_relative '../../../spec_helper' + +describe "ObjectSpace::WeakMap#[]=" do + def should_accept(map, key, value) + (map[key] = value).should == value + map.should.key?(key) + map[key].should == value + end + + it "is correct" do + map = ObjectSpace::WeakMap.new + key1, key2 = %w[a b].map(&:upcase) + ref1, ref2 = %w[x y] + should_accept(map, key1, ref1) + should_accept(map, key1, ref1) + should_accept(map, key2, ref2) + map[key1].should == ref1 + end + + ruby_version_is ""..."2.7" do + it "does not accept primitive or frozen keys or values" do + map = ObjectSpace::WeakMap.new + x = Object.new + -> { map[true] = x }.should raise_error(ArgumentError) + -> { map[false] = x }.should raise_error(ArgumentError) + -> { map[nil] = x }.should raise_error(ArgumentError) + -> { map[42] = x }.should raise_error(ArgumentError) + -> { map[:foo] = x }.should raise_error(ArgumentError) + -> { map[x] = true }.should raise_error(ArgumentError) + -> { map[x] = false }.should raise_error(ArgumentError) + -> { map[x] = nil }.should raise_error(ArgumentError) + -> { map[x] = 42 }.should raise_error(ArgumentError) + -> { map[x] = :foo }.should raise_error(ArgumentError) + + y = Object.new.freeze + -> { map[x] = y}.should raise_error(FrozenError) + -> { map[y] = x}.should raise_error(FrozenError) + end + end + + ruby_version_is "2.7" do + it "accepts primitive or frozen keys or values" do + map = ObjectSpace::WeakMap.new + x = Object.new + should_accept(map, true, x) + should_accept(map, false, x) + should_accept(map, nil, x) + should_accept(map, 42, x) + should_accept(map, :foo, x) + + should_accept(map, x, true) + should_accept(map, x, false) + should_accept(map, x, 42) + should_accept(map, x, :foo) + + y = Object.new.freeze + should_accept(map, x, y) + should_accept(map, y, x) + end + end +end diff --git a/spec/ruby/core/objectspace/weakmap/include_spec.rb b/spec/ruby/core/objectspace/weakmap/include_spec.rb new file mode 100644 index 0000000000..54ca6b3030 --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/include_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../../spec_helper' +require_relative 'shared/include' + +describe "ObjectSpace::WeakMap#include?" do + it_behaves_like :weakmap_include?, :include? +end diff --git a/spec/ruby/core/objectspace/weakmap/inspect_spec.rb b/spec/ruby/core/objectspace/weakmap/inspect_spec.rb new file mode 100644 index 0000000000..f064f6e3ea --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/inspect_spec.rb @@ -0,0 +1,25 @@ +require_relative '../../../spec_helper' + +describe "ObjectSpace::WeakMap#inspect" do + it "displays object pointers in output" do + map = ObjectSpace::WeakMap.new + # important to test with BasicObject (without Kernel) here to test edge cases + key1, key2 = [BasicObject.new, Object.new] + ref1, ref2 = [BasicObject.new, Object.new] + map.inspect.should =~ /\A\#\z/ + map[key1] = ref1 + map.inspect.should =~ /\A\# => \#>\z/ + map[key1] = ref1 + map.inspect.should =~ /\A\# => \#>\z/ + map[key2] = ref2 + + regexp1 = /\A\# => \#, \# => \#>\z/ + regexp2 = /\A\# => \#, \# => \#>\z/ + str = map.inspect + if str =~ regexp1 + str.should =~ regexp1 + else + str.should =~ regexp2 + end + end +end diff --git a/spec/ruby/core/objectspace/weakmap/key_spec.rb b/spec/ruby/core/objectspace/weakmap/key_spec.rb new file mode 100644 index 0000000000..999685ff95 --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/key_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../../spec_helper' +require_relative 'shared/include' + +describe "ObjectSpace::WeakMap#key?" do + it_behaves_like :weakmap_include?, :key? +end diff --git a/spec/ruby/core/objectspace/weakmap/keys_spec.rb b/spec/ruby/core/objectspace/weakmap/keys_spec.rb new file mode 100644 index 0000000000..7b1494bdd7 --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/keys_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../../spec_helper' +require_relative 'shared/members' + +describe "ObjectSpace::WeakMap#keys" do + it_behaves_like :weakmap_members, -> map { map.keys }, %w[A B] +end diff --git a/spec/ruby/core/objectspace/weakmap/length_spec.rb b/spec/ruby/core/objectspace/weakmap/length_spec.rb new file mode 100644 index 0000000000..3a935648b1 --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/length_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../../spec_helper' +require_relative 'shared/size' + +describe "ObjectSpace::WeakMap#length" do + it_behaves_like :weakmap_size, :length +end diff --git a/spec/ruby/core/objectspace/weakmap/member_spec.rb b/spec/ruby/core/objectspace/weakmap/member_spec.rb new file mode 100644 index 0000000000..cefb190ce7 --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/member_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../../spec_helper' +require_relative 'shared/include' + +describe "ObjectSpace::WeakMap#member?" do + it_behaves_like :weakmap_include?, :member? +end diff --git a/spec/ruby/core/objectspace/weakmap/shared/each.rb b/spec/ruby/core/objectspace/weakmap/shared/each.rb new file mode 100644 index 0000000000..3d43a19347 --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/shared/each.rb @@ -0,0 +1,10 @@ +describe :weakmap_each, shared: true do + it "must take a block, except when empty" do + map = ObjectSpace::WeakMap.new + key = "a".upcase + ref = "x" + map.send(@method).should == map + map[key] = ref + -> { map.send(@method) }.should raise_error(LocalJumpError) + end +end diff --git a/spec/ruby/core/objectspace/weakmap/shared/include.rb b/spec/ruby/core/objectspace/weakmap/shared/include.rb new file mode 100644 index 0000000000..370359e6ca --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/shared/include.rb @@ -0,0 +1,34 @@ +describe :weakmap_include?, shared: true do + it "recognizes keys in use" do + map = ObjectSpace::WeakMap.new + key1, key2 = %w[a b].map(&:upcase) + ref1, ref2 = %w[x y] + + map[key1] = ref1 + map.send(@method, key1).should == true + map[key1] = ref1 + map.send(@method, key1).should == true + map[key2] = ref2 + map.send(@method, key2).should == true + end + + it "matches using identity semantics" do + map = ObjectSpace::WeakMap.new + key1, key2 = %w[a a].map(&:upcase) + ref = "x" + map[key1] = ref + map.send(@method, key2).should == false + end + + ruby_version_is "2.7" do + ruby_bug "#16826", "2.7.0"..."2.8.1" do + it "reports true if the pair exists and the value is nil" do + map = ObjectSpace::WeakMap.new + key = Object.new + map[key] = nil + map.size.should == 1 + map.send(@method, key).should == true + end + end + end +end diff --git a/spec/ruby/core/objectspace/weakmap/shared/members.rb b/spec/ruby/core/objectspace/weakmap/shared/members.rb new file mode 100644 index 0000000000..57226c8d7a --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/shared/members.rb @@ -0,0 +1,14 @@ +describe :weakmap_members, shared: true do + it "is correct" do + map = ObjectSpace::WeakMap.new + key1, key2 = %w[a b].map(&:upcase) + ref1, ref2 = %w[x y] + @method.call(map).should == [] + map[key1] = ref1 + @method.call(map).should == @object[0..0] + map[key1] = ref1 + @method.call(map).should == @object[0..0] + map[key2] = ref2 + @method.call(map).sort.should == @object + end +end diff --git a/spec/ruby/core/objectspace/weakmap/shared/size.rb b/spec/ruby/core/objectspace/weakmap/shared/size.rb new file mode 100644 index 0000000000..1064f99d1b --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/shared/size.rb @@ -0,0 +1,14 @@ +describe :weakmap_size, shared: true do + it "is correct" do + map = ObjectSpace::WeakMap.new + key1, key2 = %w[a b].map(&:upcase) + ref1, ref2 = %w[x y] + map.send(@method).should == 0 + map[key1] = ref1 + map.send(@method).should == 1 + map[key1] = ref1 + map.send(@method).should == 1 + map[key2] = ref2 + map.send(@method).should == 2 + end +end diff --git a/spec/ruby/core/objectspace/weakmap/size_spec.rb b/spec/ruby/core/objectspace/weakmap/size_spec.rb new file mode 100644 index 0000000000..1446abaa24 --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/size_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../../spec_helper' +require_relative 'shared/size' + +describe "ObjectSpace::WeakMap#size" do + it_behaves_like :weakmap_size, :size +end diff --git a/spec/ruby/core/objectspace/weakmap/values_spec.rb b/spec/ruby/core/objectspace/weakmap/values_spec.rb new file mode 100644 index 0000000000..6f6f90d0ba --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap/values_spec.rb @@ -0,0 +1,6 @@ +require_relative '../../../spec_helper' +require_relative 'shared/members' + +describe "ObjectSpace::WeakMap#values" do + it_behaves_like :weakmap_members, -> map { map.values }, %w[x y] +end diff --git a/spec/ruby/core/objectspace/weakmap_spec.rb b/spec/ruby/core/objectspace/weakmap_spec.rb new file mode 100644 index 0000000000..2f3f93c291 --- /dev/null +++ b/spec/ruby/core/objectspace/weakmap_spec.rb @@ -0,0 +1,12 @@ +require_relative '../../spec_helper' + +describe "ObjectSpace::WeakMap" do + + # Note that we can't really spec the most important aspect of this class: that entries get removed when the values + # become unreachable. This is because Ruby does not offer a way to reliable invoke GC (GC.start is not enough, neither + # on MRI or on alternative implementations). + + it "includes Enumerable" do + ObjectSpace::WeakMap.include?(Enumerable).should == true + end +end diff --git a/spec/ruby/core/process/clock_getres_spec.rb b/spec/ruby/core/process/clock_getres_spec.rb index 02e36b2d9c..b3fc9a4e31 100644 --- a/spec/ruby/core/process/clock_getres_spec.rb +++ b/spec/ruby/core/process/clock_getres_spec.rb @@ -19,13 +19,13 @@ describe "Process.clock_getres" do # These are observed - platform_is_not :solaris, :aix, :openbsd, :android do + platform_is :linux, :darwin, :windows do it "with Process::CLOCK_REALTIME reports at least 1 microsecond" do Process.clock_getres(Process::CLOCK_REALTIME, :nanosecond).should <= 1_000 end end - platform_is_not :aix, :openbsd, :android do + platform_is :linux, :darwin, :windows do it "with Process::CLOCK_MONOTONIC reports at least 1 microsecond" do Process.clock_getres(Process::CLOCK_MONOTONIC, :nanosecond).should <= 1_000 end diff --git a/spec/ruby/core/time/shared/to_i.rb b/spec/ruby/core/time/shared/to_i.rb index 03497c700b..06c966b708 100644 --- a/spec/ruby/core/time/shared/to_i.rb +++ b/spec/ruby/core/time/shared/to_i.rb @@ -6,4 +6,11 @@ describe :time_to_i, shared: true do it "doesn't return an actual number of seconds in time" do Time.at(65.5).send(@method).should == 65 end + + it "rounds fractional seconds toward zero" do + t = Time.utc(1960, 1, 1, 0, 0, 0, 999_999) + + t.to_f.to_i.should == -315619199 + t.to_i.should == -315619200 + end end diff --git a/spec/ruby/core/tracepoint/inspect_spec.rb b/spec/ruby/core/tracepoint/inspect_spec.rb index 9ff1653ae8..465f01e229 100644 --- a/spec/ruby/core/tracepoint/inspect_spec.rb +++ b/spec/ruby/core/tracepoint/inspect_spec.rb @@ -3,26 +3,32 @@ require_relative 'fixtures/classes' describe 'TracePoint#inspect' do it 'returns a string containing a human-readable TracePoint status' do - TracePoint.new(:line) {}.inspect.should == - '#' + TracePoint.new(:line) {}.inspect.should == '#' end it 'returns a String showing the event, path and line' do inspect = nil - line = __LINE__ - TracePoint.new(:line) { |tp| inspect = tp.inspect }.enable do - inspect.should == "#" + line = nil + TracePoint.new(:line) { |tp| + inspect ||= tp.inspect + }.enable do + line = __LINE__ end + + inspect.should == "#" end it 'returns a String showing the event, path and line for a :class event' do inspect = nil - line = __LINE__ - TracePoint.new(:class) { |tp| inspect = tp.inspect }.enable do + line = nil + TracePoint.new(:class) { |tp| + inspect ||= tp.inspect + }.enable do + line = __LINE__ + 1 class TracePointSpec::C end end - inspect.should == "#" + inspect.should == "#" end end diff --git a/spec/ruby/language/string_spec.rb b/spec/ruby/language/string_spec.rb index 68c5fd221b..d19b909cab 100644 --- a/spec/ruby/language/string_spec.rb +++ b/spec/ruby/language/string_spec.rb @@ -32,6 +32,11 @@ describe "Ruby character strings" do "#@my_ip".should == 'xxx' end + it "does not interpolate invalid variable names" do + "#@".should == '#@' + "#$%".should == '#$%' + end + it "has characters [.(=?!# end simple # interpolation" do "#@ip[".should == 'xxx[' "#@ip.".should == 'xxx.' @@ -260,6 +265,12 @@ describe "Ruby String literals" do end describe "Ruby String interpolation" do + it "permits an empty expression" do + s = "#{}" # rubocop:disable Lint/EmptyInterpolation + s.should.empty? + s.should_not.frozen? + end + it "returns a string with the source encoding by default" do "a#{"b"}c".encoding.should == Encoding::BINARY eval('"a#{"b"}c"'.force_encoding("us-ascii")).encoding.should == Encoding::US_ASCII diff --git a/spec/ruby/library/matrix/unitary_spec.rb b/spec/ruby/library/matrix/unitary_spec.rb index 69739a2cd2..c52f9d97d9 100644 --- a/spec/ruby/library/matrix/unitary_spec.rb +++ b/spec/ruby/library/matrix/unitary_spec.rb @@ -10,7 +10,10 @@ describe "Matrix.unitary?" do it "returns true for unitary matrices" do Matrix[[0, Complex(0, 1)], [Complex(0, 1), 0]].unitary?.should == true - version_is((Matrix::const_defined?(:VERSION) ? Matrix::VERSION : "0.1.0"), "0.3.0") do + end + + version_is((Matrix::const_defined?(:VERSION) ? Matrix::VERSION : "0.1.0"), "0.3.0") do + it "returns true for unitary matrices with a Complex and a negative #imag" do Matrix[[0, Complex(0, 1)], [Complex(0, -1), 0]].unitary?.should == true end end 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 49e8f437cc..aeb0babda1 100644 --- a/spec/ruby/library/net/http/http/fixtures/http_server.rb +++ b/spec/ruby/library/net/http/http/fixtures/http_server.rb @@ -53,10 +53,10 @@ module NetHTTPSpecs end end - class << self - @server = nil - @server_thread = nil + @server = nil + @server_thread = nil + class << self def port raise "server not started" unless @server @server.config[:Port] @@ -89,8 +89,12 @@ module NetHTTPSpecs if @server begin @server.shutdown - rescue Errno::EPIPE + rescue Errno::EPIPE, Errno::EBADF # Because WEBrick is not thread-safe and only catches IOError + + # EBADF can happen because WEBrick @server_thread concurrently closes the shutdown pipe + # once @status = :Shutdown, while the current thread does write_nonblock("\0"). + # On MRI this EBADF is replaced by IOError due to the GIL around both #close and #write_nonblock. end @server = nil end diff --git a/spec/ruby/library/rbconfig/rbconfig_spec.rb b/spec/ruby/library/rbconfig/rbconfig_spec.rb index f88dc673e5..1aa12df741 100644 --- a/spec/ruby/library/rbconfig/rbconfig_spec.rb +++ b/spec/ruby/library/rbconfig/rbconfig_spec.rb @@ -51,6 +51,22 @@ describe 'RbConfig::CONFIG' do end end end + + platform_is :linux do + it "['AR'] exists and can be executed" do + ar = RbConfig::CONFIG.fetch('AR') + out = `#{ar} --version` + $?.should.success? + out.should_not be_empty + end + + it "['STRIP'] exists and can be executed" do + strip = RbConfig::CONFIG.fetch('STRIP') + out = `#{strip} --version` + $?.should.success? + out.should_not be_empty + end + end end describe "RbConfig::TOPDIR" do diff --git a/spec/ruby/optional/capi/class_spec.rb b/spec/ruby/optional/capi/class_spec.rb index 0b03fb9e6c..c2424668b9 100644 --- a/spec/ruby/optional/capi/class_spec.rb +++ b/spec/ruby/optional/capi/class_spec.rb @@ -1,5 +1,6 @@ require_relative 'spec_helper' require_relative 'fixtures/class' +require_relative '../../core/module/fixtures/classes' load_extension("class") compile_extension("class_under_autoload") @@ -39,6 +40,69 @@ describe "C-API Class function" do @s = CApiClassSpecs.new end + describe "rb_class_instance_methods" do + it "returns the public and protected methods of self and its ancestors" do + methods = @s.rb_class_instance_methods(ModuleSpecs::Basic) + methods.should include(:protected_module, :public_module) + + methods = @s.rb_class_instance_methods(ModuleSpecs::Basic, true) + methods.should include(:protected_module, :public_module) + end + + it "when passed false as a parameter, returns the instance methods of the class" do + methods = @s.rb_class_instance_methods(ModuleSpecs::Child, false) + methods.should include(:protected_child, :public_child) + end + end + + describe "rb_class_public_instance_methods" do + it "returns a list of public methods in module and its ancestors" do + methods = @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild) + methods.should include(:public_3) + methods.should include(:public_2) + methods.should include(:public_1) + + methods = @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild, true) + methods.should include(:public_3) + methods.should include(:public_2) + methods.should include(:public_1) + end + + it "when passed false as a parameter, should return only methods defined in that module" do + @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild, false).should == [:public_1] + end + end + + describe "rb_class_protected_instance_methods" do + it "returns a list of protected methods in module and its ancestors" do + methods = @s.rb_class_protected_instance_methods(ModuleSpecs::CountsChild) + methods.should include(:protected_3) + methods.should include(:protected_2) + methods.should include(:protected_1) + + methods = @s.rb_class_protected_instance_methods(ModuleSpecs::CountsChild, true) + methods.should include(:protected_3) + methods.should include(:protected_2) + methods.should include(:protected_1) + end + + it "when passed false as a parameter, should return only methods defined in that module" do + @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild, false).should == [:public_1] + end + end + + describe "rb_class_private_instance_methods" do + it "returns a list of private methods in module and its ancestors" do + @s.rb_class_private_instance_methods(ModuleSpecs::CountsChild).should == ModuleSpecs::CountsChild.private_instance_methods + @s.rb_class_private_instance_methods(ModuleSpecs::CountsChild, true).should == ModuleSpecs::CountsChild.private_instance_methods + end + + it "when passed false as a parameter, should return only methods defined in that module" do + methods = @s.rb_class_private_instance_methods(ModuleSpecs::CountsChild, false) + methods.should == [:private_1] + end + end + describe "rb_class_new_instance" do it "allocates and initializes a new object" do o = @s.rb_class_new_instance(0, nil, CApiClassSpecs::Alloc) @@ -338,7 +402,7 @@ describe "C-API Class function" do end describe "rb_class_new" do - it "returns an new subclass of the superclass" do + it "returns a new subclass of the superclass" do subclass = @s.rb_class_new(CApiClassSpecs::NewClass) CApiClassSpecs::NewClass.should be_ancestor_of(subclass) end diff --git a/spec/ruby/optional/capi/ext/class_spec.c b/spec/ruby/optional/capi/ext/class_spec.c index e62b9efe2e..36b8c8f2f3 100644 --- a/spec/ruby/optional/capi/ext/class_spec.c +++ b/spec/ruby/optional/capi/ext/class_spec.c @@ -37,6 +37,26 @@ static VALUE class_spec_rb_path_to_class(VALUE self, VALUE path) { return rb_path_to_class(path); } +static VALUE class_spec_rb_class_instance_methods(int argc, VALUE* argv, VALUE self) { + VALUE mod = argv[0]; + return rb_class_instance_methods(--argc, ++argv, mod); +} + +static VALUE class_spec_rb_class_public_instance_methods(int argc, VALUE* argv, VALUE self) { + VALUE mod = argv[0]; + return rb_class_public_instance_methods(--argc, ++argv, mod); +} + +static VALUE class_spec_rb_class_protected_instance_methods(int argc, VALUE* argv, VALUE self) { + VALUE mod = argv[0]; + return rb_class_protected_instance_methods(--argc, ++argv, mod); +} + +static VALUE class_spec_rb_class_private_instance_methods(int argc, VALUE* argv, VALUE self) { + VALUE mod = argv[0]; + return rb_class_private_instance_methods(--argc, ++argv, mod); +} + static VALUE class_spec_rb_class_new(VALUE self, VALUE super) { return rb_class_new(super); } @@ -146,6 +166,10 @@ void Init_class_spec(void) { rb_define_method(cls, "rb_class2name", class_spec_rb_class2name, 1); rb_define_method(cls, "rb_path2class", class_spec_rb_path2class, 1); rb_define_method(cls, "rb_path_to_class", class_spec_rb_path_to_class, 1); + rb_define_method(cls, "rb_class_instance_methods", class_spec_rb_class_instance_methods, -1); + rb_define_method(cls, "rb_class_public_instance_methods", class_spec_rb_class_public_instance_methods, -1); + rb_define_method(cls, "rb_class_protected_instance_methods", class_spec_rb_class_protected_instance_methods, -1); + rb_define_method(cls, "rb_class_private_instance_methods", class_spec_rb_class_private_instance_methods, -1); rb_define_method(cls, "rb_class_new", class_spec_rb_class_new, 1); rb_define_method(cls, "rb_class_new_instance", class_spec_rb_class_new_instance, 3); rb_define_method(cls, "rb_class_real", class_spec_rb_class_real, 1); diff --git a/spec/ruby/optional/capi/ext/rbasic_spec.c b/spec/ruby/optional/capi/ext/rbasic_spec.c new file mode 100644 index 0000000000..b5779ef062 --- /dev/null +++ b/spec/ruby/optional/capi/ext/rbasic_spec.c @@ -0,0 +1,71 @@ +#include "ruby.h" +#include "rubyspec.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +VALUE rbasic_spec_taint_flag(VALUE self) { + return INT2FIX(RUBY_FL_TAINT); +} + +VALUE rbasic_spec_freeze_flag(VALUE self) { + return INT2FIX(RUBY_FL_FREEZE); +} + +VALUE rbasic_spec_get_flags(VALUE self, VALUE val) { + return INT2FIX(RBASIC(val)->flags); +} + +VALUE rbasic_spec_set_flags(VALUE self, VALUE val, VALUE flags) { + RBASIC(val)->flags = FIX2INT(flags); + return INT2FIX(RBASIC(val)->flags); +} + +VALUE rbasic_spec_copy_flags(VALUE self, VALUE to, VALUE from) { + RBASIC(to)->flags = RBASIC(from)->flags; + return INT2FIX(RBASIC(to)->flags); +} + +VALUE rbasic_spec_get_klass(VALUE self, VALUE val) { + return RBASIC(val)->klass; +} + +VALUE rbasic_rdata_spec_get_flags(VALUE self, VALUE structure) { + return INT2FIX(RDATA(structure)->basic.flags); +} + +VALUE rbasic_rdata_spec_set_flags(VALUE self, VALUE structure, VALUE flags) { + RDATA(structure)->basic.flags = FIX2INT(flags); + return INT2FIX(RDATA(structure)->basic.flags); +} + +VALUE rbasic_rdata_spec_copy_flags(VALUE self, VALUE to, VALUE from) { + RDATA(to)->basic.flags = RDATA(from)->basic.flags; + return INT2FIX(RDATA(to)->basic.flags); +} + +VALUE rbasic_rdata_spec_get_klass(VALUE self, VALUE structure) { + return RDATA(structure)->basic.klass; +} + +void Init_rbasic_spec(void) { + VALUE cls = rb_define_class("CApiRBasicSpecs", rb_cObject); + rb_define_method(cls, "taint_flag", rbasic_spec_taint_flag, 0); + rb_define_method(cls, "freeze_flag", rbasic_spec_freeze_flag, 0); + rb_define_method(cls, "get_flags", rbasic_spec_get_flags, 1); + rb_define_method(cls, "set_flags", rbasic_spec_set_flags, 2); + rb_define_method(cls, "copy_flags", rbasic_spec_copy_flags, 2); + rb_define_method(cls, "get_klass", rbasic_spec_get_klass, 1); + + cls = rb_define_class("CApiRBasicRDataSpecs", rb_cObject); + rb_define_method(cls, "get_flags", rbasic_rdata_spec_get_flags, 1); + rb_define_method(cls, "set_flags", rbasic_rdata_spec_set_flags, 2); + rb_define_method(cls, "copy_flags", rbasic_rdata_spec_copy_flags, 2); + rb_define_method(cls, "get_klass", rbasic_rdata_spec_get_klass, 1); +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/spec/ruby/optional/capi/ext/symbol_spec.c b/spec/ruby/optional/capi/ext/symbol_spec.c index d2ca62d81e..7d9a7b4379 100644 --- a/spec/ruby/optional/capi/ext/symbol_spec.c +++ b/spec/ruby/optional/capi/ext/symbol_spec.c @@ -75,6 +75,10 @@ VALUE symbol_spec_rb_sym2str(VALUE self, VALUE sym) { return rb_sym2str(sym); } +VALUE symbol_spec_rb_to_symbol(VALUE self, VALUE val) { + return rb_to_symbol(val); +} + void Init_symbol_spec(void) { VALUE cls = rb_define_class("CApiSymbolSpecs", rb_cObject); rb_define_method(cls, "SYMBOL_P", symbol_spec_SYMBOL_P, 1); @@ -93,6 +97,7 @@ void Init_symbol_spec(void) { rb_define_method(cls, "rb_is_const_id", symbol_spec_rb_is_const_id, 1); rb_define_method(cls, "rb_is_instance_id", symbol_spec_rb_is_instance_id, 1); rb_define_method(cls, "rb_sym2str", symbol_spec_rb_sym2str, 1); + rb_define_method(cls, "rb_to_symbol", symbol_spec_rb_to_symbol, 1); } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/ext/tracepoint_spec.c b/spec/ruby/optional/capi/ext/tracepoint_spec.c new file mode 100644 index 0000000000..78c459d6cb --- /dev/null +++ b/spec/ruby/optional/capi/ext/tracepoint_spec.c @@ -0,0 +1,49 @@ +#include "ruby.h" +#include "rubyspec.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static VALUE callback_called = Qnil; + +static void callback(VALUE tpval, void *data) { + callback_called = (VALUE) data; +} + +static VALUE tracepoint_spec_rb_tracepoint_new(VALUE self, VALUE data) { + return rb_tracepoint_new(Qnil, RUBY_EVENT_LINE, callback, (void*) data); +} + +static VALUE tracepoint_spec_callback_called(VALUE self){ + return callback_called; +} + +static VALUE tracepoint_spec_rb_tracepoint_disable(VALUE self, VALUE trace) { + rb_tracepoint_disable(trace); + return rb_tracepoint_enabled_p(trace); +} + +static VALUE tracepoint_spec_rb_tracepoint_enable(VALUE self, VALUE trace) { + rb_tracepoint_enable(trace); + return rb_tracepoint_enabled_p(trace); +} + +static VALUE tracepoint_spec_rb_tracepoint_enabled_p(VALUE self, VALUE trace) { + return rb_tracepoint_enabled_p(trace); +} + +void Init_tracepoint_spec(void) { + VALUE cls = rb_define_class("CApiTracePointSpecs", rb_cObject); + rb_define_method(cls, "rb_tracepoint_new", tracepoint_spec_rb_tracepoint_new, 1); + rb_define_method(cls, "rb_tracepoint_disable", tracepoint_spec_rb_tracepoint_disable, 1); + rb_define_method(cls, "rb_tracepoint_enable", tracepoint_spec_rb_tracepoint_enable, 1); + rb_define_method(cls, "rb_tracepoint_enabled_p", tracepoint_spec_rb_tracepoint_enabled_p, 1); + rb_define_method(cls, "callback_called?", tracepoint_spec_callback_called, 0); +} + +#ifdef __cplusplus +} +#endif diff --git a/spec/ruby/optional/capi/rbasic_spec.rb b/spec/ruby/optional/capi/rbasic_spec.rb new file mode 100644 index 0000000000..283e70db70 --- /dev/null +++ b/spec/ruby/optional/capi/rbasic_spec.rb @@ -0,0 +1,22 @@ +require_relative 'spec_helper' +require_relative 'shared/rbasic' +load_extension("rbasic") +load_extension("data") +load_extension("array") + +describe "RBasic support for regular objects" do + before :all do + @specs = CApiRBasicSpecs.new + @data = -> { [Object.new, Object.new] } + end + it_should_behave_like :rbasic +end + +describe "RBasic support for RData" do + before :all do + @specs = CApiRBasicRDataSpecs.new + @wrapping = CApiWrappedStructSpecs.new + @data = -> { [@wrapping.wrap_struct(1024), @wrapping.wrap_struct(1025)] } + end + it_should_behave_like :rbasic +end diff --git a/spec/ruby/optional/capi/shared/rbasic.rb b/spec/ruby/optional/capi/shared/rbasic.rb new file mode 100644 index 0000000000..efd5c85e61 --- /dev/null +++ b/spec/ruby/optional/capi/shared/rbasic.rb @@ -0,0 +1,81 @@ +describe :rbasic, shared: true do + + before :all do + specs = CApiRBasicSpecs.new + @taint = specs.taint_flag + @freeze = specs.freeze_flag + end + + it "reports the appropriate FREEZE flag for the object when reading" do + obj, _ = @data.call + initial = @specs.get_flags(obj) + obj.freeze + @specs.get_flags(obj).should == @freeze | initial + end + + it "supports setting the FREEZE flag" do + obj, _ = @data.call + initial = @specs.get_flags(obj) + @specs.set_flags(obj, @freeze | initial).should == @freeze | initial + obj.frozen?.should == true + end + + ruby_version_is ""..."2.7" do + it "reports the appropriate FREEZE and TAINT flags for the object when reading" do + obj, _ = @data.call + initial = @specs.get_flags(obj) + obj.taint + @specs.get_flags(obj).should == @taint | initial + obj.untaint + @specs.get_flags(obj).should == initial + obj.freeze + @specs.get_flags(obj).should == @freeze | initial + + obj, _ = @data.call + obj.taint + obj.freeze + @specs.get_flags(obj).should == @freeze | @taint | initial + end + + it "supports setting the FREEZE and TAINT flags" do + obj, _ = @data.call + initial = @specs.get_flags(obj) + @specs.set_flags(obj, @taint | initial).should == @taint | initial + obj.tainted?.should == true + @specs.set_flags(obj, initial).should == initial + obj.tainted?.should == false + @specs.set_flags(obj, @freeze | initial).should == @freeze | initial + obj.frozen?.should == true + + obj, _ = @data.call + @specs.set_flags(obj, @freeze | @taint | initial).should == @freeze | @taint | initial + obj.tainted?.should == true + obj.frozen?.should == true + end + end + + it "supports user flags" do + obj, _ = @data.call + @specs.get_flags(obj) == 0 + @specs.set_flags(obj, 1 << 14 | 1 << 16).should == 1 << 14 | 1 << 16 + @specs.get_flags(obj).should == 1 << 14 | 1 << 16 + @specs.set_flags(obj, 0).should == 0 + end + + it "supports copying the flags from one object over to the other" do + obj1, obj2 = @data.call + @specs.set_flags(obj1, @taint | 1 << 14 | 1 << 16) + @specs.copy_flags(obj2, obj1) + @specs.get_flags(obj2).should == @taint | 1 << 14 | 1 << 16 + @specs.set_flags(obj1, 0) + @specs.copy_flags(obj2, obj1) + @specs.get_flags(obj2).should == 0 + end + + it "supports retrieving the (meta)class" do + obj, _ = @data.call + @specs.get_klass(obj).should == obj.class + obj.singleton_class # ensure the singleton class exists + @specs.get_klass(obj).should == obj.singleton_class + end +end diff --git a/spec/ruby/optional/capi/symbol_spec.rb b/spec/ruby/optional/capi/symbol_spec.rb index 0d71c1c711..b8fda34c0e 100644 --- a/spec/ruby/optional/capi/symbol_spec.rb +++ b/spec/ruby/optional/capi/symbol_spec.rb @@ -153,4 +153,20 @@ describe "C-API Symbol function" do @s.rb_sym2str(:bacon).should == "bacon" end end + + describe "rb_to_symbol" do + it "returns a Symbol for a Symbol" do + @s.rb_to_symbol(:foo).should == :foo + end + + it "returns a Symbol for a String" do + @s.rb_to_symbol("foo").should == :foo + end + + it "coerces to Symbol using to_str" do + o = mock('o') + o.should_receive(:to_str).and_return("foo") + @s.rb_to_symbol(o).should == :foo + end + end end diff --git a/spec/ruby/optional/capi/tracepoint_spec.rb b/spec/ruby/optional/capi/tracepoint_spec.rb new file mode 100644 index 0000000000..6aeac54921 --- /dev/null +++ b/spec/ruby/optional/capi/tracepoint_spec.rb @@ -0,0 +1,56 @@ +require_relative 'spec_helper' + +load_extension("tracepoint") + +describe "CApiTracePointSpecs" do + before :each do + @s = CApiTracePointSpecs.new + end + + after :each do + @trace.disable if @trace and @trace.enabled? + end + + describe "rb_tracepoint_new" do + it "returns a tracepoint object" do + @trace = @s.rb_tracepoint_new(7) + @trace.should be_an_instance_of(TracePoint) + @trace.enabled?.should == false + end + + it "traces lines when given RUBY_EVENT_LINE" do + @trace = @s.rb_tracepoint_new(8) + @trace.enable + @s.callback_called?.should == 8 + end + end + + describe "rb_tracepoint_disable" do + it "disables an enabled TracePoint" do + @trace = @s.rb_tracepoint_new(9) + @trace.enabled?.should == false + @trace.enable + @trace.enabled?.should == true + @s.rb_tracepoint_disable(@trace).should == false + @trace.enabled?.should == false + end + end + + describe "rb_tracepoint_enable" do + it "enables a disabled TracePoint" do + @trace = @s.rb_tracepoint_new(10) + @trace.enabled?.should == false + @s.rb_tracepoint_enable(@trace).should == true + @trace.enabled?.should == true + end + end + + describe "rb_tracepoint_enabled_p" do + it "returns correct enabled status" do + @trace = @s.rb_tracepoint_new(11) + @s.rb_tracepoint_enabled_p(@trace).should == false + @trace.enable + @s.rb_tracepoint_enabled_p(@trace).should == true + end + end +end -- cgit v1.2.3